Thanks for the books and taobao Miaojing’s signature.

preface

The author started programming in 1964 and has written small embedded systems, large batch systems, command line, graphical interface, process management, billing, communications, design tools, drawing tools for more than 50 years until 2016.

The takeaway: The rules of software architecture are the same.

With so many different systems, software architecture rules are completely independent of other variables. Software today is essentially the same as it was in the past, consisting of if statements, assignment statements, and while loops.

The quality of tools has improved and the programming language has improved a bit, but the basic structure of computer programs has not changed much in the past 50 years.

The rules of software architecture are really the rules of permutations and combinations of pieces of code.

An overview of the

It is not difficult for programmers to translate requirements documents into working code, but it is difficult to have a good architecture. Architectural ability requires experience and time, and not everyone is willing to spend time learning architecture.

Because the components of a system are so complex and tightly coupled, no matter how small a change is, it can take weeks to complete.

A good software architecture can greatly reduce the cost of building and maintaining software projects, making each change short, simple, easy to implement, defect avoidance, and less costly.

Chapter 1 What is Architecture and Design

Short note: There is no difference between architecture and design.

The ultimate goal of software architecture is to meet the needs of building and maintaining systems with minimal human cost.

Then the author gives several examples to illustrate how poor design can increase the human cost of corporate code.

This can be frustrating for system developers because no one is slacking off and everyone is working as hard as before. But no matter how much personal time they put in, how many fires they put out, how many extra shifts they put in, their output never goes up. Engineers spend most of their time tinkering with existing systems rather than actually completing actual new features. The real task of these engineers is to knock off Peter to pay Paul, and then have the energy to realize a little function.

To quote the story of the race between the tortoise and the hare:

  1. Slow but steady is the secret of success.
  2. It’s not about who starts out faster and who has more strength.
  3. The more anxious you are, the slower you will run.

A reminder: Don’t be overconfident and don’t continually underestimate the importance of good, well-designed, clean code. If you want to run fast, run steady.

And it ends with a question: if the way to save a system is to redesign it, then why should we think that starting from scratch would be better?

Chapter two two value dimensions

Programmers should not have to “write code and fix bugs according to requirements documentation” as their whole job.

Each new requirement is like an irregular jigsaw puzzle that needs to be inserted into the existing jigsaw puzzle to create a new shape. If our architectural design is biased towards maintaining the overall shape, each change will be very difficult, and good architectural design should be “shape-agnostic”.

But in daily development work, architectural design work is not given the priority it deserves:

If you ask the business if they want to be able to change requirements, they will generally say yes, and they will add that it is more important to do today’s functionality than to achieve future flexibility. Ironically, if the business comes up with a requirement after the fact, and your estimated workload exceeds their expectations, these guys will often be furious that you’ve allowed the system to get so messed up that it can’t be changed.

Therefore, it is the responsibility of the software developer to balance the importance of the system architecture with the urgency of the function.

The architect’s job is to create an architecture that is easy to function, easy to modify, and easy to extend. If you ignore the long-term value of the architecture and a system becomes difficult to maintain, then the software development team is not fighting the requirements enough and not doing its job.

Chapter 3 programming paradigm overview

Structured programming, object-oriented programming, functional programming three programming paradigms were put forward in the decade from 1958 to 1968, and no new programming paradigms have appeared since.

  1. Structured programming limits and standardizes the direct transfer of program control.
  2. Object – oriented programming limits and standardizes the indirect transfer of program control.
  3. Functional programming limits and normalizes assignment in programs.

Chapter 4 structured programming

The peculiarity of scientific theories and laws: they can be falsified, but there is no way to prove them.

Scientific methodology does not need to prove that a conclusion is true; it needs to find a way to prove it wrong. If a conclusion cannot be falsified after a certain amount of effort, we assume that it is true enough for the moment.

Bohm and Jocopini showed that one could construct any program using three structures: sequential structure, branch structure, and loop structure.

Dijkstra believed that programmers could prove their programs by reasoning like mathematicians. They could connect some structures that had been proved to be usable with codes. As long as the external codes were proved to be correct by themselves, the correctness of the whole program could be deduced.

Some uses of the earliest go to statements resulted in a module that could not be recursively broken down into smaller, provable units.

The most valuable thing about the structured programming paradigm is that it gives us the ability to create units of falsifiable program. This is why functional degradation is still one of the best practices in architectural design.

This brings me to the root of the relationship between “100% test coverage” and “no bugs” :

Dikstra once said, “A test can only show the existence of a Bug, but not prove its absence.” In other words, a program can be proved wrong by a test, but it cannot be proved correct. The purpose of testing is to conclude that a program is sufficient to achieve the current goal.

Chapter 5 object oriented programming

Three features of object-oriented programming:

  1. A wrapper can enclose a set of related data and functions so that only part of the function is visible to the code outside the wrapper and the data is not visible at all.
  2. The main purpose of inheritance is to allow us to override a set of externally defined variables and functions in a scope.
  3. Polymorphism is the ability to have many different manifestations or forms of the same behavior.

Polymorphism solves dependency inversion problems: for example, implementing a player function requires that audio and video can be played; Audio and audio respectively rely on their own stream reception, decoding, playback functions, in the absence of the concept of polymorphism, to introduce audio and video in the playback function of their respective stream reception, decoding, playback and other functions, in other words, these underlying implementation functions are the strong dependence of the player function.

With object-oriented polymorphism, video and audio become two separate parser objects, and players only need to distinguish between the play method of calling video and the paly method of audio according to different types. The specific internal stream receiving, decoding and other functions are all encapsulated in them, independently developed and deployed.

Take C language as an example, can realize these three features, object-oriented programming did not create new or new concepts in encapsulation, inheritance, polymorphism. But object-oriented programming languages offer the ability to use all three features more easily and safely.

Object-oriented programming is the ability to control dependencies in code by means of polymorphism. Enabling architects to decouple high-level strategic components from low-level implementation components to build plug-in architectures.

Chapter 6 Functional programming

Features: The variables in the function transformation are immutable.

Variability causes a lot of problems, and in a complex system, it would be a disaster if the underlying function could easily change an important public variable.

A well-architased application should isolate the parts of the application where state changes and those that do not need state changes into separate components, and then protect the variables with appropriate mechanisms.

The software architect should focus on putting most of the processing logic into immutable components, with as little logic for mutable state components as possible.

conclusion

  1. Structured programming limits the direct transfer of program control.
  2. Object – oriented programming limits the indirect transfer of program control.
  3. Functional programming is a restriction on assignment operations in a program.

All three programming paradigms impose new constraints on programmers. Each paradigm constrains a certain way of writing code, and none of the programming paradigms is adding new capabilities.

In other words, what we’ve learned over the past 50 years is mostly what not to do.