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

简介: 在软件开发中,良好的变量名和函数名能够显著提升代码的可读性和可维护性。对于变量命名,建议使用有意义且易于发音的名字(如 `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,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。下面我们来分别看一下这六大设计原则。

「不好的写法」

相关文章
|
30天前
|
设计模式
建模底层逻辑问题之以命令设计模式为例,要用定义法建模,如何实现
建模底层逻辑问题之以命令设计模式为例,要用定义法建模,如何实现
|
19天前
|
SQL 开发者
访问者模式问题之FunctionExtractor是怎么工作的,以从SqlNode中提取函数名称的
访问者模式问题之FunctionExtractor是怎么工作的,以从SqlNode中提取函数名称的
|
23天前
|
设计模式
抽象工厂和原型设计模式之间的区别
【8月更文挑战第22天】
28 0
|
3月前
|
Java
Java面向对象特征(一)----- 封装
Java面向对象特征(一)----- 封装
|
4月前
|
C++
C++ 接口的实现,及作用通俗理解方式
C++中的接口,一般就是指抽象类,是一种用来描述类对外提供的操作、方法或功能的集合——注意,一般只是描述(声明),而不对这些方法或功能进行定义实现,通常在
55 2
|
4月前
|
Java 程序员
揭秘编程世界的构造块:一文教你理解方法的本质与运用
揭秘编程世界的构造块:一文教你理解方法的本质与运用
21 0
|
算法 C++ 容器
关系类算法函数
关系类算法函数
|
安全 搜索推荐
如何避免写重复代码?两种常见的方法:抽象和组合
如何避免写重复代码?两种常见的方法:抽象和组合
218 0
|
存储 编译器 C语言
C++ 基础篇之类 & 对象的关系
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
|
编译器 C++
C++把类的设计看成类型设计
C++把类的设计看成类型设计
104 0