0 x00 preface
I am a front-end engineer from the insurance business group of Ant Financial Service. I write code in the business department of a first-line factory, which is very hard but very substantial. Business code is different from framework code, personal project or open source project. It is characterized by complex logic, multiple dependencies, poor reusability, and short iteration cycle. The code written today may be offline after a week of operation. Engineers who are skilled at writing framework code and building the underlying infrastructure are not necessarily good at writing business code.
Some people say that business code is nothing more than step-by-step, elegant? Who care? . But the actual business rules are much more complex, not to be able to follow the rules of the stick to easily solve, write a bad code, may take twice the time to find and solve the problem, trouble yourself, and uncomfortable with your comrades in arms.
Sometimes in order to reduce the cost of repeated development, repeatedly refining and precipitation of reusable functionality, we need to reasonably abstract and even elaborate business code, to write elegant business code is not easy. I have always believed that the biggest difference between programming and carrying bricks is design, writing code is also an art. Today is an opportunity to share best practices for writing business code from the perspective of a front-end engineer.
0x01 Progressive refactoring
Progressive refactoring is the continuous abstraction, separation, and composition of existing code. There are two questions to answer before refactoring:
1. What kind of code needs refactoring? 2. When to refactor?Copy the code
Design doesn’t happen overnight. Sometimes, as you write, you find that some code can be taken out and used separately. Code that needs to be refactored needs to meet several conditions:
The code can be reused in the later stage. 2. The code has no side effectsCopy the code
Refactoring too early can waste a lot of time because requirements change too quickly; Refactoring late makes the risk of change too high to maintain because of complex code logic and a backlog of similar code. The incremental refactoring is shown in the figure below (the added code is shown in red) :
First of all, we added functions in the same source file, and found that part of the code has no side effects and can be separated, so we divided the code in the same file to form many modules with single function. Over and over again, as the size of the single file became larger, it was possible to pull out the modules associated with the function and put them into separate files such as helpers, Components, constants, and so on.
0x02 High cohesion and low coupling
High cohesion and low coupling have always been a constant topic in the field of software design. The goal of refactoring is to improve the cohesion of code, reduce the degree of coupling between functions, and reduce maintenance costs, especially in writing business code, which is quite important.
For example, a new demand wants to add the function of sending red packets on the existing product page to attract users to open a certain function. According to the normal logic, I need:
1. Introduce related dependencies in the current page. 2. Initialize and query the information related to the red envelopeCopy the code
The white part represents the code from the previous version, and the red part represents the code that needs to be changed to complete this requirement:
In this way, the bonus function is heavily coupled to the previous code, and if it is a temporary requirement that only needs to be up for a week, it is a high-risk move when the code is offline. If the product page needs to be iterated while it is up and running, it becomes less clear who is who. A reasonable design would look something like this:
The functional code that is not related to the product code is split into another file to maintain the entire lifecycle state internally and expose only a few interfaces or methods externally, so that the transformation of the product page requires only:
2. When the user clicks, the awarding method of the red envelope component is calledCopy the code
Such changes are minimal, unambiguous, and manageable. In other words, the entire red envelope functionality is highly cohesive and low coupled to the production code. This practice also brought another benefit: I got a reusable red envelope component!
0x03 Reasonable Redundancy
Business requirements are fluid, and so is written code, and frequent abstractions are likely to lead to overdesign, and an abstraction is likely to become complex with the number of iterations. Redundancy is a good choice in branching business scenarios where there are multiple variables, such as whether an activity is out of date, participated in an activity, or completed a task, and there are multiple nested if-else structures. Here’s an example of what reasonable redundancy is:
At the beginning, it was very simple. We needed to design two operation booths:
So abstract a component:
const Item = ({ title, content }) = > (
<div>
<h4>{title}</h4>
<p>{content}</p>
</div>
);
Copy the code
Now the demand is to add a hot message mark to the title of the first booth:
It’s also easy:
const Item = ({ title, content }, index) = > (
<div>
<h4>{title}{index === 0 && <span>hot</span>}</h4>
<p>{content}</p>
</div>
);
Copy the code
Requirements have changed again. Requirements: remove the content in the first booth, and add a button below; Add a hyperlink and a subtitle to the right of the title of the second booth:
This is a little gross:
const Item = ({ title, content }, index) = >(< div > < h4 > {title} {index = = = 0 && < span > < / span > hot} {index = = = 1 && < a href = "XXX" > to see < / a >} < / h4 > {index && = = = 1 <h5> subtitle </h5>} <p> {index! = = 0 && content} {index = = = 0 && < button > brought benefits < button >} < / p > < / div >).Copy the code
As you can see, the code is completely different from the abstraction before, and there are two states (the first and the second) in the middle. The actual situation is probably more complex than this. In cases where multi-state interweaving logic is difficult to articulate in a single set of code, reasonable redundancy is a good option. Rewrite the above example with two Ifs as follows:
// The first booth
if (index === 0) {
return(< div > < h4 > title a < span > hot < / span > < / h4 > < p > < button > brought benefits < button > < / p > < / div >). } / / second booth if (index = = = 1) {return (< div > < h4 > two < a href = "XXX" > title to see < / a > < / h4 > < h5 > subtitle < / h5 > < p > content < / p > < / div >). }Copy the code
Reasonable redundancy is actually a kind of refactoring, depending on the business logic and the size of the code, do similar abstraction or code redundancy, this is also a kind of gradual refactoring. Either way, as long as the business logic is expressed clearly and the code is always readable and maintainable, that’s fine.
Here’s an overly abstract example.
0x04 Excessive abstraction rejected
Deep abstractions in JavaScript code are sometimes not a good thing, and students with an OOP background can easily assume that all data structures want to be encapsulated as a Class. Class is actually a bad design in JavaScript, it’s not really a Class. A few years ago, I saw a Java-to-front-end classmate write code like this:
class DataItem {
constructor(id, name, value) {
this.id = id;
this.name = name;
this.value = value; }}class DataCollection {
constructor() {
this.items = new Array(a); } insert(item) {this.items.push(item); }}const item1 = new DataItem(1.'name1'.100);
const item2 = new DataItem(2.'name2'.200);
const list = newDataCollection(); list.insert(item1); list.insert(item2); .Copy the code
A strong smell of Java came to my face. The above code doesn’t take advantage of JavaScript’s language advantages and adds a lot of cost to understanding. Writing front-end code, especially business code, using object-oriented programming is a nightmare. The correct way to write it is as follows:
const list = [{
id: 1.name: 'name1'.value: 100
}, {
id: 2.name: 'name2'.value: 200
}];
Copy the code
Since JS is a weak type language, weak type language should play to the advantages of weak type, without too much type definition and Class abstraction, with the most primitive object and function is enough to be qualified for simple to complex business scenarios. In Redux, state is a common object, Reducer is a common function, and action is also a common object without any type constraints. Because it’s simple, it’s powerful.
0x05 See six ways
Programming in a weakly typed language means you don’t need to compile, and an inherent problem with uncompiled languages is that they lack the necessary type checking before they are run, and exposing problems at runtime often results in very serious failures. This requires strict code quality assurance during the code writing phase, especially when writing business code.
The integrated development environment (IDE) has limited intelligent hints for JavaScript code. In many cases, the IDE cannot find all references to a variable or function. In this case, you need to make good use of Ctrl + F for global lookup to ensure that your single point of change does not affect other places. TypeScript helps with type checking and reference lookup.
0 x06 summary
Here are some practical lessons about writing business code: Incremental refactoring of code is a powerful weapon to improve the robustness of code; Designing code with high cohesion and low coupling allows you to precipitate a common solution as you do the requirements; Reasonable redundancy can simplify complex scenarios, making development efficient and testing easy; Reject excessive abstraction and embrace simplicity and flexibility. Keeping an eye on everything can bring code quality to a new level.
Finally, I hope everyone can experience and learn in the actual development process, constantly think and summarize, write elegant business code, is a great challenge.
About us:
We are ant Insurance experience technology team, from the Insurance business group of Ant Financial. We are a young team (no historical technology stack baggage), current average age is 92 years (remove a highest score 8x years – team leader, remove a lowest score 97 years – intern young brother). We support almost all of alibaba group’s insurance businesses. 18 years our output of mutual treasure sensational insurance industry, 19 years we have a number of heavyweight projects in preparation for mobilization. With the rapid development of the business group, the team is also expanding rapidly. Welcome to join us
We want you to be: technically grounded, deep in a specific field (Node/ interactive marketing/data visualization, etc.); Good at precipitation, continuous learning; Personality optimistic, cheerful, lively and outgoing.
If you are interested in joining us, please send your resume to:[email protected]
Ant Insurance – Experience technology group – Yiyuan
Address: Micooz