Lately I have seen a lot of blog posts concerning how to build loosely coupled applications. Which patterns do you use most when creating loosely coupled applications? Dependency Injection? Inversion of Control?
Aside: things that stops me writing coupled applications aren't just patterns:
Naming. If I can't easily think of a name for my class, it either does nothing or too many things.
Testability. If I can't easily mock out my class' dependencies, it's a coupled design.
I find myself using the Command pattern quite often. It's a pattern that just keeps giving project after project.
Dependency injection with spring is my favourite. Additionally with maven it's common to do this really neat trick of hiding all the implementations behind an API module. So if your code has three modules, "application-core", "externalsystems-api" and "externalsystems", you can make "application-core" depend ONLY on externalsystems-api. The actual-implementations and all their dependencies can be totally invisible to the application-core module. This really enforces a much harder separation of concerns and makes loose coupling easier.
The neat thing is that IDEs that load these maven setups enforce these visibility constraints. So you're not going to be able to reference SQL, AXIS, JAXB or whatever in your application-core
I think one of the fundamental techniques is "Tell Don't Ask Principle, Law Of Demeter". Maybe it is not like DI,UI or other Desing Patterns but I think objects that fallow this principle are loosely coupled and do the one thing well.
"Keep It Shy Keep It Dry Tell The Other Guy"
Some of the SOA related patterns (enterprise service bus for example) offer abstraction at a higher level and support separation of concerns across business services and technical services. Loose coupling between the services is then (arguably) supported by introducing a broker or bus that de-couples the services in the solution.
Yes, the important ones are Dependency Injection and Inversion of Control, but lets not forget the Abstract Factory and Registries.
Bridge pattern (http://en.wikipedia.org/wiki/Bridge_pattern)
Dependency Injection is a form of Inversion-of-control.
The Spring Framework has a large base of Java programmers, and it has a .NET implementation, too.
I'm surprised this hasn't been mentioned yet - strategies allow you to avoid creating classes that know too much about different types in your domain model. Each strategy is responsible for codifying a particular interaction involving specific types. This avoids creating a master type that is aware of many others and the nuances of the implementation of each.
From Wikipedia:
The strategy pattern uses composition instead of inheritance. In the strategy pattern behaviors are defined as separate interfaces and specific classes that implement these interfaces. Specific classes encapsulate these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time.
Dependency injection and IOC are both excellent for decoupling code.
Dotnetrocks show 362 provides very good definitions. Also watch the related DNR TV episode to get a clearer understanding.
Dependency injection is the pattern that I use in nearly all classes that I write - if the class has a dependency, I always inject it (using constructor injection). Only classes which have no dependencies (i.e. value objects) don't use the DI pattern. Being able to test classes which use DI is a major benefit.
For information on the benefits of DI, these two presentations are very good: http://googletesting.blogspot.com/2008/11/clean-code-talks-dependency-injection.html http://googletesting.blogspot.com/2008/11/clean-code-talks-global-state-and.html
No DI container is needed to use the DI pattern, but when the program becomes big (tens of classes or many scopes), then a DI container can reduce much boilerplate. On the JVM my default choice is Guice.
Inversion of Control as overall code/architecture style.
DI as a mechanism to configure IoC.
Local abstractions (I call this "Ideal Environment Development" - write as if you had the exact environment you wanted).
Objects typically communicate using void methods, and by passing data, rather than having getters/setters.
I never use a dependency directly in a core business class - it is always abstracted to a local abstraction, and an explicit Bridge deals with the dependency.
I've found that this combination allows for extremely flexible code with a very compositional feel to it.
© 2022 - 2024 — McMap. All rights reserved.