This was to be a FAQ, but due to the fact that the practices around this are unproven yet, there is no definitive answer to this question, rather a discussion of approaches, issues, guidelines and raising general awareness.
At the moment, there is quite a buzz about the correct usage of DSL's and modelling domains appropriately in the context of software factories.(within Microsoft at least, I would expect the rest of the DSM community have a more mature view on this).
We are starting to see an emergence of software factories of different varieties. Much of this innovation is growing from an absence of a formal framework for building factories and mechanisms to stitch them together, with navigation etc. (which may one day be available to us all).
A lot of the innovation is being put into how to describe a whole domain with multiple models, and when and how to relate those DSL's together. Services and practices are starting to emerge such as the integration service introduced by Mauro and Victor in their article on Integration Scenarios which allows you to reference elements from one model to another. Other factories, like the Ordina Factory, are using other techniques to achieve the same ends.
There appear to be two extreme views on how to model any part of a domain (sub-domain). On the one hand, some folks are using very few (or single) models to cover the sub domains. Others are decomposing the sub-domain into very many models.
Now, we need to be accurate here. There is a difference between the actual model and view (of the model). Ideally, you could have multiple models with multiple views, each view considers a whole model or part of a model. In some technologies a view can span multiple models also. Its the model that describes the logical architecture, and the view that provides the interface of that to the user. For the user, its the view that's important.
[It should be noted at this stage, that multiple views for one model is currently not supported in the Microsoft DSL toolkit. Views to span multiple models is also not supported currently. Only one view per model is presently supported.]
In the context of architectural guidance in a factory, imagine we are modelling a service, for example. Architecturally speaking, this is composed of several abstraction layers, and few deployment tiers. Lets consider the following standard .NET architecture for service orientation from patterns & practices. Since this is quite a popular architecture to create factories around at present.
Considering the abstraction layers in the logical architecture, the objective is to decompose the architecture into layers, with differing concerns, all in the scope of the whole service. i.e. Service Interface, Business Layer, Resource Access layers and their component layers.
Now undoubtedly each layer of the logical architecture is concerned with different aspects of the overall solution, and further, each layer has more than one concern to address, as well as the variability of that layer and its components.
The question is how best to apply DSL's to model these concerns and variability?
There are a number of patterns that address these kinds of architecture, and its typically these patterns that determine the answer to this question.
However, I assert that basing your models and views upon these patterns alone, may not always be the best approach to exposing your DSL's to the users.
To be a purest about separation of concerns, when analysing a problem domain, you would take the approach to define a single model for each layer which addressing a small number of concerns and the variability of that layer and its components. Or perhaps even, a model per concern!
Ideally, you would present several different views (if possible) of the model perhaps each one exposing each one of the concerns, or maybe just one view for all the concerns (which is the case today with using the DSL toolkit).
Then you would develop an appropriate mechanism to reference components from one model to another.
For example, a separate model for each of the layers:
- A model for the Service Contract, and Service Adapter,
- A model for the Business Logic implementation
- Perhaps a separate model for the Business Entities
- A model for the Data Access Logic
- A model for the Service Agents
That's 6 models, but some could be combined. So in reality 4-6 models to cover the whole architecture.
All models address the concerns and variability of their layer.
A more natural (perhaps less purest) approach, would be to define a single model for all layers which addresses all the concerns and variability.
This does not necessarily infer that appropriate emphasis has not been given to separation of concerns. It just means they are defined in the same model instead of separate models.
Ideally, you would present several different views (if possible) of the model perhaps each one exposing each one of the concerns or aspect of variability, or maybe just one view for all the concerns and variability (which is the case today with using the DSL toolkit).
For example, a single model for all layers. (example here from the EFx factory).
Considering these two approaches (in this context).
These approaches aim to achieve the following:
- Multiple Models
- Maximum physical separation of concerns.
- Maximum physical de-coupling of the layers.
- Maximum flexibility in reuse of one model in another architecture.
- Facilitate better source control in team environments
- As developers can work on different parts of the architecture in isolation from others.
- Single Model
- Maximum holistic description of the architecture (big picture view).
- Maximum usability.
The challenges with these approaches (in this context):
- Multiple Models
- No holistic view of the architecture. The inter-related pieces are presented in different views.
- The interface to reference dependencies in other views is usually poorly visualised/represented.
- Information to perform common user tasks maybe spread throughout several files.
- Single Model
- Complexity of diagram can be high, if the abstraction of the model is low.
- Team development on same model can be challenging, as the view/model could be used by different roles addressing different aspects.
[If you have any other pros and cons to add I be glad to add them.]
So what can we learn from this? I believe neither of these extreme approaches is ideal. The answer lies somewhere in-between - a compromise of both approaches.
The emphasis of the views that you provide for your models, needs to be high usability. A software factory is a productivity tool for users that should not have to have the level of knowledge and experience that those building them have. So even though your model(s) employ the best architectural practices in separation of concerns, and pattern application etc, these should not necessarily be forced upon the users. Instead, these patterns and architectural practices should be abstracted in the views, in a way, that makes it easy for the users to get the job done in describing the solution domain. (Its the classic: Usability <-> Flexibility trade-off struggle)
Perhaps building the models and the views are two different roles of defining a model for your domain?
Here are some things to consider to make the modelling solutions (in a factory context) more usable:
- Use fewer models when the abstraction is high and variability is low. Use many more loosely coupled models when the abstraction is low and variability is high.
- For single models, use multiple instances of the model file to partition the solution into bite-sized chunks, and use cross-model references where applicable.
- This will assist in team development.
- For multiple models, provide holistic views of the other views that bring them together to form a composite 'zoomed out' view of how the models relate, so the user can get a feel of the whole picture rather than one aspect of it.
- This will enable the users to stay focused on the objectives of the solution.
- For any approach, analyse which layers are more tightly bound to others, and require less flexibility in reality - from the users perspective.
- For example, in the above example, it is unlikely that the 'Resource Access Layer' is going to be used separately from the 'Business Layer', but it is highly coupled to it architecturally speaking. So it would make sense from a usability perspective to combine these layers into a single view.
- For any approach, use views that expose particular concerns or aspects of the architecture.
- A good use of these views is by role, so for example, a security expert can view the cross-cutting concerns of authorization across the whole architecture, without having to understand all other aspects or abstractions of the architecture.
[Again, if you have any other considerations to add, I be glad to add them here.]