Writing High Quality Maintainable Code: Paradigms

preface

What is a programming paradigm?

Programming paradigm is a type of typical Programming style. It refers to a typical style of software engineering (see methodology). For example: functional programming, procedural programming, object-oriented programming, instruction programming and so on for different programming paradigms.

JS is a dynamic prototype-based and multiparadigm scripting language that supports OOP, imperative and declarative (such as Functional Programming) Programming styles.

So what is object-oriented, imperative, declarative programming? What’s the difference?

Imperative programming

Imperative programming is an example of programming that describes the behavior a computer needs to perform, that is, telling the computer step by step what to do first and then what to do. Take a simple 🌰 : find out who is older than 35, and you tell the computer:

  1. Create a new array newArry to store the results;
  2. Loop over the set of all people people;
  3. If the current person is older than 35, store that person’s name in the new array;
const people = [
    { name: 'Lily'.age: 33 },
    { name: 'Abby'.age: 36 },
    { name: 'Mary'.age: 32 },
    { name: 'Joyce'.age: 35 },
    { name: 'Bella'.age: 38 },
    { name: 'Stella'.age: 40},];const newArry = [];
  for (let i = 0; i < people.length; i++) {
    if (people[i].age > 35) { newArry.push(people[i].name); }}Copy the code

Imperative programming is very easy to understand, according to the actual steps, the advantage lies in high performance, but will rely on, modify more external variables, low readability;

Declarative programming

Declarative programming is the antithesis of imperative programming, where you tell the computer what to do without telling it how to do it. Declarative languages include database query language (SQL), regular expressions, logical programming, functional programming, and configuration management systems. The above example of declarative programming looks like this:

const peopleAgeFilter = (people) = > {
return people.filter((item) = > item.age > 35)}Copy the code

Functional programming

What is functional programming?

Functional programming is not a Function, as we know it, but a mathematical Function, a mapping between variables that returns one and only one output.

// function in js
function fun(data, value, type) {
  // Logical code
}
/ / function
y=f(x)
Copy the code

Functional programming has been around since 1958, with the creation of LISP. In the last few years, functional programming has been on the front end: arrow functions, Map, Reduce, filter, and Middleware from Redux has been used for functional programming…

Features of functional programming
  • The function is first class citizen

    A “first class citizen” is a function that, like any other data type, has equal status. It can be assigned to other variables, passed in as arguments to another function, or returned as a value from another function. Such as:

  let fun = function(i){
    console.log(i);
  }
  [1.2.3].forEach(element= > {
    fun(element);
  });
Copy the code
  • The inertia calculation

    In lazy computation, the expression is not evaluated immediately when it is bound to a variable, but when the evaluator needs to produce the value of the expression. That is, functions are executed only when needed.

  • There are no side effects.

    A “side effect” is an interaction between the inside and outside of a function (most typically, modifying the value of a global variable) that produces a result other than the operation. Since objects in JS pass reference addresses, they can be changed even when we declare them with const keywords. This can lead to arbitrary changes in objects. Such as:

 const user = {
  name: 'jingjing',}const changeName = (obj, name) = > obj.name = name;
const changeUser = changeName(user, 'lili');
console.log(user); // {name: "lili"} user object has been changed
Copy the code

Write it as a pure function with no side effects:

const user = {
  name: 'jingjing',}// const changeName = (obj, name) => obj.name = name;
const changeName = (obj, name) = >({... user, name });const changeUser = changeName(user, 'lili');
console.log(user); // {name: "jingjing"}, although the user object has not changed
Copy the code
  • Referential transparency

    That is, if the same input is provided, the function always returns the same result. That is, whenever the arguments are the same, the return value from the reference function is always the same.

In functional programming, Currying and function combinations are essential.

  • Currie,

There are many online articles about curryization, here no longer repeat, you can refer to here, function curryization Currying.

Currization is the technique of transforming a function that takes multiple arguments into a function that takes a single argument (the first argument of the original function), and returning a new function that takes the remaining arguments and returns the result. Simply put, you call a function by passing it one argument and have it return a function to process the rest of the arguments. That is:

f(x, y, z) -> f(x)(y)(z)
Copy the code

For example, find the sum of squares of two numbers:

// Original version
const squares = function(x, y) {
  return x * x + y * y;
}
// Currified version
const currySquares = function(x) {
    return function(y){
    returnx * x + y * y; }}console.log(squares(1.2));
console.log(currySquares(1) (2));
Copy the code

In the Currified version, the actual execution is as follows:

currySquares(1) = function(y){
  return 1 + y * y;
}
currySquares(1) (2) = 1 + 4 = 5;
Copy the code
  • Function composition (Compose)

    Function composition is the combination of two or more functions to produce a new function.

    In computer science, function composition is the act or mechanism of combining simple functions into more complex functions. As usual with function composition in mathematics, the result of each function is passed as an argument to the next function, and the result of the last function is the result of the whole function. So currization is the basis of function combinations.

Such as:

Double function case:

const compose = (f, g) = > x= > f(g(x))
const f = x= > x * x;
const g = x= > x + 2;
const composefg = compose(f, g);
composefg(1) / / 9
Copy the code

For multi-function cases, the simple implementation is as follows:

const compose = (. fns) = > (. args) = > fns.reduceRight((val, fn) = > fn.apply(null, [].concat(val)), args);
const f = x= > x * x;
const g = x= > x + 2;
const h = x= > x - 3;
const composefgh = compose(f, g, h);
composefgh(5); / / 16
Copy the code

Declarative programming is characterized by no “side effects” and does not rely on or change data outside the current function. The advantages of declarative programming include:

  1. Reduced variable variables, the program is more secure;
  2. Compared with imperative programming, it has much less declaration and maintenance of state variables, which is naturally suitable for tasks such as high-concurrency and multi-off-the-peg parallel computing. This is also an important reason why functional programming has become hot in recent years.
  3. The code is more concise, closer to natural language, easier to understand, and more readable. But functional programming also has natural drawbacks:
  4. Compared with imperative programming, functional programming tends to over-wrap methods, resulting in poor performance.
  5. Because functional programming emphasizes no “side effects,” it is not good at mutable state;

Object-oriented programming

Object-oriented programming regards a computer program as a collection of objects, and each object can receive and process messages from other objects. The execution of a computer program is a series of messages passed between objects.

Two basic concepts of object orientation:

  1. Class: A class is a type template for an object; For example, the front-end ZooTeam is a class;
  2. Instance: An instance is an object created from a class; For example, ZooTeam can create an instance of Liu Jing. Three basic features of object orientation: encapsulation, inheritance, polymorphism: note ⚠️ : The following examples are written in ES6
  • Encapsulation: encapsulation hides the attributes and implementation details of the object, only exposes the interface externally, and controls the access level of reading and modifying attributes in the program; Abstract data and behavior (or function) combined to form an organic whole. As FAR as I understand it, it’s basically taking the attributes of the subclass and the public methods and putting them in the parent class as public methods;
class Zcy {
  constructor(name){
      this.name = name;
  }
  doSomething(){
      let {name} = this;
      console.log(`${name}The morning meeting is at half past nine);
  }
  static soCute(){
      console.log("Zcy is a big family!"); }}let member = new Zcy("jingjing".18);
member.soCute();   // member.soCute is not a function
member.doSomething();  // Jingjing has a morning meeting at half past nine
Zcy.soCute();  Zcy is a big family!
Copy the code

The members of Zcy have names and ages, and the morning meeting is held at 9:30, so the name and age are regarded as common attributes, and the morning meeting at 9:30 is separated and encapsulated as a common method. Static means static methods. Static methods only belong to the Zcy class, so the console reports an error when member calls the soCute method.

  • Inheritance: Inheritance is when a subclass inherits the characteristics and behavior of its parent class so that its objects (instances) have the attributes and methods of the parent class, or a subclass inherits methods from the parent class so that the subclass has the same behavior as the parent class. When a subclass inherits from its parent class, it has the attributes and methods of its parent class, but it can also declare its own attributes and methods. Therefore, the functions of a subclass are greater than or equal to the parent class, but not less than the parent class.
class Zcy {
  constructor(name){
      this.name = name;
  }
  doSomething(){
      let {name} = this;
      console.log(`${name}The morning meeting is at half past nine);
  }
  static soCute(){
      console.log("Zcy is a big family!"); }}class ZooTeam extends Zcy{
    constructor(name){
        super(name);
    }
    eat(){
      console.log("Dinner party on Friday!"); }}let zooTeam = new ZooTeam("jingjing");
zooTeam.doSomething(); // Jingjing has a morning meeting at half past nine
zooTeam.eat(); // Let's have dinner together on Friday!
zooTeam.soCute();    // zooTeam.soCute is not a function
Copy the code

ZooTeam inherits Zcy’s properties and methods, but not its static methods; And ZooTeam declared its own method eat;

  • Polymorphism: Polymorphism literally means “multiple states” and allows assigning Pointers of subclass types to Pointers of superclass types. That is, the same operation on different objects can be interpreted differently, resulting in different execution results. Polymorphism can be represented by rewriting, overloading and interface. Native JS can only implement polymorphism by rewriting.
  • Overrides: Overrides are methods that a subclass inherits from its parent class without having to rewrite the same method. However, sometimes subclasses do not want to inherit the methods of the parent class, but want to make certain changes, which requires method overwriting. Method override is also called method override.
class Zcy {
  constructor(name){
      this.name = name;
  }
  getName(){
    console.log(this.name);
  }
  doSomething(){
      let {name} = this;
      console.log(`${name}The morning meeting is at half past nine);
  }
  static soCute(){
      console.log("Zcy is a big family!"); }}class ZooTeam extends Zcy{
    constructor(name){
        super(name);
    }
    doSomething(){
      console.log("ZooTeam has a weekly meeting on Friday!"); }}const zcy = new Zcy('jingjing');
const zooTeam = new ZooTeam('yuyu');
zcy.doSomething(); // Jingjing has a morning meeting at half past nine
zcy.getName(); // jingjing
zooTeam.doSomething(); // zooTeam has a weekly meeting on Friday!
zooTeam.getName(); // yuyu
Copy the code

In order to meet their own needs, ZooTeam inherited the doSomething method of the parent class and then rewrote the doSomething method, so different results were obtained after calling the doSomething method, while getName method was only inherited but not rewritten.

Object-oriented programming is characterized by abstract description of the basic characteristics of the object, the advantage is that the object is easy to understand and abstract, the code is easy to expand and reuse. But it is also easy to generate useless code, which can easily lead to data modification.

conclusion

Imperative, declarative and object-oriented programming are not superior or inferior in nature. Object-oriented and imperative and declarative programming are not independent and have strict boundaries. After abstracting each independent object, the concrete behavior of each object is realized by functional and procedural methods. In practical applications, because the requirements are often special, it is still necessary to choose the appropriate paradigm according to the actual situation.

Refer to the article

Three basic characteristics of object orientation

A primer on simple JavaScript functional programming

One article to understand the focus of JavaScript functional programming – practice summary

Functional programming in JavaScript: functions, composition, and Currification

Recommended reading

How to implement binary heap with JS

Writing high quality maintainable code: Component abstraction and granularity

, recruiting

ZooTeam, a young passionate and creative front-end team, belongs to the PRODUCT R&D department of ZooTeam, based in picturesque Hangzhou. The team now has more than 40 front-end partners, with an average age of 27, and nearly 30% of them are full-stack engineers, no problem in the youth storm group. The members consist of “old” soldiers from Alibaba and netease, as well as fresh graduates from Zhejiang University, University of Science and Technology of China, Hangzhou Electric And other universities. In addition to daily business docking, the team also carried out technical exploration and practice in material system, engineering platform, building platform, performance experience, cloud application, data analysis and visualization, promoted and implemented a series of internal technical products, and continued to explore the new boundary of front-end technology system.

If you want to change what’s been bothering you, you want to start bothering you. If you want to change, you’ve been told you need more ideas, but you don’t have a solution. If you want change, you have the power to make it happen, but you don’t need it. If you want to change what you want to accomplish, you need a team to support you, but you don’t have the position to lead people. If you want to change the pace, it will be “5 years and 3 years of experience”; If you want to change the original savvy is good, but there is always a layer of fuzzy window… If you believe in the power of believing, believing that ordinary people can achieve extraordinary things, believing that you can meet a better version of yourself. If you want to be a part of the process of growing a front end team with deep business understanding, sound technology systems, technology value creation, and impact spillover as your business takes off, I think we should talk. Any time, waiting for you to write something and send it to [email protected]