I've been reading Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin. One point he makes:G34 Functions should descend only one level of abstractionHowever, I'm wondering about the functions that actually create the objects for an application. Say we have dependenciesApp -> Book -> DatabaseThen using dependency injection, App would need to create both a Book and Database instance, and inject the database instance into Book.Is this an acceptable breaking of the mixing level of abstraction rule?If yes / no, why?
Dependency Injection vs Mixing Levels of Abstraction
dependency injection;abstraction;clean code;inversion of control
Let's start by defining what an abstraction is. In Agile Principles, Patterns, and Practices, Robert C. Martin defines an abstraction like this:Abstraction is the elimination of the irrelevant and the amplification of the essentialWhat is essential, and what is irrelevant, changes with the client's perspective. From the perspective of the Composition Root, the relevant abstractions are types (classes, primitives, etc.) and the graph(s) composed from objects.The purpose of the Composition Root is to construct a valid object graph. In that perspective, all types have the same level of abstraction. They're just types being composed together; the Composition Root doesn't invoke any of the object members, so it's irrelevant whether the object originates from a UI package, a Data Access package, a Domain Model package, etc. The abstraction is Composition.