Related
The open/closed principle states that a class should be open for extension but closed for modification.
I thought that the modification part referred strictly to altering the source code of the base class. But I had an argument with someone saying that this also involves overriding methods from the base class.
It this interpretation correct?
Virtual methods allow replacing behavior of a base class in a derived class, without having to alter the base class and this means you adhere to the Open/Closed principle since you can extend the system without having to modify existing code.
Base classes (that are not purely abstract) however, tend to violate the Dependency Inversion Principle, since the derived class takes a dependency on the base class, which is a concrete component instead of being an abstraction. Remember, the DIP states that:
High-level modules should [...] depend on abstractions.
Besides this, base classes tend to violate the Interface Segregation Principle as well in case they define multiple public (or protected) methods that are not all used by the derived type. This is a violation of the ISP because:
no client should be forced to depend on methods it does not use
"I thought that the modification part referred strictly to altering the source code of the base class."
You thought right.
There is a plethora of ways to make a class extensible and allowing one to inherit from it is one of them. The keyword extend is even used in a few languages to enable inheritance which makes it quite obvious that we aren't modifying, we are extending...
Whether inheritance is the right solution to extensibility or not is another concern, but usually it is not though. Composition should be the preferred way to make classes extensible (e.g. Strategy, Observer, Decorator, Pipes and Filters, etc...)
An override is a lot like a callback that anyone can register. It's like:
if (IsOverridden) CallCallback();
else DefaultImplementation(); //possibly empty
In that sense there is no modification. You are just reconfiguring the object to call the callback instead of doing the default behavior.
It's just like the click event of a button. You wouldn't consider subscribing to an event a modification. It's extension.
Form "Adaptive Code via C#" book, virtual methods is a instrument to achieve OCP.
I was recently having a debate about the Dependency Inversion Principle, Inversion of Control and Dependency Injection. In relation to this topic we were debating whether these principles violate one of the pillars of OOP, namely Encapsulation.
My understanding of these things is:
The Dependency Inversion Principle implies that objects should depend upon abstractions, not concretions - this is the fundamental principle upon which the Inversion of Control pattern and Dependency Injection are implemented.
Inversion of Control is a pattern implementation of the Dependency Inversion Principle, where abstract dependencies replace concrete dependencies, allowing concretions of the dependency to be specified outside of the object.
Dependency Injection is a design pattern that implements Inversion of Control and provides dependency resolution. Injection occurs when a dependency is passed to a dependent component. In essence, the Dependency Injection pattern provides a mechanism for coupling dependency abstractions with concrete implementations.
Encapsulation is the process whereby data and functionality that is required by a higher level object is insulated away and inaccessible, thus, the programmer is unaware of how an object is implemented.
The debate got to a sticking point with the following statement:
IoC isn't OOP because it breaks Encapsulation
Personally, I think that the Dependency Inversion Principle and the Inversion of Control pattern should be observed religiously by all OOP developers - and I live by the following quote:
If there is (potentially) more than one way to skin a cat, then do not
behave like there is only one.
Example 1:
class Program {
void Main() {
SkinCatWithKnife skinner = new SkinCatWithKnife ();
skinner.SkinTheCat();
}
}
Here we see an example of encapsulation. The programmer only has to call Main() and the cat will be skinned, but what if he wanted to skin the cat with, say a set of razor sharp teeth?
Example 2:
class Program {
// Encapsulation
ICatSkinner skinner;
public Program(ICatSkinner skinner) {
// Inversion of control
this.skinner = skinner;
}
void Main() {
this.skinner.SkinTheCat();
}
}
... new Program(new SkinCatWithTeeth());
// Dependency Injection
Here we observe the Dependency Inversion Principle and Inversion of Control since an abstract (ICatSkinner) is provided in order to allow concrete dependencies to be passed in by the programmer. At last, there is more than one way to skin a cat!
The quarrel here is; does this break encapsulation? technically one could argue that .SkinTheCat(); is still encapsulated away within the Main() method call, so the programmer is unaware of the behavior of this method, so I do not think this breaks encapsulation.
Delving a little deeper, I think that IoC containers break OOP because they use reflection, but I am not convinced that IoC breaks OOP, nor am I convinced that IoC breaks encapsulation. In fact I'd go as far as to say that:
Encapsulation and Inversion of Control coincide with each other
happily, allowing programmers to pass in only the concretions of a
dependency, whilst hiding away the overall implementation via
encapsulation.
Questions:
Is IoC a direct implementation of the Dependency Inversion Principle?
Does IoC always break encapsulation, and therefore OOP?
Should IoC be used sparingly, religiously or appropriately?
What is the difference between IoC and an IoC container?
Does IoC always break encapsulation, and therefore OOP?
No, these are hierarchically related concerns. Encapsulation is one of the most misunderstood concepts in OOP, but I think the relationship is best described via Abstract Data Types (ADTs). Essentially, an ADT is a general description of data and associated behaviour. This description is abstract; it omits implementation details. Instead, it describes an ADT in terms of pre- and post-conditions.
This is what Bertrand Meyer calls design by contract. You can read more about this seminal description of OOD in Object-Oriented Software Construction.
Objects are often described as data with behaviour. This means that an object without data isn't really an object. Thus, you have to get data into the object in some way.
You could, for example, pass data into an object via its constructor:
public class Foo
{
private readonly int bar;
public Foo(int bar)
{
this.bar = bar;
}
// Other members may use this.bar in various ways.
}
Another option is to use a setter function or property. I hope we can agree that so far, encapsulation is not violated.
What happens if we change bar from an integer to another concrete class?
public class Foo
{
private readonly Bar bar;
public Foo(Bar bar)
{
this.bar = bar;
}
// Other members may use this.bar in various ways.
}
The only difference compared to before is that bar is now an object, instead of a primitive. However, that's a false distinction, because in object-oriented design, an integer is also an object. It's only because of performance optimisations in various programming languages (Java, C#, etc.) that there's an actual difference between primitives (strings, integers, bools, etc.) and 'real' objects. From an OOD perspective, they're all alike. Strings have behaviours as well: you can turn them into all-upper-case, reverse them, etc.
Is encapsulation violated if Bar is a sealed/final, concrete class with only non-virtual members?
bar is only data with behaviour, just like an integer, but apart from that, there's no difference. So far, encapsulation isn't violated.
What happens if we allow Bar to have a single virtual member?
Is encapsulation broken by that?
Can we still express pre- and post-conditions about Foo, given that Bar has a single virtual member?
If Bar adheres to the Liskov Substitution Principle (LSP), it wouldn't make a difference. The LSP explicitly states that changing the behaviour mustn't change the correctness of the system. As long as that contract is fulfilled, encapsulation is still intact.
Thus, the LSP (one of the SOLID principles, of which the Dependency Inversion Principle is another) doesn't violate encapsulation; it describes a principle for maintaining encapsulation in the presence of polymorphism.
Does the conclusion change if Bar is an abstract base class? An interface?
No, it doesn't: those are just different degrees of polymorphism. Thus we could rename Bar to IBar (in order to suggest that it's an interface) and pass it into Foo as its data:
public class Foo
{
private readonly IBar bar;
public Foo(IBar bar)
{
this.bar = bar;
}
// Other members may use this.bar in various ways.
}
bar is just another polymorphic object, and as long as the LSP holds, encapsulation holds.
TL; DR
There's a reason SOLID is also known as the Principles of OOD. Encapsulation (i.e. design-by-contract) defines the ground rules. SOLID describes guidelines for following those rules.
Is IoC a direct implementation of the Dependency Inversion Principle?
The two are related in a way that they talk about abstractions, but that's about it. Inversion of Control is:
a design in which custom-written portions of a computer program
receive the flow of control from a generic, reusable library (source)
Inversion of control is allowing us to hook our custom code into the pipeline of a reusable library. In other words, Inversion control is about frameworks. A reusable library that does not apply Inversion of Control is merely a library. A framework is a reusable library that does apply Inversion of Control.
Do note that we as developers can only apply Inversion of Control if we are writing a framework ourselves; you can't apply inversion of control as an application developer. We can (and should) however apply Dependency Inversion Principle and the Dependency Injection pattern.
Does IoC always break encapsulation, and therefore OOP?
Since IoC is just about hooking into the pipeline of a framework, there is nothing that's leaking here. So the real question is: does Dependency Injection break encapsulation.
The answer to that question is: no, it does not. It doesn't break encapsulation because of two reasons:
Since the Dependency Inversion Principles states that we should program against an abstraction, a consumer will not be able to access the internals of the used implementation and that implementation will therefore not be breaking encapsulation to the client. The implementation might not even be known or accessible at compile time (because it lives in an unreferenced assembly) and the implementation can in that case not leak implementation details and break encapsulation.
Although the implementation accepts the dependencies it requires throughout its constructor, those dependencies will typically be stored in private fields and can't be accessed by anyone (even if a consumer depends directly on the concrete type) and it will therefore not break encapsulation.
Should IoC be used sparingly, religiously or appropriately?
Again, the question is "Should DIP and DI be used sparingly". In my opinion, the answer is: NO, you should actually use it throughout the application. Obviously, you should never apply things religiously. You should apply SOLID principles and the DIP is a crucial part of those principles. They will make your application more flexible and more maintainable and in most scenarios it is very appropriate to apply the SOLID principles.
What is the difference between IoC and an IoC container?
Dependency Injection is a pattern that can be applied either with or without a IoC container. An IoC container is merely a tool that can help building your object graph in a more convenient way, in case you have an application that applies the SOLID principles correctly. If you have an application that doesn't apply the SOLID principles, you will have a hard time using a IoC container. You will have a hard time applying Dependency Injection. Or let me put it more broadly, you will have a hard time maintaining your application anyway. But in no way an IoC container is a required tool. I'm developing and maintaining an IoC container for .NET, but I don't always use a container for all my applications. For the big BLOBAs (boring line of business applications) I often use a container, but for smaller apps (or windows services) I don't always use a container. But I do almost always use Dependency Injection as a pattern, because this is the most effective way to adhere to DIP.
Note: Since an IoC container helps us in applying the Dependency Injection pattern, "IoC container" is a terrible name for such library.
But despite of anything I said above, please note that:
in the real world of the software developer, usefulness trumps theory [from Robert C. Martin's Agile Principle, Patterns and Practices]
In other words, even if DI would break encapsulation, it wouldn't matter, because these techniques and patterns have proven to be very valuable, because it results in very flexible and maintainable systems. Practice trumps theory.
Summing up the question:
We have the ability for a Service to instantiate its own dependencies.
Yet, we also have the ability for a Service to simply define abstractions, and require an application to know about the dependent abstractions, create concrete implementations, and pass them in.
And the question is not, "Why we do it?" (Because we know there is a huge list of why). But the question is, "Doesn't option 2 break encapsulation?"
My "pragmatic" answer
I think Mark is the best bet for any such answers, and as he says: No, encapsulation isn't what people think it is.
Encapsulation is hiding away implementation details of a service or abstraction. A Dependency isn't an implementation detail. If you think of a service as a contract, and its subsequent sub-service dependencies as sub-contracts (etc etc chained along), then you really just end up with one huge contract with addendums.
Imagine I'm a caller and I want to use a legal service to sue my boss. My application would have to know about a service that does so. That alone breaks the theory that knowing about the services/contracts required to accomplish my goal is false.
The argument there is... yeah, but I just want to hire a lawyer, I don't care about what books or services he uses. I'll get some random dood off the interwebz and not care about his implementation details... like so:
sub main() {
LegalService legalService = new LegalService();
legalService.SueMyManagerForBeingMean();
}
public class LegalService {
public void SueMyManagerForBeingMean(){
// Implementation Details.
}
}
But it turns out, other services are required to get the job done, such as understanding workplace law. And also as it turns out... I am VERY Interested in the contracts that lawyer is signing under my name and the other stuff he's doing to steal my money. For example... Why the hell is this internet lawyer based in South Korea? How will THAT help me!?!? That isn't an implementation detail, that's part of a dependency chain of requirements I'm happy to manage.
sub main() {
IWorkLawService understandWorkplaceLaw = new CaliforniaWorkplaceLawService();
//IWorkLawService understandWorkplaceLaw = new NewYorkWorkplaceLawService();
LegalService legalService = new LegalService(understandWorkplaceLaw);
legalService.SueMyManagerForBeingMean();
}
public interface ILegalContract {
void SueMyManagerForBeingMean();
}
public class LegalService : ILegalContract {
private readonly IWorkLawService _workLawService;
public LegalService(IWorkLawService workLawService) {
this._workLawService = workLawService;
}
public void SueMyManagerForBeingMean() {
//Implementation Detail
_workLawService.DoSomething; // { implementation detail in there too }
}
}
Now, all I know is that I have a contract which has other contracts which might have other contracts. I am very well responsible for those contracts, and not their implementation details. Though I am more than happy to sign those contracts with concretions that are relevant to my requirements. And again, I don't care about how those concretions do their jobs, as long as I know I have a binding contract that says we exchange information in some defined way.
I will try to answer your questions, According to my understanding:
Is IoC a direct implementation of the Dependency Inversion Principle?
we can't label IoC as the direct implementation of DIP , as DIP focuses on making higher level modules depending on the abstraction and not on the concretion of lower level modules. But rather IoC is an implementation of Dependency Injection.
Does IoC always break encapsulation, and therefore OOP?
I don't think the mechanism of IoC will violate Encapsulation. But can make the system become Tightly coupled.
Should IoC be used sparingly, religiously or appropriately?
IoC can be used as a in many patterns like Bridge Pattern, where seperating Concretion from Abstraction improves the code. Thus can be used in order to achieve DIP.
What is the difference between IoC and an IoC container?
IoC is a mechanism of Dependency Inversion but containers are those which uses IoC.
Encapsulation does not contradict with Dependency Inversion Principles in Object-Oriented Programming world. For example in a car design, you will have an 'internal engine' which will be encapsulated from outside world, and also 'wheels' that can be replaced easily, and considered as outside component of the car. The car has specification (interface) to rotate the shaft of the wheels, and the wheels component implements part that interact with the shaft.
Here, The internal engine represents the encapsulation process, while the wheel components represent the Dependency Inversion Principles (DIP) in the car design. With DIP, basically we prevent building a monolithic object, and instead we make our object composable. Can you image you build a car, where you cannot replace the wheels because they are built-in into the car.
Also you can read more about Dependency Inversion Principles in more details in my blog Here.
I'm only going to answer one question as many other people have answered everything else. And keep in mind, there is no right or wrong answer, just user preferences.
Should IoC be used sparingly, religiously or appropriately?
My experience leads me to believe that Dependency Injection should only be used on classes that are general and might need changing in the future. Using it religiously will lead to some classes needing 15 interfaces in the constructor which can get really time consuming. That tends to lead to 20% development and 80% house keeping.
Someone brought up an example of a car, and how the builder of the car will want to change the tires. Dependency injection allows one to change the tires without caring of the specific implementation details. But if we take dependency injection religiously... Then we need to start building interfaces to the constituents of the tires as well... Well, what about the threads of the tire? What about the stitching in those tires? What about the chemical in those threads? What about the atoms in those chemical? Etc... Okay! Hey! At some point you're going to have to say "enough is enough"! Let's not turn every little thing into an interface... Because that can get too time consuming. It's okay to have some classes be self contained in and instantiated in the class itself! It's faster to develop, and instantiating the class is a ton easier.
Just my 2 cents.
I have found a case when ioc and dependency injection breaks encapsulation . Lets assume we have a ListUtil class . In that class there is a method called remove duplicates . This method accepts a List . There is an interface ISortAlgorith with a sort method . There is a class called QuickSort which implements this interface. When we write the alogorithm to remove duplicates we have to sort the list inside . Now if RemoveDuplicates allow an interface ISortAlgorithm as a parameter(IOC/Dependency Injection) to allow extensibility for others to choose an another algorithm for remove duplicate we are exposing the complexity of remove duplicate feature of the ListUtil class . Thus violating the foundation stone of Oops.
The DIP states:
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
And the OCP states:
Software entities (classes, modules, functions, etc.) should be open
for extension, but closed for modification.
I think if we satisfy the DIP, it will cover the OCP too, So, why we separate these two principles?
Uncle Bob Martin, who popularized the Open-Closed Principle (OCP) and Dependency Inversion Principles (DIP) as two of the SOLID principles, states himself that DIP arises from an application of OCP and the Liskov Substitution Principle:
In this column, we discuss the structural implications of the OCP and
the LSP. The structure that results from rigorous use of these
principles can be generalized into a principle all by itself. I call
it “The Dependency Inversion Principle” (DIP).
Robert C. Martin, Engineering Notebook, C++ Report, 1996.
So you're right in stating that every instance of DIP will be an instance of OCP, but OCP is much more general. Here's a use-case of OCP but not DIP I ran into recently. Many web frameworks have a notion of signals, where upon one action, a signal is fired. The object sending the signal is completely unaware of the listeners who are registered with the signal. Every time you want to add more listeners to the signal, you can do so without modifying the sender.
This is clearly exemplifying OCP ("closed to modification, open for extension"), but not DIP, as the sender is not depending on anything, so there's no sense in talking about whether it depends on something more abstract or less so.
More generally you can say the Observer Pattern (one of the GoF patterns) describes how to comply with OCP but not DIP. It'd be interesting to go through the GoF book and see which ones have to do with OCP and how many of those are not DIP-related.
I think adhering to the DIP makes it easier to comply with the OCP. However, one does not guarantee the other.
For example, I can create a class that has a method that takes a parameter of base. If base is an abstract class then I'm adhering to the DIP as I have inverted the dependency to the caller. However, if the code in that method does something like:
if (base is derived)
(derived)base.DoSomethingSpecificToDerived;
elsif (base is evenMoreDerived)
(evenMoreDerived)base.DoSomethingSpecificToEvenMoreDerived;
Then it's not OCP compliant as I have to modify it every time I add a new derivative.
It's very contrived example, but you get my point.
The DIP tells you how to organize the dependencies. It doesn't tell you when you are done with a particular interface.
Roughly speaking, the message of OCP is to have complete but minimalistic interfaces. In other words, it tells you when you are done with an interface but it doesn't tell you how to achieve this.
In some sense, DIP and OCP are orthogonal.
So, why we separate these two principles?
As for design patterns and named principles, almost all of them have in common that:
Find what varies and encapsulate (hide) it.
Prefer aggregation over inheritance.
Design to interfaces.
Even if the named patterns and principles partially overlap in some sense, they tell you something more specific (in a more specific situation) than the above three general principles.
Good answer by #CS. To summarize,
The DIP is an extension of the OCP, so
When we satisfy the DIP, we generally satisfy the OCP as well.
The reverse is not true, and we can conceive of OCP-compliant, DIP violations. Here is one more (Java) example.
public abstract class MyClass {
DependencyOne d1;
DependencyTwo d2;
MyClass() {
d1 = new DependencyOne();
d2 = new DependencyTwo();
}
}
The OCP is satisfied because we can extend the class. The DIP is violated because we directly instantiate dependencies.
Now the challenge is, can we think of a DIP-compliant, OCP violation. The best example I can come up with is an annotation. In Java we use the #Deprecated annotation to mark code which is open for modification, thereby violating the OCP. At the same time, this code may be perfectly DIP compliant in terms of its abstractions and dependencies. Certain libraries use an #Beta annotation to similar effect.
I cannot imagine an example that is DIP-compliant and yet closed to extension, beyond the nullary example of a class which has no dependencies, which is not very interesting. I would say the DIP implies openness to extension. However, there may be edge cases where the DIP does not imply closedness to modification.
The OCP makes a dependent class easy to consume. The OCP enables asynchronous consumption of an interface by decoupling old implementations from newer versions. It allows the things that depend upon it to continue to depend on it even in the face of change for other purposes. That way a class never has to care who's calling it.
The DIP does a couple of things. It makes depending on external classes easy. Dependency Injection enables the substitutions of dependencies by encouraging the separation of creation duties from consumption. Instead of creating the external dependency that is to be consumed, the pattern states that it should be provided externally. Ultimately, this encourages code that is idempotent (code that does not change external state). Idempotent code is good because it can be verified that it does only what is immediately visible. It doesn't have external side effects. It's very testable, understandable, and readable.
How to ensure maintainability in a class? Can it simply be done by creating class using design patterns or is there something else involved? Also, what are the characteristics of a good method?
You won't do badly by following the SOLID and DRY principles.
SOLID is:
SRP Single responsibility principle
the notion that an object should have only a single responsibility.
OCP
Open/closed principle
the notion that “software entities … should be open for extension, but closed for modification”.
LSP
Liskov substitution principle
the notion that “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program”. See also design by contract.
ISP
Interface segregation principle
the notion that “many client specific interfaces are better than one general purpose interface.”[5]
DIP
Dependency inversion principle
the notion that one should “Depend upon Abstractions. Do not depend upon concretions.”[5]
Dependency injection is one method of following this principle.
And DRY stands for Don't Repeat Yourself, meaning you should strive to remove any duplication in your code.
Put in a lot of effort to make sure you have a good interface. Once you have that, you can completely rewrite the class, if you want, without affecting any other code in the project. If your class is so big that you can't easily rewrite it, then that is an issue too.
Although Oded's answer is good for ensuring the maintainability of a program or library, this question is about class maintainability and for that, there are only two requirements... a good interface, and strong cohesion.
If I understand correctly, the typical mechanism for Dependency Injection is to inject either through a class' constructor or through a public property (member) of the class.
This exposes the dependency being injected and violates the OOP principle of encapsulation.
Am I correct in identifying this tradeoff? How do you deal with this issue?
Please also see my answer to my own question below.
There is another way of looking at this issue that you might find interesting.
When we use IoC/dependency injection, we're not using OOP concepts. Admittedly we're using an OO language as the 'host', but the ideas behind IoC come from component-oriented software engineering, not OO.
Component software is all about managing dependencies - an example in common use is .NET's Assembly mechanism. Each assembly publishes the list of assemblies that it references, and this makes it much easier to pull together (and validate) the pieces needed for a running application.
By applying similar techniques in our OO programs via IoC, we aim to make programs easier to configure and maintain. Publishing dependencies (as constructor parameters or whatever) is a key part of this. Encapsulation doesn't really apply, as in the component/service oriented world, there is no 'implementation type' for details to leak from.
Unfortunately our languages don't currently segregate the fine-grained, object-oriented concepts from the coarser-grained component-oriented ones, so this is a distinction that you have to hold in your mind only :)
It's a good question - but at some point, encapsulation in its purest form needs to be violated if the object is ever to have its dependency fulfilled. Some provider of the dependency must know both that the object in question requires a Foo, and the provider has to have a way of providing the Foo to the object.
Classically this latter case is handled as you say, through constructor arguments or setter methods. However, this is not necessarily true - I know that the latest versions of the Spring DI framework in Java, for example, let you annotate private fields (e.g. with #Autowired) and the dependency will be set via reflection without you needing to expose the dependency through any of the classes public methods/constructors. This might be the kind of solution you were looking for.
That said, I don't think that constructor injection is much of a problem, either. I've always felt that objects should be fully valid after construction, such that anything they need in order to perform their role (i.e. be in a valid state) should be supplied through the constructor anyway. If you have an object that requires a collaborator to work, it seems fine to me that the constructor publically advertises this requirement and ensures it is fulfilled when a new instance of the class is created.
Ideally when dealing with objects, you interact with them through an interface anyway, and the more you do this (and have dependencies wired through DI), the less you actually have to deal with constructors yourself. In the ideal situation, your code doesn't deal with or even ever create concrete instances of classes; so it just gets given an IFoo through DI, without worrying about what the constructor of FooImpl indicates it needs to do its job, and in fact without even being aware of FooImpl's existance. From this point of view, the encapsulation is perfect.
This is an opinion of course, but to my mind DI doesn't necessarily violate encapsulation and in fact can help it by centralising all of the necessary knowledge of internals into one place. Not only is this a good thing in itself, but even better this place is outside your own codebase, so none of the code you write needs to know about classes' dependencies.
This exposes the dependency being injected and violates the OOP principle of encapsulation.
Well, frankly speaking, everything violates encapsulation. :) It's a kind of a tender principle that must be treated well.
So, what violates encapsulation?
Inheritance does.
"Because inheritance exposes a subclass to details of its parent's implementation, it's often said that 'inheritance breaks encapsulation'". (Gang of Four 1995:19)
Aspect-oriented programming does. For example, you register onMethodCall() callback and that gives you a great opportunity to inject code to the normal method evaluation, adding strange side-effects etc.
Friend declaration in C++ does.
Class extention in Ruby does. Just redefine a string method somewhere after a string class was fully defined.
Well, a lot of stuff does.
Encapsulation is a good and important principle. But not the only one.
switch (principle)
{
case encapsulation:
if (there_is_a_reason)
break!
}
Yes, DI violates encapsulation (also known as "information hiding").
But the real problem comes when developers use it as an excuse to violate the KISS (Keep It Short and Simple) and YAGNI (You Ain't Gonna Need It) principles.
Personally, I prefer simple and effective solutions. I mostly use the "new" operator to instantiate stateful dependencies whenever and wherever they are needed. It is simple, well encapsulated, easy to understand, and easy to test. So, why not?
A good depenancy injection container/system will allow for constructor injection. The dependant objects will be encapsulated, and need not be exposed publicly at all. Further, by using a DP system, none of your code even "knows" the details of how the object is constructed, possibly even including the object being constructed. There is more encapsulation in this case since nearly all of your code not only is shielded from knowledge of the encapsulated objects, but does not even participate in the objects construction.
Now, I am assuming you are comparing against the case where the created object creates its own encapsulated objects, most likely in its constructor. My understanding of DP is that we want to take this responsibility away from the object and give it to someone else. To that end, the "someone else", which is the DP container in this case, does have intimate knowledge which "violates" encapsulation; the benefit is that it pulls that knowledge out of the object, iteself. Someone has to have it. The rest of your application does not.
I would think of it this way: The dependancy injection container/system violates encapsulation, but your code does not. In fact, your code is more "encapsulated" then ever.
This is similar to the upvoted answer but I want to think out loud - perhaps others see things this way as well.
Classical OO uses constructors to define the public "initialization" contract for consumers of the class (hiding ALL implementation details; aka encapsulation). This contract can ensure that after instantiation you have a ready-to-use object (i.e. no additional initialization steps to be remembered (er, forgotten) by the user).
(constructor) DI undeniably breaks encapsulation by bleeding implemenation detail through this public constructor interface. As long as we still consider the public constructor responsible for defining the initialization contract for users, we have created a horrible violation of encapsulation.
Theoretical Example:
Class Foo has 4 methods and needs an integer for initialization, so its constructor looks like Foo(int size) and it's immediately clear to users of class Foo that they must provide a size at instantiation in order for Foo to work.
Say this particular implementation of Foo may also need a IWidget to do its job. Constructor injection of this dependency would have us create a constructor like Foo(int size, IWidget widget)
What irks me about this is now we have a constructor that's blending initialization data with dependencies - one input is of interest to the user of the class (size), the other is an internal dependency that only serves to confuse the user and is an implementation detail (widget).
The size parameter is NOT a dependency - it's simple a per-instance initialization value. IoC is dandy for external dependencies (like widget) but not for internal state initialization.
Even worse, what if the Widget is only necessary for 2 of the 4 methods on this class; I may be incurring instantiation overhead for Widget even though it may not be used!
How to compromise/reconcile this?
One approach is to switch exclusively to interfaces to define the operation contract; and abolish the use of constructors by users.
To be consistent, all objects would have to be accessed through interfaces only, and instantiated only through some form of resolver (like an IOC/DI container). Only the container gets to instantiate things.
That takes care of the Widget dependency, but how do we initialize "size" without resorting to a separate initialization method on the Foo interface? Using this solution, we lost the ability to ensure that an instance of Foo is fully initialized by the time you get the instance. Bummer, because I really like the idea and simplicity of constructor injection.
How do I achieve guaranteed initialization in this DI world, when initialization is MORE than ONLY external dependencies?
As Jeff Sternal pointed out in a comment to the question, the answer is entirely dependent on how you define encapsulation.
There seem to be two main camps of what encapsulation means:
Everything related to the object is a method on an object. So, a File object may have methods to Save, Print, Display, ModifyText, etc.
An object is its own little world, and does not depend on outside behavior.
These two definitions are in direct contradiction to each other. If a File object can print itself, it will depend heavily on the printer's behavior. On the other hand, if it merely knows about something that can print for it (an IFilePrinter or some such interface), then the File object doesn't have to know anything about printing, and so working with it will bring less dependencies into the object.
So, dependency injection will break encapsulation if you use the first definition. But, frankly I don't know if I like the first definition - it clearly doesn't scale (if it did, MS Word would be one big class).
On the other hand, dependency injection is nearly mandatory if you're using the second definition of encapsulation.
It doesn't violate encapsulation. You're providing a collaborator, but the class gets to decide how it is used. As long as you follow Tell don't ask things are fine. I find constructer injection preferable, but setters can be fine as well as long as they're smart. That is they contain logic to maintain the invariants the class represents.
Pure encapsulation is an ideal that can never be achieved. If all dependencies were hidden then you wouldn't have the need for DI at all. Think about it this way, if you truly have private values that can be internalized within the object, say for instance the integer value of the speed of a car object, then you have no external dependency and no need to invert or inject that dependency. These sorts of internal state values that are operated on purely by private functions are what you want to encapsulate always.
But if you're building a car that wants a certain kind of engine object then you have an external dependency. You can either instantiate that engine -- for instance new GMOverHeadCamEngine() -- internally within the car object's constructor, preserving encapsulation but creating a much more insidious coupling to a concrete class GMOverHeadCamEngine, or you can inject it, allowing your Car object to operate agnostically (and much more robustly) on for example an interface IEngine without the concrete dependency. Whether you use an IOC container or simple DI to achieve this is not the point -- the point is that you've got a Car that can use many kinds of engines without being coupled to any of them, thus making your codebase more flexible and less prone to side effects.
DI is not a violation of encapsulation, it is a way of minimizing the coupling when encapsulation is necessarily broken as a matter of course within virtually every OOP project. Injecting a dependency into an interface externally minimizes coupling side effects and allows your classes to remain agnostic about implementation.
It depends on whether the dependency is really an implementation detail or something that the client would want/need to know about in some way or another. One thing that is relevant is what level of abstraction the class is targeting. Here are some examples:
If you have a method that uses caching under the hood to speed up calls, then the cache object should be a Singleton or something and should not be injected. The fact that the cache is being used at all is an implementation detail that the clients of your class should not have to care about.
If your class needs to output streams of data, it probably makes sense to inject the output stream so that the class can easily output the results to an array, a file, or wherever else someone else might want to send the data.
For a gray area, let's say you have a class that does some monte carlo simulation. It needs a source of randomness. On the one hand, the fact that it needs this is an implementation detail in that the client really doesn't care exactly where the randomness comes from. On the other hand, since real-world random number generators make tradeoffs between degree of randomness, speed, etc. that the client may want to control, and the client may want to control seeding to get repeatable behavior, injection may make sense. In this case, I'd suggest offering a way of creating the class without specifying a random number generator, and use a thread-local Singleton as the default. If/when the need for finer control arises, provide another constructor that allows for a source of randomness to be injected.
Having struggled with the issue a little further, I am now in the opinion that Dependency Injection does (at this time) violate encapsulation to some degree. Don't get me wrong though - I think that using dependency injection is well worth the tradeoff in most cases.
The case for why DI violates encapsulation becomes clear when the component you are working on is to be delivered to an "external" party (think of writing a library for a customer).
When my component requires sub-components to be injected via the constructor (or public properties) there's no guarantee for
"preventing users from setting the internal data of the component into an invalid or inconsistent state".
At the same time it cannot be said that
"users of the component (other pieces of software) only need to know what the component does, and cannot make themselves dependent on the details of how it does it".
Both quotes are from wikipedia.
To give a specific example: I need to deliver a client-side DLL that simplifies and hides communication to a WCF service (essentially a remote facade). Because it depends on 3 different WCF proxy classes, if I take the DI approach I am forced to expose them via the constructor. With that I expose the internals of my communication layer which I am trying to hide.
Generally I am all for DI. In this particular (extreme) example, it strikes me as dangerous.
I struggled with this notion as well. At first, the 'requirement' to use the DI container (like Spring) to instantiate an object felt like jumping thru hoops. But in reality, it's really not a hoop - it's just another 'published' way to create objects I need. Sure, encapsulation is 'broken' becuase someone 'outside the class' knows what it needs, but it really isn't the rest of the system that knows that - it's the DI container. Nothing magical happens differently because DI 'knows' one object needs another.
In fact it gets even better - by focusing on Factories and Repositories I don't even have to know DI is involved at all! That to me puts the lid back on encapsulation. Whew!
I belive in simplicity. Applying IOC/Dependecy Injection in Domain classes does not make any improvement except making the code much more harder to main by having an external xml files describing the relation. Many technologies like EJB 1.0/2.0 & struts 1.1 are reversing back by reducing the stuff the put in XML and try put them in code as annoation etc. So applying IOC for all the classes you develope will make the code non-sense.
IOC has it benefits when the dependent object is not ready for creation at compile time. This can happend in most of the infrasture abstract level architecture components, trying establish a common base framework which may need to work for different scenarios. In those places usage IOC makes more sense. Still this does not make the code more simple / maintainable.
As all the other technologies, this too has PROs & CONs. My worry is, we implement latest technologies in all the places irrespective of their best context usage.
Encapsulation is only broken if a class has both the responsibility to create the object (which requires knowledge of implementation details) and then uses the class (which does not require knowledge of these details). I'll explain why, but first a quick car anaology:
When I was driving my old 1971 Kombi,
I could press the accelerator and it
went (slightly) quicker. I did not
need to know why, but the guys who
built the Kombi at the factory knew
exactly why.
But back to the coding. Encapsulation is "hiding an implementation detail from something using that implementation." Encapsulation is a good thing because the implementation details can change without the user of the class knowing.
When using dependency injection, constructor injection is used to construct service type objects (as opposed to entity/value objects which model state). Any member variables in service type object represent implementation details that should not leak out. e.g. socket port number, database credentials, another class to call to perform encryption, a cache, etc.
The constructor is relevant when the class is being initially created. This happens during the construction-phase while your DI container (or factory) wires together all the service objects. The DI container only knows about implementation details. It knows all about implementation details like the guys at the Kombi factory know about spark plugs.
At run-time, the service object that was created is called apon to do some real work. At this time, the caller of the object knows nothing of the implementation details.
That's me driving my Kombi to the beach.
Now, back to encapsulation. If implementation details change, then the class using that implementation at run-time does not need to change. Encapsulation is not broken.
I can drive my new car to the beach too. Encapsulation is not broken.
If implementation details change, the DI container (or factory) does need to change. You were never trying to hide implementation details from the factory in the first place.
DI violates Encapsulation for NON-Shared objects - period. Shared objects have a lifespan outside of the object being created, and thus must be AGGREGATED into the object being created. Objects that are private to the object being created should be COMPOSED into the created object - when the created object is destroyed, it takes the composed object with it.
Let's take the human body as an example. What's composed and what's aggregated. If we were to use DI, the human body constructor would have 100's of objects. Many of the organs, for example, are (potentially) replaceable. But, they are still composed into the body. Blood cells are created in the body (and destroyed) everyday, without the need for external influences (other than protein). Thus, blood cells are created internally by the body - new BloodCell().
Advocators of DI argue that an object should NEVER use the new operator.
That "purist" approach not only violates encapsulation but also the Liskov Substitution Principle for whoever is creating the object.
PS. By providing Dependency Injection you do not necessarily break Encapsulation. Example:
obj.inject_dependency( factory.get_instance_of_unknown_class(x) );
Client code does not know implementation details still.
Maybe this is a naive way of thinking about it, but what is the difference between a constructor that takes in an integer parameter and a constructor that takes in a service as a parameter? Does this mean that defining an integer outside the new object and feeding it into the object breaks encapsulation? If the service is only used within the new object, I don't see how that would break encapsulation.
Also, by using some sort of autowiring feature (Autofac for C#, for example), it makes the code extremely clean. By building extension methods for the Autofac builder, I was able to cut out a LOT of DI configuration code that I would have had to maintain over time as the list of dependencies grew.
I think it's self evident that at the very least DI significantly weakens encapsulation. In additional to that here are some other downsides of DI to consider.
It makes code harder to reuse. A module which a client can use without having to explicitly provide dependencies to, is obviously easier to use than one where the client has to somehow discover what that component's dependencies are and then somehow make them available. For example a component originally created to be used in an ASP application may expect to have its dependencies provided by a DI container that provides object instances with lifetimes related to client http requests. This may not be simple to reproduce in another client that does not come with the same built in DI container as the original ASP application.
It can make code more fragile. Dependencies provided by interface specification can be implemented in unexpected ways which gives rise to a whole class of runtime bugs that are not possible with a statically resolved concrete dependency.
It can make code less flexible in the sense that you may end up with fewer choices about how you want it to work. Not every class needs to have all its dependencies in existence for the entire lifetime of the owning instance, yet with many DI implementations you have no other option.
With that in mind I think the most important question then becomes, "does a particular dependency need to be externally specified at all?". In practise I have rarely found it necessary to make a dependency externally supplied just to support testing.
Where a dependency genuinely needs to be externally supplied, that normally suggests that the relation between the objects is a collaboration rather than an internal dependency, in which case the appropriate goal is then encapsulation of each class, rather than encapsulation of one class inside the other.
In my experience the main problem regarding the use of DI is that whether you start with an application framework with built in DI, or you add DI support to your codebase, for some reason people assume that since you have DI support that must be the correct way to instantiate everything. They just never even bother to ask the question "does this dependency need to be externally specified?". And worse, they also start trying to force everyone else to use the DI support for everything too.
The result of this is that inexorably your codebase starts to devolve into a state where creating any instance of anything in your codebase requires reams of obtuse DI container configuration, and debugging anything is twice as hard because you have the extra workload of trying to identify how and where anything was instantiated.
So my answer to the question is this. Use DI where you can identify an actual problem that it solves for you, which you can't solve more simply any other way.
I agree that taken to an extreme, DI can violate encapsulation. Usually DI exposes dependencies which were never truly encapsulated. Here's a simplified example borrowed from Miško Hevery's Singletons are Pathological Liars:
You start with a CreditCard test and write a simple unit test.
#Test
public void creditCard_Charge()
{
CreditCard c = new CreditCard("1234 5678 9012 3456", 5, 2008);
c.charge(100);
}
Next month you get a bill for $100. Why did you get charged? The unit test affected a production database. Internally, CreditCard calls Database.getInstance(). Refactoring CreditCard so that it takes a DatabaseInterface in its constructor exposes the fact that there's dependency. But I would argue that the dependency was never encapsulated to begin with since the CreditCard class causes externally visible side effects. If you want to test CreditCard without refactoring, you can certainly observe the dependency.
#Before
public void setUp()
{
Database.setInstance(new MockDatabase());
}
#After
public void tearDown()
{
Database.resetInstance();
}
I don't think it's worth worrying whether exposing the Database as a dependency reduces encapsulation, because it's a good design. Not all DI decisions will be so straight forward. However, none of the other answers show a counter example.
I think it's a matter of scope. When you define encapsulation (not letting know how) you must define what is the encapsuled functionality.
Class as is: what you are encapsulating is the only responsability of the class. What it knows how to do. By example, sorting. If you inject some comparator for ordering, let's say, clients, that's not part of the encapsuled thing: quicksort.
Configured functionality: if you want to provide a ready-to-use functionality then you are not providing QuickSort class, but an instance of QuickSort class configured with a Comparator. In that case the code responsible for creating and configuring that must be hidden from the user code. And that's the encapsulation.
When you are programming classes, it is, implementing single responsibilities into classes, you are using option 1.
When you are programming applications, it is, making something that undertakes some useful concrete work then you are repeteadily using option 2.
This is the implementation of the configured instance:
<bean id="clientSorter" class="QuickSort">
<property name="comparator">
<bean class="ClientComparator"/>
</property>
</bean>
This is how some other client code use it:
<bean id="clientService" class"...">
<property name="sorter" ref="clientSorter"/>
</bean>
It is encapsulated because if you change implementation (you change clientSorter bean definition) it doesn't break client use. Maybe, as you use xml files with all written together you are seeing all the details. But believe me, the client code (ClientService)
don't know nothing about its sorter.
It's probably worth mentioning that Encapsulation is somewhat perspective dependent.
public class A {
private B b;
public A() {
this.b = new B();
}
}
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
From the perspective of someone working on the A class, in the second example A knows a lot less about the nature of this.b
Whereas without DI
new A()
vs
new A(new B())
The person looking at this code knows more about the nature of A in the second example.
With DI, at least all that leaked knowledge is in one place.