Pregunta

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.

¿Fue útil?

Solución

A truly independent module would expose API to create objects that it exposes and every such object would expose an interface that is clear to what the object is supposed to do.

Instead of any one gigantic API somewhere. For example jQuery - one object because it does one thing. jQueryUI is not one object but offers individual objects as widgets.

So from a client (code) from of view what the module does is well documented. Complex steps to create the objects is simplified.

How and when do you specify those dependencies?

The client code should be only adding the module as a dependency. If module has other dependencies they need to be resolved as the module dependency is resolved. (RequireJS, Maven Dependencies)

Dependency Injection

This is different than the code dependency as you have noted. Model should be injected in the Module interface. Your service objects can also be injected here but in that case it is your services which will inject the Model and the service objects could be created only from your MyModuleFactory(Impl).

The client code you inject the MyModuleFactory. The injection chain will be resolved down the path.

Specific point About Model and Services - non Anemic model

Services may seem like an nice idea but it becomes a problem down the line. Checkout cases against this.

Anemic Domain Model

Licenciado bajo: CC-BY-SA con atribución
scroll top