Welcome to pay attention to the public account “JAVA Front” to view more wonderful sharing articles, mainly including source code analysis, practical application, architecture thinking, workplace sharing, product thinking and so on, at the same time, welcome to add my personal wechat “JAVA_front” to communicate and learn together

1 Why write technical documentation

Reviewing the history of software development, we can divide it into three historical stages: the era of program design, the era of program system and the era of software engineering.

In the era of programming (1946-1956), software development relied heavily on individual programming skills, and technical documentation was as simple as the brain of an individual developer, since there was no need for communication and collaboration, and there was no urgency to write technical documentation.

In the era of program systems (1956-1968), the performance of computers improved significantly, and the scope and scale of applications gradually expanded, so that it was impossible to rely on individuals to complete the development of software, so team cooperation emerged. In the early process of team cooperation, developers still maintained the habit of developing independently in the early stage. Even though some prototypes of methodology appeared, they could not fundamentally control the huge cost of communication and collaboration, and thus the software crisis appeared. The concept of software crisis and software engineering was proposed at the 1968 International Academic Conference:

Software crisis is defined as the phenomenon that a series of serious problems occur in the process of development and maintenance because the backward software production mode cannot meet the rapidly growing demand of computer software. The definition of software engineering is to establish and use sound engineering principles to obtain reliable software that can run effectively on real machines in an economical way

Since software development has entered the engineering stage, a large number of development methodologies and development models have emerged. Among them, standard and perfect documents are an important part of software engineering, which can greatly reduce the cost of communication and collaboration, while development documents are an important part of technical documents.


What should the development document show

The software system life cycle includes four stages: definition, development, operation and maintenance, and extinction. The definition phase consists of defining the problem, feasibility study, and requirements analysis. The development stage includes outline design, detailed design, code writing and testing stages. The operation and maintenance stage includes corrective maintenance, adaptive maintenance, preventive maintenance and improvement maintenance. The dying phase includes system obsolescence and graceful offline.

Each phase of the lifecycle has its own importance, but developers should focus more on defining phases and development phases. Definition stage needs to solve why development (why), what is the demand (what) two problems, development stage needs to solve how to design, how to code, how to test (how) three problems.

Do development documents need to represent all the sub-phases of definition and development? I don’t think it’s necessary. Problem definition and feasibility studies are primarily the responsibility of the product manager, the testing phase is primarily the responsibility of the tester, and the developer can focus on but not necessarily reflect in the development documentation. I believe that the development document must reflect requirements analysis, outline design, detailed design, code writing four sub-stages.


3 Seven Dimensions

In my opinion, a complete development document should have at least seven dimensions, each of which describes one aspect of the system and, when combined, the system as a whole. These dimensions are:

Four color division field

Use cases look at functionality

Flow three musketeers

Domains and data

Horizontal and horizontal design

Look at architecture in layers

Interface look docking

This article we analyze a football player information management system, this system we may not have done, we analyze this system together. This paper focuses on the introduction of methodology, business details are difficult to cover.


3.1 Four-color field

3.1.1 Process sorting

First of all, there are two questions to consider. The first question is from what perspective? Because different people see the process differently. The answer is that it depends on what problem the system needs to solve, because we have to manage the whole link from the player’s transfer to the game, so it’s a good choice from the player’s point of view.

The second question is what to do if you are not familiar with the business? Since we are not sports and exercise experts, we do not know the business details of the whole link. The answer is to have a business expert present when you comb through the process, because without real business details, you can’t domain-driven design. Similarly, when sorting out complex business processes on the Internet, product managers or operators who are familiar with relevant businesses must be involved.

Suppose a football business expert has sorted out the business process, a player proposes a transfer, gets a medical at a new club by consensus, and signs a contract once the medical passes. After entering the new club, I trained. After reaching the training quota, I played in the game and attended the press conference after the game. Of course, the actual process will be much more complicated, but this article will focus on the methodology.


3.1.2 Four-color modeling

(1) Time index object

The first color for four-color modeling is red, representing the time scale object. The timing object is the most important object in four-color modeling and can be understood as the core business document. In the process of business, it is necessary to leave documents for key business, through which the whole business process can be traced.

The time scale object has two characteristics: the first is the fact immutability, which records the fact that happened at a certain point or time in the past. The second is accountability traceability, which records the information that managers are concerned about. Now we analyze what the target of the system is and what core business documents need to be left.

Transfer documents correspond to transfer documents, medical documents correspond to medical documents, contract documents correspond to contract documents, training documents correspond to training indicators, matches correspond to competition indicators, press conferences correspond to interview documents. According to the analysis, draw the following timescale objects:


(2) Participants, land and objects

These three types of objects are represented in green in four-color modeling, and we take the scene of electric shopping mall as an example to illustrate. When the user pays to buy the goods of the merchant, the user and the merchant are the participants. Delivery documents of logistics system need to have delivery address object, and address object is place. Order needs goods object, logistics distribution needs goods, goods and goods are things.

By analyzing this example, we can know that the participants include the general manager, team doctor, coach, fans and journalists, including the training address, match address and interview address, and the signed jerseys and signed football:


(3) Role object

In four-color modeling, represented in yellow, these objects represent the roles in which participants, places, and objects participate in the business process:


(4) Description object

We can add relevant description information to the object, represented in blue in four-color modeling:


3.1.3 Domain division

In the process of four-color modeling, we realize that time mark object is the most important object, because it carries the core documents of the business system. When dividing domains, we also can’t do without the time scale object and divide domains by convergent correlation time scale object.


3.1.4 Domain Events

When something happens to a business system, we call it a domain event if there is follow-up action in the domain or other domains, and that event needs to be perceived.

For example, if a player gets injured during a match, this is a match subdomain event, but the health and training subdomains are aware, then the match subdomain emits an event, and the health and training subdomains subscribe. A player scoring a goal in a match is also a match subdomain event, but the training and contract subdomains also pay attention to this event, so the match subdomain also emits a match goal event, which the training and contract subdomains subscribe to.

One issue to be aware of through event interaction is that implementing business through event subscription can only adopt final consistency, requiring the abandonment of strong consistency and possibly introducing new complexity trade-offs.


3.2 Use cases look at functions

By now, the domain has been defined, the large domain has been broken down into smaller domains, and we are no longer helpless, but can do use case analysis for smaller domains. A use-case diagram consists of actors and use cases to answer the question of who uses the system for what.

Below said in the field of competition, athletes perspective (what) system is used for goals, assists the statistics, foul, running distance, match score statistics, the accuracy of the statistics, injury statistics (doing things), in the same way we also can choose four color other participants in the modeling perspective drawing a use case diagram.

The include keyword indicates the inclusion relationship. For example, the game is a basic use case, which includes seven sub-use cases: goal statistics, assist statistics, foul statistics, running distance statistics, game score statistics, pass success rate statistics and injury statistics. Inclusion notation has two advantages: first, it can clearly organize subcases, and second, it facilitates reuse of subcases. For example, the coach perspective use case diagram also contains match scores, so it can point directly to match evaluator use cases.

The extend keyword represents the extension relationship. For example, penalty statistics is an extension of goal statistics. Penalty statistics will not affect the goal statistics function even if they do not exist, because penalties may not be obtained. Yellow card statistics and red card statistics are the extension of foul statistics, because common fouls do not receive red and yellow cards, so red and yellow card statistics do not exist, and will not affect the foul statistics function.

Use case diagrams do not care about implementation details, but describe system functions from an external perspective. Even those who do not know implementation details can quickly understand system functions by looking at use case diagrams. This feature stipulates that use case diagrams should not be too complex, but should be able to illustrate core functions.


3.3 Process three Musketeers

Use-case diagrams describe the system from an external perspective, but analyzing the system always goes deep inside the system, where the process view is the view that describes how the system flows. Activity diagram, sequence diagram and state machine diagram are the three most important views in the process view, which are called the three senders of the process. Activity diagrams focus on logical branches, sequence diagrams focus on interactions, and state machine diagrams focus on state flow.


Figure 3.3.1 activity

The activity diagram is suitable for describing the branches of complex logic. Imagine a business scenario where a team needs to select a player to be the team’s Footballer of the Year. The selection criteria are as follows: one candidate each for the front court, midfielder, back court and goalkeeper. The frontcourt players compare the number of goals and assists, the midfielders compare the number of assists and steals, the backcourt players compare the number of clearances and steals, and the goalkeeper compares the number of saves and points. If all indicators are the same, the draw is made. After each position has been selected, the entire coaching staff will vote, and if the number of votes is equal, the lottery will be drawn.

We often say that a picture is worth a thousand words, and one of the big reasons is that text is linear, so it’s not as good at expressing logical branches as it is in the flow view, where activity diagrams are the best.


Figure 3.3.2 rainfall distribution on 10-12 order

Sequence diagrams, which focus on interactions, are good for showing the details of interactions in a business process in chronological order, but sequence diagrams are not good at showing complex logical branches.

If a logical branch is particularly important, you can choose to draw another sequence diagram. For example, there are normal flow of successful payment and abnormal flow of failed payment in the payment process. These two processes are very important, so they can be reflected in two sequence diagrams. Going back to the example in this article, we can use the sequence diagram to show the whole process of the player from the proposed transfer to the match.


3.3.3 State machine diagram

Assume that A piece of data has three states ABC. From the perspective of normal services, the state can only be transferred from A to B, and then from B to C, but cannot be disorderly or irreversible. However, if the status of data is A and the status changes after receiving an asynchronous message, the status of B message is delayed later than that of C message and finally changes to C and then B, then the status is wrong.

The state machine diagram focuses on state flow, showing which states can flow from one state to another and, combined with the state machine code pattern, addressing the above state exception. Going back to the example in this article, we can use a state machine diagram to represent the entire state process of a player from proposing a transfer to signing a contract.


3.4 Domain and data

The above chapter analyzes the system from the functional level and process level. Now we need to analyze the system from the data level. We first compare two groups of concepts: value object and entity, domain object and data object.

An entity is an object with a unique identity that is present throughout the life cycle of the entity object and cannot be changed. A value object is essentially a collection of attributes with no unique identity.

One important difference between domain objects and data objects is how value objects are stored. Domain objects retain the business meaning of value objects while containing them, while data objects can hold value objects in a looser structure, simplifying database design.

Now we need to manage the basic information and match data of football players. How should the corresponding domain model and data model be designed? Name, height and weight are the essential attributes of an athlete, and a unique number can correspond to the entity object. Distance run, pass success rate, goals scored are the performance of the player, and the set of these attributes can correspond to the value object.

We code domain objects and data objects according to the diagram:

// Data object
public class FootballPlayerDO {
    private Long id;
    private String name;
    private Integer height;
    private Integer weight;
    private String gamePerformance;
}

// Domain objects
public class FootballPlayerDMO {
    private Long id;
    private String name;
    private Integer height;
    private Integer weight;
    private GamePerformanceVO gamePerformanceVO;
}

public class GamePerformanceVO {
    private Double runDistance;
    private Double passSuccess;
    private Integer scoreNum;
}
Copy the code

Why use JSON to store value objects? Because scripting is a way to extend flexibility, scripting not only means using Groovy, QLExpress scripts to enhance system flexibility, but also loosely extensible data structures. The data model abstracts the basic attributes such as name, height and weight. For the frequently changing performance attributes, the values of these attributes may change frequently, and even the attributes themselves may also change frequently, including the number of shots and breakthrough times, so they are stored in a loose structure.

If you need to search by KEY in the JSON structure, for example, you can find a player with more than 5 goals. We can tile MySQL table data into ES, one data according to JSON KEY tiling into multiple data, so that can be retrieved.


3.5 Vertical and horizontal design

An important reason for the complexity of complex businesses is that there are many roles or types involved and it is difficult to design in a straightforward manner, so we need to increase the analysis dimension. One of the most common is to add horizontal and vertical dimensions, and this paper also focuses on two dimensions. Generally speaking, horizontal expansion is the breadth of thinking, vertical expansion is the depth of thinking, corresponding to the system design can be summarized as: vertical isolation, horizontal arrangement.

We first analyze an ordering scenario to pave the way. Currently there are three order types of ABC. The price of order A is 10% off. The maximum weight of logistics cannot exceed 8kg, and refund is not supported. B order price 20% off, logistics maximum weight is not more than 5 kg, refund support. C the price of the order is 30% off. The maximum weight of the logistics cannot exceed 1kg. Refund is supported. It is also not difficult to write the code in a straightforward way as the requirements are written:

public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Override
    public void createOrder(OrderBO orderBO) {
        if (null == orderBO) {
            throw new RuntimeException("Abnormal parameter");
        }
        if (OrderTypeEnum.isNotValid(orderBO.getType())) {
            throw new RuntimeException("Abnormal parameter");
        }
        // Type A order
        if (OrderTypeEnum.A_TYPE.getCode().equals(orderBO.getType())) {
            orderBO.setPrice(orderBO.getPrice() * 0.9);
            if (orderBO.getWeight() > 9) {
                throw new RuntimeException("Excess of logistics maximum weight");
            }
            orderBO.setRefundSupport(Boolean.FALSE);
        }
        // Type B order
        else if (OrderTypeEnum.B_TYPE.getCode().equals(orderBO.getType())) {
            orderBO.setPrice(orderBO.getPrice() * 0.8);
            if (orderBO.getWeight() > 8) {
                throw new RuntimeException("Excess of logistics maximum weight");
            }
            orderBO.setRefundSupport(Boolean.TRUE);
        }
        // Type C order
        else if (OrderTypeEnum.C_TYPE.getCode().equals(orderBO.getType())) {
            orderBO.setPrice(orderBO.getPrice() * 0.7);
            if (orderBO.getWeight() > 7) {
                throw new RuntimeException("Excess of logistics maximum weight");
            }
            orderBO.setRefundSupport(Boolean.TRUE);
        }
        // Save data
        OrderDO orderDO = newOrderDO(); BeanUtils.copyProperties(orderBO, orderDO); orderMapper.insert(orderDO); }}Copy the code

The above code is functionally sufficient to fulfill the business requirements, but programmers need to think about the maintainability of the code as well as the functionality. If we add an order type, or if we add an order attribute processing logic, we need to add code to that logic, and if we don’t handle it properly, it will affect the original logic.

To avoid this, the open and close principle of design patterns requires us to open for additions and close for modifications, which I think is the most important principle of design patterns.

Requirements change by extending rather than modifying existing code, thus ensuring code stability. Extensions are not arbitrary, either, because the algorithm is defined beforehand, extensions are based on the algorithm, frameworks are built with abstractions, and details are extended with implementations. In the final analysis, the 23 design modes in the standard sense are all following the open and closed principle.

How to change the way of thinking? Therefore, two dimensions, vertical and horizontal, should be added to the problem analysis. I choose the analysis matrix method, in which the vertical represents the strategy and the horizontal represents the scene.


3.5.1 Vertical isolation

The vertical dimension represents policies, and different policies should be logically and businesswise isolated. This example includes preferential policy, logistics policy and refund policy. As an abstraction, different order types extend this abstraction, and the policy mode is very suitable for this scenario. This paper makes a detailed analysis of preferential strategy, logistics strategy and refund strategy.

// Discount strategy
public interface DiscountStrategy {
    public void discount(OrderBO orderBO);
}

// Type A preferential policy
@Component
public class TypeADiscountStrategy implements DiscountStrategy {

    @Override
    public void discount(OrderBO orderBO) {
        orderBO.setPrice(orderBO.getPrice() * 0.9); }}// Type B preferential policy
@Component
public class TypeBDiscountStrategy implements DiscountStrategy {

    @Override
    public void discount(OrderBO orderBO) {
        orderBO.setPrice(orderBO.getPrice() * 0.8); }}// Type C preference policy
@Component
public class TypeCDiscountStrategy implements DiscountStrategy {

    @Override
    public void discount(OrderBO orderBO) {
        orderBO.setPrice(orderBO.getPrice() * 0.7); }}// Discount strategy factory
@Component
public class DiscountStrategyFactory implements InitializingBean {
    private Map<String, DiscountStrategy> strategyMap = new HashMap<>();

    @Resource
    private TypeADiscountStrategy typeADiscountStrategy;
    @Resource
    private TypeBDiscountStrategy typeBDiscountStrategy;
    @Resource
    private TypeCDiscountStrategy typeCDiscountStrategy;

    public DiscountStrategy getStrategy(String type) {
        return strategyMap.get(type);
    }

    @Override
    public void afterPropertiesSet(a) throws Exception { strategyMap.put(OrderTypeEnum.A_TYPE.getCode(), typeADiscountStrategy); strategyMap.put(OrderTypeEnum.B_TYPE.getCode(), typeBDiscountStrategy); strategyMap.put(OrderTypeEnum.C_TYPE.getCode(), typeCDiscountStrategy); }}// Preferential policy execution
@Component
public class DiscountStrategyExecutor {
    private DiscountStrategyFactory discountStrategyFactory;

    public void discount(OrderBO orderBO) {
        DiscountStrategy discountStrategy = discountStrategyFactory.getStrategy(orderBO.getType());
        if (null == discountStrategy) {
            throw new RuntimeException("No preferential strategy"); } discountStrategy.discount(orderBO); }}Copy the code


3.5.2 Horizontal arrangement

The horizontal dimension represents the scenario. In a broad sense, an order type can be considered as a business scenario in which independent strategies are connected in series. The template method design pattern is suitable for this scenario.

The template method pattern typically uses abstract classes to define an algorithm skeleton, along with some abstract methods that are deferred to subclasses so that they not only comply with the algorithm skeleton conventions, but also implement their own algorithms. Flexibility as well as specification is ensured by building the framework with abstractions and extending the details with implementations.

// Create the order service
public interface CreateOrderService {
    public void createOrder(OrderBO orderBO);
}

// Abstract the order creation process
public abstract class AbstractCreateOrderFlow {

    @Resource
    private OrderMapper orderMapper;

    public void createOrder(OrderBO orderBO) {
        // Check parameters
        if (null == orderBO) {
            throw new RuntimeException("Abnormal parameter");
        }
        if (OrderTypeEnum.isNotValid(orderBO.getType())) {
            throw new RuntimeException("Abnormal parameter");
        }
        // Calculate discount
        discount(orderBO);
        // Calculate the weight
        weighing(orderBO);
        // Refund support
        supportRefund(orderBO);
        // Save data
        OrderDO orderDO = new OrderDO();
        BeanUtils.copyProperties(orderBO, orderDO);
        orderMapper.insert(orderDO);
    }

    public abstract void discount(OrderBO orderBO);

    public abstract void weighing(OrderBO orderBO);

    public abstract void supportRefund(OrderBO orderBO);
}

// Implement the order creation process
@Service
public class CreateOrderFlow extends AbstractCreateOrderFlow {

    @Resource
    private DiscountStrategyExecutor discountStrategyExecutor;
    @Resource
    private ExpressStrategyExecutor expressStrategyExecutor;
    @Resource
    private RefundStrategyExecutor refundStrategyExecutor;

    @Override
    public void discount(OrderBO orderBO) {
        discountStrategyExecutor.discount(orderBO);
    }

    @Override
    public void weighing(OrderBO orderBO) {
        expressStrategyExecutor.weighing(orderBO);
    }

    @Override
    public void supportRefund(OrderBO orderBO) { refundStrategyExecutor.supportRefund(orderBO); }}Copy the code


3.5.3 Comprehensive application

The above example business and code are not complicated. In fact, complex business scenarios are just the superposition, combination and interweaving of simple scenarios. It is nothing more than seeking answers through vertical isolation and horizontal arrangement.

The vertical dimension abstractions the concept of capability pool, which contains many capabilities. Different capabilities are aggregated according to different business dimensions, such as preferential capability pool, logistics capability pool and refund capability pool. We can see two degrees of isolation, capability pools are isolated from each other and capabilities are isolated from each other.

The horizontal dimension selects capabilities from the capability pool and links them together according to business requirements to form different business processes. Because the ability can be arbitrarily combined, it embodies great flexibility. In addition, different capabilities can be executed in serial. If there is no dependency between different capabilities, they can also be executed in parallel as in process Y to improve execution efficiency.

At this point, we can return to the football player management system in this paper. If we adopt vertical and horizontal thinking and analyze the business scenarios of 3.3.1 Football Player selection, the following figure can be obtained:

Vertical isolation of the attack ability pool, defense ability pool, goalkeeper ability pool, horizontal layout of the front court, midfield, back court, goalkeeper four processes, in different processes can be arbitrarily selected from the ability pool for combination, rather than writing lengthy judgment logic, significantly improve the scalability of the code.


3.6 Layered Architecture

The architecture is generally divided into two layers. The first layer is where the project is located across the company. Persistence layer, cache layer, middleware, business center, service layer, gateway layer, client and proxy layer are common layered architectures. In most cases, business requirements will ultimately be reflected in the service layer, and different domains correspond to different microservices.

The second level refers to the organization mode of the internal code of the project, which is generally divided into interface layer, access layer, business layer, domain layer, external access layer and basic layer.

(1) api

Interface layer: Provides externally oriented interface declarations and Dtos

(2) controller

Access layer: Provides HTTP access points

(3) service

Business layer: Provides BO objects, domain layer and business layer both contain business, but for different purposes. Compared with the domain layer, the service layer can combine services of different domains and add aspects of flow control, monitoring, logging, and permission control

(4) domain

Domain layer: provides DMO, VO, event, DO and data access. The core is subcontracting by domain, with high cohesion within domain and low coupling between domains

(5) dependency

External access layer: In this module, the external RPC service is invoked to parse the return code and return data

(6) infrastructure

Basic layer: contains common basic functions, such as basic tools, caching tools, printing logs, and message sending

This paper analyzes the domain layer. The core of the domain layer is to subcontract according to the domain and provide DMO, VO, event, DO and data access, with high cohesion within the domain and low coupling between the domains.


3.7 Interface View Interconnection

When an interface code is written, questions about how the interface is called and what the input and output parameters are need to be answered in the interface documentation. Interface documents can be generated in two ways: automatically, for example, using Swagger, or manually.

The advantage of automatic generation is that the code is the document, but also has debugging function, in the company’s internal coordination is very convenient. But if the interface is to be used by external third parties, you still need to document the interface manually. The description of an interface includes the interface name, interface description, interface protocol, input parameters, and output parameter information.


4 Article Summary

Through a business example, this paper introduces seven dimensions of the development document: four colors divided into fields, use cases to see functions, three swordmen flow, field and data, vertical and horizontal design, hierarchical architecture, interface. Each dimension describes one aspect of the system, which, taken together, gives a picture of the whole system.

In the actual development, if the demand is not big, then it is not the seven dimensions to reflect, but according to the actual situation to make a choice, can make the plan clearly, I hope this article is helpful to you.

Welcome to pay attention to the public account “JAVA Front” to view more wonderful sharing articles, mainly including source code analysis, practical application, architecture thinking, workplace sharing, product thinking and so on, at the same time, welcome to add my personal wechat “JAVA_front” to communicate and learn together