每个开发者都应该知道的七个原则

软件开发是一门复杂的领域 。是什么让高质量的软件与容易出错、充满错误的软件有所不同?答案通常在开发人员在编写代码时采用的核心原则中 。

每个开发者都应该知道的七个原则

文章插图
编程原则:优秀代码的基石编程原则是卓越软件的基石 。这些建议和最佳实践指导开发人员编写既功能强大又优雅、易维护和可扩展的代码 。
在本文中,我们深入探讨了每个开发者工具包中都应该有的七个基本编程原则:
1. DRY 原则DRY:不要重复自己 — 减少冗余的关键原则 。如果你发现自己复制粘贴同一段代码超过两次 , 现在是考虑抽象的时候了 。
考虑这种情况:你有三个函数,每个函数都以相同的方式格式化日期 。与其在所有三个函数中都有重复的格式化代码 , 不如创建一个单一的辅助函数:
// 格式化日期的辅助函数function formatDate(date) {return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;}// 函数 1: 显示今天的日期function displayTodaysDate() {const today = new Date();return formatDate(today);}// 函数 2: 显示一周后的日期function displayDateOneWeekFromNow() {const oneWeekFromNow = new Date();oneWeekFromNow.setDate(oneWeekFromNow.getDate() + 7);return formatDate(oneWeekFromNow);}// 函数 3: 显示一个月前的日期function displayDateOneMonthAgo() {const oneMonthAgo = new Date();oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1);return formatDate(oneMonthAgo);2. KISS 原则KISS:保持简单,愚蠢 — 在你的代码中追求简单 。例如,如果你写了一个复杂的 if-else 链,也许使用 switch 语句或字典会简化和美化结构:
之前:
function getErrorMessage(errorCode) {if (errorCode = 'E001') {return 'Invalid input.';} else if (errorCode = 'E002') {return 'Connection timed out.';} else if (errorCode = 'E003') {return 'Database error.';} else if (errorCode = 'E004') {return 'File not found.';} else {return 'Unknown error.';}}重构后:
const ERROR_MESSAGES = {'E001': 'Invalid input.','E002': 'Connection timed out.','E003': 'Database error.','E004': 'File not found.'};function getErrorMessage(errorCode) {return ERROR_MESSAGES[errorCode] || 'Unknown error.';}3. SOLID 原则SOLID 不是一个单一的原则 , 而是五个设计原则的集合 。尽管它们根植于面向对象编程(OOP),但它们的智慧可以更广泛地应用 。
(1) 单一职责原则(SRP): 一个类应该只有一个改变的理由 。这意味着每个类应该只有一个任务或功能,确保更容易维护和在更改过程中减少副作用 。
考虑这个例子:
// 错误的方法class UserManager {saveUser(user) {// 保存用户到数据库的逻辑}generateReport(user) {// 生成用户报告的逻辑}}更优雅的解决方案是将其拆分为两个各自处理单一职责的类:
// 正确的方法class UserDatabase {save(user) {// 将用户数据保存到数据库}}class UserReport {generate(user) {// 为用户生成报告}}在上面的代码片段中,我们分担了责任:UserReport 处理用户的报告生成 , 而 UserDatabase 管理将用户数据保存到数据库 。
(2) 开闭原则(OCP): 软件组件应该对扩展开放,对修改关闭 。这允许开发人员在不修改现有代码的情况下添加新功能,促进可重用性并减少错误 。
假设你有一个 AreaCalculator 类,用于计算矩形的面积 。现在 , 如果我们添加一个 Circle,AreaCalculator 将需要修改 。
// 错误的方法class AreaCalculator {calculateArea(shape) {if (shape.type = "circle") {return 3.14 * shape.radius * shape.radius;} else if (shape.type = "square") {return shape.side * shape.side;}}}相反,使用 OCP:我们从一个基础的 Shape 类扩展我们的形状,允许轻松添加新形状而不修改 AreaCalculator 。
// 正确的方法class Shape {calculateArea() {}}class Circle extends Shape {constructor(radius) {super();this.radius = radius;}calculateArea() {return 3.14 * this.radius * this.radius;}}class Square extends Shape {constructor(side) {super();this.side = side;}calculateArea() {return this.side * this.side;}}(3) 里氏替换原则(LSP): 子类应该能够替换其基类而不产生异常 。这确保继承类保持其父类的属性和行为 。
遵循 LSP,我们应该重构设计以确保正确的继承:
class Bird {fly() {// 通用飞行行为}}class Penguin extends Bird {// 企鹅不能飞,所以这个方法不应该在这里}


推荐阅读