当前位置:首页 > 科技  > 软件

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

来源: 责编: 时间:2023-11-17 17:13:27 173观看
导读软件开发是一门复杂的领域。是什么让高质量的软件与容易出错、充满错误的软件有所不同?答案通常在开发人员在编写代码时采用的核心原则中。编程原则:优秀代码的基石编程原则是卓越软件的基石。这些建议和最佳实践指导开

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

gtd28资讯网——每日最新资讯28at.com

编程原则:优秀代码的基石

编程原则是卓越软件的基石。这些建议和最佳实践指导开发人员编写既功能强大又优雅、易维护和可扩展的代码。gtd28资讯网——每日最新资讯28at.com

在本文中,我们深入探讨了每个开发者工具包中都应该有的七个基本编程原则:gtd28资讯网——每日最新资讯28at.com

1. DRY 原则

DRY:不要重复自己 — 减少冗余的关键原则。如果你发现自己复制粘贴同一段代码超过两次,现在是考虑抽象的时候了。gtd28资讯网——每日最新资讯28at.com

考虑这种情况:你有三个函数,每个函数都以相同的方式格式化日期。与其在所有三个函数中都有重复的格式化代码,不如创建一个单一的辅助函数:gtd28资讯网——每日最新资讯28at.com

// 格式化日期的辅助函数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 语句或字典会简化和美化结构:gtd28资讯网——每日最新资讯28at.com

之前:gtd28资讯网——每日最新资讯28at.com

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.';    }}

重构后:gtd28资讯网——每日最新资讯28at.com

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),但它们的智慧可以更广泛地应用。gtd28资讯网——每日最新资讯28at.com

(1) 单一职责原则(SRP): 一个类应该只有一个改变的理由。这意味着每个类应该只有一个任务或功能,确保更容易维护和在更改过程中减少副作用。gtd28资讯网——每日最新资讯28at.com

考虑这个例子:gtd28资讯网——每日最新资讯28at.com

// 错误的方法class UserManager {    saveUser(user) {      // 保存用户到数据库的逻辑    }  generateReport(user) {      // 生成用户报告的逻辑    }}

更优雅的解决方案是将其拆分为两个各自处理单一职责的类:gtd28资讯网——每日最新资讯28at.com

// 正确的方法class UserDatabase {    save(user) {      // 将用户数据保存到数据库    }}class UserReport {    generate(user) {      // 为用户生成报告    }}

在上面的代码片段中,我们分担了责任:UserReport 处理用户的报告生成,而 UserDatabase 管理将用户数据保存到数据库。gtd28资讯网——每日最新资讯28at.com

(2) 开闭原则(OCP): 软件组件应该对扩展开放,对修改关闭。这允许开发人员在不修改现有代码的情况下添加新功能,促进可重用性并减少错误。gtd28资讯网——每日最新资讯28at.com

假设你有一个 AreaCalculator 类,用于计算矩形的面积。现在,如果我们添加一个 Circle,AreaCalculator 将需要修改。gtd28资讯网——每日最新资讯28at.com

// 错误的方法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。gtd28资讯网——每日最新资讯28at.com

// 正确的方法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): 子类应该能够替换其基类而不产生异常。这确保继承类保持其父类的属性和行为。gtd28资讯网——每日最新资讯28at.com

遵循 LSP,我们应该重构设计以确保正确的继承:gtd28资讯网——每日最新资讯28at.com

class Bird {    fly() {      // 通用飞行行为    }}class Penguin extends Bird {    // 企鹅不能飞,所以这个方法不应该在这里}

正确的方法是我们将形状从基本的 Shape 类扩展出来,允许轻松添加新的形状而不修改 AreaCalculator。gtd28资讯网——每日最新资讯28at.com

(4) 接口隔离原则(ISP): 类不应该被迫实现它们不使用的接口。相反,接口应该对其目的具体而清晰。gtd28资讯网——每日最新资讯28at.com

这意味着接口不应该有太多方法,尽量我们将小接口抽取出来,以便类可以只实现它们需要的接口,就像下面的例子:gtd28资讯网——每日最新资讯28at.com

// 错误的方法interface Worker {    work();    eat();    sleep();    swim();}// 正确的方法interface Worker {    work();}interface Eater {    eat();}interface Swimmer {    swim();}

(5) 依赖反转原则(DIP): 高层模块不应与低层模块纠缠在一起;它们都应依赖于抽象。例如在开关和设备的设计中可以找到:gtd28资讯网——每日最新资讯28at.com

// 错误的方法class LightBulb {    turnOn() {}    turnOff() {}}class Switch {    constructor(bulb) {      this.bulb = bulb;    }  operate() {      // 直接控制灯泡    }}

我们可以重构这样,以便 Switch 可以对任何实现 SwitchableDevice 的设备进行操作,而不仅仅是 LightBulb。gtd28资讯网——每日最新资讯28at.com

// 正确的方法class SwitchableDevice {    turnOn() {}    turnOff() {}}class Bulb extends SwitchableDevice {    // 实现 turnOn 和 turnOff 方法  }class SwitchDIP {    constructor(device) {      this.device = device;    }  operate() {      // 控制设备    }}

4. YAGNI 原则

YAGNI,“你不会需要它”,警告不要在必要之前添加功能。gtd28资讯网——每日最新资讯28at.com

例如,如果你正在构建一个博客网站,并考虑添加一个基于用户写作的功能来预测用户的心情,但这对于网站正常运行并不是必需的,那么最好将其留在一边,至少现在是这样。gtd28资讯网——每日最新资讯28at.com

有不必要功能的应用:gtd28资讯网——每日最新资讯28at.com

class Blog {    constructor(posts) {      this.posts = posts;    }  addPost(post) {      this.posts.push(post);    }  displayPosts() {      // 显示所有帖子    }  predictUserMoodBasedOnWritings(post) {      // 预测情绪的复杂算法      // ...      return "Happy"; // 只是一个示例情绪    }  notifyUserAboutMood(mood) {      // 通知逻辑      console.log(`Based on your writing, you seem to be ${mood}`);    }}

删除不必要功能后:gtd28资讯网——每日最新资讯28at.com

class Blog {    constructor(posts) {      this.posts = posts;    }  addPost(post) {      this.posts.push(post);    }  displayPosts() {      // 显示所有帖子    }}

5. SoC 原则

SoC,或“关注点分离”,建议不同的功能区域应由不同且最小重叠的模块管理。gtd28资讯网——每日最新资讯28at.com

例如,在一个天气应用程序中,一个模块可以处理数据获取,另一个可以管理数据存储,另一个则可以控制用户界面。每个都有自己的关注点,与其他模块分开。gtd28资讯网——每日最新资讯28at.com

// 1. 数据获取模块function fetchWeatherData(city) {    const apiKey = 'YOUR_API_KEY';    const response = fetch(`https://api.weather.com/v1/${city}?apiKey=${apiKey}`);    return response.json();}// 2. 数据存储模块function storeWeatherData(data) {    localStorage.setItem('weatherData', JSON.stringify(data));}// 3. 用户界面模块function displayWeatherData(data) {    const weatherBox = document.querySelector('#weather-box');    weatherBox.innerHTML = `<h1>${data.city}</h1><p>${data.temperature}°C</p>`;}// 在主应用程序函数中组合它们function weatherApp(city) {    const data = fetchWeatherData(city);    storeWeatherData(data);    displayWeatherData(data);}

6. LoD 原则

LoD(迪米特法则)是开发软件的一个指导原则,特别是面向对象的程序。在其一般形式中,LoD是松散耦合的一个具体案例。gtd28资讯网——每日最新资讯28at.com

想象一下餐厅的场景:顾客将订单(方法)交给服务员,然后服务员将订单交给厨师。顾客不直接与厨师互动。gtd28资讯网——每日最新资讯28at.com

class Customer {  constructor(waiter) {    this.waiter = waiter;  }  giveOrder(order) {    console.log("Customer: I'd like to order " + order);    this.waiter.takeOrder(order);  }}class Waiter {  constructor(chef) {    this.chef = chef;  }  takeOrder(order) {    console.log('Waiter: Order received - ' + order);    this.chef.prepareOrder(order);  }}class Chef {  prepareOrder(order) {    console.log('Chef: Preparing ' + order);    // Logic to prepare the food...  }}

7. COI 原则

组合优于继承原则(COI)建议使用组合(将简单对象组合以创建更复杂的对象)而不是类继承。gtd28资讯网——每日最新资讯28at.com

想象一下你有一个类 Bird 和一个类 Airplane。它们都能飞,但有继承关系并不合理。相反,你可以有一个 CanFly 类,并将你的 Bird 和 Airplane 类与它组合。gtd28资讯网——每日最新资讯28at.com

// 错误的方法:继承class CanFly {  fly() {    console.log(this.constructor.name + ' is flying!');  }}class BirdInherit extends CanFly {}class AirplaneInherit extends CanFly {}

通过以下组合方法,你可以轻松地向 BirdCompose 或 AirplaneCompose 添加或删除功能,而无需进行结构更改或添加不必要的冗余,强调灵活性。gtd28资讯网——每日最新资讯28at.com

// 正确的方法:组合class CanFlyComposition {  fly() {    console.log('Flying in the sky!');  }}class BirdCompose {  constructor() {    this.flyingCapability = new CanFlyComposition();  }  fly() {    this.flyingCapability.fly();  }}class AirplaneCompose {  constructor() {    this.flyingCapability = new CanFlyComposition();  }  fly() {    this.flyingCapability.fly();  }}

本文链接:http://www.28at.com/showinfo-26-27961-0.html每个开发者都应该知道的七个原则

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C++中生成二维码和识别二维码内容的方法

下一篇: C++中函数参数的优秀传递方式

标签:
  • 热门焦点
  • 鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    华为全新的HarmonyOS 4.0操作系统将于今天下午正式登场,官方在发布会之前也已经正式给出了可升级的机型产品,这意味着这些机型会率先支持升级享用。这次的HarmonyOS 4.0支持
  • 一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    终于,在经过了几波预热之后,一加Ace2 Pro的外观真机图在网上出现了。还是博主数码闲聊站曝光的,这次的外观设计还是延续了一加11的方案,只是细节上有了调整,例如新加入了钛空灰
  • 消息称迪士尼要拍真人版《魔发奇缘》:女主可能也找黑人演员

    消息称迪士尼要拍真人版《魔发奇缘》:女主可能也找黑人演员

    8月5日消息,迪士尼确实有点忙,忙着将不少动画改成真人版,继《美人鱼》后,真人版《白雪公主》、《魔发奇缘》也在路上了。据外媒消息称,迪士尼将打造真人版
  • 掘力计划第 20 期:Flutter 混合开发的混乱之治

    掘力计划第 20 期:Flutter 混合开发的混乱之治

    在掘力计划系列活动第20场,《Flutter 开发实战详解》作者,掘金优秀作者,Github GSY 系列目负责人恋猫的小郭分享了Flutter 混合开发的混乱之治。Flutter 基于自研的 Skia 引擎
  • SpringBoot中使用Cache提升接口性能详解

    SpringBoot中使用Cache提升接口性能详解

    环境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架从 3.1 开始,对 Spring 应用程序提供了透明式添加缓存的支持。和事务支持一样,抽象缓存允许一致地使用各
  • 如何通过Python线程池实现异步编程?

    如何通过Python线程池实现异步编程?

    线程池的概念和基本原理线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任
  • Python异步IO编程的进程/线程通信实现

    Python异步IO编程的进程/线程通信实现

    这篇文章再讲3种方式,同时讲4中进程间通信的方式一、 Python 中线程间通信的实现方式共享变量共享变量是多个线程可以共同访问的变量。在Python中,可以使用threading模块中的L
  • 阿里瓴羊One推出背后,零售企业迎数字化新解

    阿里瓴羊One推出背后,零售企业迎数字化新解

    作者:刘旷近年来随着数字经济的高速发展,各式各样的SaaS应用服务更是层出不穷,但本质上SaaS大多局限于单一业务流层面,对用户核心关切的增长问题等则没有提供更好的解法。在Saa
  • 回归OPPO两年,一加赢了销量,输了品牌

    回归OPPO两年,一加赢了销量,输了品牌

    成为OPPO旗下主打性能的先锋品牌后,一加屡创佳绩。今年618期间,一加手机全渠道销量同比增长362%,凭借一加 11、一加 Ace 2、一加 Ace 2V三款爆品,一加
Top