创建一个仅用一个函数/模块/类就可以处理这组不同事物的抽象

简介: 在软件开发中,良好的变量名和函数名能够显著提升代码的可读性和可维护性。对于变量命名,建议使用有意义且易于发音的名字(如 `currentDate` 而非 `yyyymmdstr`),对同类变量使用一致的词汇(如统一使用 `getUser`),以及使用解释性的变量名以减少理解成本(如使用常量 `MILLISECONDS_IN_A_DAY` 替代数字 `86400000`)。此外,避免不必要的上下文重复,并使用默认参数代替逻辑运算。对于函数,应限制参数数量(理想情况下不超过两个),确保每个函数只做一件事,并且函数名应清晰描述其功能。通过遵循这些原则,代码将更加简洁明了。

在开发中,变量名,函数名一般要做到清晰明了,尽量做到看名字就能让人知道你的意图,所以变量和函数命名是挺重要,今天来看看如果较优雅的方式给变量和函数命名。

一、变量

使用有意义和可发音的变量名

// 不好的写法 const yyyymmdstr = moment().format("YYYY/MM/DD"); // 好的写法 const currentDate = moment().format("YYYY/MM/DD");
对同一类型的变量使用相同的词汇

// 不好的写法 getUserInfo(); getClientData(); getCustomerRecord(); // 好的写法 getUser();
使用可搜索的名字

我们读的会比我们写的多得多,所以如果命名太过随意不仅会给后续的维护带来困难,也会伤害了读我们代码的开发者。让你的变量名可被读取,像 buddy.js 和 ESLint 这样的工具可以帮助识别未命名的常量。

// 不好的写法 // 86400000 的用途是什么? setTimeout(blastOff, 86400000); // 好的写法 const MILLISECONDS_IN_A_DAY = 86_400_000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY);
使用解释性变量

// 不好的写法 const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,]+[,\s]+(.+?)\s(\d{5})?$/; saveCityZipCode( address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2] ); // 好的写法 const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,]+[,\s]+(.+?)\s(\d{5})?$/; const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode);
避免费脑的猜测

显式用于隐式

// 不好的写法 const locations = ["Austin", "New York", "San Francisco"]; locations.forEach(l => { doStuff(); doSomeOtherStuff(); // ... // ... // ... // 等等,“l”又是什么? dispatch(l); // 好的写法 const locations = ["Austin", "New York", "San Francisco"]; locations.forEach(location => { doStuff(); doSomeOtherStuff(); // ... // ... // ... dispatch(location); });
无需添加不必要的上下文

如果类名/对象名已经说明了,就无需在变量名中重复。

// 不好的写法 const Car = { carMake: "Honda", carModel: "Accord", carColor: "Blue" }; function paintCar(car) { car.carColor = "Red"; } // 好的写法 const Car = { make: "Honda", model: "Accord", color: "Blue" }; function paintCar(car) { car.color = "Red"; }
使用默认参数代替逻辑或(与)运算

// 不好的写法 function createMicrobrewery(name) { const breweryName = name || "Hipster Brew Co."; // ... } // 好的写法 function createMicrobrewery(name = "Hipster Brew Co.") { // ... }
二、函数

函数参数(理想情况下为2个或更少)

限制函数参数的数量是非常重要的,因为它使测试函数变得更容易。如果有三个以上的参数,就会导致组合爆炸,必须用每个单独的参数测试大量不同的情况。

一个或两个参数是理想的情况,如果可能,应避免三个参数。除此之外,还应该合并。大多数情况下,大于三个参数可以用对象来代替。
https://nanjing.92demo.com/sitemap
// 不好的写法 function createMenu(title, body, buttonText, cancellable) { // ... } createMenu("Foo", "Bar", "Baz", true); // 好的写法 function createMenu({ title, body, buttonText, cancellable }) { // ... } createMenu({ title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true });
函数应该只做一件事

这是目前为止软件工程中最重要的规则。当函数做不止一件事时,它们就更难组合、测试和推理。可以将一个函数隔离为一个操作时,就可以很容易地重构它,代码也会读起来更清晰。

// 不好的写法 function emailClients(clients) { clients.forEach(client => { const clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } }); } // 好的写法 function emailActiveClients(clients) { clients.filter(isActiveClient).forEach(email); } function isActiveClient(client) { const clientRecord = database.lookup(client); return clientRecord.isActive(); }
函数名称应说明其作用

// 不好的写法 function addToDate(date, month) { // ... } const date = new Date(); // 从函数名称很难知道添加什么 addToDate(date, 1); // 好的写法 function addMonthToDate(month, date) { // ... } const date = new Date(); addMonthToDate(1, date);
函数应该只有一个抽象层次

当有一个以上的抽象层次函数,意味该函数做得太多了,需要将函数拆分可以实现可重用性和更简单的测试。

// 不好的写法 function parseBetterJSAlternative(code) { const REGEXES = [ // ... ]; const statements = code.split(" "); const tokens = []; REGEXES.forEach(REGEX => { statements.forEach(statement => { // ... }); }); const ast = []; tokens.forEach(token => { // lex... }); ast.forEach(node => { // parse... }); } // 好的写法 function parseBetterJSAlternative(code) { const tokens = tokenize(code); https://92demo.com/sitemap/post49.html:const syntaxTree = parse(tokens); syntaxTree.forEach(node => { // parse... }); } function tokenize(code) { const REGEXES = [ // ... ]; const statements = code.split(" "); const tokens = []; REGEXES.forEach(REGEX => { statements.forEach(statement => { tokens.push(/ ... /); }); }); return tokens; } function parse(tokens) { const syntaxTree = []; tokens.forEach(token => { syntaxTree.push(/ ... /); }); return syntaxTree; }https://92demo.com/sitemap/post64.html
删除重复的代码

尽量避免重复的代码,重复的代码是不好的,它意味着如果我们需要更改某些逻辑,要改很多地方。

通常,有重复的代码,是因为有两个或多个稍有不同的事物,它们有很多共同点,但是它们之间的差异迫使我们编写两个或多个独立的函数来完成许多相同的事情。 删除重复的代码意味着创建一个仅用一个函数/模块/类就可以处理这组不同事物的抽象。

获得正确的抽象是至关重要的,这就是为什么我们应该遵循类部分中列出的 「SOLID原则」。糟糕的抽象可能比重复的代码更糟糕,所以要小心!说了这么多,如果你能做一个好的抽象,那就去做吧!不要重复你自己,否则你会发现自己在任何时候想要改变一件事的时候都要更新多个地方。

「设计模式的六大原则有」

Single Responsibility Principle:单一职责原则
Open Closed Principle:https://92demo.com/sitemap/post1.html,开闭原则
Liskov Substitution Principle:里氏替换原则
Law of Demeter:迪米特法则
Interface Segregation Principle:接口隔离原则
Dependence Inversion Principle:依赖倒置原则
把这六个原则的首字母联合起来(两个 L 算做一个)就是 SOLID (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。下面我们来分别看一下这六大设计原则。

「不好的写法」

相关文章
|
6月前
|
C++
C++ 接口的实现,及作用通俗理解方式
C++中的接口,一般就是指抽象类,是一种用来描述类对外提供的操作、方法或功能的集合——注意,一般只是描述(声明),而不对这些方法或功能进行定义实现,通常在
69 2
|
6月前
|
Java 程序员
揭秘编程世界的构造块:一文教你理解方法的本质与运用
揭秘编程世界的构造块:一文教你理解方法的本质与运用
39 0
|
6月前
|
存储 编译器 C语言
C++:类的概念
C++:类的概念
44 0
|
设计模式 存储 Java
JAVA设计模式11:组合模式,以统一的方式处理单个对象和组合对象
JAVA设计模式11:组合模式,以统一的方式处理单个对象和组合对象
169 0
|
算法 C++ 容器
关系类算法函数
关系类算法函数
|
编译器 C++
C++把类的设计看成类型设计
C++把类的设计看成类型设计
110 0
|
自然语言处理 编译器 程序员
带你读《计算机程序的构造和解释(原书第2版)典藏版》之一:构造过程抽象
《计算机程序的构造和解释(原书第2版)》1984年出版,成型于美国麻省理工学院(MIT)多年使用的一本教材,1996年修订为第2版。在过去的二十多年里,《计算机程序的构造和解释(原书第2版)》对于计算机科学的教育计划产生了深刻的影响。第2版中大部分重要程序设计系统都重新修改并做过测试,包括各种解释器和编译器。作者根据其后十余年的教学实践,还对其他许多细节做了相应的修改。
|
算法 程序员 网络架构
带你读《计算机程序的构造和解释(原书第2版)典藏版》之二:构造数据抽象
《计算机程序的构造和解释(原书第2版)》1984年出版,成型于美国麻省理工学院(MIT)多年使用的一本教材,1996年修订为第2版。在过去的二十多年里,《计算机程序的构造和解释(原书第2版)》对于计算机科学的教育计划产生了深刻的影响。第2版中大部分重要程序设计系统都重新修改并做过测试,包括各种解释器和编译器。作者根据其后十余年的教学实践,还对其他许多细节做了相应的修改。
下一篇
无影云桌面