I've got a microservice called ExamResults, with a very simple component structure:

  • ExamResults
    • (offers: IExamResults)
    • (requires: IExamResultsDAO)
  • ExamResultsDAO
    • (offers: IExamResultsDAO)

This service gets passed exam results (student ids, exam ids, given answers) in JSON format, and the component ExamResults converts them to local domain objects, does some validation, and saves it in the database using the ExamResultsDAO. (nomenclature suggestions are not discouraged)

Now, this was all well and fine, until we started implementing it. We gave ExamResults the classes for validation and (de)serialisation, but also the domain classes (ExamResult, GivenAnswer) - and that's where we started scratching our head: why are they there, exactly? The domain classes get used by the DAO all the same.

First thought was making them another component, but we learned (we're students) that a component must always offer an interface. And the domain classes have no meaningful methods: just getters and setters and (de)serialisation keywords. Is it proper conduct to put the domain in a separate package and mark it down as a component in the component diagram? Or mark it as something else? Or not include it at all? Or is it more proper to leave the domain classes with the component ExamResults, since that creates them and uses them the most?

What's the preferred solution here?

有帮助吗?

解决方案

Are the domain classes a component ?

A component is something self-contained and substitutable with well defined interfaces:

A Component is a self-contained unit that encapsulates the state and behavior of a number of Classifiers. A Component specifies a formal contract of the services that it provides to its clients and those that it requires from other Components or services in the system in terms of its provided and required Interfaces.
A Component is a substitutable unit that can be replaced at design time or run-time by a Component that offers equivalent functionality based on compatibility of its Interfaces.
- UML 2.5 standard, section 11.6.3.1, Semantics of components

But interfaces are however not necessarily to be conceived as a technical artifact, like a java interface:

An Interface specifies a contract; any instance of a Classifier that realizes the Interface shall fulfill that contract. The obligations associated with an Interface are in the form of constraints (such as pre- and postconditions) or protocol specifications, which may impose ordering restrictions on interactions through the Interface.
- UML 2.5 standards, section 10.4.3.1, Semantics of interfaces

Your domain classes should be self-contained, substitutable and have clear interfaces, so you can consider them as a component:

  • Self-contained: there is no reason that they would depend on anything else of ExamResults and ExamResultsDAO.
  • Interfaces: those used by ExamResults and ExamResultsDAO (either explicit interface, or implicit via their public elements)
  • Substitutable: you could replace their implementation with another as long as you respect the same interfaces to offer the same behavior.

Should the component stand on its own ?

Your ExamResults service offers an application service, which is to read JSON data and store it to a database. To perform its work it needs:

  • a request handler: depends on the interface and protocols supported by the application service (e.g. HTTP requests ? SOAP messages ? Remote function calls ?)
  • a parser: depends on the format used for the exams. Here you go for JSON. Tomorrow you may go for XML because you have to interconnect with another system of another university.
  • ExamDAO: depends on the database used. THe DAO classes would not be implemented in the same way, if it's an SQL database or a NoSQL database (e.g. key-value store, graph database, or document based database).
  • Domain model: depends solely on the domain model and neither on the data format, nor on the technical protocols, nor on the DBMS used

This suggests that there are big advantage to isolate the domain model from the rest, in order to enforce separation of concerns.

Well, it would have been much faster to point at clean architecture to support come to this conclusion. However all this reasoning is valid whatever other architecture model you may have chosen.

Additional thoughts

Your microservice does only a small task in a broader system. Other microservices might use the data in the database and perform other tasks. It could be tempting then to reuse the domain classes, and the DAO classes in this context. For school project it's nice. However, be cautious:

  • microservice are intended to be as decoupled as possible. Sharing of common code creates however a hidden coupling between things that should remain independent, which may require constraints for the deployment of new releases.
  • in a microservice landscape, the shared database creates an even stronger coupling between services. For big data applications it can also become a bottleneck, as it may limit scalability.

其他提示

It was resolved. It turns out that a component is more abstract than we thought, and does not need to correspond one-on-one with a package. Therefore, the domain classes technically belong to both components, but they can be implemented in any package we choose.

许可以下: CC-BY-SA归因
scroll top