I'm studying software engineering and one thing I'm really trying to improve is my skill in software architecture. My question is quite broad, so I'll try to explain it with an example.
Suppose you have a model layer and a service layer. The model manages various entities (such as users, products, orders, campains etc.). The services provide features, such as evaluating the efficency of a campaign, and use several modules of the model layer to access the required data.
How and when do you specify those dependencies? I see the following possibilities:
Allow general access to all models. This is the approach taken in many MVC frameworks, where the controllers can access any model classes.
Pro: You don't have to specify the dependencies, the developer writing the controller is very flexible.
Contra: If you want to test a service, you don't really know which model you have to mock because the service could use everything. These implicit dependencies can also make maintainance a pain.
The services specify the required models explicitly. Dependency management systems like requirejs or CommonJS require work this way.
Pro: No implicit dependencies simplifies maintanance
Contra: Mocking is impossible. When designing the module, you have to know exactly what the module will need. If you later notice that you need another interface, you have to change the architecture.
Specify explicit interfaces that will be provided to the service. Anyone instancing the service will have to provide implementations of the interfaces. I think dependency injection works this way, although the injection is automated there.
Pro: No implicit dependencies simplifies maintanance, Testing is simplified, because you know exactly what to mock.
Contra: When designing the module, you have to know exactly what the module will need. If you later notice that you need another interface, you have to change the architecture.
In theory, dependency injection seems like the best way. But is it practical to specify each requirement? How fine-grained should it be? Per entity? Group them? Or one dependency per "thing you can do with an entity"?
There are simply too many possibilities, and I'd like to get some real-world advice.