Novice and experienced developers alike often ask the question, “How do I write good code?” To know how to write good code, we first need to know what good code is. You must have a clear goal in order to know how to achieve it. The “ETC Principle” mentioned in The “How to Be a Programmer” — the easy to adapt Principle. This principle seems simple, but the more we think about it, the more we realize that simplicity is not simple.

In this article, we’ll go into the details of why it is “easy to adapt” in real product development and how it can be done so that we can write better code.

Why does “ONE” program need to be “easy to adapt”?

Why does code have to be easy to adapt? Because a system will follow the development of a product, the daily growth of users will have endless demand. As long as the company is running the product, the requirements will change as the company grows. As long as we developers keep up with the new technology, we need to keep improving.

Only by understanding exactly what drives our programs to change over the course of a system’s life cycle can we better understand why our code needs to be “easily adapted.”

Demand will be

No matter what system we develop, product requirements change all the time. This is the eternal fate. Why is that?

  1. Product direction — with the marketing, operation and development of the product, the requirements of the product will be constantly added, modified and optimized.
  2. Usage – with the level of users, data, and concurrency of the product, it also drives changes in application architecture and strategy.
  3. Technology upgrades and optimizations – even the language, framework, dependency packages we use can cause our code to adapt.
  4. Technical debt – previous code was heavier than implementation and of poor quality, probably due to time constraints.

So our code is constantly iterated and optimized over time.

“Rapid change” is the core of a software

In recent years, many technical teams have adopted the agile iterative development model. What is an Agile iteration?

Agile iterations are about shortening the development cycle to 1-4 weeks. Quick, iterative, incremental delivery features live. The process of agile iteration is as follows:

  1. Identify requirements – Confirm requirements and processes with boss and marketing
  2. Requirements review – function points and business processes in parallel with the development of requirements
  3. Technical reverse – development and product frequency requirements, to ensure that both parties understand the misunderstanding, development also needs to assess the difficulty of development and development time
  4. Development cycle – Developers begin to invest in development directly to the completion of features and requirements, which are handed over to testing and tested in the test environment
  5. Test cycle – Testers and developers begin to troubleshoot defects and fix any bugs that arise during development
  6. Acceptance/pre-release cycle – After testing has eliminated all bugs in the test environment, the current iteration is released to the pre-release environment for market and product acceptance
  7. Release formal – When accepted, the current iteration can be deployed to a formal environment
  8. Formal regression testing – After launch, there will be formal regression testing, the last line of defense, to ensure that all new features added to the system are fine
  9. Iteration summary – At the end of each iteration, summarize the problems encountered in this iteration, continue to optimize, and improve efficiency

Think about an APP or system that only gets new features and upgrades every few months or even a year. In fact, it is boring for us to use, and we may even find many problems. There are also many functions that can facilitate or improve our use experience. But after such a long time, do we still hold out hope for this product? (Except for wechat, which is already very mature, but even wechat is constantly updated).

So a good product is one that needs to iterate quickly, in small steps, and deliver quickly. Because of this, features need to be constantly updated, upgraded, and optimized. Naturally, the code we develop needs to be constantly adapted as the product changes. And it will still be updated and optimized every 1-4 weeks.

๐Ÿ† To summarize:

  • A system is constantly changing and updating as the product evolves and iterates.
  • Because the system changes all the time, the code needs to respond to the changes in the system, continuous rapid iteration upgrades and optimizations.
  • Since the code needs to be changed and updated quickly, the program must be “easy to adapt”.

“Two” how to achieve “easy to adapt”?

We have a good understanding of why systems change all the time, so we need to know how to write code so that a program is “easy to adapt” while responding quickly to changing requirements in agile iterations. If we want to make it easier to write programs that respond to changing requirements, business, and logic, we need to give our programs enough logic.

When it comes to the decomposition of logic and business, we should first think deeply and analyze the requirements and functions, and then design an architecture for them. The most common way is to modular system, componentized system architecture design.

Modular Design — “Modular Design”

Module design, is to carry on the program design with the function block as the unit, the method that realizes its solution algorithm is called modularization. The purpose of modularization is to reduce the complexity of the program and simplify the operation of program design, debugging and maintenance.

We have modular and component design patterns for both front-end and back-end development. Using modular design to break down our functionality and logic, the goal is to reduce the complexity of the program, facilitate debugging, maintenance, modification, and new functionality.

For example, now we are going to make a CMS (content management system), and we are going to try to use module design to break down the functionality of the system.


Design ideas

First we need to understand what a content management system does, and then break each function down into its modules. But many children’s shoes at the beginning of contact with a system, and then began to carve up the module will feel unable to start, may spend a long time sitting in front of the computer thinking ๐Ÿค”, but a long time can not spit out a reason. Next, let’s learn a set of logical thinking together, so that we can more easily structure a set of module design!


Start by thinking about the purpose and usage scenarios of the system. What is the system used for?

A content management system, generally used for publishing articles, news, or content management of an official website. There must be articles. So what’s the function of managing the content?

Article module “Article module”

  • Add, delete, check and revise articles
  • The article drafts
  • The article set-top

Article Sub-module — Category “Article Category Module”

  • Add delete check change classification
  • The article images

Can these functions related to articles be managed in the “Article” module? Then there is a sub-module of Article classification called “Category” in the “Article” module.


Have article must need to have the author, that author is actually a user in the system. Then we need to have a user module. Add a management system, and you must have administrators, authors, and even members. Going through this logic we find that there should be the following function points.

User module “User module”

  • Users add, delete, check and modify
  • User identity Management
  • User Rights Management
  • Membership level Management

This allows us to create a separate User module. This module mainly manages user – related information and functions.


Seeing here we should have some idea of the modular idea of a system. At this time, the product manager came to us and put forward a demand, “We are going to add a label system to this system, which is specially used to manage article labels.” .

So kids, which module do you think this requirement should go into? ๐Ÿค”…

And you were right! ๐ŸŽ‰ this is a sub-module of articles, the Tag module, which manages the tags of articles and has many-to-many relationships with each article. So the tag module goes into the article module. If our content management system is made big, it has video content, graphic articles and so on. We can start by grouping all of these together into a “Content module,” aka the Content module.


Front-end module design

Said here the front of the children’s shoes estimated to raise their hands ๐Ÿ™‹โ™‚๏ธ, the front of our attention! “The front end is based on pages and interactions. You can’t break down modules by functional logic like the back end, right?” — What the child said is reasonable. The design of the front end is slightly different from that of the back end.

The back end breaks down the modules in business logic, but the front end has code for both page and data logic. So the front end relative to the back end will separate two kinds of module decomposition ideas.

Page (row) surface (version) module design

  • Front-end page modules and product-defined system modules are more appropriate. The modules decomposed by the front end are grouped with the operational functions that the user sees.
  • Simple module decomposition, you can use the product to our navigation to decompose, so that it will be more reasonable to organize our page module.
  • If you want to further refine the page function, you can use itComponent designLet’s break it down.

Front-end logic module design

  • A few years ago, the front end was a “graph cutter”, with little concern for business logic, data logic, data interaction and other technical areas. But because of the separation of the front and back ends, it has now become the r&d strategy of most companies. Over time, both the front and back ends split the processing of business logic and data interaction.

  • Because there is also a lot of business logic and interaction logic in the front end, when we encapsulate and decouple, we will also encounter the need to decompose modules to deal with. The most typical example is when using Vue’s state management Vuex, which requires module management to break down the logic and make it easier to maintain and modify later.

  • In fact, the front end is to use the same set of thinking mode of the back end to decompose the business can, to function as a unit to decompose your module can.


Decoupling – “Decoupling”

Decoupling is the breaking down of complex logic into smaller pieces. In this way, the complex logic is decomposed into small logic processing, which makes the logic more simplified and easier to debug and maintain.

In a system with many functions, complex business and many system modules, the code in each module will also become bloated and become more and more difficult to debug, maintain and manage. In fact, modularity and decoupling are consistent. Modularity is also for decoupling your program. (95) Here we focus on decoupling between modules and logic.

I want to share an experience that really brings home the importance of decoupling. One of the most dramatic I’ve ever encountered was a logic that wrote 5000 lines of code, but what’s even scarier is that 5000 lines of code were copied and pasted in the same place. ๐Ÿ˜ฑ my goodness, this kid has a flower in the r&d team named “copy brother”. However, with everyone’s help and suggestions, he became an excellent programmer in the group.


If we don’t know how to decouple code, the code we write will leave us with heavy “technical debt” down the road. Let’s say your 5,000 lines of processing logic are used in dozens of places. It’s sad that we have to change that logic. Even if the logic is not reusable, it can be a headache when you have to go back and modify it. Even a small change in this logic could result in 10 bugs.

We know the importance of decoupling, so how can we decouple code efficiently?

In Design by Contract, we write “shy” code, which is helpful. Shy has two meanings: “Don’t expose yourself to others” and “don’t interact with too many people.” What does this mean? Let’s use examples from the book to understand this.

In a large spy organization, agents are divided into small groups, and the agents in each group basically know each other, but the agents in each group don’t know each other. If an agent is captured, one group may be destroyed, but the agents of other groups will not be exposed or affected. Because the relationships between the groups are absolutely isolated. But in the task, each group will cooperate and help each other, but do not know each other. That’s why such a large espionage operation can survive safely for so long.

This kind of isolation mode is great for programming. Decouple our code into relatively independent modules and methods to minimize their relevance and impact. If there is a problem with one module or logical method, we can refactor or fix it independently without having a huge impact on the other modules. As long as the end result is consistent, you can optimize the upgrade or fix perfectly.

In the program, we need a Service to process an Object for us, or request a Service to obtain an Object. We want the Service to give us the result we need, but we don’t need to worry about how it processes and obtains the Object. The service or method runs independently, and the logic and code inside it is completely separate from the code we write. We just need to verify that the result is available when we get it, and throw an error if the result is not what we want. As long as the service makes the corresponding correction, it can continue to run.

Now that we’ve covered the theory, let’s have a practical example:

Example: Suppose we need to write a class that gets weather forecast data. To get weather forecast data, you first need to provide Geolocation location information. The Geolocation object contains an address object. It has longitude, latitude, province, city and other data. We need to get the latitude and longitude of the address in order to get accurate weather forecasts. Our code would say:

/** * Get the weather method */
public function getWeather(Geolocation $geolocation) {
	// Suppose we have encapsulated a method called getWeatherByGeo() to get the weather of the location
	return $this->getWeatherByGeo($geolocation->getLocation()->getLat());
}
Copy the code
  • We’re throughgetLocationMethod to get the address object inside the location object
  • Then throughgetLat()Methods To obtain the longitude and latitude information of the location address

In the previous example, we need to get the latitude and longitude from the Geolocation object, so we need to get the latitude and longitude from the address object. In fact, there is an unnecessary correlation. Whether it’s writing a service or writing an object method, we don’t want developers who use that service/object to over-understand and over-use your internal methods that are very relevant. This would result in multiple code changes if we changed the correlation that day.

If Liu changes the Geolocation object on that day, the Location object is no longer in it, and the getLocation() method is no longer in it, the longitude and latitude can be obtained directly from the Geolocation object. At this point, all the other people who used this object before need to change their code. Many times it’s hard to change code, or it breaks your bones to change it, because of this excessive correlation.

So, as a wrapper around a Geolocation object, we should give the method getLat() directly to the developer who calls this object:

/** * Get the weather method */
public function getWeather(Geolocation $geolocation) {
	// Suppose we have encapsulated a method called getWeatherByGeo() to get the weather of the location
	return $this->getWeatherByGeo($geolocation->getLat());
}
Copy the code

This cuts through the defect of the strong relationship in the object.


Servitization — “Service”

Service definition:

Roles: Services are the business processing layer within the system architecture. Purpose: To achieve a high degree of decoupling and encapsulation of different scenarios of business and functions to the corresponding services, while achieving a high degree of centralized business code.

To understand the service

  • Assuming thatpeopleIs aThe controllerAnd now I’ve got oneClothes objecttheparameterAnd then the person has oneWash the clothesthemethods
  • Now people need to wash clothes, but the efficiency of hand washing is too low, so we wrote a multifunctionalWashing machine serviceGive it to people to use
  • The washing machineThere are many different kinds of laundry in this servicemethodsBut in fact, people do not know how to realize every cleaning method in the specific washing machine, and they use it directly according to the function provided.
  • So all the methods in the service are decoupled from the service, and the methods that the service provides are user-friendly.

Does that make sense? So the simplest way to think about it is:

A service is used to encapsulate the business logic code, which is an independent logical layer that is highly encapsulated and decoupled and provided to controllers or other places that need to use the service.


Write the ideas

โŒ Error Example

Making all the washing machine methods available to humans is the same as letting humans determine all the washing machine parameters and cleaning procedures. When people put clothes in the washing machine, they should choose to add water first, how much water, then wash, wash for how long, and then shake dry, etc.

Just think about how many options you have to choose from to do your laundry, and what’s the right order to do it in! I’m too hard! Wash a chicken leg! (Blue ‘โ–ก ยด) Blue โŒ’ loot added

โญ•๏ธ Correct example

The washing machine service implements many different patterns commonly used for washing clothes, such as quick washing, sweater washing, carpet washing, air drying, spin drying and so on. These are common functions. Each function method actually calls many processes and methods encapsulated by washing machines. So when people use the washing machine, they do not need to know how to realize these functions, as long as they know what to do, the washing machine just has this mode, directly use the thing.

(โœง แ—œ โœง ๐Ÿ‘) wow! It’s humanized! I’ll have a dozen of these washing machines, please.

I wrote a detailed article about writing services called “Do you Really Know how to Write a service layer?” , interested children’s shoes can go to check oh. I won’t go into the details here.

conclusion

By the end of this article, we have a good idea of what the principle of easy to adapt is and how to write easy to adapt code. In fact, in the process of development, we still need to think, design, and then write. According to the functional requirements, do a good job of the program architecture design, so as to write easy to adapt the program. Only in this way can we write better and better code and get to the top of the technology!