primers

Try stratification based on NodeJS and Good Practices, find another similar stratification while doing, continue to translate records.

The Clean Architecture

The body of the

Over the past few years, we’ve seen a series of ideas about system architecture. These include:

  • Alistair Cockburn’s Hexagonal Architecture (also known as Ports and Adapters) It was adopted in Steve Freeman and Nat Pryce’s wonderful book Growing Object Oriented Software
  • Onion Architecture by Jeffrey Palermo
  • Screaming Architecture was my article last year
  • DCI by James Coplien and Trygve Reenskaug
  • It’s written by Ivar JacobsonObject Oriented Software Engineering: A Use-Case Driven Approach[BCE] [url9]

Although these architectures differ in detail, they are very similar. They all have the same goal, separation of concerns. Both achieve this separation by dividing the software into different layers. Each has at least one layer for business rules and another layer for interfaces.

Each of these architectures results in the following:

  1. Independent of the framework. The architecture does not depend on some feature-rich software library. This allows you to use these frameworks as tools without having to cram systems into their limited constraints.
  2. Testable. Business rules can be tested without a UI, database, Web server, or any other external element.
  3. Independent of the UI. The UI can be easily changed without changing the rest of the system. For example, the Web UI can be replaced with a console UI without changing business rules.
  4. Database independent. You can replace Oracle or SQL Server with Mongo, BigTable, CouchDB, or something else. Your business rules are not tied to the database.
  5. Independent of any external agency. In fact, your business rules don’t know anything about the outside world.

The diagram at the top of this article attempts to integrate all of these architectures into a workable idea.

The Dependency Rule

Concentric rings represent different areas of software. In general, the deeper you go, the higher the level of software. The outer circles are mechanisms. The inner circles are policies.

The most important rule that makes this architecture work is the dependency rule. The rule is that source code dependencies can only point inward. Nothing in the inner ring can know anything in the outer ring. In particular, the name of something declared in the outer ring cannot be referred to by the code in the inner ring. These include functions, classes, variables, or any other named software entity.

Similarly, data formats used in the outer ring should not be used by the inner ring, especially if they were generated by a frame in the outer ring. We don’t want anything from the outer ring to affect the inner ring.

Entities

Entities encapsulate enterprise wide business rules. An entity can be an object with methods or a set of data structures and functions. It doesn’t matter as long as the entity can be used by many different applications in the plan.

If you write a single application without planning (enterprise), these entities are the business objects of the application. They encapsulate the most general and superlative rules. When external things change, they are least likely to change. For example, you don’t want these objects to be affected by page navigation or security changes. Operational changes to any particular application should not affect the entity layer.

Use Cases

The software in this layer contains application-specific business rules. It encapsulates and implements all use cases of the system. These use cases orchestrate the flow of data to and from the entities and instruct those entities to use their programmatic scope for business rules to achieve the purposes of the use cases.

We do not want changes in this layer to affect entities. We also don’t want this layer to be affected by changes to external factors such as the database, UI, or any common framework. This layer is irrelevant to these issues.

However, we do want changes to the operation of the application to affect the use cases and therefore the software in that layer. If the details of the use case change, some code in this layer will definitely be affected.

Interface Adapters (Adapters)

The software in this layer is a set of adapters that transform data formats that are most convenient for use cases and entities into formats that are most convenient for external organizations such as databases or the Web. For example, it is this layer that will completely contain the MVC architecture of the GUI. Presenters, Views, Controllers all belong here. The model is like a data structure that passes from Controllers to use cases, and then from use cases back to Presenters and Views.

Similarly, in this layer, data is transformed from the form that is most convenient for entities and use cases to the form that is most convenient for persistence frameworks such as databases. No code in this ring should know anything about the database. If the database is an SQL database, then all SQL should be restricted to this layer, especially the database-related parts of this layer.

This layer is also the adapter used to transform data from some external forms, such as external services, to internal forms used by use cases and entities.

Frameworks and Drivers

The outermost layer is usually made up of frameworks and tools, such as databases, Web frameworks, and so on. In general, you don’t write much code in this layer except for the glue code that communicates with the next ring inward.

This layer is where all the details are. The Web is a detail. The database is a detail. We put these things outside so they cause as little damage as possible.

Only four rings, right?

No, the circle is just a schematic. You may find that you need more than just these four. There’s no rule that says you have to have these four. However, the dependency rule always applies. Source code dependencies are always inward. As you move inward, the level of abstraction increases. The outermost circle is low level detail. As you move inward, the software becomes more abstract and encapsulates higher-level policies. The innermost circle is the most versatile.

Across the border

In the lower right corner of the diagram is an example of how to cross borders. It shows Controllers and Presenters communicating with the next layer of use cases. Pay attention to the flow of control. It starts with Controllers, goes through use cases, and is implemented in Presenters. Also note the source code dependencies. Each of them points inward to the use case.

We usually use Dependency Inversion Principle to resolve this apparent contradiction. For example, in a language like Java, we arrange interfaces and inheritance relationships so that source code dependencies are opposed to control flow at the right point of the boundary.

For example, consider a use case that calls Presenter. However, this cannot be a direct call, because that would violate the dependency rule: any name in the outer ring cannot be referred to by the inner ring. Therefore, we let the Use Case invoke an interface in the inner ring (here is the Use Case Output Port in the diagram) and let the presenter in the outer ring implement it.

The same technique is used to cross all boundaries in an architecture. We use dynamic polymorphism to create source code dependencies that are opposite to the control flow so that we can follow the dependency rules no matter which direction the control flow goes.

What data crosses borders

Typically, the data that crosses the boundary is a simple data structure. You can use basic structures or simple data transfer objects if you like. Or the data can just be arguments in a function call. Or you can put it in a hashmap, or you can construct it as an object. It is important that the data structures passed across borders are independent and simple. We don’t want to cheat and pass entity or database rows. We don’t want data structures to have any dependencies that violate dependency rules.

For example, many database frameworks return a convenient data format in response to queries. We can call this a RowStructure. We don’t want the row structure to pass in across the boundary. This would violate the dependency rule because it would force the inner ring to know something about the outer ring.

Therefore, when we pass data across borders, it is always passed in the form that is most convenient for the inner loop.

conclusion

Following these simple rules isn’t hard and will save you a lot of trouble down the road. By dividing the software into layers and following dependency rules, you will create an essentially testable system that contains all the benefits. When any external part of the system, such as a database or web framework, becomes obsolete, you can replace those obsolete elements with minimal cost.

The resources

Many years later, when I watched the TV version of “Chinese Of Evil,” I had a completely different feeling.

I remember the first time I saw it, it made me feel very depressed. Now when I see it, it feels amazing to be able to talk about the different sides of people’s hearts in this way.

Although there are only 13 episodes, 4 opening songs are changed, and the ending song is very interesting. Whenever the rhythm of the ending song is played, it seems to emphasize the change in the heart of the protagonist.

I don’t know why, but now douban is directly blocking some TV works. I remember it clearly when I first saw it. It’s on Douban.

After watching TV, I went to read the comic book. I found that there was more interesting information in the comic book, because the author would also make some communication at the end of the comic book.