This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Both business development and all kinds of rolling process, before began to knock the code, design should give priority to, is the so-called knife don’t miss your job, good design can lay a good foundation for the for the entire project, not only can solve some problems at present, can also be in the face of changing business needs play a crucial role in the future

SOLID

In object-oriented design, SOLID five design principles ensure that our code has stability, flexibility, robustness and maintainability

SOLID stands for SRP, OCP, LSP, ISP, and DIP

Single responsibility principle

S: The single-responsibility Principle (SRP), which means that The object should have a Single function Principle to reduce The coupling between functions and ensure high cohesion and low coupling functions

For example, when submitting a form, we will verify whether the input content meets the expectation before submitting the data, so there will be a lot of verification logic in the verification process. At this time, each verification rule will be extracted into a function, and only the corresponding rules will be verified

// Verify the mailbox
const validateEmail = () = > {
	return new Promise((resolve, reject) = > {
		// todo ...
		resolve(true)})}// Check the age
const validateAge = () = > {
	return new Promise((resolve, reject) = > {
		// todo ...
		resolve(true)})}Copy the code

Open and closed principle

O: OCP(The Open/Closed Principle), which means “The program is Closed to modification for extension development”. After a class or function determines its capabilities, it cannot modify its original capabilities, but can only expand new capabilities on top of its original capabilities

Continue the form validation above

/** * Verify that the check is carried out in resolve or reject */
const validate = () = > {
	return new Promise((resolve, reject) = > {
		Promise.all([validateEmail(), validateAge()]).then(res= > {
			console.log('Verification successful', res);
			resolve(true)
		}).catch(err= > {
			console.log('Verification failed',err);
			resolve(err)
		})
	})
}

/** * Submit data */
const submit = async() = > {// 1. Verify data
	const pass = await validate()
	console.log('pass', pass);
	
	if(pass) {
		// 2 Commit data
	}else {
		// todo ...}}Copy the code

If a verification rule is added:

// Check time
const validateTime = () = > {
	return new Promise((resolve, reject) = > {
		// todo ...
		resolve(true)})}Copy the code

Only extend promise. all, which will not affect the original business logic. Then add new verification rules and directly add new verification functions

Tips:

For example, in today’s commonly used element-UI framework, promise. all is automatically validated by the props property bound to the form element and does not display the call as described above

There is no specific verification rule in the verification function. The specific business logic is written according to the business

Richter’s substitution principle

L: Objects in a program should be replaceable by its subclasses without changing The correctness of The program. Subclasses can completely override and replace The base class where it can be used. The use of base class and subclass does not affect the normal operation of the program, the function is completely consistent, the main emphasis is the implementation of inheritance, JS use less

First look at the code:

class Cat {
	constructor(name) {
		this.name = name;
	}

	eat(){}}class BritishShorthair extends Cat {
	constructor(name) {
		super(name);
	}

	eat(){}}const animal = new Cat("Cats");
const bs = new BritishShorthair("The short");

const my = {
	pet(p: Cat) { // Restricted pass is Cat or a subclass of Cat
		console.log('My pet is${p.name}`);
	}
}

my.pet(bs)
my.pet(animal)
Copy the code

There is a Cat class and a BritishShorthair class, BritishShorthair as a subclass of Cat, I have a pet, and the pet is a Cat, so at this point when I introduce my pet, I can say that my pet is a BritishShorthair, It can also be said to be Cat, since English short is a branch of Cat refinement, and can be used here entirely instead of Cat

Interface Isolation Principle

I: The Interface Segregation Principle (ISP), which means that an Interface should have as few behaviors as possible and keep it single and independent. Therefore, fat interfaces must appear in a second. For modules with different functions, different interfaces are used, rather than using the same general interface, which is similar to the principle of single responsibility. There is no concept of interface in JS, which can be implemented by using the interface in TS

Separate different interfaces and isolate each other

interface Alarm {
    alert(): void;
}

interface Light {
    lightOn(): void;
    lightOff(): void;
}

class Car implements Alarm.Light {
    alert() {
        console.log('Car alert');
    }
    lightOn() {
        console.log('Car light on');
    }
    lightOff() {
        console.log('Car light off'); }}Copy the code

Dependency inversion principle

D: The Dependency Inversion Principle (DIP) : a high-level module should not depend on a low-level module, but both should depend on its abstraction; Abstract should not depend on details, details should depend on abstractions, users only care about the interface and not the implementation of concrete classes, JS use less

The pet parameter in the above code should be Cat, not BritishShorthair, if a Cat of another breed is later raised, it will not affect the pet call, and vice versa

const my = {
	pet(p: Cat) { // Restricted pass is Cat or a subclass of Cat
		console.log('My pet is${p.name}`); }}Copy the code