In the past, like most engineers, I thought that the design of front-end code was mostly directly related to the ability of the engineer. But as I’ve worked on several large front-end projects with multiple people working together, I’ve come to realize that while this may be true for small projects with short life cycles, for really large projects, improving the quality of engineers alone sometimes doesn’t directly improve the quality of the code.
This article will combine some of my practical experience to illustrate my point of view: reasonable code constraints and correct team operation mechanism may be more important in building large and high-quality front-end projects.
What is high quality engineering code?
High quality engineering code is not equivalent to the best performance, the latest technology, the most reusable technology selection. Back in the days of JQuery, you had to manipulate the DOM by hand, but back then Google Closure and the Ext.js team provided complete componentization concepts and even innovative event mechanisms like component bubbling. The code maintained with Zepto at the time was even faster than some React projects are today. Different technologies are just tools. How to use the tools and to what extent the tools can be used ultimately depends on the developers themselves. Therefore, high-quality engineering code should be considered from the perspective of business and engineering rather than technology selection.
For example, when the whole company was developing with React, we knew that Vue would be easier and easier to use, but we definitely didn’t use it. At that time, although it seemed easier to write code, you couldn’t reuse other people’s experience in React. In addition, the whole team is required to learn a new set of technology. Such engineering design, in this context, is obviously unreasonable.
According to Thenewstack’s developer stats for 2019, developers spend 32% of their time on business development and 19% on code maintenance, which means that engineers spend half as much time on development as they do on work. For developers, it is the strongest appeal to improve the extensibility and maintainability of the code and reduce the time of developing and maintaining the code through reasonable code design at this time.
Therefore, high-quality engineering code should be combined with the business and team situation, can really improve the efficiency of research and development, reduce the cost of project maintenance code.
Who determines the quality of project code?
An analogy can be made with the barrel theory: the water level in the barrel does not depend on the highest board, but on the lowest board. Similarly, the quality of front end engineering depends not on the average ability of the team, but on the ability of the less experienced technical students on the team. In the case of high work pressure, due to their lack of experience and short term requirements, most of the time, they did not consider engineering problems, but directly oriented to the implementation of functional programming. Basically, the code that we are facing now is generated under such conditions.
We can certainly hope that the less experienced students can improve the engineering quality of the project through continuous growth, but in practice, this is not feasible. The reason is that the accumulation of engineering ability requires a lot of coding experience. The problem of lack of practical experience can not be solved quickly in a short period of time. Any good engineer grows up in the process of making mistakes and learning. At the same time, the project development process is likely to encounter personnel changes, a team members can not always be highly competent.
Then we need to change a strategy to ensure the quality of our code. We can think from another perspective: can we make engineers with different coding abilities write consistent code with relatively high quality through some rules, procedures and coding constraints?
Improve project quality through constraints
Constraints make things easier
Without constraints, it’s hard to form a consensus at work and judge whether we’re doing a good job or not. The same goes for writing code. Without constraints, we can’t tell if the code makes sense. Constraints are ubiquitous in popular libraries and frameworks, such as Redux and React:
Redux provides a single data source, State read-only, and uses pure functions to implement the three basic principles of modification. Meanwhile, it requires the Reducer to be triggered by Action, which is the constraint of Redux. React also gives the concept of constraints such as one-way data flow.
Frameworks are reusable and scalable because they encapsulate, providing only limited constraints that people can use so that they can form a consistent idea and write code that can be read by each other. With this in mind, business engineering code is actually about providing reasonable constraints to make development more efficient and scalable.
Project code constraints, more with certain project attributes, such as:
- Specify that the same request address is allowed only once in the API layer (the number of project interfaces reduces code redundancy)
- Do not use more than 100 lines of Hook code (enhance logic splitting and avoid overly complex logic)
- When choosing between reusability and maintainability, prioritize maintainability (avoiding false encapsulation, coupling a lot of logical judgment in encapsulated code)
- Business code comment coverage must exceed 10% (code readability for automated document generation)
- Cross-component communication in a project must be via Redux (team understanding costs for reducing component-passing code)
- Multiple NPM packages with the same function cannot be installed (to avoid unnecessary dependency on installation and increase maintenance costs).
These business constraints are not the same as Eslint, and different businesses may have different requirements for code, so business constraints need to be fully communicated, discussed and firmly implemented by developers. Students in different teams may discuss different results, but it is not important what the constraint conclusion is, what is important is to form a consistent development consensus.
The landing of constraints is achieved through mechanisms
The constraint itself is not difficult to formulate, for engineering design, engineers through discussion is easier to form a conclusion after the game. But landing the mechanism is a relatively difficult part. Here are some of the safeguards that can be implemented:
- CodeReview (Each CR, in addition to the logical analysis of the business, also needs to comply with constraints as part of the audit)
- Automatically generate parts of the code using tools (such as scaffolding a module in the project code, directives like AngularCLI ng G Component header help you constrain the structure of the component-created code)
- Configuration generates code (through configuration, generating logic or form code, establishing configuration item standards)
- Zero code/PaaS platform (the platform generates code, directly isolates users from the code, and the platform guarantees the quality of the generated code)
- Responsible person mechanism (Constraint landing is directly related to performance and becomes a clear indicator for follow-up)
- Precipitate the document (through the document, precipitate the constraint mechanism)
By using these mechanisms to ensure that constraints are effectively implemented, we can smooth out differences in team members’ technical abilities and develop a consistent coding style. While the code under this constraint is not necessarily the most elegant code, at least the engineering quality is not bad. So here I think constraints actually help us secure the lower limit of engineering quality, so let’s talk about how we can raise the upper limit of engineering quality through technological innovation.
Seek innovation above constraints
You may ask, “Will the constraints of the project limit technological innovation?” This may be true for small projects with short life cycles, where more breakthroughs with new technologies may lead to more team expertise; However, for large projects, the code design decisions we make every day may affect the development process of tomorrow’s business system, and any technical upgrade must be careful. At this time, we should not regard constraints as an obstacle to innovation, but as a training ground for innovation.
If you’re working on a large project and you want to break the rules, use new technology, and innovate, it definitely means doing the following things:
- Have a good understanding of the context of the constraints of the past: the context has not changed, and whether new technologies can solve the problems the constraints solve without creating new ones
- Articulate the value of new technology: Consensus on whether the new technology will have a significant impact on performance, stability, experience, r&d efficiency, and business performance
- Be able to give an overall plan for the technology upgrade: when confirming the technology upgrade, have you considered how the historical technical plan gracefully implemented the replacement
- Be able to convince the team to agree on new technology upgrades: Based on existing technology, can you convince team members to move forward with you
- Ability to lead a team or deliver a technical solution yourself: Do you have the ability to deliver a new technology or innovation
Most of the time, the technological innovation we do is just the update of the technology stack, without bringing any value to the team or the business side. However, when we think clearly about these problems and can convincingly prove that the new technology or innovation point is valuable, the upgrade of the system may be really valuable.
Innovation in constraints can make engineers think more in combination with business and produce truly valuable innovation. Such quality thinking and innovation determines the upper limit of engineering quality and cultivates more excellent engineers.
How to improve the quality of existing projects?
For a new large-scale project, we can carry out architecture design and optimization in stages through the above method. However, most of the time, we take on projects that may be found to be of low engineering quality when we take over, so how can we improve the existing code?
Determine if your system needs improvement
The life cycle of a system can be summarized as three stages:
- Development period: The business develops rapidly
- Stable: The business situation is stable
- Recession: Businesses close and turn around
For the system in the development stage and the system in the stable stage, reasonable engineering design can bring obvious benefits in performance, stability and other aspects in the future. At this time, we can consider to upgrade the system. For the system in the decline period, although the short-term development and maintenance efficiency is not high, but the development potential of the future system cannot be seen, in this case, it may be a better choice to continue to maintain the old system. Not every system has to be improved, and excellence is great, but it comes back to business value.
How to make engineering improvements
Engineering improvement of large-scale projects can be divided into two ways: top-down and bottom-up. For large projects, total top-down refactoring is expensive and not recommended unless you know the system very well. On the contrary, current mainstream frameworks like React and Vue can host local DOM, so bottom-up upgrade may be a better strategy. This approach has two advantages: low cost and low risk. For an example in their engineering, we need to put the JQuery upgrade to React, adopted this way, step by step up the Backbone of the JQuery code to replace:
export default View.extend({
componentName: 'AuctionDetailContainer'.initialize(options) {
const { dataSchemaV1, pageSchema } = options;
this.ref = React.createRef();
this.dataSchemaV1 = dataSchemaV1;
this.children = pageSchema.getChildren()[0];
this.attributes = pageSchema.getAttributes() || {};
},
render() {
ReactDOM.render((
<AuctionDetailContainerWithRef
ref={this.ref}
taskFields={this.dataSchemaV1}
attributes={this.attributes}
crossTableData={this.children}
/>
), this.$el[0]);
return this; }});Copy the code
For each replacement, we only need to test the logic of the replacement part, without affecting other external logic. In this way, layer by layer replacement achieves a good balance under the bi-directional requirements of ensuring stability and system upgrade. At the same time, when you take on new projects, this kind of upgrading method can gradually help you sort out the business logic and understand the business.
In this process of gradual replacement, combined with the coding constraints mentioned earlier, we can gradually improve the code quality of the system. After that, the project can be further optimized in innovative ways to complete the refactoring process.
There are some tools that can also help us in this process, just to name a few:
- CommintLint + SemVer semantic version number control specification: Helps teams identify risks associated with refactoring and saves communication costs
- Front-end automated testing tools: ensure engineering quality through unit testing and reduce the probability of regression errors
- Chrome Coverage: Code execution analysis tool that helps you find useless code and comb through project logic
conclusion
The specific coding content involved in this article is not much, I hope to bring you some engineering test inspiration and thinking from another aspect, some conflicts of views are also welcome to communicate and discuss.
The article can be reproduced at will, but please keep this link to the original text.
You are welcome to join ES2049 Studio. Please send your resume to [email protected].