如何避免硬编码_为什么应始终避免将类型编码为名称

如何避免硬编码

规则:命名变量时,即使使用动态类型的语言,也不要将其类型编码为名称。

需要静态和动态示例

在上一篇文章中,我谈到了良好命名的一般规则 。 在此,我简短地谈到了不将类型编码为变量名的想法。 但是,在选择这些通用规则时,我只考虑了与语言类型无关的事物。

语言可以是静态或动态类型。 它们的类型取决于其定义或任务。

对于静态和动态类型的语言,实际上都不要在名称中编码类型,这是一个好规则,但是两者之间的原因有所不同。 出于这个原因,我想另外发表一篇文章,重点介绍该规则及其原因。

静态类型语言

在Java之类的静态类型语言中,我们必须在定义变量时声明其类型。 因此,如果我想建立一个整数列表,我会写:

final List<Integer> integerList = new ArrayList<>();

请注意此处固有的信息重复。 我已经通知我的读者,我正在用List<Integer>创建一个整数List<Integer> ,而无需通过命名变量integerList来再次进行处理。 这是一个容易想到的名字,但是没有添加任何新信息,也没有告诉读者整数实际代表什么。 我可以使用以下名称来改进:

final List<Integer> primesList = new ArrayList<>();

现在,读者可以很容易地看出这是质数的列表,但是我仍然包含有关它是列表的重复信息。 这使名称面临潜在的风险,另一位开发人员意识到所有素数都是唯一的,并在将来更改类型。 现在,我们得出的定义具有误导性,例如:

final Set<Integer> primesList = new TreeSet<>();

由于SetList的用法完全不同,因此该变量的读者会感到困惑。 尽管此变量的定义站点提供了正确的信息,但如果距离其使用站点还有很长的路要走,那么读者将被认为是谎言。

public class Example  {
    private final Set<Integer> primesList = 
        new HashSet<>(); // This is the definition site

    // ...
    // A very long class full of code
    // ...

    private int doSomething ()  {
        //...
        this .primesList.add(prime); // Use-site: Here the name is misleading
        //...
    }
}

如果这里有错误,我们会使此代码的调试更加复杂。 对于使用站点的读者来说,可以对该对象进行排序,按索引访问,以及一堆不存在的其他功能。

显然,令人沮丧的是第二个作者没有更新名称以匹配类型的更改,但这并不意外。 这种变化经常发生在现实世界中。

并行数据通常是软件工程中问题的根源,因为保持同步具有挑战性。 在一个好的系统设计中,通常只有一个事实来源是优先事项,在好的编程中也是如此(写代码注释也是如此,我将在以后的文章中介绍)。 在静态类型的语言中,我们将来可以通过不对类型进行两次编码来证明我们的名称。

我最好调用上述函数primes ,使用名称的复数表示它是一个集合。 看起来像:

final Set<Integer> primes = new TreeSet<>();

在动态类型语言中

在像python这样的动态类型语言中,定义变量时不必声明变量的类型。 而是在分配时设置类型。 想象一下,我正在将Duck对象的集合传递给类似这样的函数:

def quack_all_ducks (ducksList) :
    for duck in ducksList:
        duck.quack()

在这里,我非常有意地探讨了动态类型语言的一项重要功能,即鸭子打字 (如果鸭子走路或说话的感觉很浓,那么它就是鸭子)。 这个想法是,在quack_all函数中,我实际上并不在乎输入是列表还是包含鸭子。 在此函数中,我真正关心的是,我可以遍历给定的项目,并且可以为每个项目调用quack()方法。 在此处对单词Listduck编码都限制了此功能的功能。 我放弃了使用动态类型语言的主要优势之一。

此方法将对传递的所有内容调用quack; 甚至是鹅 该代码可以正确执行,但对读者而言却是意外的(而且更难调试- 为什么我所有的鹅都发出嘎嘎声? )。 例如:

def on_loud_noise (pond_area) :
    birds = [pond_area.get_all_ducks()] + [pond_area.get_all_geese()] 
    quack_all_ducks(birds)
    #...

如果不进一步研究代码,这也使鹅很震惊。 简洁代码的症结在于使编写者付出了更多工作,以简化读者的生活。

我最好将参数命名为quackables 。 这表示它是一个遍历多个的迭代(集合),并且每个内容都可以被quacked 。 看起来像:

def quack_all_quackables (quackables) :
    for quackable in quackables:
        quackable.quack()

现在, quack_all函数可用于可能会quack_all的任何东西,例如鹅或天鹅的集合。 在动态类型语言中,将类型编码为名称会抵消鸭子输入的能力。

现在,我们的呼叫站点将如下所示:

def on_loud_noise (pond_area) :
    birds = [pond_area.get_all_ducks()] + [pond_area.get_all_geese()] 
    quack_all_quackables(birds)
    #...

既然鹅发出嘎嘎声,这对于读者来说也很清楚,他们也会被嘎嘎叫。

翻译自: https://hackernoon.com/why-you-should-always-avoid-encoding-type-into-names-f62y37ba

如何避免硬编码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值