Agile thinking-methodology in Architecture Design (5) Simple Design

Source: Internet
Author: User
XP emphasizes a simple design principle: the functions that can be implemented using arrays are never linked lists. In other agile methods, simple principles are repeatedly emphasized. In this chapter, we have a comprehensive understanding of simplicity.
Context
To what extent should the architecture be designed?
Problem
The software architecture is very complex, with a large number of documents and charts. The time it takes for developers to understand the architecture itself is even longer than the time it takes to implement the architecture. Previous Article We mentioned some reasons against the Ivory Tower architecture. One of the reasons is that the design of the ivory tower architecture often involves too much experience, instead of strictly designing as needed.
In the field of software development, the most common design is the "Code and fix" design. The design increases with the software development process. Or, we can think that this method is simply not a design. It holds a natural attitude of sailing to the bridgehead, but after the design is constantly changed, Code It becomes bloated and hard to understand, with repeated code everywhere. Under such circumstances, the design of the architecture is impossible, and the software is like a broken house in the storm, and is on the verge of collapse.
In this case, a new design approach emerged, which Martin Fowler called "planned design ". Similar to architectural design, it emphasizes strict design prior to coding. This is the typical practice of architecture designers we talked about in team design. Designers usually do not program on the grounds that in civil engineering, you cannot see a designer who needs to build bricks.
"Planned design" is much better than "code and fix", but there are still many problems. In addition to the issues we talk about in team design, demand changes will cause greater trouble. Therefore, we naturally think of "elastic design": elastic design can meet the needs of changes. The price paid by elastic design is complicated design.
Digress:
Here we are talking about some of the issues raised by "planned design" and there is no such exclusion. "Planned design" still has many merits, but there are also many areas for improvement. In fact, the architecture design method we discussed in this article is essentially a "planned design" method. The method corresponding to "planned design" is XP's "evolutionary design" method, but this method still needs to be tested by practice, it cannot be simply said that he must be more advanced or backward than "planned design. However, it is certain that there are many ideas and skills in the "evolutionary design" method that deserve the reference of "planned design.
Solution
XP has two very loud slogans: "do the simplest thing that cocould possibly work" and "You aren't going to need it" (usually called yagni ). Their core idea is not to add unnecessary functions to the software to consider the future.
In a rough view, many developers think this is an unrealistic slogan. I can understand this idea. In fact, when I am keen on models and reusable component technologies, I sneer at XP's simple slogan. However, in reality, when some of my software costs rise due to complicated design, I rethink this problem and find that simple design makes sense.
Reduce development costs
Both models, reusable components, and framework technologies aim to reduce development costs. However, their approach is to invest a lot first, and then save subsequent development costs. Therefore, many ideas about architecture design are centered on this idea, which may be the reason why developers generally think that architecture design is unattainable.
XP is the opposite. When dealing with the first problem, it is impossible to design an elastic and almost perfect architecture. This work should gradually mature with the evolution of development. I dare not say that this method is correct, but if we treat the biological structure as the same architecture, isn't this method very similar to the evolution of the natural world?
There was nothing wrong with the idea of creating a perfect architecture from the very beginning. The key is that it is difficult to achieve this. There are always a lot of problems that you didn't consider when designing. In this way, when a "perfect" architecture is designed with a lot of energy at the beginning, unexpected problems will inevitably occur. At this time, the complicated architecture will affect the improvement of the design, this increases development costs. This is like if the direction is wrong, and the transportation is faster, it leads to rapid expansion of errors. Martin Fowler said in his paper, "working on the wrong solution early is even more wasteful than working on the right solution early" (doing something wrong in advance is a waste of time than doing something right in advance ), I believe this is the truth.
What's more interesting is that we are generally more likely to make mistakes. When we design the architecture, we cannot fully obtain detailed requirements. In fact, even if you have achieved a complete requirement, it may change. In this case, the architecture design cannot be correct. In this way, it is better to spend a lot of time designing the "perfect architecture" that is impossible to achieve in the initial stage to spend the time on subsequent improvements.
Improve communication efficiency
One of the goals of the team design has been discussed in the team design process to reduce the cost of communication, so that everyone can understand the architecture. However, if the architecture is too complex, the communication cost will rise again, and the cost will not decrease as the project progresses, instead, the communication cost will continue to rise due to the new problems we mentioned above.
A simple architecture design can speed up the development team's understanding of the architecture. We can understand simple meanings in two ways. First, simplicity means that the solution to the problem will not be very complex. Architecture is the key to solving the problem. No matter how complicated and changing the demand is, we can always find a simple and stable part, we can use this simple and stable part as the basis, and then improve and expand as needed to solve complicated problems. In the example, we mentioned measurement pattern, which is designed according to this idea.
Second, simplicity is also reflected in the simplicity of representation. A 5-page document can clearly show why architecture design takes 50 pages? In the same way, there is no need to use documents for architecture design that can be expressed with a simple figure. After all, face-to-face communication is the most efficient communication. No matter how complicated the document is, it cannot be fully understood. Moreover, it takes a lot of time to maintain complicated documents. In only two cases, we advocate the use of complex documents: first, the development team cannot communicate face-to-face; second, the development results should be accumulated as team knowledge, used for the next development.
Future considerations
The main reason for us to consider the future is the unstable demand. Therefore, if we consider future demand changes, we will unconsciously add complex components to the architecture design. This violates the simple spirit. However, if you do not consider the possible situations, those changes that do not fit the current design will lead to a lot of rework.
Do you still remember yagni? In principle, we still insist that we do not design possible future conditions in the existing system. However, we must think about it and prepare for possible future situations. In fact, isn't the idea of a great interface in software originated from this? Therefore, think about the future, but wait until it is necessary.
The change case helps us think about the future. The change case is what you may or may not want to meet in the future, but you do not need to meet it now. When we design the architecture, the change case will also become one of the design considerations, but it cannot be the only consideration for decision-making. Many times, we are addicted to the challenges posed by designing a universal system. In fact, what we do is meaningless to users.
Stable Architecture
What is the relationship between architecture simplification and architecture stability? The simpler the architecture, the better its stability. The reason is simple. one class with four methods and three attributes is more stable than one class with 20 methods and 30 attributes? Of course, it is the former. The architecture is ultimately mapped to the code level, so the simplicity of the architecture will bring about the stability of the architecture. Make your class smaller as much as possible, make your method shorter as much as possible, and minimize the relationship between classes. This is not my advice. Many Design articles say this. On this topic, we can further read similar articles (about refactoring ).
Simple Correction
Therefore, for us, the simple meaning is not to add future or unimplemented functions to the current software, the corresponding architecture design does not need to consider these additional requirements, as long as it can meet the current needs. This is a simple definition. But in reality, there is always one or another reason, making the design more complicated. In general, if a design is valuable to the team, it makes sense to pay a certain amount of cost to study, verify, develop, document the design. On the contrary, if a design has no great value or the cost of developing it exceeds the value it can provide, you do not need to consider this design.
Value has different meanings for different teams. Sometimes it may be time, sometimes it may be user value, sometimes it may be for the design accumulation and code reuse of the team, sometimes for experience, sometimes it is to work out reusable frameworks ). These can also be called goals. Therefore, when designing an architecture, you must first determine your purpose and consider things that are helpful to the purpose.
Scott W. ambler mentioned in his article a story that he experienced personally. During the architecture design process of software development, he spent a lot of time designing the ing architecture from the database to the business logic, although this is something that any developer is willing to work on (because it is cool ). However, he had to admit that for users, this advanced design architecture is of little significance, because users do not care about specific technologies. When I saw this story, I was very touched. A developer is always keen on novelty technology. But is it reasonable if the cost of novelty technology is borne by users? Although the adoption of new technologies can bring benefits to users, no one has ever calculated the cost behind the benefits. For projects I have developed, this cost is often greater than the benefits. There may be no definite answer to this question.
Example 1. Java I/O system
from the Java I/O system design, we can feel the difficulties in simple design.
I/O system design difficulty has always been recognized. One purpose of Java's Io design is to simplify the use of Io. In Java 1.0, the I/O system of Java mainly divides the I/O system into two parts: input and output, and defines the abstract classes inputstream and outputstream respectively. Starting from these two abstract classes, a series of input and output classes with different functions are implemented. At the same time, the Java Io system also implements the abstract classes of filterinputstream and filteroutputstream in the input and output, as well as a series of related implementations. In this way, the input and output functions of different functions are connected together to implement complex functions. This implementation is actually in the decorator mode (because I have not read the source code and relevant information, I just want to speculate based on the functions and usage skills. If you have different opinions, please send us a letter to discuss it ).
therefore, we can combine multiple objects to provide complex functions:
datainpustream in =
New datainputstream (
New bufferedinputstream (
New fileinputstream ("test.txt ");

the above Code uses two filterinputstream: datainpustream and bufferedinputstream to implement the read and buffer functions, at the same time, an inputstream: fileinputstream is used to read stream data from files. Although it is not very convenient to use, the design should be very clear.
what makes the design messy is neither inputstream nor outputstream class, such as randomaccessfile, which indicates that due to function complexity, this makes the original design based on input/output classification messy. Based on our experience, we say that the design requires refactoring. Therefore, in java1.1, the IO system was re-designed, using the reader and writer bit-based design, and adding new features. However, the current design seems more confusing, because we need to use two different Io designs, 1.0 and 1.1 at the same time.

Simplicity does not mean simplicity.
Speaking of this, if you have a misunderstanding that a simple architecture must be easy to design, it will be wrong. A simple architecture does not mean implementation or simplicity. A simple architecture requires the designer to spend a lot of effort and require the designer to have a deep understanding of the technology. In a project we are working on, the infrastructure designed at the beginning has been modified several times in implementation, but each modification reduces the amount of code by one point, the readability of the Code is also enhanced. From a psychological point of view, it takes some courage to constantly modify your own architecture. Because both design and code are the painstaking efforts of developers. However, it is worthwhile to take this step.
The example on the right discusses the Java IO Design. the Java class library design should be excellent, but it still cannot be modified. In fact, in the field of software development, there are many situations where the design is too complex due to the original design mistakes (such as Microsoft's OLE ). Similarly, when designing software, we also need to constantly modify the design. It is not easy to implement complex functions, but to implement simple design.
What kind of designers do simple design require?
A simple architecture requires a comprehensive designer. What is a comprehensive designer? My definition is both design and coding. We have talked about ivory tower architecture and ivory tower architecture designers in our team design model. One of their most common mistakes is the separation of design and code. From our own experience, even if we consider a very perfect architecture in the design phase, there will also be one or another problems in the coding phase. As a result, the architecture implementation becomes complex. The most obvious feature is that classes with a large number of methods or long methods appear during encoding. This indicates that the architecture is decoupled from the code. In our development process, this phenomenon occurs more than once, or bad smell ). Refactoring also helps identify bad taste.
After an architecture design is completed, developers can program according to the design and speed. After a period of time, new features are constantly added. We find that the code is getting messy, the amount of Code increases, the readability decreases, debugging becomes difficult, and the symptoms of uncontrollable code begin to appear. We know that the architecture design needs to be adjusted. This is the refactoring mode we mentioned later. What we want to talk about here is that if the architecture designer does not participate in coding, it will not feel bad, so it will not take the initiative to improve the design. To solve this problem, the best way is to let the designer participate in code writing. In particular, the real part of the important architecture requires the participation of the designer. If a designer cannot participate in coding, a mechanism is required to feed the code back to the designer so that the designer can reconsider the architecture improvement when appropriate. One possible method is code review. Let the designer review the Code to ensure that the coders truly understand the intent of the architecture design.
Example 1. Java Io System
From the design of Java I/O system, we can feel the difficulties in simple design.
I/O system design difficulty has always been recognized. One purpose of Java's Io design is to simplify the use of Io. In Java 1.0, the I/O system of Java mainly divides the I/O system into two parts: input and output, and defines the abstract classes inputstream and outputstream respectively. Starting from these two abstract classes, a series of input and output classes with different functions are implemented. At the same time, the Java Io system also implements the abstract classes of filterinputstream and filteroutputstream in the input and output, as well as a series of related implementations. In this way, the input and output functions of different functions are connected together to implement complex functions. This implementation is actually in the decorator mode (because I have not read the source code and relevant information, I just want to speculate based on the functions and usage skills. If you have different opinions, please send us a letter to discuss it ).
Therefore, we can combine multiple objects to provide complex functions:
Datainpustream in =
New datainputstream (
New bufferedinputstream (
New fileinputstream ("test.txt ");
The above Code uses two filterinputstream: datainpustream and bufferedinputstream to read data and buffer data. At the same time, an inputstream: fileinputstream is used to read stream data from the file. Although it is not very convenient to use, the design should be very clear.
What makes the design messy is neither inputstream nor outputstream class, such as randomaccessfile. This shows that the original design based on input/output classification is messy due to feature complexity, based on our experience, the design requires refactoring. Therefore, in java1.1, the IO system was re-designed, using the reader and writer bit-based design, and adding new features. However, the current design seems more confusing, because we need to use two different Io designs, 1.0 and 1.1 at the same time.
Example 2. Measurement Pattern
There is a measurement pattern in the Analysis Mode book, which originally aims to solve various complicated and measurable attributes in reality. For example, a medical system may have thousands of measurable attributes, such as height, weight, and blood pressure. If they are expressed separately, the complexity of the system will inevitably increase. Therefore, measurement pattern starts from the measurable commonalities of these attributes, studies new solutions, and puts forward the idea of measurement pattern:
The measurable attribute (measurement) is used as the phenomenon type instance. In addition, each person can have multiple measurement. At the same time, measurement also corresponds to the processing attribute. In this example, quantity, the number and unit of measurement. For example, if a person's weight is 65 kilograms, then phenomenon type is the weight, the amount of quantity is 65, and the units is the kg.

Figure 5. Category measurement pattern class diagram
This is actually a simple design, but it clearly represents the relationship between attributes and simplifies the complexity of thousands of attributes. In addition, we will further think about it and find that this architecture is only a basic solution to the numerous attribute problems currently. It can also be expanded according to specific needs, for example, dynamically Add units or convert different units.
Therefore, what we show here is actually a way of thinking. Imagine that when you are facing a complicated medical system, there are a lot of attributes and different processing methods, can you find a simple part from such complex requirements? In the first part of our architecture design, we talked about the essence of Architecture Design in abstraction. Here is the most typical example. In our traditional ideas, we use height, weight, and other concepts as attributes or classes. However, to meet the requirements, we abstract these specific concepts and propose measurable categories, it is designed as a class (phenomenon type), and the specific concept is used as an instance. This abstract idea is everywhere in software design, such as the concept of metadata.
More in-depth understanding
In the next chapter, we will discuss iterative design, which also involves the knowledge of simple design. We recommend that you combine the two chapters.

(To be continued)
Author profile:
Lin Xing, Senior Project Manager of the Project Management Group of Chen Xun software studio, has many years of project implementation experience. Chen Xun software studio is committed to the application of advanced software ideas and software technology. Its main research direction is software process ideas, Linux cluster technology, OO technology and software factory model. You can contact him by email iamlinx@21cn.com.

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.