On the Self-cultivation of Software Engineers: Role, Refactoring and Quality

Abstract: In this article, we will discuss the role, refactoring, and quality issues in the software development process.

"Every day there are more technologies happening, every company is on the Internet, every company will become a technology company." OKTA COO and co-founder Frederic Kerrest said, because they have to find out who uses the software A better way. Software has not only become a necessity, it has become a competitive advantage. Because many companies compete around software, matters related to software development have become more important. People who develop software-software engineers are becoming more and more important.

"For knowledge, you need to know if you are thirsty; for yourself, you must be imaginary." Excellent software engineers must be the forerunners on the road of software development. Self-study is an important means of its growth. In the process of self-study, we can converge our minds through examinations, urge ourselves to study, and improve our basic qualities. It is true that principles and patterns are the cornerstones of software engineering quality. But technology is a tool and serves people, not the other way around. We can't make ourselves particularly uncomfortable just to cater to a certain technology. At the same time, in order to maximize one's abilities, a good mood is necessary, because a core factor in software engineering is the human factor.

It is true that in the software development process, we should not only cultivate our own internal skills, but also "speak with products." So, in this process, how can we ensure the quality of development? How do you focus on what you are good at during the development process? In this article, we will discuss the role, refactoring, and quality issues in the software development process.

Roles

We often mention a sentence: Revolutionary work differs only in the division of labor, and there is no distinction between high and low . The division of labor here is actually the division of roles. The role division is to minimize the workload of the individual , which can free us from red tape and focus on what we are good at . So, how should such a concept be implemented in software engineering?

Software work inside the dirty child, so hard children generally refers to technology old and some of the work had to maintain . There are also some repetitive tasks that are also called dirty work and tired work.

For this kind of work, the average engineer wants to get rid of it . The main reason is that there is little room for improvement in the skills of doing this kind of work, coupled with the obsolete technology, these skills will not be used after they are learned, and they are also relatively boring.

Engineers for this type of work are generally assigned . Need to carry out some necessary technical training for related engineers or directly recruit engineers who understand related technologies to join the work .

Efficiency and value are mainly reflected in helping customers solve problems in existing software systems or add new functions. Customers may be seldom willing to buy a brand-new system, because the price is relatively high, so they would rather spend less money to do some repair work, can solve the urgent need.

The value of operation and maintenance work is to integrate the components and systems that have been developed into a unified work . It is an important step in launching user-oriented software system products. I don't think it is leftover work.

The simpler and clearer the operation and maintenance related work, the better . This part of the related documents is generally stored in the repo of the software system in the form of read me markdown . By viewing these documents, you should be able to deploy the entire system by yourself.

System deployment is generally divided into several categories, development mode, qa mode, staging mode and production mode .

The industry has different understandings and views on the role in the software development process. The author's views are as follows:

1 . Project Product Manager is responsible for handling business needs , responsible for dealing with customers and the development team .

2. The project development team leader must be a full stack , and needs to plan as a whole , discuss requirements analysis with the project manager, and discuss development design, task allocation and development realization with the development team members.

3. The front-end engineer is responsible for web page program development, mobile phone application development, desktop application development, etc.

4. The back-end engineer is responsible for API design and development, data analysis and processing, and message push .

5. The operation and maintenance engineer is responsible for the establishment and care of the deployment environment .

6. In response to specific business needs, but also there will be more breakdown of the role categories , such as large data engineers, algorithm engineers, AI engineers, machine learning engineering, deep learning engineers,  middleware engineer.

7. The test engineer is responsible for the business requirement case test after system integration . The input of this part is the same as the input of the development team, which is the user's needs. The output is the test report corresponding to the demand case. The output of the development team is the entire software system.

Refactor

Why do we need to refactor the code and design? Mainly because we have found better practices, such as higher efficiency, easier maintenance, and so on.

We are all familiar with simple code refactoring. For example, you can do some sorting through tools.

Generally speaking, refactoring is to solve the problem of complexity .

One of the more troublesome topics now is the reconstruction of old products. Some old products involve tens of millions of lines of code.

Regarding the rectification of old products. If it is just sewing and mending, it may not achieve the purpose of simplifying the complexity. In fact, if you do similar work, there is a more feasible plan. It is to treat the existing product as a molding system, that is, an existing running product. Do not make major changes, at most, fix bugs.

Then use these formed systems as a benchmark to write new systems. It is equivalent to writing a small white box with reference to a large white box. In this way, the new small white box will definitely have an advantage over the performance of the large white box.

If you do it step by step like this, it will be more reliable.

Some friends will say that the above method is a rewrite, which is correct in the literal sense.

Actually not contradictory. The difference is that the method of reconstruction should be from bottom to top or from top to bottom . For example, most of our current reconstructions are understood to be done from the bottom up . That is to say, there is a smell of bad code in this file, and then I change this file. This is no problem. The premise is that the context of this work is relatively simple and there is no technical debt.

Many situations are not so lucky. For example, the problem that some people encounter now is that the context is not very clear. Why is this code written like this? Why a file has 10,000 or 30,000 lines? The ins and outs are not very clear .

At this time, it may be necessary to conduct a top-down analysis from the entire sub-module . Sort out the functional requirements of this sub-module and how many public interfaces are needed? Should the internal public interface be implemented as it is now?

A file can be written into 10,000 lines or 30,000 lines, there must be some historical reasons, and to a large extent it is caused by insufficient programming ability to grasp the overall situation.

In this case, it is very difficult to refactor from the file itself, but it may be easier to refactor from the perspective of the entire design of the module from top to bottom.

For such a behemoth, the best way is to divide and conquer . First of all, we must determine the functional logic points of the system. For these logic points, we must arrange the corresponding inspection points. That is to say, after we have completed the reconstruction, we must ensure that our reconstruction is correct. These inspection points are done This, we can understand it as an integrated test .

The tests of these integration classes must ensure that they can run normally on the current system before refactoring .

With this facility, we can carry out our reconstruction work. There are many refactoring methods, such as using better tools, changing the naming of functions and variables, and changing the calling method. These are refactorings based on the existing code . Here we focus on rewriting the way to achieve reconstruction. The so-called rewriting is to open up another code base . You can even choose different programming languages.

In this case, the reconstruction must first reuse the existing business logic to achieve a 100% pass rate for the business logic integration test .

Regardless of which method is adopted, it must be advanced module by module. One verification is one. Don't rush for success and try to solve certain problems at once. If there are many failures, it may wear down your confidence. Therefore, we must move forward little by little, always in progress . After adopting this method, no matter how large the current system is, as long as you stick to it, you will be able to completely complete the reconstruction work.

The specific steps that need to be done at this time can refer to the following:

1. Define public interfaces according to functional requirements.

2. Write the test case code according to the public interface.

3. At this time, you can fill in the code according to the concept of test-driven development.

4. The code can be extracted from the existing code.

5. Organize and reconstruct during the extraction process.

In this way, after this submodule is completed, you can try to replace the existing submodule to see if it can run safely in the entire system.

For the entire system, we can divide it into many sub-modules. Then each sub-module can be broken down to complete the reconstruction of the entire system .

If the entire system is refactored at the beginning, it can also be viewed from a top-down perspective .

For example, at the beginning, consider all sub-modules as some placeholders, assuming they have completed their interfaces. For the entire system, it itself is a sub-module, which belongs to the module under the outline.

This process can be understood as rewriting in a literal sense. In fact, it is also a refactoring process, because we will definitely reuse some existing codes and existing logic of the system itself.

Above we assume that the system has been refactored after it has been completed. In fact, refactoring can run through the entire software development process . The primary goal of software development is to implement business logic and be able to solve customer problems. After this goal is achieved, we will pursue code cleanliness, complexity can be minimized, and current technology can be used to the most advanced.

So whenever there is a chance, we should refactor the code and design.

quality

Quality is directly related to whether customers are satisfied with our products . So how should we ensure the quality of software development?

The quality must be guaranteed by following the consensus of the entire development team . Consensus is a term that can be large or small, ranging from ideals, philosophy, and outlook on life; as small as software design principles, design patterns, and code styles. If it is to build a team, that is the long-term goal, and the consensus must start from the general direction . If it is only for the development of a project, the consensus can start from specific details .

Assurance of software quality requires the entire team to form a consensus , and everyone follows this consensus . This consensus is embodied in the development principles, design patterns and codes, specifically in the architecture code and template code . In the initial development stage of the project , the development speed must be slow, in order to establish the consensus part of the code after repeated deliberation and consolidation . Get up .

The goal of style is that no matter how many people there are on the team , the code written is just like the code of one person, and the style is consistent .

The quality of the code is also reflected in the complexity. The goal of complexity is that under current technical conditions , the complexity of the current code should be the lowest .

Another important indicator of software quality is the white box testability of the code . Testing framework should be in the beginning of the project to take up . When part of the code takes shape , gradually add the necessary test cases . The selection of test cases can be determined according to the calculation method of the loop complexity , or according to the user requirements corresponding to the integration test .

Next, let's talk more about testing in software development . Code-related tests generally include unit tests, integration tests and system-level tests .

Unit testing is generally considered very cumbersome . The cumbersomeness of unit testing is mainly reflected in the selection of test cases . If the full coverage method is used to select test cases , a large amount of test code will be generated, which is also a burden for future maintenance. If the ring complexity is used to select the test cases , an appropriate amount of test code will be generated, but the calculation of the ring complexity is also a big time overhead.

Integration testing is related to the actual business needs of customers . In this process, it is necessary to clarify the input and output of the interface, as well as the running path, and then design the test case accordingly and write the test case code.

Developers generally do not refuse to write integration tests . Because the benefits it brings are tangible, it will greatly improve your development efficiency and debugging efficiency. Especially for non-interface programming interface is particularly important.

System-level testing is the integration test between subsystems in a large system. This mainly includes two aspects:

One aspect is automated testing with an interface. Through such a testing architecture, the use process of human users is simulated, and some random behaviors are added to try to find some vulnerabilities in the system.

The other is interfaceless testing, which is reflected in calls between multiple service systems or the use of similar browser automation frameworks.

A complete test system can help engineers improve development efficiency and reduce future system maintenance and reconstruction costs .

In terms of the urgency of testing, integration testing is the most necessary. Testing between systems is sometimes replaced by manual testing with some testing tools. Unit testing can have a very broad discussion space, this part requires specific analysis of specific issues.

It is meaningless to write test code just to cope with inspections .

If the test code does not play its due value , writing test code is meaningless .

Engineers are the main executors of high-quality software . The project team leader, architect and development manager are the escorts and guardians of high-quality software .

Therefore, engineers should not be allowed to ensure software quality from the bottom up. This requirement is too high for engineers.

summary

Finally, let me mention the engineering culture and the spirit of ownership. As for the connotation of engineer culture, I think it includes the following points:

  • (1) The spirit of craftsman, who has the enthusiasm for what he does.
  • (2) Trial and error culture, have the courage to try, and are willing to be the first person to eat crabs.
  • (3) Self-discipline, this self-discipline refers to "My day and my body". Continuous self-correction and self-reflection improvement.

As for the spirit of ownership, no matter what job you do, as long as you want to give full play to your abilities and really do something, no matter what your level or salary is, in simple terms, you always take what you do as your own. Otherwise, we always care about everything and we can't do our best when we do things.

If we have a mentality of suffering from gains and losses, our work efficiency will decrease. Over time, not only will I not be able to make the "big money" I want to make, but it will also hinder my ability and mood improvement. Time is precious and really should not be wasted.

There are many specific manifestations of the spirit of ownership, such as: never saying "this is not my business"; doing things without sacrificing long-term interests for short-term interests; and so on.

Through this article, the author sorted out the experience and experience of working in software for more than 20 years, hoping to bring you some meaningful enlightenment.

 

Click to follow and learn about Huawei Cloud's fresh technology for the first time~

Guess you like

Origin blog.csdn.net/devcloud/article/details/108997795