Abstraction without Decoupling

This antipattern describes a situation where a client uses a service represented as an abstract type, but also a concrete implementation of this service, represented as a non-abstract subtype of the abstract type. This makes it difficult to replace the service implementation and to dynamically reconfigure or upgrade systems. To do this, the client code must be updated. The client couples service description and service implementation together. Techniques such as dependency injection [1] could be used to break instances of this pattern. Fowler discusses how design patterns such as Separated Interface and Plugin can be used to avoid AWD in [2].

This antipattern is implemented as graph query (motif) as follows:


motif awd
select client, service, service_impl
where "!client.abstract" and "service.abstract" and "!service_impl.abstract"
connected by inherits(service_impl>service) and service_invocation(client>service)[1,1] and implementation_dependency(client>service_impl)
where "inherits.type=='extends' || inherits.type=='implements'" and "service_invocation.type=='uses'" and "implementation_dependency.type=='uses'"
group by "client" and "service"

References

  1. M. Fowler: Inversion of control containers and the dependency injection pattern, 2004.
  2. M. Fowler: Patterns of Enterprise Application Architecture. Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA, 2002.