This principle “feels” right, but I’m working through trying to formulate it properly.
Consider a point class (in pseudo-code because lazy):
class Point
private x, y
construct(x, y)
draw(Drawable surface)
(Instead of surface, it could also be a save-function with a database connection as argument (or indeed any type of persistence)).
If the surface was instead injected into the constructor, the point would look like:
class Point
private x, y, surface
constructor(x, y, surface)
Isn’t that weird, to have two properties related to state, and then a third property related to something completely different? Especially when it’s something effectful, like drawing or writing to disk.
On the other hand, you can imagine a command object class like this:
class InstallApp
private db, io, logger, mailer
constructor(db, io, logger, mailer)
execute(app)
In this case, all dependencies are effectful classes. Makes more sense, right? And then the app class has only “pure” properties, like User
or Configuration
.
A rectangle depending on points is also OK, since the points are pure:
class Rectangle
private bottomLeft, topRight
constructor(Point bottomLeft, Point topRight)
// draw, save, etc
Another way to phrase it is that classes should only depend on other classes in the same layer (domain layer vs “effectful” layer).
We also want to enable polymorphism, like:
shapes = [
new Point(1, 2),
new Rectangle(new Point(2, 3), new Point(3, 4))
]
surface = new Surface()
forall shapes as shape
shape.draw(surface)
The major drawback is that no language can actually distinguish between a dependency and “normal” class property. Possibly they should have different semantics? Or the possibility to separate pure and effectful classes.
Thoughts?