Ever since the software crisis of the 1960s gave birth to software engineering, the promise of managing, designing, building and maintaining software in an engineering way, clever engineers have been working hard on the long road to better software.

The development language has experienced assembly, C, C++, Java, Erlang, Python; Programming paradigm covers procedural (POP), object-oriented (OOP), generic (GP), functional (FP); Software architecture from single to distributed to cloud native, including rock, library service component module, layered, micro service, MVC/ServiceMesh Serverless, etc.; Software engineering ideas and methodologies include Waterfall Model with lifecycle management as the core, Agile Development with iterative and gradual Development as the core, and Domain driven design with boundary division and control as the core focusing on domain modeling (DDD: Domain Driven Design).

The world is complex, and mapping the real world to virtual software is bound to be difficult. Software development is the art of balancing choices. For example, fast delivery and safe production are often at odds, and development efficiency and operational efficiency are often inconsistent. So in the long history of software, inventing a way to solve one problem almost always introduces another, and software engineers have to deal with a world of chaos.

Process-oriented (C) believes that everything is a process and the real world can be encapsulated as a process, and the world can be simulated through process series and arrangement. However, as software is used to solve complex business problems on a large scale, this paradigm has been proved to lack sufficient abstraction. Although functions can be regarded as the smallest granularity of modular technology, it still cannot cover up its lack of modular ability, and the separation of process and manipulated data also leads to the deviation of software from the direction of high cohesion and low coupling.

In order to solve the above problems, object-oriented paradigm (C++ /Java) is designed to model the world through objects, objects encapsulate properties and methods together, and interact with the outside world through open interfaces, providing a logical level of modular means for software design; Furthermore, objects are easily mapped to real-world objects. Objects represent more complex concepts through composition and more abstract concepts through interface generalization.

The motivation of the generic type is more simple, need a language mechanism, to provide standard containers to solve across the data type of disorder, c + + template through the language mechanism provides the ability of a parameterized type, compile-time type checking and class instantiation both types of security and improve execution efficiency, but also increase readability compilation time and damage, In particular, the introduction of new gameplay such as template metaprogramming makes things more complicated.

UML was born in the age of waterfall model, which is an object-oriented modeling tool independent of specific programming language. UML divides object-oriented development into three stages: analysis (OOA), design (OOD) and coding (OOP). This process pays more attention to analysis and design than coding implementation.

Due to the design and implementation is divided into two mutually to clamp down on stage, so there are two development process model, that is, a manifest in UML drawing design model, implementation model of a hidden in the software source code, two phase model inevitably lead to the design and coding, design and implementation to different person seemingly promotes collaboration, In fact, it increases communication cost and reduces delivery efficiency.

The academic pursuit of automatically generating code according to the architect’s UML drawings was beautiful, but in reality this goal could only be met under limited circumstances. In increasingly complex commercial software development, project sent to feel more time consumed on the development and maintenance, the final deliverables only source rather than the drawings, so developers can only (SOLID) to design principle and design patterns (GOF) seek solace, design personnel is the top of the head “the architect” of a good name is a powerful and unconstrained style.

Waterfall model is difficult to reverse the process, and only to the project late to see the results, in view of the defect falls, agile development to improve the end-to-end communication software development, extreme programming (XP) is a lightweight implementation of agile development software engineering methodology, try to use a spiral way of evolution, the complexity of extreme programming software activity in the face, Recognising that requirements cannot be set in stone at the beginning, developers should prioritise their efforts in the code and respond flexibly to changing requirements by introducing concepts such as basic values, principles, and methods.

Agile development has flourished in the Internet boom because the demands of Internet applications are so dynamic that it is difficult to strictly follow the heavy traditional waterfall process.

Heavy prototype implementation of agile methods have even been misconstrued as completely don’t need to design and document development way, the advantage of agile at the same time become the disadvantages of it, ignore the importance of the document, in the case of personnel flow big will no doubt increase the difficulty of maintenance, and organization and application of it in the face of complex domain knowledge, agile development is also in question.

With the explosion of Web Service applications, new languages like Java are taking over, Controller->Service->Dao or SOA design is changing into the standard solution of the industry, Service layer is acting as god class, all logic is packed into it. The anaemic pattern of getter/setter DAOs stinks, the data-driven development model gets bogged down, and domain-driven design comes into view.

In 2003, Domain Driven Design (DDD) advocated by Eric Evans regarded “domain kernel” as the most important asset of an enterprise and advocated eliminating the inaccuracy of expression through universal Language. Domain driven Design inherited and developed agile development. DDD puts domain and design at the heart of software design, giving business people and developers equal attention, and recommends working together to capture congested domain models. DDD strategic design defines the bounded context at the macro level, while tactical design provides some best practices at the implementation level.

While the traditional pattern is data-centric, domain-driven design is shifting to domain-model-centric, which is a fundamental design shift. DDD by quad border demarcation space settlement space, determine the core, gm, support three kinds of areas, within the boundaries of the context, through hierarchical (base layer – field layer, application layer – show layer) realize the internal and external isolation, application layer to form a protective layer, effectively isolate the complexity of the complexity of the business and technology. Taking domain layer as the stable and cohesive core of the whole system is a key feature of domain-driven design.

Reviewing the various doctrines emerging in the development of software engineering, every popular trend of thought has its own set of theories, claiming to solve some problems perfectly, but falling into another frame trap without exception, but none of them can put an end to the disorderly design of software engineering. We can’t get out of the endless refactoring cycle of our own entertainment, and we’re still stuck with all kinds of technical debt, so let’s get out of the mental shackles of all kinds of frameworks and look back at the nature of design. Let’s think about the fundamental principles of dealing with software complexity.

The methods to solve large-scale complex software problems can be simply classified into several points: abstraction, decomposition and isolation.

Abstraction is categorization, and categorization is reuse. The meaning of abstraction is to find the essence behind things through expression. The purpose of abstraction is to reduce the cognitive burden, avoid repetitive thinking and labor, simplify the problem space, and let people pay attention to things at a higher level. Modeling is the process of refining the mental model, which is essentially a kind of abstraction.

Decomposition is to divide a complex problem into smaller problems that are easy to solve. The process of decomposition is to simplify the problem. After the problem is decomposed, there is also a need for cooperation, which is actually the concept of divide and conquer. There are two ways to split problems: technical dimension and business dimension. Microservices and DDD are split problems from business dimension. The separation can follow the AKF principle and Conway’s law, high cohesion and low coupling is the standard to evaluate the separation, let God be God, let Caesar be Caesar.

Isolation is established for decoupling, loosely coupled system has always been the goal of the engineers cobest, stratification is the effective means to realize isolation, the function of each layer focus on their implementation, the ability to use the lower at the top, to provide services to the upper, lower on the lower interface interaction through agreement, between between the adjacent layers are completely transparent. The rules of the external world are contract, communication, and system-level architectural styles and patterns, while the rules of the internal world are layering, collaboration, and class-level design grids and patterns.

In software change of flood, the pioneer of software engineering and philosophers, put forward a variety of programming thought and methodology, but none fundamentally thoroughly solve the problem, the mythical man-month chapter 16, because of software engineering is a complex system, so asserts that there is no silver bullet, not only no cure-all muti, It also points out that there is no way to improve efficiency tenfold over the next decade.

Historically, each a perfect scheme from Dui solve all the problems in existing schemes and claim, and then spread sermons, take the public into their elaborate design the logic of the closed loop, and then followers to a kind of religious devotion, the theory of derivative in the project, the final delivery of the code is still filled with all sorts of vague, filthy, Any evolution could lead to a sudden collapse of accidental invariance, leaving a field of feathers, and the new theories would eventually drift like smoke across the vast sky of history.

The ancients say: life without ignorance is not stupid, but education makes people stupid. The ancients also said: learning without thought is idle. Therefore, we should realize the importance of speculation, for knowledge, we study it, but do not blindly follow it. So what principles should we follow in software engineering?

First of all, people are the key, there is no ultimate solution to software development, because software is the externalization of people’s ideas, and people are full of flaws. We must recognize the creature in some inevitable defects in the process of abstraction, and abstract ability difference, this would mean that, compared to the rules and processes, and people actually is the soul in the process of software implementation, thoughts and principles to provide guidance, but they can’t magic solve all the problems in software engineering, the key factors affecting the quality of software development is a person, Not the design method. Code that focuses on form over content, documentation over delivery, is putting the cart before the horse.

Second, seek truth from facts, specific analysis of specific problems, the scope of the software is too wide, which means that each specific implementation rules have its limitations, can not be stuck with rigid standards, can not stick to the rules and make it into a dogma, can not use the sword of heaven to cut nails, do not use dragon knife shave. The simplest business such as CRUD model may be enough, and some may be applicable CQRS, hexagon structure, some anaemia domain objects can, some possible event storm mode is better, sometimes data and operation should be separated, even, speaking, reading and writing should be separated, and sometimes better encapsulation and operating together, from the actual wheel kill chickens will only increase the ear smile.

Third, both sides of the almost any language and technology is good or bad, has applicability, such as C, although it is lack of abstract ability, but its core syntax set is very simple, simple means focusing and reliable, means lower demand for programmers, you need to know only a few years a few dozens of STD C API can build all applications, But you have to recognize its lack of abstraction and development efficiency. While C++ has good abstraction, its syntax set is too large and it seems difficult to constrain everyone to act with minimal common knowledge, but it does write programs that are more maintainable if consensus is reached or if everyone is at a higher level.

Fourth, discipline! Yes, discipline is the key. No matter how perfect a method system is, it is meaningless if the team does not strictly enforce the discipline prescribed by the method system. Whether it is clean coding or architectural design or agile development or domain modeling, only consistent and consistent compliance with discipline, discipline imposed constraints, can continuously improve quality.

Finally, although there is no silver bullet, we should not be too pessimistic. Software engineering has been moving forward in a roundabout way. Every step forward, it can solve a large number of problems, while introducing some controllable side effects.

So why not embrace imperfection?


Click to follow, the first time to learn about Huawei cloud fresh technology ~