【问题标题】:Do we apply DRY principle only to the state of the object or also to its behavior?我们是仅将 DRY 原则应用于对象的状态还是也应用于其行为?
【发布时间】:2013-12-09 18:06:10
【问题描述】:

我很难理解 DRY 原理

1) 我知道 DRY 原则的目的是避免信息的重复/重复,但在 DRY 的上下文中,information 一词指的是什么?它是否仅引用the state of the object(即Person 实体应该只有一个表示其birth data 的属性)还是该术语也引用behavior of the object(即Dog 实体应该只有一个表示@ 的方法987654327@)

2) 问题假设术语information 也指behavior

DRY 就是不重复相同的信息,我将其解释为 我们不应该有两个或多个方法/代码 sn-ps 做完全相同的事情。但我认为术语repetition 在 DRY 的上下文中使用得更松散?也就是说,我已经看到了 DRY 也应用于具有 相似 行为的方法/代码 sn-ps 的示例(因此这些方法/代码 sn-ps 并没有做完全相同的事情)但是然后将这些方法/代码 sn-ps 替换为单个方法/代码 sn-p?!

谢谢

【问题讨论】:

  • Don't Repeat Yourself- 不要忘记你自己部分。每当您开始输入您已经输入的内容时,您的 DRY 警铃至少应该发出警告音。这实际上与状态或功能无关,而与代码重复有关。
  • @Floegipoky:“这与状态或功能无关”如果两个不同的类包含相同的状态,但是这两个状态中的每一个都是使用非常不同的逻辑获得的,或者如果两个类包含两个具有相同的方法行为,但是这两种行为是用两种截然不同的算法来表示的,那么根据你的说法,这不违反 DRY 吗?
  • 不,您又忘记了Yourself 部分。 DRY 不是一成不变的编程法则,它是当有人意识到重复往往会导致多少问题时提出的经验法则。不要去寻找涵盖其所有细微差别的定义。像许多其他软件工程术语一样,它实际上只是对特定代码气味的描述。代码可以逐字复制,也可以在设计级别复制。你评论中的两次反例尝试都是后者的例子,这种类型往往更难发现。
  • @Floegipoky:所以在设计层面重复的代码也违反了 DRY?
  • 通常,是的。就像我说的,不要去寻找 DRY 的定义,而是要了解促使为其创建标签的问题。这些问题主要涉及必须使多个相似的代码保持最新的额外复杂性。有些人将它应用于开发过程中涉及的所有内容,包括文档、样板代码等。每个人都有自己的工作定义;重要的是想想你(又是你自己)如何使用避免重复的原则来创建更好的软件。

标签: design-patterns dry


【解决方案1】:

1) “信息”是指任何一段代码

  • 来自大代码sn-p(到处手动计算一个数的平方根应该换成Sqrt方法)
  • 为一个简单的值(到处使用字符串“Monday”,应替换为一周中的天数的枚举)。

2) 如果两种方法相似,那么人们可以争辩说它的某些部分做了完全相同的事情。如果是这样,并且如果将这两种方法中的逻辑概括为解决一个通用问题而不是两个具体问题是可行的,那么它们应该被重构以符合 DRY 原则。

如果概括整个算法不可行,那么至少考虑重构执行完全相同操作的部分。

【讨论】:

    【解决方案2】:

    DRY 原则的存在主要是为了使增强和维护更容易。这个想法是每次引入重复时,可维护性和可扩展性都会下降。这里有两个例子:

    重复代码

    public class Dog {
    
        int barkCount = 0;
    
        public void bark(){
            println "bark";
            barkCount++;
        }
    
        public void defendHouse(){
            println "bark";
            barkCount++;
            println "run in circles";
        }
    
    }
    

    虽然这个例子有些原始,但你会看到 bark 中的逻辑在 defendHouse 中是重复的。出于以下几个原因,这是不可取的:

    • 代码更难阅读(更长、更多部分,开发人员必须注意重复)
    • 代码更难维护(开发人员在更新 bark() 逻辑时可能会忘记更新 defendHouse() 逻辑。)

    这两个要点都是长寿命软件的重要考虑因素(提示:所有软件都是长寿命的),因为它们是每次更改/读取都会产生的经常性成本。如果重复发生在更远的距离上,情况会更糟——例如,重复的逻辑可能位于不同的文件或包中。

    重复数据

    public class Person {
        String birthDay = null;
        Date birthDate = null;
    
        public void setBirthDate(Date newDate){
            birthDate = newDate;
            birthDay = newDate.getDayOfWeek();
        }
    
        public void clearBirthDate(){
            birthDate = null;
            birthDay = null;
        }
    
        public String getBirthDay(){
            if(newDate == null){
                return null;
            } else {
                return newDate.getDayOfWeek();
            }
        }
    }
    

    这里的问题是birthDay 是birthDate 的一个子集。这里最大的问题是:

    • 数据完整性:当另一个字段发生变化时,开发人员可能无法更新一个字段。可能很难保证一致性(例如,如果 newDate.getDayOfWeek() 引发异常,则字段可能会不同步)。
    • 可读性:此代码更难阅读,因为开发人员必须注意到birthDay 和birthDate 是相关联的(但仅按照惯例)。

    为了完整起见,这里有两个改进的例子,以及我对何时违反 DRY 原则的想法......

    清理:重复代码

    public class Dog {
    
        int barkCount = 0;
    
        public void bark(){
            println "bark";
            barkCount++;
        }
    
        public void defendHouse(){
            bark();
            println "run in circles";
        }
    
    }
    

    清理:重复数据

    public class Person {
        Date birthDate = null;
    
        public void setBirthDate(Date newDate){
            birthDate = newDate;
        }
    
        public void clearBirthDate(){
            birthDate = null;
        }
    
        public String getBirthDay(){
            if(newDate == null){
                return null;
            } else {
                return newDate.getDayOfWeek();
            }
        }
    
    }
    

    其他想法

    那么什么时候可以复制代码/数据?本节将主要基于我的经验/观点,因此请准备好不同意。

    • 对于非常简单的代码(如简单的表达式),重复可能是可以接受的。仅当表达式易于阅读、不易出错并且不容易与附近的某个逻辑实体分组时,这才是正确的。
    • 当语言不支持抽象来删除重复时。例如,由于 Java 没有闭包,因此从比较器和其他“函数对象”中删除重复项可能会让人厌烦。因此,某些类型的重复很常见。
    • 一旦遇到性能问题,可能需要复制数据以加快处理速度。
    • 您没有足够的时间让它“恰到好处”。这一点实际上更多是关于选择你的战斗。某些类型的复制比其他的更危险。很多时候,需求的变化会迫使重复到设计良好的系统中。唯一的解决办法可能很昂贵。在这种情况下,与您的团队/经理交谈并确定修复的重要性是有意义的。

    【讨论】:

      猜你喜欢
      • 2012-10-08
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      相关资源
      最近更新 更多