Implement Domain Object in Golang

Source: Internet
Author: User
Tags multiple inheritance in c
This is a creation in Article, where the information may have evolved or changed.

Preface

In the evolution process of software design, the author finally evolves the DDD hierarchical model of communication system software into a five-layer model, that is, the dispatch layer (Schedule), the transaction layer (Transaction DSL), the Environment layer (context), the domain layer (domain) and the infrastructure layer ( Infrastructure), let's take a brief look at:


Ddd-layer-with-dci-dsl.png
    1. Scheduling layer: The state model of the UE is maintained, including only the essential state of the business, sending the received message to the transaction layer.
    2. Transaction layer: Corresponds to a business process, such as UE Attach, that combines the processing of individual synchronous messages or asynchronous messages into a single transaction, which is rolled back when a transaction fails. When the transaction layer receives a message from the dispatch layer, the action of the environment layer is delegated for processing.
    3. Environment layer: In action, process a synchronous message or asynchronous message, cast the domain object of the domain layer into the appropriate role, and let role interact to complete the business logic.
    4. Domain layer: Includes not only the modeling of domain objects and their relationships, but also the explicit modeling of role roles of objects.
    5. Basic implementation layer: provides common technical capabilities for other tiers, such as message communication mechanisms, object persistence mechanisms, and common algorithms.

Transactional and domain tiers are important for business. In the article of "Golang Transaction model", the author focuses on the transaction layer, this paper mainly expounds the realization technology of the domain layer, and will gradually unfold through a case.

The case used in this article originates from Magicbowen's "DCI in C + +", and has made some changes in order to render the main implementation technology of the Golang version of the domain objects as smooth as possible to the reader.

Implementation of Domain objects

Suppose there is a scenario in which an analog man and a robot manufacture a product. People make products that consume the energy they eat, the lack of energy, and the need to eat again, while robots produce products that consume electricity and require recharging after a lack of energy. Here the man and the robot are working as a worker, and the process is the same, but the difference is that the energy consumption and the way of acquiring depend on the different.

Domain model

By analyzing the scene, we get a domain model based on the basic idea of modular design:


Human-robot.png

Physical design

As can be seen from the domain model, the role worker can be combined in the domain object human, and can be combined in the domain object robot, visible domain objects and roles are two different direction of change, so the subdirectory structure of domain is:


Object-role-dir.png

The implementation of role

Energy

Energy is an abstract role, which is a interface in Golang. It contains two methods: one consumes energy consume and the other is whether the energy is depleted isexhausted.

Energy's code is simple, as follows:

package roletype Energy interface {    Consume()    IsExhausted() bool}

Humanenergy

Humanenergy is a specific role, which is a struct in Golang. It has both the method of eating and eat, and all the methods of interface energy. For Humanenergy, all the energy eat once acquired is completely depleted after consume 10 times.

The code for Humanenergy is as follows:

package roletype HumanEnergy struct {    isHungry bool    consumeTimes int}const MAX_CONSUME_TIMES = 10func (h *HumanEnergy) Eat() {    h.consumeTimes = 0    h.isHungry = false}func (h *HumanEnergy) Consume() {    h.consumeTimes++    if h.consumeTimes >= MAX_CONSUME_TIMES {        h.isHungry = true    }}func (h *HumanEnergy) IsExhausted() bool {    return h.isHungry}

Robotenergy

Robotenergy is a specific role, which is a struct in Golang. It has both the charge of energy charging method and the realization of all the methods of interface power. For Robotenergy, all the energy charge once acquired is completely depleted after consume 100 times.

The code for Robotenergy is as follows:

package roletype RobotEnergy struct {    percent int}const (    FULL_PERCENT = 100    CONSUME_PERCENT = 1)func (r *RobotEnergy) Charge() {    r.percent = FULL_PERCENT}func (r *RobotEnergy) Consume() {    if r.percent > 0 {        r.percent -= CONSUME_PERCENT    }}func (r *RobotEnergy) IsExhausted() bool {    return r.percent == 0}

Worker

Worker is a worker, man and robot are working as a worker, the process of work is the same, but the difference is that the energy consumption and the way of obtaining depend on different. For code implementations, the worker relies only on another role energy, and only the dependency of the injected energy needs to be considered during the instantiation phase of the worker.
A worker is a specific role, which is a struct in Golang. It has both the method of producing products and produce, and the way to obtain the number of products produced getproducenum.

The code for the worker is as follows:

package roletype Worker struct {    produceNum int    Energy Energy}func (w *Worker) Produce() {    if w.Energy.IsExhausted() {        return    }    w.produceNum++    w.Energy.Consume()}func (w *Worker) GetProduceNum() int {    return w.produceNum}

Implementation of Domain objects

There are two domain objects in this case, one is human and the other is robot. We know that through multiple inheritance in C + +, the relationship between the domain object and its supported role is accomplished, and the dependency description between the role is accomplished through the relationship interleaving within the multiple inheritance tree. This approach is simpler and more efficient in C + + than traditional dependency injection, so in Golang we try to achieve domain objects by simulating multiple inheritance in C + +, rather than simply relying on humble delegates.

In Golang, the multiple inheritance in C + + can be simulated by an anonymous combination, and the dependency injection between role is no longer injected into the specific role, but the domain object is injected directly to avoid producing many small objects.
In our case, the role worker relies on abstract role energy, so when you instantiate a worker, either inject humanenergy or inject robotenergy, which requires the object (small object) that produces the specific role. The domain object human is a worker at work and consumes the energy gained through eating, so human is combined anonymously by Humanenergy and the worker. Golang through the anonymous combination to achieve inheritance, then the equivalent of human multiple inherited humanenergy and worker, that is, human also realized the energy interface, then inject energy into the human is equivalent to inject humanenergy, Also avoids the creation of small object humanenergy. In the same vein, robot is composed of anonymous combinations of robotenergy and workers, and the energy injected by the worker is robot.

The realization of human

The human object has a method inject for role dependency injection, and the creation of human objects is implemented Createhuman the factory function.

The code for human is as follows:

package objectimport(    "domain/role")type Human struct {    role.HumanEnergy    role.Worker}func (h *Human) inject() {    h.Energy = h}func CreateHuman() *Human {    h := &Human{}    h.inject()    return h}

The realization of robot

Similarly, the robot object has a method inject for role dependency injection, and robot object creation is implemented Createrobot the factory function.

The code for robot is as follows:

package objectimport(    "domain/role")type Robot struct {    role.RobotEnergy    role.Worker}func (r *Robot) inject() {    r.Energy = r}func CreateRobot() *Robot {    r := &Robot{}    r.inject()    return r}

Use of Domain objects

In the context layer, for any action, there is a clear scene where the domain object is cast into the role of the scene and the action is done through the interaction of the role. In Golang for a struct with an anonymous combination, the default variable name is the name of the struct. When we access the struct's method, we can access it either directly (omitting the default variable name) or by default variable name. We recommend accessing the default variable name to explicitly express the role. Thus, it is very simple to cast the role of the domain object in Golang, and we can access the role directly by using the properties of the default variable.

Humanproduceinonecycleaction

For human, a production cycle is the process by which the humanenergy role eat once acquired energy is consumed by the role worker's production of the product. Humanproduceinonecycleaction is an action for this process, and the code implementation is simply simulated as follows:

package contextimport (    "fmt"    "domain/object")func HumanProduceInOneCycleAction() {    human := object.CreateHuman()    human.HumanEnergy.Eat()    for {        human.Worker.Produce()        if human.HumanEnergy.IsExhausted() {            break        }    }    fmt.Printf("human produce %v products in one cycle\n", human.Worker.GetProduceNum())}

Print as follows:

human produce 10 products in one cycle

Meet expectations!

Robotproduceinonecycleaction

For robot, a production cycle is the process by which the Robotenergy role charge once acquired energy is consumed by the role worker's production of the product. Robotproduceinonecycleaction is an action for this process, and the code implementation is simply simulated as follows:

package contextimport (    "fmt"    "domain/object")func RobotProduceInOneCycleAction() {    robot := object.CreateRobot()    robot.RobotEnergy.Charge()    for {        robot.Worker.Produce()        if robot.RobotEnergy.IsExhausted() {            break        }    }    fmt.Printf("robot produce %v products in one cycle\n", robot.Worker.GetProduceNum())}

Print as follows:

robot produce 100 products in one cycle

Meet expectations!

Summary

In this paper, we summarize the main points of realization of Golang in a case, which are summarized as follows:

    1. Class is a modular approach that follows cohesion-poly-low coupling, making the software easy to respond to changes, corresponding to role, and object as a direct mapping of domain objects, which solves the understandable problems caused by too many classes, and domain objects are composed of role groups.
    2. Domain objects and roles are two different directions, and we should be a two side-by-side directory when we do physical design.
    3. Multiple inheritance is achieved through anonymous composition.
    4. The dependency injection unit of role is a domain object, not a specific role.
    5. When using a domain object, do not directly access the method of role, but first cast into role re-access method.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.