In this article, we’ll look at roles, refactoring, and quality in the software development process.

“More technology is happening every day, every company is on the Internet, every company is going to be a technology company.” Because they had to figure out a better way to use the software, says Frederic Kerrest, chief operating officer and co-founder of OKTA. Software has become not just a necessity, but a competitive advantage. As so many companies compete around software, software developing-related issues become more important. The people who develop software — software engineers — are becoming more important.

“For knowledge, be hungry; Be modest about yourself.” A good software engineer must be a forerunner 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 thoughts and urge ourselves to study by means of examinations, so as to improve our basic quality. Admittedly, principles and patterns are the cornerstones of software engineering quality. But technology is a tool for people, not the other way around. We can’t make ourselves particularly uncomfortable by being tied down to cater to certain technologies. At the same time, to maximize your capabilities, a good mood is a must, because a core element in software engineering is the human factor.

Of course, in software development, we should not only improve our own internal skills, but also “let the product speak”. So how do we ensure the quality of development in this process? How do you focus on what you’re good at during development? In this article, we’ll explore roles, refactoring, and quality in the software development process.

role

We often say that revolutionary work consists only in the division of labor, and there is no distinction between high and low. The division of labor here is the division of roles. Role division is designed to minimize the workload of individuals, freeing us from red tape and focusing on what we’re good at. So, in software engineering, how should such a concept be implemented?

The dirty work in software work generally refers to the work that has to be maintained because the technology is old. Other types of repetitive work are also called dirty work.

The usual engineer would try to get out of this kind of work. The main reason is that there is little room for technical improvement in this kind of work, and the technology is old, so these skills will not be used after learning them, and they are also boring.

Engineers for this kind of work are usually assigned. It is necessary to provide some necessary technical training to the relevant engineers or directly recruit the engineers who know the relevant technology to join the work.

Efficiency and value can be found in helping customers solve problems in existing software systems or adding new features. Customers may be less willing to buy a brand new system because the price is relatively high, so they would rather spend less money to do some tinkering, as long as they can solve the immediate need.

The value of operation and maintenance work is the integration of developed components and systems. It is an important step to launch software system products facing users. I don’t think it’s a side job.

The more concise and clear the o&M work, the better. This part of the related documentation is typically stored in the repO of the software system in the form of a Read Me Markdown. By looking at these documents, you should be able to deploy the entire system yourself.

There are several types of system deployment: development mode, QA mode, staging mode, and production mode.

The industry has different understandings and views on the role of software development. The author’s views are as follows:

1**. The project product manager is responsible for handling business requirements ** and dealing with customers and development teams.

2. The project development team leader must be a full stack, which requires overall planning, discussing requirements analysis with the project manager, development design, task allocation and development implementation with the development team members.

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

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

5. O&m engineers are responsible for setting up and maintaining the deployment environment.

6. For specific business needs, there will be more subdivided role categories, such as big data engineer, algorithm engineer, AI engineer, machine learning engineer, deep learning engineer, middleware engineer.

7. Test engineer is responsible for business requirement case test after system integration. This part of the input is the same as the development team input, is the user requirements. The output is the test report corresponding to the requirements case. The output of the development team is the entire software system.

refactoring

Why do we need to refactor code and design? Mainly because we found better practices, such as more efficient, easier to maintain and so on.

Simple code refactoring is something we’re all familiar with, such as tools that you can use to do some refactoring.

In general, refactoring is about complexity.

One of the most vexing topics right now is refactoring older products, some of which involve tens of millions, hundreds of millions of lines of code.

Problems about the rectification of old products. If you just sew, you may not achieve the purpose of simplifying complexity. In fact, there is a feasible solution for this kind of work. The idea is to treat an existing product as a formalized system, as an existing product, and not make major changes, but just fix bugs.

Then write new systems based on those formed systems. It is equivalent to referring to a large white box to write a small white box, so that the new small white box quality must be better than the performance of the large white box.

This way step by step to do, will be more reliable.

Some friends would say that the above is rewriting, which is literally true.

Actually there is no contradiction. The difference is whether you refactor from the bottom up or from the top down. For example, most of our current refactoring is understood to be done from the bottom up. It’s okay to change a file that smells like bad code. The premise is that the context of the work is pure and there is no technical debt.

A lot of times it’s not so lucky, like the problem that some people have now, is that the context is not very clear, why is this code written this way? The context of why a file has 10, 000 or 30, 000 lines is not clear.

At this point, a top-down analysis may be required from the entire submodule. Figure out what the functional requirements of this submodule are. How many common interfaces do you need? Should the internal public interface be implemented as it is now?

There must be some historical reason why a file can be written in 10,000 or 30,000 lines, mostly due to poor programming ability to grasp the global situation.

In this case, it would be difficult to refactor from the file itself, but it would be easier to refactor from the top down, from the overall design of the module.

The best thing to do with a behemoth like this is divide and conquer. First of all, we need to determine the functional logic points of the system. For these logic points, we need to arrange the corresponding test points. That is to say, after we complete the refactoring, we need to make sure that our refactoring is ok.

The tests for these integration classes must ensure that they run properly on the current, pre-refactoring system.

With this facility in place, we can begin our refactoring work. There are many ways to refactor, such as using better tools, changing the names of functions and variables, changing the way they are called, and so on. These are refactorings based on existing code. Here we focus on rewriting to implement refactoring. By rewriting, we mean opening up another code base. You can even choose a different programming language.

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

No matter which way is used, we should advance module by module. Verification is one thing at a time. Don’t try to do things all at once. If you fail too many times, your self-confidence may be eroded. So we must move forward bit by bit, always in the process of progress. With this approach, no matter how big the current system is, if you keep doing it, you’ll be able to get the refactoring done.

In this case, you can refer to the following steps:

1. Define public interfaces based on functional requirements.

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

3. This is the time to populate your code with test-driven development concepts.

4. Code can be extracted from existing code.

5. Organize and reconstruct in the extraction process.

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

For the whole system, we can be divided into many sub-modules. Then we can destroy each sub-module and finally complete the reconstruction of the whole system.

If you refactor the entire system from the beginning, you can do it from a top-down perspective.

For example, start by treating all submodules as placeholders, assuming they have completed their interfaces. It is itself a submodule of the system, a module that is quintessential.

This process, literally rewrite, is actually a refactoring process, because we will definitely reuse some of the existing code and logic of the system itself.

The above refactoring assumes that the system is already complete, but refactoring can occur throughout software development. The primary goal of software development is to achieve business logic that can solve customer problems. Once this goal is achieved, we aim for code that is clean, minimizes complexity, and uses the most advanced technology available.

So we should refactor code and design whenever possible.

The quality of

Quality has a direct bearing on whether customers are satisfied with our products. So how do we ensure the quality of software development?

Quality is guaranteed by following the consensus of the entire development team. Consensus is a term that can be as big as an ideal, a philosophy, an outlook on life; Down to software design principles, design patterns, code styles. If it is to build a team that is a long-term goal, consensus must start from the general direction. If it’s just to develop a project, consensus can start with the specifics.

The assurance of software quality requires that the entire team form a consensus that everyone follows. This consensus is reflected in the development principles, design patterns and codes, specifically in the framework 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 review and tamp.

The stylistic goal is that no matter how many people on the team, the code will be as consistent as the code of one person.

The quality of the code is also reflected in its complexity. The goal of complexity is that the current code should be minimal given the current technology.

Another important indicator of software quality is white-box testability of code. The framework for testing should be put together at the beginning of the project. As 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 ring complexity, or according to the user requirements corresponding to the integration test.

Let’s take a closer look at testing in software development. Code related tests are generally unit tests, integration tests, and system level tests.

Unit testing, in general, is considered tedious. The tedious 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 number of test codes will be generated, which is also a burden to maintain in the future. Selecting test cases using ring complexity can generate a reasonable amount of test code, but the calculation of ring complexity is also a large time cost.

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

Developers generally do not refuse to write integration tests. Because the benefits it brings are real, will greatly improve your development efficiency and debugging efficiency. This is especially important for unbounded programming interfaces.

System-level testing is an integration test between sub-systems of a large system. There are two main aspects to this:

** One aspect is automated testing with interface. ** Through such testing framework, it simulates the use process of human users and adds some random behaviors to try to find some loopholes in the system.

** The other is unbounded testing, which is embodied in calls between multiple service systems or the use of frameworks such as browser automation.

A complete test system can help engineers improve development efficiency and reduce the cost of system maintenance and reconstruction in the future.

In terms of the urgency of testing, integration testing is the most necessary, and inter-system testing is sometimes replaced by manual testing through some testing tools. Unit testing has a lot of room for discussion, and it’s a case-by-case approach.

There is no point in writing test code just to cope with inspections.

There’s no point writing test code if it’s not doing what it should be doing.

Engineers are the primary enforcers of software quality. Project leaders, architects, and development managers are the guardians and guardians of high software quality.

Therefore, it is too high for engineers to allow engineers to ensure software quality from the bottom up.

summary

Finally, engineer culture and ownership. As for the connotation of engineer culture, I think it includes the following points:

  • (1) Craftsman spirit, dedicated to what we do.
  • (2) Culture of trial and error, dare to experiment, willing to be the first to eat crab.
  • (3) Self-discipline, this self-discipline refers to “I save my body three times a day”. Constant self – correcting reflection improves.

For the spirit of ownership, no matter what work, as long as you want to give full play to their ability, really do something, no matter how level, salary, simply said, is the moment to do things as their own things to do. Otherwise, we won’t be able to put our best foot forward when we do things.

If we have a worry about gain and loss mentality, our work efficiency will decline. Over time, not only can not earn the “big money” you want to earn, but also hinder the improvement of your ability and mood. It can be said that you have picked up the sesame seed and lost the watermelon. Time is too precious to waste.

There are many concrete signs of ownership, such as never saying “this is not my business”; Do not sacrifice long-term interests for short-term gains; And so on.

Through this article, the author combs the experience that is engaged in software work for more than 20 years, hope can bring some meaningful enlightenment to everybody.

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