Separation by problem area
Change does not come about by itself, it comes from a problem area. A problem area is an area where problems that require changes in code are formulated in the same language, using the same set of concepts or related business logic. Correspondingly, there will most likely be one set of restrictions, invariants that you can rely on when writing the code, within one problem area.
Separation of service responsibility by problem areas rather than by essence usually leads to a more supported and understandable architecture. Problem areas most often correspond to business processes. For an online store, the most likely problem areas will be "payment and billing", "delivery", "ordering process".
Changes that would affect several problem areas simultaneously are less than changes that would affect several entities.
In addition, services broken down by business processes can be reused in the future. For example, if we wanted to sell airplane tickets next to an online store, we could reuse the common billing and payment service. Not to make another similar but specific one for ticket sales.
For example, we can divide it into services in this way:
Service or group of services "Delivery", which will store the logic of work with the delivery of a particular order, the organization of the work of suppliers, evaluation of the quality of their work, mobile application supplier, etc.
Service or a group of services "Billing and payment", which will store the logic of work with payment, invoices for legal entities, generation of contracts and closing documents.
Service or service group "Order process", which stores the logic of the customer's choice of products, cataloguing, brands, basket logic, etc.
Service "authorization and authentication".
It may even make sense to separate the discount service.
To interact with each other, services can use the event model or exchange simple objects (restful api, grpc, etc.). However, it should be noted that it is not easy to organize interaction between such services. At the very least, data decentralization has problems with eventual consistency and transactionality (if it is important).
Decentralization of data, exchange of simple objects has its advantages, disadvantages and pitfalls. On the one hand, decentralisation allows several services to be developed and operated autonomously. On the other hand, the costs of storing two or three copies of data and maintaining consistency in different systems.
In a real life often meets something average. Service is an essence with minimal set of attributes which is used by all services by consumers. And some minimal layer of logic - for example, the status model, and events in the queue with notification of all changes in the essence. At the same time, consumers still quite often keep the "cache" of data. Everything is being done to make the changes in such a service as little as possible, and it is difficult to do because of the fact that there are so many consumers.
It is important to understand that any division - both in essence and by problem areas - is not a silver bullet, there will always be features that will require dependent changes in several services. Simply, one division of such changes will be much more than the other. And the task of development is to minimize the number of dependent changes.
Perfect partitioning is only possible if you have two completely independent products. In any business, everything is related to everything, but the question is how much it is related.
And the question is in the responsibility department and in the height of barriers for abstractions.
Service API design
Interface design within the service repeats the history with division into services only on a smaller scale. Changing the interface (not just an extension) is a complicated and time-consuming process. In complex applications, the interface must be universal enough not to cause permanent changes and must be specific enough not to cause liability and semantics to spread.
Therefore, the service interfaces should be designed in such a way that their semantics is resistant to changes. This is possible if the semantics or responsibility of the interface was based on the limitations of the problem area.
To be continued in the next part https://zen.yandex.ru/profile/editor/id/5d7f7f203639e600ac6686e5/5d8ed7da0ce57b00ada1a0d8/edit