Going bananas with loose coupling and dependency injection - dependency-injection

With the latest additions to our dependency injection framework (annotations in spring), the marginal cost of creating DI-managed components seems to have hit some critical new threshold. While there previously was an overhead associated with spring (tons of XML and additional indirections), dependency injection seems to have started going where lots of patterns go; they go under the hood and "disappear".
The consequence of this is that the conceptual overhead associated with a large number of components becomes acceptable. It's arguable that we could make a system where most classes only expose
one single public method and build the whole system by just aggregating these pieces like crazy. In our case a few things are given; the user interface of your application has some functional requirements that shape the topmost services. And the back-end systems control the lower part. But in between these two, everything is up for grabs.
Our constant discussion is really why are we grouping things in classes and what should the principles be ? A couple of things are certain; the facade pattern is dead and buried. Any service containing multiple unrelated features also tend to get split up. "Unrelated feature" is interpreted in an extremely much stricter sense than I have ever done earlier.
In our team there are two prevailing trains of thought here: Implementation dependencies restrict grouping; any functionality in a single class should preferably be a client of all injected dependencies. We are a DDD project and the other fraction thinks the domain restricts grouping (CustomerService or finer grained CustomerProductService, CustomerOrderService) - normalized usage of injected dependencies is unimportant.
So in the loosely coupled DI universe, why are we grouping logic in classes ?
edit: duffymo point out that this may be moving towards a functional style of programming; which brings up the issue of state. We have quite a few "State" objects that represent (small) pieces of relevant application state. We inject these into any service that has a legitimate need for this state. (The reason we use "State" objects instead of regular domain objects is that spring construct these at an unspecified time. I see this as a slight workaround or alternate solution to letting spring manage the actual creation of domain objects. There may be better solutions here).
So for instance any service that needs OrderSystemAccessControlState can just inject this, and the scope of this data is not readily known to the consumer. Some of the security-relate state is typically used at a lot of different levels but totally invisible on the levels in-between. I really think this violates fundamentally with functional principles. I even had a hard time adjusting to this concept form an OO perspective - but as long as the injected state is precise and strongly type then the need is legit aka the use case is proper.

The overriding principals of good OO Design do not stop at loose coupling, but also high cohesion, which gets ignored in most discussions.
High Cohesion
In computer programming, cohesion is a
measure of how strongly-related or
focused the responsibilities of a
single module are. As applied to
object-oriented programming, if the
methods that serve the given class
tend to be similar in many aspects,
then the class is said to have high
cohesion. In a highly-cohesive system,
code readability and the likelihood of
reuse is increased, while complexity
is kept manageable.
Cohesion is decreased if:
* The functionality embedded in a class, accessed through its methods,
have little in common.
* Methods carry out many varied activities, often using coarsely-grained or
unrelated sets of data.
Disadvantages of low cohesion (or "weak cohesion") are:
* Increased difficulty in understanding modules.
* Increased difficulty in maintaining a system, because logical changes in
the domain affect multiple modules, and because changes in one module
require changes in related modules.
* Increased difficulty in reusing a module because most applications
won’t need the random set of operations provided by a module.
One thing that gets lost when people go crazy with IoC containers is the cohesion is lost and traceability of what and how something does something becomes a nightmare to figure out later own down the road, because all the relationships are obscured by a bunch of XML configuration files ( Spring I am looking at you ) and poorly named implementation classes.

Why are we grouping things in classes and what should the principles be ?
Are you stressing the, "Grouping," or the, "Classes?"
If you're asking why are we grouping things, then I'd second Medelt's, "Maintainability," though I'd rephrase it as, "To reduce the potential cost of ripple effects."
Consider, for a moment, not the actual coupling between your components (classes, files, whatever they may be) but the potential coupling, that is, the maximum possible number of source code dependencies between those components.
There is a theorem which shows that, given a chain of components a - b - c - d - e, such that a depends on b, etc., the probability that changing e will then change the c component cannot be greater than the possibility that changing e will then change d. And in real software systems, the probability that changing e will affect c is usually less than the probability that changing e will affect d.
Of course, you might say, that's obvious. But we can make it even more obvious. In this example, d has a direct dependency on e, and c has an indirect (via d) dependency on e. Thus we can say that, statistically, a system formed predominantly of direct dependencies will suffer from a greater ripple effect than a system formed predominantly from indirect dependencies.
Given that, in the real world, each ripple effect costs money, we can say that the cost of ripple effect of an update to system formed predominantly of direct dependencies will be higher than the cost of ripple effect of an update to system formed predominantly of indirect dependencies.
Now, back to potential coupling. It's possible to show that, within an absolute encapsulation context (such as Java or C#, where recursive encapsulation is not widely employed) all components are potentially connected to one another via either a direct dependency or an indirect dependency with a single, intermediate component. Statistically, a system which minimises the direct potential coupling between its components minimises the potential cost of ripple effect due to any update.
And how do we achieve this distinction between direct and indirect potential coupling (as if we haven't already let the cat out of the bag)? With encapsulation.
Encapsulation is the property that the information contained in a modelled entity is accessible only through interactions at the interfaces supported by that modelled entity. The information (which can be data or behavior) which is not accessible through these interfaces is called, "Information hidden." By information-hiding behavior within a component, we guarantee that it can only be accessed indirectly (via the interfaces) by external components.
This necessarily requires some sort of grouping container in which some sort of finer-grained functionality can be information-hidden.
This is why we are, "Grouping," things.
As to why we're using classes to group things:
A) Classes provide a language-supported mechanism for encapsulation.
B) We're not just using classes: we're also using namespaces/packages for encapsulation.
Regards,
Ed.

I can think of two reasons.
Maintainability: You'll naturally expect some logic to go together. Logic that defines operations on one particular outside service for example a database should probably be grouped together in a logical way. You can do this in a namespace or a class.
State and identity: objects do not only contain logic but also maintain state. Logic that is part of the interface of working with the state of a particular object should be defined on that object. Objects also maintain identity, an object that models one entity in the problem domain should be one object in your software.
As a side-node: The state and identity argument is mostly applicable to domain objects. In most solutions I've used the IoC container mainly for the services around those. My domain objects are usually created and destroyed as part of the program flow and I usually use separate factory objects for this. The factories can then be injected and handled by the IoC container. I've had some success creating factories as wrappers around the IoC container. This way the container handles lifetime of the domain objects too.
This is a very interesting question. If I look back at the way I've implemented things in the past I can see a trend towards smaller and more granular interfaces and classes. Things certainly got better this way. I don't think the optimal solution has one function per class though. This will effectively mean you're using an OO language as a functional language and while functional languages are very powerful there is a lot to be said for combining the two paradigms.

Pure DI perfect universe, I think single classes+method design is ideal. In reality we need to balance the cost of that which makes it less feasible.
Cost factors
Overhead of DI. Spinning up all the underlying and related underlyings for a single method is expensive. Grouping into a class allows us to offset some of that.
Skills - DI is new to many (myself ESPECIALLY) so understanding how to do it better or get out of old/habitual designs is tough
Brown field apps which have them already, it's easier/cheaper/quicker to live with them and worry about this in future green field apps
Hopefully my newbie-ness (yes, I am filled with made up words) with DI hasn't made me completely wrong with this.

Related

Is it possible to properly use DDD with all building blocks in monolith application?

I watched some videos, read some blogs about it. SO has many questions and answers on that subject but I can not find anywhere exact answer for my question.
Almost every question and answer has a lack of usage context.
I have one middle sized, asp.net-mvc, monolith application which is running in one process on IIS. I want to (refactor and) go all the way with DDD (and CQRS without separated storage for reads and writes for now) but for me it looks like impossible mission without breaking some rules/guides/etc.
Bounded Context
For example I have more than one BCs. Each should not cross their boundaries which means should not share their storage. Right?
It is not possible if you use the whole known (everywhere scattered over the web) solution to work with NHibernate session and UoW.
Aggregate Root
Only one AR should be modified in one transaction. When others ARs are involved should introduce eventual consistency (if I remember those are Eric Evans words).
I try to do it but it is not easy in app like that. Pub/Sub not working as desired because if event is published then all subscribers are take their action within one transaction (NSB/MT does that way).
If event handlers wants to modify others ARs they should be executed in separated transactions, right?
Is it possible to deal with it in monolith application (application where whole code works in one process)?
It is not possible if you use the whole known (everywhere scattered
over the web) solution
[...]
if event is published then all subscribers are take their action
within one transaction
I think you're setting yourself useless and harmful constraints by trying to stick to some "state of the art".
Migrating an entire application to DDD + CQRS is a massive undertaking. Some areas of it don't have well-documented beaten paths yet and you'll probably have a fair bit of exploration to do. My best advice would be to stay at a reasonable distance from "the way people do things". Both in traditional ASP.Net web apps because mainstream practices often don't match the way DDD+CQRS works, and in CQRS itself because the case studies out there are few and far between and most probably very domain specific, with a tendency to advocate the use of heavy tools which may not make sense in your context.
You may need to think out of the box, adopt things incrementally and refrain from goldplating everything. You'll be better off starting with very simple implementations that suit your needs exactly than throwing a ton of tools and frameworks at your codebase.
For instance, do you really need a service bus or could a simple Observer pattern suffice ?
Regarding NHibernate, most implementations out there use a (single) Session Per Request approach, but just because it's the most popular doesn't mean it's the only one. Have you tried using multiple ISessions (one for each BC) available at a more programmable level, such as per-action, or managed entirely manually ? Conversely, have you considered sharing a database between Bounded Contexts at first and see for yourself if that's bad or not ?

Does dependency inversion principle mean that I have to create an interface for every module?

If I want my code to follow SOLID principles, specifically the dependency inversion principle, does that mean that I have to create an interface (abstraction) for every module, even if it has only one implementation ?
In my opinion, and according to these posts:
https://josdejong.com/blog/2015/01/06/code-reuse/
https://blog.ploeh.dk/2010/12/02/Interfacesarenotabstractions/
creating an "abstraction" for every module is a code clutter and violates the YAGNI principle.
My rule of thumb is: do not use dependency injection, or create an interface for a module unless it has more than one implementation (the second implementation could be a mock class for unit testing in case of database/server/file modules).
Can somebody clear this up for me ? Does SOLID mean that I have to inject every module and abstract it ? If yes, isn't it just a lot of clutter we're simply not going to use most of the times ?
The Dependency Inversion Principle states:
High-level modules should not depend on low-level modules. Both should
depend on abstractions.
In other words, each module that is depended upon (so that's everything except the entry point modules in your application) should be abstracted. Otherwise a high-level module will have to depend upon the low-level module directly, causing a violation of the DIP.
The number of implemenations an abstraction has is irrelevant to the DIP, because its goal is to make modules resistent to change. Without abstractions, it would become impossible to easily change implementations or add cross-cutting concerns without having to change or recompile a high-level component.
If, however, you find yourself defining many abstractions with just one implementation, you are violating the Reused Abstraction Principle, as Mark Seemann already stated in the article you are referencing:
Having only one implementation of a given interface is a code smell.
What this means, though, is not that you shouldn't define interfaces at all, but you need to take a good look at your design and spot the classes that are related in behavior. Those related classes can often be placed behind the same generic abstraction (generic interface) and this not only allows abstraction reuse, but makes applying cross-cutting concerns childs play.
Here are a few suggestions of functionality that you can place behind the same generic abstraction:
ICommandHandler<TCommand> for classes that make changes to the system on behalf of the user (use cases).
IQueryHandler<TQuery, TResult> as an abstraction for classes that query the database (or file system, web service, what ever) and return data.
IValidator<T> for classes that check report validation errors back to the user
ISecurityValidator<T> for classes that verify whether a user is allowed to execute a certain operation.
IAuthorizationFilter<T> for classes that allow applying row based security based on the user's permissions and roles.
IEventHandler<T> for classes that respond to a certain business event that has occurred.
These are just a few examples of abstractions. It highly depends on the application and design which generic abstractions you will get.
The applications I write make use of these generic abstractions and those applications just have a few interfaces with just one implementation. About 90% to 98% of the modules in the system implement one of those generic abstractions (depending a bit on the size of the application; the bigger the application, the higher the percentage).
These generic abstractions make it really easy to register all implementations in one line of code in your DI library (or at least, if you are using .NET), but more importantly, as I said before, applying cross-cutting concerns becomes really easy. For instance, without having to make sweeping changes to your application, you can run use cases in a database transaction, or apply a deadlock retry mechanism. Or you can apply caching of queries, without having to do sweeping changes throughout your application.

Should domain objects have dependencies injected into them?

I'm specifically referring to this question:
DDD - How to implement factories
The selected answer has stated:
"factories should not be tied with dependency injection because domain objects shouldn't have dependencies injected into them."
My question is: what is the reasoning of not being able to inject dependencies in to your entities? Or am I just misunderstanding the statement? Can someone please clarify?
Kind of old, but I really want to address this because I've been running into this a lot, and express my opinion on it:
I often hear that Domain Objects should not "depend" on things. And this is true. I often see people extrapolate this to mean we should not inject things into domain object.
That's the opposite of what dependency means. The domain shouldn't depend on other projects, this is true. But, the domain can define its own interfaces which other projects may then implement, which can then be injected back into the domain. As we all know, that's what is called Dependency Inversion (DI).
That is literally the opposite of having a dependency. Not allowing DI into the domain completely hamstrings your ability to accurately model the domain, forces odd SRP violations, and pretty much kills the usability of domain services.
I really feel like I must be the crazy one here, because I feel like everyone reads "the Domain must not have any dependencies" then thinks "being injected with something means you are dependant on it" and comes to the conclusion "therefore we can't inject dependencies into the domain.
That leaves us with the wonderful logic:
Dependency Inversion == Dependency
Domain Objects aren't Factories, Repos, etc. They are only Entities, Value Objects, Domain Services and Aggregate Roots. That is, they must be classes which encapsulates the data your business domain uses, the relationships between them, and the behaviour(read modifications) that the domain can do on that data.
Repository is a pattern to abstract away the persistence infrastructure you are using. It's in DDD because it makes your app decoupled from your database, but not all DDD app need or even should use repository.
Factory is a pattern to isolate the construction logic of objects. It's also just a good practice that DDD recommends, but not really needed in all scenarios.
Domain Objects shouldn't depend on anything else, because they are the core of your app. Everything will depend on them. So keeping them free of other dependency makes a clear one way dependency chain, and reduces the dependency graph. They are the invariants, the model, the foundation. Change them, and you probably need to change a lot of stuff. So changing other things shouldn't force them to change.
Domain objects should not have many dependencies.
By Fowler's Tell-Don't-Ask principle (https://martinfowler.com/bliki/TellDontAsk.html), you would want the domain objects to do as much as possible. Including having dependencies. But in Clean Code (Uncle Bob) Chapter 6, it mentions it can be a good design to have data structures operated on by procedure/function classes (services). As long as you don't have hybrid objects which combine simple getters/setters as well as more complex tell-don't-ask operations.
Fowler disagreed with thin models and called it an antipattern - AnemicDomainModel. https://www.martinfowler.com/bliki/AnemicDomainModel.html
I disagree with Fowler. I strongly agree with the following quote from another article about this Fat-Models problem: "Following this logic basically every behaviour would end up in the model classes. This is something that we know (by experience) is a bad idea. Hundreds or thousands of lines of code crammed into a single class is a recipe for disaster. Service Objects grew out of this frustration." - https://tmichel.github.io/2015/09/14/oo-controversies-tell-dont-ask-vs-the-web/
We actually have a project with fat domain models which has this exact problem. As requirements change over time and code gets more complex, a huge, fat model is quite inflexible to perform different operations and handle new requirements. Instead of adding new service workflow paths (classes) acting differently on the same simple data model, you have to make expensive, difficult refactors on the enormous, complicated domain model. It encapsulates the data and prevents anyone from modifying the data in unexpected ways but at the same time, it makes it really difficult for new workflow to manipulate the data in new ways.

Is there any hard data on the value of Inversion of Control or dependency injection?

I've read a lot about IoC and DI, but I'm not really convinced that you gain a lot by using them in most situations.
If you are writing code that needs pluggable components, then yes, I see the value. But if you are not, then I question whether changing a dependency from a class to an interface is really gaining you anything, other than more typing.
In some cases, I can see where IoC and DI help with mocking, but if you're not using Mocking, or TDD then what's the value? Is this a case of YAGNI?
I doubt you will have any hard data on it, so I will add some thoughts on it.
First, you don't use DI (or other SOLID principles) because it helps you do TDD. Its the other way around, you do TDD because it helps you with the design - which usually means you get code that follow those principles.
Discussing why to use interfaces is a different matter, see: https://stackoverflow.com/questions/667139/what-is-the-purpose-of-interfaces.
I will assume you agree that having your classes do many different things results in messy code. Thus, I am assuming you are already going for SRP.
Because you have different classes that do specific things, you need a way to relate them. If you relate them inside the classes (i.e. the constructors), you get plenty of code that uses specific versions of the classes. This means that making changes to the system will be hard.
You are going to need to change the system, that's a fact of software development. You can call YAGNI about not adding specific extra features, but not on that you won't be needing to change the system. In my case that's something really important as I do weekly sprints.
I use a DI framework where configuration is done through code. With a really small code configuration, you hook up lots of different relations. So, when you take away the discussion on interface vs. concrete classes, you are actually saving typing not the other way around. Also for the cases a concrete class is on the constructor, it hooks it up automatically (I don't have to configure) building the rest of the relations. It also allows me to control some objects life time, in particular I can configure an object to be a Singleton and it hands a single instance all the time.
Also note that just using these practices isn't more overhead. Using them for the first times, is what causes the overhead (because of the learning process + in some cases mind set change).
Bottom line: you ain't gonna need to put all those constructor calls all over the place to go faster.
The most significant gains from DI are not necessarily due to the use of interfaces. You do not actually need to use interfaces to have beneficial effects of dependency injection. If there's only one implementation you can probably inject that directly, and you can use a mix of classes and interfaces.
You're still getting loose coupling, and quite a few development environments you can introduce that interface with a few keypresses if needed.
Hard data on the value of loose coupling I cannot give, but it's been a vision in textbooks for as long as I can remember. Now it's real.
DI frameworks also give you some quite amazing features when it comes to hierarchical construction of large structures. Instead of looking for the leanest DI framework around, I'd recommend you look for a full-featured one. Less isn't always more, at least when it comes to learning about new ways of programming. Then you can go for less.
Apart from testing also the loose coupling is worth it.
I've worked on components for an embedded Java system, which had a fixed configuration of objects after startup (about 50 mostly different objects).
The first component was legacy code without dependency injection, and the subobjects where created all over the place. Now it happened several times that for some modification some code needed to talk to an object which was only available three constructors away. So what can you do but add another parameter to the constructor and pass it through, or even store it in a field to pass it on later. In the long run things became even more tangled than they already where.
The second component I developed from scratch, and used dependency injection (without knowing it at the time). That is, I had one factory which constructed all objects and injected then on a need to know basis. Adding another dependency was easy, just add it to the factory and the objects constructor (or add a setter to avoid loops). No unrelated code needed to be touched.

When do you use dependency injection?

I've been using StructureMap recently and have enjoyed the experience thoroughly. However, I can see how one can easily get carried away with interfacing everything out and end up with classes that take in a boatload of interfaces into their constructors. Even though that really isn't a huge problem when you're using a dependency injection framework, it still feels that there are certain properties that really don't need to be interfaced out just for the sake of interfacing them.
Where do you draw the line on what to interface out vs just adding a property to the class?
The main problem with dependency injection is that, while it gives the appearance of a loosely coupled architecture, it really doesn't.
What you're really doing is moving that coupling from the compile time to the runtime, but still if class A needs some interface B to work, an instance of a class which implements interface B needs still to be provided.
Dependency injection should only be used for the parts of the application that need to be changed dynamically without recompiling the base code.
Uses that I've seen useful for an Inversion of Control pattern:
A plugin architecture. So by making the right entry points you can define the contract for the service that must be provided.
Workflow-like architecture. Where you can connect several components dynamically connecting the output of a component to the input of another one.
Per-client application. Let's say you have various clients which pays for a set of "features" of your project. By using dependency injection you can easily provide just the core components and some "added" components which provide just the features the client have paid.
Translation. Although this is not usually done for translation purposes, you can "inject" different language files as needed by the application. That includes RTL or LTR user interfaces as needed.
Think about your design. DI allows you to change how your code functions via configuration changes. It also allows you to break dependencies between classes so that you can isolate and test objects easier. You have to determine where this makes sense and where it doesn't. There's no pat answer.
A good rule of thumb is that if its too hard to test, you've got some issues with single responsibility and static dependencies. Isolate code that performs a single function into a class and break that static dependency by extracting an interface and using a DI framework to inject the correct instance at runtime. By doing this, you make it trivial to test the two parts separately.
Dependency injection should only be used for the parts of the
application that need to be changed dynamically without recompiling
the base code
DI should be used to isolate your code from external resources (databases, webservices, xml files, plugin architecture). The amount of time it would take to test your logic in code would almost be prohibitive at a lot of companies if you are testing components that DEPEND on a database.
In most applications the database isn't going to change dynamically (although it could) but generally speaking it's almost always good practice to NOT bind your application to a particular external resource. The amount involve in changing resources should be low (data access classes should rarely have a cyclomatic complexity above one in it's methods).
What do you mean by "just adding a property to a class?"
My rule of thumb is to make the class unit testable. If your class relies on the implementation details of another class, that needs to be refactored/abstracted to the point that the classes can be tested in isolation.
EDIT: You mention a boatload of interfaces in the constructor. I would advise using setters/getters instead. I find that it makes things much easier to maintain in the long run.
I do it only when it helps with separation of concerns.
Like maybe cross-project I would provide an interface for implementers in one of my library project and the implementing project would inject whatever specific implementation they want in.
But that's about it... all the other cases it'd just make the system unnecessarily complex
Even with all the facts and processes in the world.. every decision boils down to a judgment call - Forgot where I read that
I think it's more of a experience / flight time call.
Basically if you see the dependency as a candidate object that may be replaced in the near future, use dependency injection. If I see 'classA and its dependencies' as one block for substitution, then I probably won't use DI for A's deps.
The biggest benefit is that it will help you understand or even uncover the architecture of your application. You'll be able to see very clearly how your dependency chains work and be able to make changes to individual parts without requiring you to change things that are unrelated. You'll end up with a loosely coupled application. This will push you into a better design and you'll be surprised when you can keep making improvements because your design will help you keep separating and organizing code going forward. It can also facilitate unit testing because you now have a natural way to substitute implementations of particular interfaces.
There are some applications that are just throwaway but if there's a doubt I would go ahead and create the interfaces. After some practice it's not much of a burden.
Another item I wrestle with is where should I use dependency injection? Where do you take your dependency on StructureMap? Only in the startup application? Does that mean all the implementations have to be handed all the way down from the top-most layer to the bottom-most layer?
I use Castle Windsor/Microkernel, I have no experience with anything else but I like it a lot.
As for how do you decide what to inject? So far the following rule of thumb has served me well: If the class is so simple that it doesn't need unit tests, you can feel free to instantiate it in class, otherwise you probably want to have a dependency through the constructor.
As for whether you should create an interface vs just making your methods and properties virtual I think you should go the interface route either if you either a) can see the class have some level of reusability in a different application (i.e. a logger) or b) if either because of the amount of constructor parameters or because there is a significant amount of logic in the constructor, the class is otherwise difficult to mock.

Resources