函数式编程初学者的 3 条代码整洁原则

2025-06-04

函数式编程初学者的 3 条代码整洁原则

1. 给事物起一个有意义的名字

当你给变量命名时,你给它起的名字必须能告诉我们这个变量的整个生命周期。它必须告诉我们这个变量是谁,以及它为什么存在。变量的名称是它的卖点,因此必须对其进行恰当的描述。

它应该告诉你它存在的原因、它的作用以及如何使用。如果一个名称需要注释,那么这个名称就没有意义。

替代文本

考虑变量

const p = [] //list of pets
Enter fullscreen mode Exit fullscreen mode

P 可以是任何值,当在复杂循环或函数中使用此变量时,这会使其更难读取。

这是一个更有意义的名字

const bertsPetList = []
Enter fullscreen mode Exit fullscreen mode

因为它告诉你

什么? 伯特的宠物列表
为什么? 用于对伯特和他的宠物感兴趣的代码操作
怎么做? 作为标准 js 数组

1.2 函数名必须体现意图

当命名一个函数时,我们还必须考虑“什么?”,“为什么?”和“如何?”

它起什么作用?
为什么这样做?
它是如何做到的?

举个例子,你想要获得特定主人可能拥有的动物列表,这些动物被允许与主人一起待在家里。

const bertsPets = [
    {
       name: "Snizzles"
       type: "nope"
       lives: "outdoors"
    },
    {
       name: "Terrance"
       type: "danger-woof"
       lives: "outdoors"
    },
    {
       name: "Kevin"
       type: "doggo"
       lives: "indoors"
    }
]
Enter fullscreen mode Exit fullscreen mode

例如,这种函数的名称可能是findPets,尽管名称有意义,但对于下一个阅读代码的程序员来说,它不足以轻松理解正在发生的事情。

所以也许你可以尝试一下这个名字findPetsThatLiveIndoors

这很好,但就 DRY 而言(我们将在下一节讨论这个问题),你的代码是有害的,因为对于每个生活区类型,你都必须创建一个与该类型相对应的函数,

const findPetsThatLiveIndoors = () => {}
const findPetsThatLiveOutdoors = () => {}
const findPetsThatLiveInOtherPlace1= () => {}
const findPetsThatLiveInOtherPlace2 = () => {}
Enter fullscreen mode Exit fullscreen mode

从而不必要地重复自己。(这很糟糕)
那么我们可以给我们的函数起什么名字呢?

const filterPetsByLivingAreaInList  = () => {}

// which could then be

const filterPetsByLivingAreaInList  = (area, list) => list.filter(pet => pet.lives === area)

// and can produce

const bertsIndoorPets = filterPetsByLivingAreaInList('indoors',bertsPets)

Enter fullscreen mode Exit fullscreen mode

现在这个名字告诉我们
什么? 生活在特定区域的宠物
如何? 通过过滤列表
为什么? 获取特定主人可能拥有并允许其在家中生活的动物列表

2.不要重复自己

DRY 原则简单地意味着您不应该有代码重复。

替代文本

2.1 变量作用域

当可以使用全局作用域时,不要为每个函数作用域重新创建变量,
例如

const getDoggosThatLiveIndoors = () => {
    const doggos = getPetsByType('doggo', bertsPets);
    const doggosThatLiveIndoors = filterPetsByLivingAreaInList('indoors', doggos);
    return doggosThatLiveIndoors;
}

const getDoggosThatLiveOutdoors= () => {
    const doggos = getPetsByType('doggo', bertsPets);
    const doggosThatLiveIndoors = filterPetsByLivingAreaInList('indoors', doggos);
    return doggosThatLiveOutdoors;
}

console.log(`${getDoggosThatLiveIndoors().length} doggos live indoors`)
console.log(`${getDoggosThatLiveOutdoors().length} doggos live outdoors`)
Enter fullscreen mode Exit fullscreen mode

在上面的例子中,变量 doggos 可以在全局范围内定义,以避免为每个函数重新定义它

const doggos = getPetsByType('doggo', bertsPets);

const getDoggosThatLiveIndoors = () => {
    const doggosThatLiveIndoors = filterPetsByLivingAreaInList('indoors', doggos);
    return doggosThatLiveIndoors;
}

const getDoggosThatLiveOutdoors = () => {
    const doggosThatLiveIndoors = filterPetsByLivingAreaInList('outdoors', doggos);
    return doggosThatLiveOutdoors;
}

console.log(`${getDoggosThatLiveIndoors().length} doggos live indoors`)
console.log(`${getDoggosThatLiveOutdoors().length} doggos live outdoors`)
Enter fullscreen mode Exit fullscreen mode

2.2 函数操作

在上面的例子中,两个函数getDoggosThatLiveIndoorsgetDoggosThatLiveOutdoors执行相同的操作,因此可以优化为一个

const doggos = getPetsByType('doggo', bertsPets);

const getDoggosByLivingArea = (areaType) => {
    const doggosInArea = filterPetsByLivingAreaInList(areaType, doggos);
    return doggosInArea;
}

const areaTypes = ['indoors', 'outdoors'];

areaTypes.map( type => 
    console.log(`${getDoggosByLivingArea(type).length} doggos live ${type}`)
)
Enter fullscreen mode Exit fullscreen mode

重复可能是软件中所有问题的根源。为了控制或消除重复,人们创建了许多原则和实践。

3. 函数应该只做一件事

在创建函数时,我们应该确保它们只实现一个定义的目标

现在想象以下函数

const favoritePets = ['cat', 'doggo']

const getFavoritePets = (favoritePets, petList) => {
       const ownerHasCats = hasPetType('cats', petList);
       if(!ownerHasCats){
          const cats = [cat1, cat2, cat3]
          const petsWithCats = insertPets(cats, petList)
          return filterPets(favoritePets, petsWithCats )
       }
       return filterPets(favoritePets, petList )
}
Enter fullscreen mode Exit fullscreen mode

这个函数应该只用来获取主人最喜欢的宠物,但它却试图查询主人的猫是否已添加到宠物列表中,如果不可用就添加。这违反了单一职责原则,因为这个函数做了太多事情。它有很多职责。它的名字就getFavoritePets
不合适getFavoritePetsAndCheckIfOwnerHasCatsIfNotAddCatsToTheOwnersPetList
😂

更好的方法是

const cats = [cat1, cat2, cat3]

const bertsPetsWithCats = insertPets(cats, bertsPets)

const favoritePets = ['cat', 'doggo']

const getFavoritePets = (favoritePetTypes, petList) => filterPets(favoritePetTypes, petList);

const bertsFavoritePets = getFavoritePets(favoritePets, bertsPetsWithCats);
Enter fullscreen mode Exit fullscreen mode

回顾

为了在函数式编程范式中编写干净的代码,我们必须遵循 3 个基本原则。

  1. 给事物起有意义的名字
  2. 不要重复自己
  3. 函数应该只做一件事

为了更深入地了解清洁代码,我建议您阅读清洁代码手册

大功告成 :)

这是一个代码土豆

替代文本

文章来源:https://dev.to/ayabongaqwabi/3-clean-code-principles-for-functional-programming-beginner-cc6
PREV
10 个很棒的 React 库和框架
NEXT
2019 年 Markdown 编辑器现状