JavaScript 的坚实原则

2025-06-07

JavaScript 的坚实原则

SOLID 原则是一组软件设计原则,它帮助我们理解如何构建代码,以尽可能地提高代码的健壮性、可维护性和灵活性

以下是SOLID原则:


S - 单一职责原则

替代文本

任何函数都必须只负责做一件事。
软件规范中只有一个潜在的变化能够影响该类的规范。

示例:假设我们要验证表单,然后在数据库中创建一个用户


/* A function with such a name is a symptom of ignoring the Single Responsibility Principle
*  Validation and Specific implementation of the user creation is strongly coupled.
*  That's not good
*/ 
validateAndCreatePostgresUser = (name, password, email) => {   

  //Call an external function to validate the user form
  const isFormValid = testForm(name, password, email); 

  //Form is Valid
  if(isFormValid){
    CreateUser(name, password, email) //Specific implementation of the user creation!
  }
}
Enter fullscreen mode Exit fullscreen mode

是的

//Only Validate
validateRequest = (req) => {

  //Call an external function to validate the user form
  const isFormValid = testForm(name, password, email); 

  //Form is Valid
  if(isFormValid){
    createUser(req); // implemented in another function/module 
  }
}

//Only Create User in the Database
createUser = (req) => CreateUser(req.name, req.password, req.email)

/*A further step is to declarel this function in another file
* and import it into this one.
*/
Enter fullscreen mode Exit fullscreen mode

这似乎是一个很小的变化,但却将验证逻辑与用户创建分离,由于多种原因,这种情况在未来可能会发生变化!


O——开放封闭原则

替代文本

必须允许软件系统通过添加新代码而不是更改现有代码来改变其行为。

对扩展开放,但对修改关闭

如果我们有这样的事情:

const roles = ["ADMIN", "USER"]
checkRole = (user) => {
  if(roles.includes(user.role)){
    return true; 
  }else{
    return false
  }
}

//Test role
checkRole("ADMIN"); //true
checkRole("Foo"); //false

Enter fullscreen mode Exit fullscreen mode

无论出于何种原因,我们都想添加超级用户,而不必修改现有代码(或者也许我们无法修改它),我们可以在另一个函数中执行此操作。

//UNTOUCHABLE CODE!!!
const roles = ["ADMIN", "USER"]
checkRole = (user) => {
  if(roles.includes(user.role)){
    return true; 
  }else{
    return false
  }
}
//UNTOUCHABLE CODE!!!

//We can define a function to add a new role with this function
addRole(role){
  roles.push(role)
}

//Call the function with the new role to add to the existing ones
addRole("SUPERUSER");

//Test role
checkRole("ADMIN"); //true
checkRole("Foo"); //false
checkRole("SUPERUSER"); //true
Enter fullscreen mode Exit fullscreen mode


L - 里氏替换原则

替代文本

使用可互换的部件构建软件系统。

程序中的对象应该可以用其子类型的实例替换,而不会改变该程序的正确性。

class Job {
  constructor(customer) {
    this.customer = customer;
    this.calculateFee = function () {
      console.log("calculate price"); //Add price logic
    };
  }
  Simple(customer) {
    this.calculateFee(customer);
  }
  Pro(customer) {
    this.calculateFee(customer);
    console.log("Add pro services"); //additional functionalities
  }
}



const a = new Job("Francesco");
a.Simple(); 
//Output:
//calculate price


a.Pro();
//Output: 
//calculate price 
//Add pro services...
Enter fullscreen mode Exit fullscreen mode


I - 接口隔离原则

替代文本

许多特定于客户端的接口比一个通用接口更好。

Javascript 中没有接口,但让我们看看这个例子


//Validate in any case
class User {
  constructor(username, password) {
    this.username = username;
    this.password = password;
    this.initiateUser();
  }
  initiateUser() {
    this.username = this.username;
    this.validateUser()
  }

  validateUser = (user, pass) => {
    console.log("validating..."); //insert validation logic here!
  }
}
const user = new User("Francesco", "123456");
console.log(user);
// validating...
// User {
//   validateUser: [Function: validateUser],
//   username: 'Francesco',
//   password: '123456'
// }
Enter fullscreen mode Exit fullscreen mode

是的

//ISP: Validate only if it is necessary
class UserISP {
  constructor(username, password, validate) {
    this.username = username;
    this.password = password;
    this.validate = validate;

    if (validate) {
      this.initiateUser(username, password);
    } else {
      console.log("no validation required"); 
    }
  }

  initiateUser() {
    this.validateUser(this.username, this.password);
  }

  validateUser = (username, password) => {
    console.log("validating...");
  }
}

//User with validation required
console.log(new UserISP("Francesco", "123456", true));
// validating...
// UserISP {
//   validateUser: [Function: validateUser],
//   username: 'Francesco',
//   password: '123456',
//   validate: true
// }


//User with no validation required
console.log(new UserISP("guest", "guest", false));
// no validation required
// UserISP {
//   validateUser: [Function: validateUser],
//   username: 'guest',
//   password: 'guest',
//   validate: false
// }
Enter fullscreen mode Exit fullscreen mode


D - 依赖倒置原则

替代文本

抽象不能依赖于细节。

细节必须依赖于抽象。


//The Http Request depends on the setState function, which is a detail
http.get("http://address/api/examples", (res) => {
 this.setState({
  key1: res.value1,
  key2: res.value2,
  key3: res.value3
 });
});
Enter fullscreen mode Exit fullscreen mode

是的

//Http request
const httpRequest = (url, setState) => {
 http.get(url, (res) => setState.setValues(res))
};

//State set in another function
const setState = {
 setValues: (res) => {
  this.setState({
    key1: res.value1,
    key2: res.value2,
    key3: res.value3
  })
 }
}

//Http request, state set in a different function
httpRequest("http://address/api/examples", setState);
Enter fullscreen mode Exit fullscreen mode

我要感谢我的朋友Oleksii Trekhleb对本文的贡献。

Oleksii 是这个传奇的GitHub 存储库https://github.com/trekhleb/javascript-algorithms的原作者


综上所述...

SOLID 原则的主要目标是任何软件都应该容忍变化并且易于理解。

SOLID 原则对于编写代码非常有用:

  • 易于理解
  • 事物在它们应该在的地方
  • 类按照预期执行
  • 可以轻松调整和扩展,且无错误
  • 这将抽象与实现分开
  • 这样可以轻松交换实现(Db、Api、框架......)
  • 易于测试

就这样。如果您有任何疑问,请在下面发表评论。

弗朗西斯科

文章来源:https://dev.to/francescoxx/solid-principles-in-javascript-3pek
PREV
CSS Deep 1. CSS 库 2. CSS 动画 3. 编码标准和最佳实践 4. CSS 网格 4.3. 工具 4.4. 示例 4.5. 幻灯片 4.6. 视频 4.7. 其他
NEXT
如何使用 React 创建时间轴组件