I’ve been working on urgent projects lately, and short timelines and unreducible (and potentially changeable) requirements mean making development as efficient as possible. The front end, because it is associated with interactions, is subject to most requirements changes. How to minimize the workload caused by changing requirements has always been a problem for front-end developers.

I suffered a lot because my code style was not standard enough and my knowledge was not deep enough, but I also gained some experience in improving development efficiency. This article is a summary and review to remind yourself in the future.

How to improve efficiency

For our students who do development, the most effective way to improve work efficiency is to reduce the BUG rate; The most effective way to reduce the BUG rate is to reduce the amount of code. Remember GitHub’s big project No Code? Senior Google engineers tell us that programs without a line of code are the most secure and stable.

Secondly, if the code is extensible enough, the workload in the face of changing requirements will be relatively reduced (as a front-end, it does not exist without changing). The common way to enhance code extensibility is the encapsulation and abstraction of common components.

Here are some summaries and reflections about these two parts.

Ways to reduce bugs

Good code style is probably the most effective way to reduce bugs. See The Code Clean Way. The following are some of the tips I’ve picked up in my daily work.

1. Reduce code

The less code you have, the harder it is to BUG. In your daily work, you should write as little code as possible. In the front end, the easiest thing to do is to use ES6 syntax as much as possible. Compared to ES5, deconstruction, arrow functions, async/await can reduce code volume by more than 30% with ES6. When there are a large number (three or more) of if judgments, the object form can be used.

// Regular assignment
let a = 1
let b = 2
let c = 3
// Use destruct assignment
let [a,b,c] = [1.2.3]

/ / use the if
if(a === '1') {... }else if(a === '2'){
  ...
}else if(a === '3') {... }...// It is logically cleaner to categorize objects
// PS: This method is useful for React component rendering
const handleAction = (act) = > {
  const actions = {
    '1': action1,
    '2': action2,
    '3': action3
  }
  const action = actions[act]
  action()
}
// Handle as the case may be
handleAction('1')
Copy the code

In the React project, if Redux is used. Use the Function component as much as possible to reduce code. This also allows us to save a lot of changes in UI porting (a recent project was a partial function migration, Redux -> DVA porting the function component with very little change), and now that we have hooks, The inability to control state in the function component can also be resolved.

2. Set the default values

The lack of default values is very bug-prone, a blood and tears lesson from a previous project. In particular, a React project that uses the object method described above to switch components will crash if default values are not set.

class A extends React.Component {
  const Components = {
    // Especially when switching components based on Response, default should be set to prevent unexpected situations
    A: Component1,
    B: Component2,
    C: Component3,
    'default': (a)= > <div />
  }

  render(){
    const {render} = this.state
    // If there is no default value, the page will crash if the object does not match
    const RenderComponent = Components[render] || Components.default
    return (
      <RenderComponent />)}}Copy the code

Second, default values for function parameters can help reduce code in addition to reducing bugs. For frequently used methods, setting the default values allows us to call without passing in arguments.

// If there are many 0.0.0.1 and API service methods, setting this parameter as the default can reduce the number of arguments passed in
function customizeFetch(service='api', base = '0.0.0.1'){... } customizeFetch()Copy the code

3. Split functions and abstract methods

When it comes to split functions, the most commonly used is the application part of the request. Such as the encapsulation of fetch.

Function customizeFetch(server = "API ", base = "0.0.0.1") {return function(API = "", options = {}, withAuth = false) { const url = `${base}/${server}/${api}`; Const opts = {method: options method | | "POST", headers: {/ / can set the default parameters, such as head of what... options.headers }, body: { ... options.body } }; return fetch(url, opts).then(response => response.json()); }; Const fetchAPI = customizeFetch("api1"); const fetchAPI = custom fetch ("api1"); const getProductList = opts => { const options = { body: { ... opts } }; return fetchAPI("getProductList", options); }; Const fetchAPI = customizeFetch(" API2); const getNewsList = opts => { const options = { body: { ... opts } }; return fetchAPI("getNewsList", options); };Copy the code

4. Strong typing and checking

Never mind the benefits of ESLint? Pairing prettier with prettier makes code format uniform (umi’s Lint can be annoying when not used to it, but can help improve code style once used). Using TypeScript allows us to detect errors while coding. TypeScript is hard to get used to at first, especially with its strong type requirement (all any equals no type). But once you get used to TypeScript, you’ll enjoy it.

With the introduction of TypeScirpt, the most common XXX from undefined error can be avoided entirely. This can save us a lot of debugging time.

Responding to changing requirements

Componentized development of the front end is more about responding to changing requirements (I think). And since the front end is closest to the user, it’s hard to escape the need for some modifications whenever the requirements change. Therefore, it is also a way to improve efficiency to reduce the workload of modification and reduce the bugs caused by modification.

1. Improve side effects by using Stateless components as much as possible

For React/Vue projects, using state management tools like Redux/Vuex makes it easy to make components stateless independent of state. This type of component is “pure” and basically only relies on the props passed in, and even if there is a state, it is autonomous and does not participate in the business logic calculation. This makes the UI layer as clean and accountable as possible. (This is wishful thinking, of course, but switching component states or other business logic operations based on side effects can still sink business logic down to the UI layer.)

Keep the UI layer as simple as possible, and the part that handles the business logic should be moved to the Action part of Redux. Reducer should also be as pure as possible without business processing. This way, if the requirements change, the changes can be narrowed down to the action section as much as possible, and it will also be convenient for porting projects (the basic action layer will most likely be rewritten). Of course, it’s not always possible to strip it out cleanly, and the UI layer often changes along with it, but you can still reduce the scope of the changes.

2. Encapsulation and abstraction of common business components

The other is to refine common business components based on project requirements, such as SMS verification codes, editable label form controls, permission validation components, search components, etc. This type of component is basically business related, and is basically a re-encapsulation of a component library (such as ANTD), which is also what many students are familiar with today. This reduces the amount of development we can do in a particular business. Specific methods such as HOC can be used for encapsulation and abstraction (such as permission validation components).

Refining components is fine, but avoid over-encapsulation. I wrote a Vue that encapsulated a configurable form component, only to be blindsided when the business needed two form controls to control each other and button state. Therefore, packaging components should also be designed with business changes in mind.

Above is a few working comprehension of this paragraph of time recently, regard oneself as a memo. The original purpose of programming is to improve the efficiency of work, and improving the efficiency of development is a problem that every programmer has to face. So one of the things that’s really interesting about programming is that you can constantly challenge and improve yourself.