Is this bad when using dependency injection:
public function __construct($service = null)
{
if(null === $service){
$service = MyNewDefaultService()
}
$this->service = $service;
}
i.e. the notion of having a default fallback class type for services
This pattern will work (in fact, the (anti)pattern has a name - Bastard Injection), but there are issues relating to this approach:
By constructing a new MyNewDefaultService() dependency in your consumer class, you are coupling to a concrete service class, in addition to the abstraction. In compiled languages, this would also mean that your consuming code now needs a hard 'reference' to the jar / library / dll / assembly containing the concrete dependency class, whereas if you omit the direct construction you could instead just be coupled on interface only. In scripted languages you would need to ensure the concrete dependency is resolvable at runtime.
The lifespan management of the Dependency MyNewDefaultService is now hard-coded to be the same as the life of the consuming class. Lifespans of objects injected and managed by an IoC container could give you more flexibility than this (e.g. inject shared objects etc).
Testing is now more complex as you cannot mock out the "default" path (i.e. when $service == null) and so you would need a mix of Unit Tests (for the injected path, with a mocked dependency) and Integration Tests (for the defaulted path) to prove the correctness of your code.
If your dependency itself has other dependencies, which also use constructor injection, the default construction path soon becomes unwieldy, and leads to even more coupling, as you now need to do all the hard work resolving dependencies that your IoC container would have done for you, e.g.
if(null === $service){
$service = MyNewDefaultService(RepoFactory.Create(LoggerFactory.Create()), ...)
}
TL;DR Although this approach might be a useful during a transient stage while you are migrating from a coupled hierarchy to a loosely coupled Dependency Injected hierarchy managed by an IoC container, the true benefits of the Dependency Inversion Principle will only be fully realized once the constructors only have one path, viz by coupling on an abstraction to all dependencies, not to any concrete implementations.
Related
I'm learning Clean Architecture with the artical .
I know Domain Layer is the most INNER part of the onion (no dependencies with other layers) and it contains Entities, Use cases & Repository Interfaces.
The following code is from the project https://github.com/lopspower/CleanRxArchitecture
GetListRepo.kt and RepoRepository.kt are located in Domain Layer, you can see Image 1
1: I think the GetListRepo class should be abstract or interface, right?
2: There are three parameters for constructor of the class GetListRepo. I don't understand why the author add dependency injection #Inject for the class's constructor.
I think I can instance GetListRepo with any way in Data Layout, why does the author need to set dependency injection in Domain Layer with Clean Architecture ?
GetListRepo.kt
class GetListRepo
#Inject internal constructor(
private val repoRepository: RepoRepository,
useCaseScheduler: UseCaseScheduler? = null,
logger: Logger? = null
) : SingleUseCase<List<Repo>, String>(useCaseScheduler, logger) {
...
}
RepoRepository.kt
interface RepoRepository {
val isConnected: Boolean
...
}
Image 1
This is similar to your another question about interfaces/abstract classes. I will quote myself:
With such architecture you could create alternative implementations of GetAlbumListUseCase in the future and switch them smoothly. You could even use multiple implementations at the same time, for example different objects use different implementations GetAlbumListUseCase. Note that in your current architecture all objects directly depend on a specific implementation, so switching to another one requires to modify half of your code.
Imagine you did as you suggested, you didn't use dependency injection, but you created GetListRepo object everywhere in your code. Then in the future you need to have two alternative ways of providing the data, e.g. with local files and with remote server. Imagine you need to make it configurable in the application settings. Or imagine that you need to create unit tests and it would be good to provide a fake, testing variant of the GetListRepo.
How would you do this if your code everywhere would just instantiate GetListRepo directly? You would need to modify many different places in the code and put some logic related to loading of application settings, etc. everywhere. By using dependency injection all components receive their dependencies from outside, they don't know how they're being created and you can put your creation logic in one place only.
Making long story short: using DI lets us decouple components of our application. It makes our code more flexible and adaptable to different scenarios.
(Related to this question, EF4: Why does proxy creation have to be enabled when lazy loading is enabled?).
I'm new to DI, so bear with me. I understand that the container is in charge of instantiating all of my registered types but in order to do so it requires a reference to all of the DLLs in my solution and their references.
If I weren't using a DI container, I wouldn't have to reference the EntityFramework library in my MVC3 app, only my business layer, which would reference my DAL/Repo layer.
I know that at the end of the day all DLLs are included in the bin folder but my problem is having to reference it explicitly via "add reference" in VS in order to be able to publish a WAP with all necessary files.
If I wasn't using a DI container, I wouldn't have to reference EntityFramework library in my MVC3 app, only my business layer which would reference my DAL/Repo layer.
Yes, that's exactly the situation DI works so hard to avoid :)
With tightly coupled code, each library may only have a few references, but these again have other references, creating a deep graph of dependencies, like this:
Because the dependency graph is deep, it means that most libraries drag along a lot of other dependencies - e.g. in the diagram, Library C drags along Library H, Library E, Library J, Library M, Library K and Library N. This makes it harder to reuse each library independently from the rest - for example in unit testing.
However, in a loosely coupled application, by moving all the references to the Composition Root, the dependency graph is severely flattened:
As illustrated by the green color, it's now possible to reuse Library C without dragging along any unwanted dependencies.
However, all that said, with many DI Containers, you don't have to add hard references to all required libraries. Instead, you can use late binding either in the form of convention-based assembly-scanning (preferred) or XML configuration.
When you do that, however, you must remember to copy the assemblies to the application's bin folder, because that no longer happens automatically. Personally, I rarely find it worth that extra effort.
A more elaborate version of this answer can be found in this excerpt from my book Dependency Injection, Principles, Practices, Patterns.
If I wasn't using an DI container, I wouldn't have to reference
EntityFramework library in my MVC3 app
Even when using a DI container, you don't have to let your MVC3 project reference Entity Framework, but you (implicitly) choose to do this by implementing the Composition Root (the startup path where you compose your object graphs) inside your MVC3 project. If you are very strict about protecting your architectural boundaries using assemblies, you can move your presentation logic to a different project.
When you move all MVC related logic (controllers, etc) from the startup project to a class library, it allows this presentation layer assembly to stay disconnected from the rest of the application. Your web application project itself will become a very thin shell with the required startup logic. The web application project will be the Composition Root that references all other assemblies.
Extracting the presentation logic to a class library can complicate things when working with MVC. It will be harder to wire everything up, since controllers are not in the startup project (while views, images, CSS files, must likely stay in the startup project). This is probably doable but will take more time to set up.
Because of the downsides I generally advice to just keep the Composition Root in the web project. Many developers don’t want their MVC assembly to depend on the DAL assembly, but that should not be a problem. Don't forget that assemblies are a deployment artifact; you split code into multiple assemblies to allow code to be deployed separately. An architectural layer on the other hand is a logical artifact. It's very well possible (and common) to have multiple layers in the same assembly.
In this case you'll end up having the Composition Root (layer) and the Presentation Layer in the same web application project (thus in the same assembly). And even though that assembly references the assembly containing the DAL, the Presentation Layer still does not reference the DAL—this is a big distinction.
Of course, when you do this, you're losing the ability for the compiler to check this architectural rule at compile time. But most architectural rules actually can't be checked by the compiler. In case you're afraid your team won't follow the architectural rules, I'd advise introducing code reviews, which is an important practice to increase code quality, consistency and improve the skills of a team. You can also use tools like NDepend (which is commercial), which help you verifying your architectural rules. When you integrate NDepend with your build process, it can warn you when somebody checked code in that violates such architectural rule.
You can read a more elaborate discussion on how the Composition Root works in chapter 4 of my book Dependency Injection, Principles, Practices, Patterns.
If I wasn't using an DI container, I wouldn't have to reference
EntityFramework library in my MVC3 app, only my business layer which
would reference my DAL/Repo layer.
You can create a seperate project called "DependencyResolver".
In this project you have to reference all your libraries.
Now the UI Layer doesn't need NHibernate/EF or any other not UI relevant library except of Castle Windsor to be referenced.
If you want to hide Castle Windsor and DependencyResolver from your UI layer you could write an HttpModule which calls the IoC registry stuff.
I have only an example for StructureMap:
public class DependencyRegistrarModule : IHttpModule
{
private static bool _dependenciesRegistered;
private static readonly object Lock = new object();
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, args) => EnsureDependenciesRegistered();
}
public void Dispose() { }
private static void EnsureDependenciesRegistered()
{
if (!_dependenciesRegistered)
{
lock (Lock)
{
if (!_dependenciesRegistered)
{
ObjectFactory.ResetDefaults();
// Register all you dependencies here
ObjectFactory.Initialize(x => x.AddRegistry(new DependencyRegistry()));
new InitiailizeDefaultFactories().Configure();
_dependenciesRegistered = true;
}
}
}
}
}
public class InitiailizeDefaultFactories
{
public void Configure()
{
StructureMapControllerFactory.GetController = type => ObjectFactory.GetInstance(type);
...
}
}
The DefaultControllerFactory doesn't use the IoC container directly, but it delegates to IoC container methods.
public class StructureMapControllerFactory : DefaultControllerFactory
{
public static Func<Type, object> GetController = type =>
{
throw new InvalidOperationException("The dependency callback for the StructureMapControllerFactory is not configured!");
};
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return base.GetControllerInstance(requestContext, controllerType);
}
return GetController(controllerType) as Controller;
}
}
The GetController delegate is set in a StructureMap Registry (in Windsor it should be an Installer).
There is a dependency : if an object instantiate another object.
There is no dependency : if an object expects an abstraction (contructor injection, method injection ...)
Assembly References (referencing dll, webservices..) are independant from the dependency concept, because to resolve an abstraction and be able to compile the code, the layer must reference it.
Currently I am working on the Racing-Car-Katas. The goal is to refactor a peach of code so that it follows the solid-principles.
I try to add the Dependency Inversion Principle. Where I can pass a dependency through the constructor.
Initial Situation
Insid the class Alarm is the dependency Sensor which generates a psiPressureValue.
public class Alarm {
Sensor sensor = new Sensor();
public void check()
{
double psiPressureValue = sensor.popNextPressurePsiValue();
/* ... */
}
}
Idea
public class Alarm {
Sensor sensor;
public Alarm() {
this.sensor = new Sensor();
}
public Alarm(ISensor sensor) {
this.sensor = sensor;
}
public void check()
{
double psiPressureValue = sensor.popNextPressurePsiValue();
/* ... */
}
}
If this would be a real application I don't want to break any dependency between Alarm and Sensor. There for I would created the following constructor
public Alarm() {
this.sensor = new Sensor();
}
But my gut feeling says this is code smell..
How to handle such dependencies in real world applications?
The Dependency Inversion Principle (DIP) states:
High-level modules should not depend on low-level modules.
But by defining the default constructor that creates a Sensor implementation, however, you are violating the DIP, because Sensor is a low-level module and Alarm (your high-level module) takes a dependency on it:
public Alarm() {
this.sensor = new Sensor();
}
If there is a need to let the high level module depend on an abstraction (as your additional constructor shows), there is no need to add a default constructor. Doing so only drags along the dependency to the low-level module. Since both your final application and your tests should make use of the overloaded constructor, the default constructor has no meaning and only causes tight coupling and therefore a violation of the DIP.
This is not a theoretical exercise. The DIP should be followed in real-world applications. A well-designed real-world application applies the SOLID principles and uses Dependency Injection as way to achieve loose coupling and the DIP. This decouples modules and allows complete object graphs to be composed in the Composition Root.
In order to not break any dependency between Alarm and Sensor, you need to:
Take all the methods of Sensor that are used by Alarm;
Put them in one (or more) interface(s); and then,
Have Sensor implement those interfaces.
The second constructor approach is not the right way to secure the dependencies. It is violating the DIP by creating an object of Sensor class.
Instead of that, add validation code to the other constructor and make sure that Alarm is always using a valid Sensor through an ISensor (and not create an instance of a Sensor directly).
Ok you want to break the direct coupling between Alarm and Sensor.
Your proposed solutions shows two constructors, one injecting the Sensor object (created externally) and one creating Sensor object directly. You should drop:
public Alarm() {
this.sensor = new Sensor();
}
because its not needed and because it prolongs the tight coupling you are trying to avoid with SOLID. Dependency is not broken by doing this.
Broadly the most common options for creating dependencies are as below.
Dependent objects are created:
1) Directly by the Client object (tight coupling)
2) Indirectly by the Client using Factory Methods of Client
3) Indirectly by the Client using Abstract Factory object injected into the Client (the factory injection is DI). You can inject different factories.
4) Externally manually and injected into the Client (DI)
5) Externally via a DI Container and injected into the Client (DI)
Its a key point of DI that the Client does not control how its dependants are created. This is explains the term "Inversion of Control".
However, the client retains control with "Factory Method", "Abstract Factory".
DI containers have become extremely popular in recent years especially with modern frameworks.
I am trying to understand and exercise the plugin pattern, as explained by Martin Fowler.
I can understand in which way it makes use of the separated interface pattern, and that it requires a factory to provide the right implementation of the interface, based on the currently used environment (test, prod, dev, etc). But:
How exactly does the factory read the environment values and decide which object (implementing the IdGenerator interface) to create?
Is the factory a dependency of the domain object (DomainObject)?
Thank you very much.
The goal of the Plugin pattern is to provide a centralized configuration runtime to promote modularity and scalability. The criteria that determines which implementation to select can be the environment, or anything else, like account type, user group, etc. The factory is just one way to create the desired plugin instance based on the selection criteria.
Implementation Selection Criteria
How your factory reads the selection criteria (environment state) depends on your implementation. Some common approaches are:
Command-Line Argument, for example, CLI calls from different CI/CD pipeline stages can pass a dev/staging/production argument
YAML Config Files could be deserialized into an object or parsed
Class Annotations to tag each implementation with an environment
Feature Flags, e.g. SaaS like Launch Darkly
Dependency Injection framework like Spring IoC
Product Line Engineering software like Big Lever
REST Endpoint, e.g. http://localhost/test/order can create a test order object without notifying any customers
HTTP Request Parameter, such as a field in the header or body
Dependency on Factory
Since the DomainObject calls the factory to create an object with the desired implementation, the factory will be a dependency of the domain object. That being said, the modern approach is to use a dependency injection (DI) library (Guice, Dagger) or a framework with built-in DI (Spring DI, .Net Core). In these cases, there still is a dependency on the DI library or framework, but not explicitly on any factory class.
Note: The Plugin design pattern described on pp.499-503 of PEAA was written by Rice and Foemmel, not Martin Fowler.
You will want to get a full PFD of the "Patterns of Enterprise Application Architecture". What is visible on Fowler's site is basically first half-page of any chapter :)
What is being describes is basically the expanded version of idea behind polymorphism.
I don't think "plugin" can actually be described as a "pattern". It's more like result of other design choices.
What you have are .. emm ... "packages", where the main class in each of them implements a third party interface. Each of those packages also have their internal dependencies (other classes or even other libraries), which are used for some specific task. Each package has it's of configuration (which might be added through DIC config) ans each of them get "registered" in your main application.
The mentioning of a factory is almost a red herring, because these days that functionality would be applied using DIC.
I've designed my classes using CRC cards and I have a lovely set of objects that contain domain/business logic AND data (properties). Some of the classes require saving to and reading from a database.
My repository should exist in a separate project to my domain objects, but needs to reference them in order to create them.
However, the domain objects/entities need to be able to reference the repository.
I could put the objects in the repository, but as they contain domain functionality, that doesn't feel right at all.
I could put the objects that require persistence in a common shared project, but again it feels wrong to single them out.
Where should I put them? I cant help feeling I'm missing something obvious.
Domain objects/entities should not use repositories. Its domain/applications services should use repositories. And that's done very simple - you should define repository interfaces in your Domain Model assembly and use them in domain/application services.
Domain library should contain
Domain Model
Repository Interfaces
Domain Services (use only interfaces of repositories)
This library does not reference other libraries - it sits at the core of your system.
Persistence library should contain implementation of repositories specific to your data provider. E.g. it can use Entity Framework. This library should reference your domain library. Thus it will know about interfaces it should implement and about entities it should work with.
However, the domain objects/entities need to be able to reference the repository.
Do they? Or do they need to reference the interface of the repository? Then the repository itself is just an implementation of that interface, a low-level detail not needed by the domain logic code.
The way I normally structure a repository pattern in my projects is:
Domain Core Project (business models, core business logic, interfaces for dependencies)
Dependency Projects (references Domain Core Project, implements interfaces)
Application Projects (references Domain Core Project, references Dependency Projects either directly, or through configuration, or through an intermediary project which handles dependency injection)
As an example, suppose I'm using a Service Locator for my dependency injection (which I very often do). Then the business models only need to reference the Service Locator object (which itself is supplied by a factory and can be injected). So internal to a business model I might have something like this:
public class SomeBusinessModel
{
private ISomeDependency SomeProperty
{
get
{
return DIFactory.Current.Resolve<ISomeDependency>();
}
}
}
The DIFactory has a static property called Current which is basically a factory method returning a dependency injection resolver, and its interface has a method called Resolve which takes a type and returns an instance.
So in this case...
SomeBusinessModel is in the Domain Core Project
ISomeDependency is in the Domain Core Project
IDIContainer (the return type for Current) is in the Domain Core Project
DIFactory is in the Domain Core Project, and is initialized (it has an Initialize method that sets the current injection container) by the Application Project for a specific dependency injection container
SomeDependency (the actual instance type being returned by the resolver) is in a Dependency Project
In this setup, the business models know that there needs to be a repository, and require that one be supplied, but they don't have a hard dependency on them. The application supplies the actual implementations for those repositories, either directly by providing an instance or indirectly by configuring a dependency injection container to provide an instance.
All actual dependencies point inward from the implementation details (applications and dependencies) to the core business logic. Never outward.