Digital transformation: service-oriented design principle | idcf

Time:2021-7-24

In the process of designing the service center, the design of service interface and data model in the service center is very important. Good design principles and methods can maximize the scalability of the service center.

Readers are strongly recommended to learn the most influential work domain driven design Tacking Complexity in the heart of software by Eric Evans, a famous modeling expert, and SOA principles of service design by Thomas ERL, In most cases, you can refer to the principles and methods in these two books. The purpose of this book is to introduce how to better carry out the construction of digital enterprises from an overall perspective, so this technology will not be discussed in depth.

Fac ̧ Ade mode

Next, when introducing the service-oriented design principles, FAC will appear many times ̧ Ade mode.

The use principle of appearance mode is shown in Figure 4-11.

Digital transformation: service-oriented design principle | idcf

The advantages of appearance mode are as follows:

  • Loose coupling: the appearance mode enables the front application to be loosely coupled with the middle service center, so that the modules inside the service center can be expanded and maintained more easily.
  • Simple and easy to use: the appearance mode makes the service of the service center easier to use. The foreground application no longer needs to understand the internal implementation of the service center, nor does it need to interact with many functional modules in the service center. It only needs to interact with the appearance class.
  • Better division of access levels: through the rational use of appearance patterns, access levels can be better divided. Some methods are external to the system, and some methods are used inside the system. The functions that need to be exposed to the outside are concentrated in the appearance, which is not only convenient for the client to use, but also hides the internal details.

Use of dto

Dto can shield the complex or changeable data objects of the service center from the foreground application, so that the foreground has better stability. Dto is a technology often used in system layered design and service architecture, and the concept itself is easy to understand, as shown in Figure 4-12.

Digital transformation: service-oriented design principle | idcf

Design principles of service interface

The core of business platform architecture is the design modeling of various business fields and the design of service interface. Combined with the excellent design principles in the industry and my own practice, the author arranges the typical design principles of service interface as follows for your reference.

1. Contract first

The interaction between services is similar to the cooperation between different organizations. According to normal logic, the primary task of cooperation between the two organizations is to sign a clear contract first, specifying the content and form of cooperation, etc., so as to form a strong contract and guarantee for both parties. At the same time, the work can go hand in hand without waiting for each other. Therefore, the best practice in the service-oriented architecture is also the service contract first, that is, the design of the service contract first. When designing the service interface, people from different aspects such as business, product and technology need to participate together, define the corresponding contract, and then implement the specific code.

In the actual middle office architecture design stage, when business requirements are collected in different business departments of the enterprise and product requirements research documents are formed, the service interface of the service center needs to be designed from a global perspective, that is, the service interface is not designed according to a single application scenario, such as only from the perspective of e-commerce or CRM system. Although these front desk systems are built step by step, the interface design of the service center first needs to be planned and designed from the overall business perspective. With a clear interface design, the front desk and service center will have a clear and relatively stable interaction boundary, which can greatly reduce the cooperation cost in the later implementation and operation period and improve the overall efficiency.

Due to the wide range of users of the service, it is necessary to ensure good stability after the public release of the service contract, and can not be reconstructed casually. Even if it is upgraded, it is necessary to consider downward compatibility as much as possible.

2. Service function cohesion

Service function cohesion is the most basic requirement in almost any service-oriented design. To create a service interface with cohesive functions, a group of operations related to functions should be aggregated together. At the same time, logic that may affect business correctness must be provided in the corresponding service, rather than relying on the service caller to follow the correct logic.

For example, the user registration service includes verification logic for the user’s mailbox format, user name and password strength. Although these logic are verified in the web page or app of the foreground application, when the foreground application finally calls the user registration service of the user center, it still needs to verify these user attributes in the service, We can’t expect the foreground application to do these verification work, so as to avoid irregular users who can register successfully because the foreground application misses verification. A typical example of service function cohesion is shown in Figure 4-13.

Digital transformation: service-oriented design principle | idcf

3. Service coarse granularity

Service users generally have less understanding of specific business processes than those in the service center, so the interface design of services usually needs coarse granularity. An operation may correspond to a complete business use case or business process, which can not only reduce the number of remote calls, but also reduce the learning cost and coupling degree.

For example, the document service should support the foreground application to delete articles in batch. The existing interface provides the deletearticle (long ID) method, which can be used by users to make circular calls to achieve the purpose of deleting articles in batch. At this time, the service center should provide the deletearticles (set < long > IDS) method for the foreground application to call, reducing N remote calls to one.

For another example, the use case in which a user places an order must have a series of operations:
Create order → add price → calculate total price

Of course, the trading center can provide these services to the foreground application in the form of a single interface method, which not only requires the foreground application to have higher requirements for the order creation process and logic, but also increases the probability of service call errors. It is best to encapsulate a coarse-grained method for users to make one-time remote calls, At the same time, it also hides many complexities of internal business. The service caller has also changed from relying on four methods to relying on one method, which greatly reduces the program coupling.

In addition, from the perspective of the number of services and interface methods, services are usually used as the unit of testing and publishing. If the granularity is too coarse and a large number of operations are grouped into a single service, the users of a single service may be increased, which brings challenges to service users to quickly find the correct operation, resulting in poor service use experience. To change the service, you must republish the whole service, which will affect more users.

Therefore, avoid the two extremes of service granularity:

  • Provide many services with only a few methods.
  • Dozens or hundreds of operations are concentrated in several services.

Several factors, such as maintainability, operability and ease of use, should be considered and compromised.

Another way to divide service granularity is to create a service interface that reflects the state of the business object life cycle. For example, in expense claim, the life cycle of each expense claim includes four states, as shown in Figure 4-14.

Digital transformation: service-oriented design principle | idcf

Because the business object status can often reflect both business and technical aspects, it is possible to split the expenseclaim service into multiple services suitable for each status: claimentryservice, claimapprovalservice and claimpaymentservice, Get the service code as follows:

ClaimEntryService {
    createClaim(String userId);
    ClaimItemDetails[] getClaimItems(int );
    ClaimErrors[] validateClaim(int claimId);
    void removeClaimItem(int claimId, int itemId);
    int addClaimItem(int claimId, ClaimItemDetails details)
    int submitClaim(int claimId);
}

ClaimApprovalService {
    int approveClaimItem(int claimId, int itemId, String comment);
    void approveClaim(claimId)
    void returnClaim(claimId)
    ClaimItemDetails[] getClaimItems(int );
    ClaimErrors[] validateClaim(int claimId);
}

ClaimPaymentService {
    void payClaim(int claimId);
}

In this way, each service can be more easily understood. Moreover, this division of interfaces is very suitable for the development, deployment, maintenance and use of services. In conclusion, by putting the partitioning logic on the object life cycle, we can establish services with appropriate granularity.

4. Eliminate redundant data

Because the remote invocation of services requires network overhead, especially in the scenario with a large amount of concurrency, this overhead is not a negligible factor. Therefore, in the input parameters and return results of the service, try to avoid carrying redundant fields that are not required by the current business scenario, so as to reduce the overhead of serialization and transmission. At the same time, removing redundant fields can also simplify the interface and avoid unnecessary confusion to external users.

For example, in “document service”, there is a method to return the article list:

List <Article> getArticles(...)

If the business requirement is only to list the title of the article, you should avoid carrying its content and other fields in the returned article object.

A classic solution is to introduce the dto mode mentioned above to customize the data fields to be transmitted for the foreground business application. Here, an additional data transmission object of ariticlesummary (article summary) needs to be added:

List<ArticleSummary> getArticleSummaries(...)

Articlesummary can well avoid redundant data transmission between the service center and the foreground application.

5. General contract

Since the service does not assume the scope of users, it generally supports clients in different languages and platforms. However, there are great differences in the functional richness of various languages and platforms, which determines that the service contract must take the maximum common divisor of common languages, platforms and serialization methods in order to ensure the wide compatibility of services. Therefore, the service contract cannot have the advanced features of some languages, and the parameters and return values must also be simple data types widely supported (for example, there can be no object circular reference).

For example, the original object model is as follows:

Class Foo {
    private Pattern regex;
}

Among them, pattern is a Java specific precompiled and serializable regular expression (which can improve performance), but it may not be recognized by other development languages without the support of a specific framework, so it is best to change it into a common data type by dto, as shown below:

Class FooDto {
    private String regex;
}

6. Isolation change principle

When the objects of the core domain model of the service center enter the foreground application, it is necessary to avoid the reconstruction or model change within the service center, resulting in the change of the foreground application.

For example, the “document service” described earlier, in which the article object may be used as the domain model of core modeling in the service center, or even as object and database mapping (O / R mapping). If the document service directly returns article to the service consumer, even if there are no problems such as redundant fields and complex types mentioned above, it may make the external users of the service associated with the core domain model of the internal system of the service, or even associated with the O / R mapping mechanism and data table structure, Internal refactoring is likely to affect users outside the service.

Similarly, appearance mode and dto can be used as intermediaries and buffers to isolate internal and external systems and minimize the impact of internal system changes on the outside.

7. Contract packaging

Although dto and facade patterns are used to isolate the changes at the service production end from the service consumption end, dto and facade patterns may be referenced everywhere by the programs at the service consumption end, so the consumer programs are strongly coupled to the service contract. Once the contract is changed, or the consumer has to choose a completely different service provider (with different contracts), the workload may be very heavy. In an ideal service-oriented design, we can consider wrapping the remote service access logic, also known as the delegate service pattern. The consumer defines the interface and parameter types, and forwards the service call to the real service client, so that the service consumer can completely shield the service contract.

Examples of service agents are as follows:

//Articlesservice is an interface customized by the consumer
class ArticlesServiceDelegate implements ArticlesService {
    //Suppose it is an automatically generated service client stub class
    private ArticleFacadeStub stub;

    public void deleteArticles(List<Long> ids) {
        stub.deleteArticles(ids);
    }
}

In the foreground application of this example, all references to document service calls refer to the articleservice, not the articlefacade stub provided by the “document service”. In this way, even if the articlefacade stub on the service provider side is changed or reconstructed, it only needs to be adjusted in the articleservice class without changing more code.

8. Service stateless principle

In order to ensure the service stability and scalability of the service center, services must be designed to be scalable and deployable to the highly available infrastructure. A corollary of this important principle is that services should not be “stateful”. That is, the service should not depend on the long-standing relationship between the service consumer and the service producer, and the service invocation should not explicitly or implicitly depend on the previous invocation. To illustrate this, let’s give a simple example. Here is a telephone conversation:

Q: what is Xiao Ming’s account balance?

Answer: 320 yuan.

Q: what is his credit limit?

A: 2000 yuan.

This example demonstrates a typical stateful pattern. The second question refers to the first question by using “his”. The operation in this example depends on the transformation context. Now let’s consider the response provided. Note that there is no context information in the response. This answer is meaningful only when the respondent knows the question asked. In this example, the user is required to maintain the conversation state in order to interpret the resulting response.

First, we consider operations that depend on the context established by the previous operation. If this is an interaction with the call center, as long as you talk to the same operator, the conversation can end effectively. However, we assume that the call is interrupted as follows:

Q: what is Xiao Ming’s account balance?

Operator 1: 320 yuan.

At this time, the call is interrupted and transferred to another operator:

Q: what is his credit limit?

Operator 2: who?

Interrupts cause context loss, so the second problem is meaningless. In terms of this telephone conversation, we can offset the consequences of the interruption by re establishing the context: “I’m asking Xiaoming’s bank account information. Can you tell me his credit limit?” However, in the field of extensible service invocation, stateful dialogue is usually more troublesome. Re establishing the context may be technically feasible, but it is likely to bring great performance overhead.

Whether relevance is required. That is, whether the continuous requests sent by the same service consumers must be delivered to the same service provider instance requires the use of relevance, which is a conflict between statefulness, scalability and reliability. In order to maintain the service quality of each service capability of the service center, we must give priority to the scalability and reliability of the final service architecture. Therefore, the author strongly recommends that services be designed to avoid the need to maintain session context.

Returning to the above example of telephone conversation, we can avoid the need for session state by designing the service to include appropriate association information in the response, as shown below:

Q: what is Xiao Ming’s credit limit?

A: Xiaoming’s credit limit is 2000 yuan.

It is good practice to include relevant information in the response for many reasons. First, it simplifies the construction of a scalable solution, provides more diagnostic assistance, and is important when it is impossible to deliver an error response to the original requester. In short, careful service design can avoid the need for state, so as to simplify the implementation of reliable and scalable service structure.

9. Service naming principles

We have a guiding principle when selecting the names of services, operations, data types and parameters: we want to maximize the ease of use of services. We hope to help business application developers identify the services and operations required to implement business processes. Therefore, it is strongly recommended to define meaningful names in the professional field for service users, and give priority to business concepts rather than technical concepts.
The suggestion is that you should use nouns to name services and verbs to name operations. For example, the following is a service definition constructed using verb phrases and it:

ManageCustomerData { 
    insertCustomerRecord();
    updateCustomerRecord();
    //etc ... }

Next is the service definition using nouns and verb phrases and business concepts:

CustomerService {
    createNewCustomer();
    changeCustomerAddress();
    correctCustomerAddress();
    // etc ... }

Obviously, the second example is easier to use. In the second example, the business purpose of the service is very clear, not just indicating its output. Therefore, it is recommended to use “enable overdraft facility” instead of “update customerrecord” (which can be any update for any reason). Similarly, when a customer moves, we use the “changecustomeraddress” method to change the customer address; When you want to correct invalid data, use “correct customer address” to correct the customer address, because it is easy to see that the two operations adopt different service logic.

10. Service operation design principles

This is a further deepening of the naming design principle of service operations: operations should be defined with specific business meaning rather than generic operations. For example, instead of using the generic update customerdetails operation, create operations such as changecustomeraddress, recordcustomer marriage, and addalternate customercontactnumber. This approach has the following benefits:

  • Operations correspond to specific business scenarios. Such scenarios may not simply update records in the database. For example, changing the address or marital status may require changing the relevant information in other business modules. For example, the modification of marital status may cause changes in the rights and interests of members. If you use less specific operations (such as updatecustomerdetails), it is not suitable to implement such business scenarios.
  • Each operation interface will be very simple and easy to understand, so as to improve ease of use.
  • The update unit for each operation is clearly defined (in our example, address, marital status, and phone number). When implementing a system with high concurrency requirements, we can adopt a finer grained locking strategy based on the operation requirements, so as to reduce resource contention.

For the design of parameters in operation, coarse-grained and flexible parameters shall be adopted to minimize the change of parameter structure caused by demand change.

Take the two interfaces of the createnewcustomer operation as an example.

  • The createnewcustomer operation interface with fine-grained parameters is as follows:
int CreateNewCustomer(String familyName,String givenName,
    String initials, int age,String address1,
    String address2, String postcode    // ...  )
  • The createnewcustomer operation interface with a single coarse-grained parameter is as follows:
int CreateNewCustomer( CustomerDetails newDetails)

The above two sample codes show an operation with many fine-grained parameters and an operation with a structured type as a single coarse-grained parameter. The reason why coarse-grained parameters are recommended is that this can largely avoid the overall service version upgrade caused by fine-grained parameter changes.

From the perspective of parameter flexibility, we should consider the diversity and flexibility of service requirements. For example, when querying commodity information, there are many fields defined by commodities, and the fields concerned by different businesses are different. Therefore, when defining the interface, you can pass in the fields of commodities to be returned by the business party, save these fields in the list object, and the service obtains the value of the corresponding field and encapsulates it into the corresponding map object for return. In this way, a commodity query operation method can meet the information acquisition requirements of different application systems for commodity fields.

11. Important services cannot rely on non important services

China Taiwan construction is service-oriented, that is, the interaction between the whole system is carried out in the form of service. Not only the foreground application and the service centers of the middle desk will interact in the form of service, but also between the service centers. In some cases, after the business complexity of the foreground application develops to a certain extent, the service system within the application system will also be established. For example, business front-end applications such as tmall and Taobao are already very complex, and a multi-layer service system has been built inside. Each service center in the business center is the lowest level of this service system, and each front-end business system above will establish its own service level according to the characteristics of its own business.

In the whole service system, there are very core and important services such as transaction, commodity and order related services, as well as relatively unimportant services, such as freight calculation or services created in front-end applications. From the impact of services on business and service scope, it will reflect the different importance of services, and the different importance of services will directly determine the differences in the available support and guarantee resources, which will eventually be reflected in the stability and reliability of services. Therefore, the lower level services will be more stable, and the higher level services will be inferior to the lower level services in terms of stability and business compatibility.

The principle that “important services cannot rely on non important services” can be more detailed as follows:

  • The top can depend on the bottom. The upper layer service implementation can rely on the lower layer services or cross level dependencies.
  • The bottom cannot depend on the top. The service implementation and operation of the lower layer must not rely on the services of the upper layer, otherwise the important services of the lower layer will be affected by the service quality problems and unstable performance of the upper layer, and the failure of the lower layer service will affect all peer service centers and foreground applications that depend on this service, resulting in a serious “avalanche” effect.
  • The level can be relied on to avoid circular dependence. The most typical embodiment of this principle is that each service center in the business platform belongs to the same level in the service level. They have the same level of service operation requirements and can be interdependent.
  • High level cannot rely on low level. Services with significantly high business importance cannot rely on services with low business importance. Corresponding service degradation shall be done, or the service dependence in this case shall be isolated through the foreground business.

summary

Simplicity is beauty. Too many principles may make the overall design cumbersome. Under what circumstances and what principles to adopt, they need to be based on business understanding and continuous practice in the process of practice, so as to deal with problems related to service design more calmly.

Source: technical Trivia

Author: Zhong Hua

This article is exclusively authorized by the machinery industry press and is a new work by Zhong Hua, the author of China Taiwan Bible – the way of enterprise IT architecture transformation《 Tao and art of digital transformation: Taking platform thinking as the core to support enterprise strategic sustainable development.

Statement: the article was authorized by the author to be forwarded in the IDCF community official account (devopshub). High quality content is shared with the technical partners of SIFO platform. If the original author has other considerations, please contact Xiaobian to delete it and thank you.

Digital transformation: service-oriented design principle | idcf

At 8 p.m. every Thursday in June, [brother Dong has something to say] have a happy “summer”. The official account is “happy” and gets the address.

  • 0603 invincible brother idcf talent growth map and 5p (Lesson 1 of end-to-end Devops continuous delivery (5p) quality course)
  • 0610 Dong GE’s play with innovative design thinking
  • 0617 invincible brother “what is agile project management?”
  • 0624 Dongge agile leadership in vuca Era