• Author: Chen Da Yu Tou
  • Making: KRISACHAN

Fishhead in the process of development, summed up some optimization of the development of coding experience, of course, these experiences are summed up by predecessors, this time to share with you, of course, these experiences are not necessarily best practices, readers interested or have different opinions can be discussed with Fishhead.

Refused to magic

As we all know, magic goes like this:

Oh, no.

There is also magic in the programming world, commonly called magic numbers, magic variables, magic strings. For example:

const a = await abcdefg();
console.log(a === 200);
const b = await asdfgh();
if (b === 0) {}else if (b === 1) {}else if (b === 2) {};
for (let i = 0; i < 10; i++) {};
Copy the code

The above direct, inexplicable variable names, strings and conditional numbers are called magic…

The resulting code is obscure, hard to maintain, and full of hidden bugs, and unless you’re ready to bury the hatches or quit your job, don’t do it (easily broken legs, 👨🦽).

So what would be more elegant?

semantic

The first is semantic. One is the semantematization of variables, constants, for example:

const SUCCESS_STATUS = 200;
const requestStatus = await getStatus();
console.log(requestStatus === SUCCESS_STATUS);
const userRole = await getUserRole();
const GUEST_CODE = 0;
const USER_CODE = 1;
const ADMIN_CODE = 2;
if (userRole === GUEST_CODE) {
} else if (userRole === USER_CODE) {
} else if (userRole === ADMIN_CODE) {};
const MAX_NUM = 10;
const MIN_NUM = 0;
for (let currentNum = MIN_NUM; currentNum < MAX_NUM; currentNum++) {};
Copy the code

The general rule is to use lowercase for variables, uppercase for constants, and semantic for variable names, so that when you see this code, you know what it does at a glance, rather than having to waste time looking at the context or guessing.

The enumeration

For the above code to determine userroles, we can do it in a more elegant way: enumerations.

In mathematical and computer science theory, an enumeration of a set is a program that lists all the members of some finite set of sequences, or a count of objects of a particular type. The two types often (but not always) overlap.

It’s a way for organizations to collect variables that are associated. The benefits of enumerations are easier management of multiple states, and more readability. Such as:

const ROLES = {
  GUEST: 0.USER: 1.ADMIN: 2
};
const userRole = await getUserRole();
if (userRole === ROLES.GUEST) {
} else if (userRole === ROLES.USER) {
} else if (userRole === ROLES.ADMIN) {};
Copy the code

It’s easier to maintain them by enumerating them, and it’s easier to add states directly to the ROLES object.

The strategy pattern

A policy pattern, as a software design pattern, refers to a behavior of an object that is implemented by different algorithms in different scenarios.

The above code is still optimizable, and here we can use the policy pattern to optimize the next level.

Examples are as follows:

const ROLES = {
  GUEST: 0.USER: 1.ADMIN: 2
};
const ROLE_METHODS = {
  [ROLES.GUEST]() {},
  [ROLES.USER]() {},
  [ROLES.ADMIN]() {},
};
const userRole = await getUserRole();
ROLE_METHODS[userRole]();
Copy the code

When adding ROLES or changing the number of ROLES, just change the fields in ROLES and ROLE_METHODS, so that we can change the if… Else code is removed to make it more granular and easier to maintain.

More in the state

In addition to the above approach, we can also use the concept of “state” to write code. Before we look at the code, let’s look at what a “finite state machine” is.

Finite-state Machine (FSM) also known as finite-State automaton (FINite-State Automation) FSA, or state machine for short, is a mathematical calculation model that represents a finite number of states and behaviors such as transitions and actions between these states.

For example, we are familiar with Promise, which is a finite state machine with one-way flow between the state set: PENDIN, depressing and REJECTED.

The concept of a state machine is similar to the policy pattern, and the implementation is similar, but the biggest difference is the “semantics”.

The policy pattern is more suitable for scenarios where there is no dependency and only one state can exist at the same time, for example:

constEat = {sha county hotel () {eat wonton ()}, kaifeng cuisine () ()} {to eat Hamburg, () at home eating take-away () {}};Copy the code

If we are hungry, we can only choose from the state of Shaxian Hotel, Kaifeng dishes and home.

You can’t eat them all, except of course…

In state mode, this is the case:

const= {get up () {}, go to work () {}, work overtime () {}, go off work () {}};// 6 amGet up ();// 9 amWorking ();// at 6 p.mWorking overtime ();// At 12 p.mWork off ();Copy the code

Here the workers are doing different tasks at different times, which is the worker mode, no, state mode. The time here is the state.

Let’s take a practical business example, which is the order list page. Usually our order may have one of the following states:

The UI displayed in different states is also different, so after we divide modules into different states, the code will be much clearer to write. Let’s take Vue code as an example:

// contants.js
export const ORDER_STATUS = {
  INIT: 0./ / initialization
  CREATED: 1.// Order creation
  ARREARAGE: 2./ / to pay
  PURCHASED: 3./ / have bought
  SHIPPED: 4./ / shipment
  COMPLETED: 5 / / has been completed
};
Copy the code
// order.vue <template> <div> <section v-if="orderIsInit"></section> <section v-if="orderIsCreated"></section> <section v-if="orderIsArrearage"></section> <section v-if="orderIsPurchased"></section> <section v-if="orderIsShipped"></section>  <section v-if="orderIsCompleted"></section> </div> </template> <script> import ORDER_STATUS from './contants'; import eq from 'lodash'; export default { computed: {/** * @func * @name orderIsInit * @desc Status to determine whether the order is initialized * @returns {string} Status to determine whether the order is initialized */ orderIsInit() {return eq(this.orderStatus, ORDER_STATUS.INIT); }, /** * @func * @name orderIsCreated * @desc Status to determine whether the order has been created * @returns {string} Whether the order has been created */ orderIsCreated() {return eq(this.orderStatus, ORDER_STATUS.CREATED); }, /** * @func * @name orderIsArrearage * @desc Status to determine whether the order is not paid * @returns {string} order is not paid */ orderIsArrearage() {return eq(this.orderStatus, ORDER_STATUS.ARREARAGE); }, /** * @func * @name orderIsPurchased * @desc indicates the status of determining whether an orderIsPurchased. * @returns {string} indicates whether an orderIsPurchased. */ orderIsPurchased() {return eq(this.orderStatus, ORDER_STATUS.PURCHASED); }, /** * @func * @name orderIsShipped * @desc Determines whether the order has been shipped * @returns {string} Whether the order has been shipped */ orderIsShipped() {return eq(this.orderStatus, ORDER_STATUS.SHIPPED); }, /** * @func * @name orderIsCompleted * @desc status to determine whether the orderIsCompleted * @returns {string} whether the orderIsCompleted */ orderIsCompleted() {return eq(this.orderStatus, ORDER_STATUS.COMPLETED); },}, data() {return {orderStatus: order_status.init // orderStatus}}, methods: {/** * @func * @name getOrderStatus * @desc check order status * @returns {string} return order status */ async getOrderStatus() {}}, async created() { this.orderStatus = await this.getOrderStatus(); } } </script>Copy the code

The page components are divided by states to achieve independence and autonomy, which not only prevents code coupling, facilitates debug maintenance, but also facilitates self-testing by developers. If you need to see the display effect of different states, just assign values to orderStatus manually, which is convenient and quick.

Aspect oriented

According to Wikipedia: Aspect-oriented programming (AOP) is a programming idea in computer science, which aims to further separate crosscutting concerns from business entities to improve the modularity of program code.

The above paragraph of text estimates no one to see, forget it, directly on the code

Let’s look at the situation above. Suppose the boss wants to know the time before each state starts and ends and what he does. What should he do? At this point, it is not difficult to think of writing code directly into the state function, for example:

constWorkman = {get up () {boss. Start (); Working people. The do (); Boss. The end (); }, work () {boss. Start (); Working people. The do (); Boss. The end (); }, work overtime () {boss. Start (); Working people. The do (); Boss. The end (); }, off work () {boss.start (); Working people. The do (); Boss. The end (); }};// 6 amGet up ();// 9 amWorking ();// at 6 p.mWorking overtime ();// At 12 p.mWork off ();Copy the code

But in this way, the worker is immediately aware that the boss is monitoring his life. If we want to do this without being detected (without affecting the business logic), we can adopt the AOP approach. The code is as follows:

import eq from 'lodash';
const TYPES = {
  FUNCTION: 'function'
}
constThe worker in the boss's monitoring =new Proxy(Migrant worker, {get(target, key, value, receiver) {
        console.log('The boss is looking at you.');
      	const res = Reflect.get(target, key, value, receiver);
      	constEmployee task = eq(typeof res, TYPES.FUNCTION) ? res() : res;
        console.log('The boss is taking notes on you.');
        return () = >Migrant work; }});Copy the code

So we can see the following results:

In this way, we can easily and easily monitor the daily work of the migrant workers without letting the migrant workers find out about it, which would make the capitalists cry.

Afterword.

The above summary is just a few of the many programming specification patterns, many such as S.O.L.I.D and the other 20 or so design patterns that are not covered in this article, so please forgive me.