Questions tagged «clean-code»

术语“干净的代码”用于描述简洁,易于理解并清楚表达程序员意图的计算机编程代码。带有此标签的问题与编写干净代码或将旧的“脏”代码重构为干净代码的过程有关。

11
多少个设计模式和抽象级别是必需的?[关闭]
我怎样才能知道我的软件有太多的抽象和太多的设计模式,或者反过来,我怎么知道它是否应该有更多的抽象呢? 与我合作的开发人员在这些方面的编程方式有所不同。 有些人确实提取每个小功能,尽可能使用设计模式,并不惜一切代价避免冗余。 其他人,包括我在内,都试图更加务实,并编写出并非完全适合每种设计模式的代码,但由于应用了较少的抽象,因此其理解速度更快。 我知道这是一个权衡。我如何知道何时将足够的抽象放入项目中,又如何知道需要更多抽象呢? 例如,当使用Memcache编写通用缓存层时。难道我们真的需要Memcache,MemcacheAdapter,MemcacheInterface,AbstractCache,CacheFactory,CacheConnector,...,或者这是更易于维护和使用仍然只有一半时,好的代码这些类的? 在Twitter中找到了这个: (https://twitter.com/rawkode/status/875318003306565633)

6
您从处理技术债务中看到了什么收获?
关于技术债务的这篇文章有一些优点,包括: 当故事驱动时,处理“技术问题”最有效。代码库可能在任何地方都需要工作,但是由于面向用户的原因,只有在要处理代码的地方才能收到回报。如果没有故事要经过某个棘手的领域,那么在这方面的工作就会被浪费掉。 因此,我更喜欢像往常一样拍摄故事(但可能更少),并遵循“童子军规则”,使故事比您发现的更好。换句话说,无论故事指引到哪里,让我们编写更多测试,让我们更积极地重构。 这种方法至少具有以下优点: 保持“最明智”的故事流; 提供所有团队人才的帮助; 让整个团队学习如何保持代码干净; 将改进的重点放在需要的地方; 不会浪费“可能”需要的改进; 我已经看到代码质量对长期生产力有很大的影响,所以我相信应该处理技术债务。我认为上面的帖子很有道理,但是我对最后两点不太确定。我有兴趣了解清除技术债务带来的收益的真实经验,即使这与用户故事无关。 通过清理代码库和消除技术债务,您看到了哪些积极的好处?您使用什么方法来完成工作?

4
像这样的代码是“火车残骸”吗(违反了得墨meter耳定律)?
浏览我编写的一些代码后,我遇到了以下使我思考的结构。乍一看,它似乎足够干净。是的,在实际代码中,该getLocation()方法的名称稍微更具体一些,可以更好地准确描述其到达的位置。 service.setLocation(this.configuration.getLocation().toString()); 在这种情况下,service是在方法中声明的已知类型的实例变量。this.configuration从传递给类构造函数开始,它是实现特定接口(强制使用公共getLocation()方法)的类的实例。因此,表达式的返回类型this.configuration.getLocation()是已知的。特别是在这种情况下,它是一个java.net.URL,而service.setLocation()想要一个String。由于这两种类型的字符串和URL不直接兼容,一些类型的转换的需要,以适应方形挂在圆孔。 但是,根据Clean Code中引用的Demeter定律,类C中的方法f应该仅调用C上的方法,由f创建或作为f的参数传递的对象以及C的实例变量中包含的对象。超出此范围的任何内容(除非是我在上面特定情况下的最终结果,除非您考虑由于方法调用本身而创建的临时对象,在这种情况下,整个法律似乎都没有意义)。toString() 考虑到列出的限制条件,为什么不鼓励或什至不允许上述呼叫,所以有合理的理由吗?还是我只是太挑剔了? 如果我要实现一种方法URLToString(),该方法只是调用作为参数传递给它toString()的URL对象(例如,由返回getLocation()),然后返回结果,则可以将getLocation()调用包装在其中以实现完全相同的结果;有效地,我只是将转换向前移了一步。那会以某种方式使其可以接受吗?(在我看来,从直觉上看,这两种方式都不应该有任何区别,因为所做的只是稍微移动一下东西。但是,按照所引用的《得墨meter耳定律》的信,这是可以接受的,因为我然后直接在函数的参数上进行操作。) 如果这比调用toString()标准类型更具有异国情调,会有所不同吗? 在回答时,请切记,更改service变量所属类型的行为或API 是不切实际的。同样,为了争辩,我们说改变返回类型getLocation()也是不切实际的。

7
软件腐烂主要是指性能还是凌乱的代码?
维基百科对软件腐烂的定义集中在软件的性能上。这与我习惯的用法不同。在代码的整洁和设计方面,我想的更多,在代码具有所有标准质量特征(可读性,可维护性等)方面。现在,当代码变得不可读时,性能可能会下降,因为没人知道发生了什么。但是术语“软件腐烂”是否对性能有特别的提及?还是我认为它是指代码的整洁性对吗?或者这可能是该术语在多种意义上被普遍使用的情况-从用户的角度来看,这与性能有关;但是对于软件工匠而言,它必须更专门地处理代码的读取方式?

3
在测试和生产代码之间复制常量?
在测试和真实代码之间复制数据是好是坏?例如,假设我有一个Python类FooSaver,该类将具有特定名称的文件保存到给定目录: class FooSaver(object): def __init__(self, out_dir): self.out_dir = out_dir def _save_foo_named(self, type_, name): to_save = None if type_ == FOOTYPE_A: to_save = make_footype_a() elif type == FOOTYPE_B: to_save = make_footype_b() # etc, repeated with open(self.out_dir + name, "w") as f: f.write(str(to_save)) def save_type_a(self): self._save_foo_named(a, "a.foo_file") def save_type_b(self): self._save_foo_named(b, "b.foo_file") 现在,在我的测试中,我想确保所有这些文件均已创建,因此我想说一下这样的话: …

6
5的规则-是否使用?
的3中的规则(5规则状态在新的C ++标准): 如果您需要自己显式声明析构函数,复制构造函数或复制赋值运算符,则可能需要显式声明这三个函数。 但是,另一方面,马丁的“ 清理代码 ”建议删除所有空的构造函数和析构函数(第293页,G12:Clutter): 没有实现的默认构造函数有什么用?它要做的只是用毫无意义的工件使代码混乱。 那么,如何处理这两种相反的意见呢?是否应该真正实现空的构造函数/析构函数? 下一个示例准确地说明了我的意思: #include <iostream> #include <memory> struct A { A( const int value ) : v( new int( value ) ) {} ~A(){} A( const A & other ) : v( new int( *other.v ) ) {} A& operator=( const A & other …

5
设计语言是否可以强制执行“干净代码”?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 因此,我正在用C ++编写我的第一个项目,似乎需要更多的精力来使代码“干净”,而不仅仅是工作。也就是说,似乎C ++允许编写丑陋但有效的代码。 这让我开始思考, 编程语言可以通过设计强制执行干净的代码吗?已经有这样的语言了吗? 另外,如何将其作为设计原则纳入编程语言开发/理论中?使用什么样的措施?

16
否则块会增加代码复杂度吗?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 这是一个非常简化的示例。这不一定是特定于语言的问题,我想请您忽略函数编写的许多其他方式以及可以对其进行的更改。。颜色是一种独特的类型 string CanLeaveWithoutUmbrella() { if(sky.Color.Equals(Color.Blue)) { return "Yes you can"; } else { return "No you can't"; } } 我遇到的很多人,ReSharper和这个人(其评论提醒我我一直想问这个问题已经有一段时间了)建议重构代码以删除else留下的代码块: (我不记得大多数人所说的话,否则我可能不会问这个) string CanLeaveWithoutUmbrella() { if(sky.Color.Equals(Color.Blue)) { return "Yes you can"; } return "No you can't"; } 问题:不包括else块会导致复杂性增加吗? else通过说明两个模块中的代码直接相关的事实,我给人的印象更直接地表明了意图。 另外,我发现我可以防止逻辑上的细微错误,尤其是在以后对代码进行修改之后。 以我的简化示例的这种变化形式为例(or由于这是故意简化的示例,因此请忽略运算符): bool CanLeaveWithoutUmbrella() { if(sky.Color != Color.Blue) { …

3
等待需求时对草率代码进行低影响的重构和代码清理
我继承了一个草率的产品的现有代码库。基本设计严重不足,不幸的是,如果没有完整的重构,我将无能为力(高耦合,低内聚,猖ramp的代码重复,没有技术设计文档,集成测试而不是单元测试)。该产品具有悠久的历史,对关键的“现金牛”客户敞口高,对风险的承受力最小,将使希腊人脸红的技术债务,非常庞大的代码库和复杂性,以及之前团队疲于奔命的错误解决方法我。 老团队跳船到另一个部门,以便他们有机会毁掉另一个项目。我很少遇到技术上无能力的项目失败,而不是项目管理失败,但这确实是其中一种。 就目前而言,我自己一个人,但我有很多时间,决定权和未来方向的自由,并且有能力从头开始建立团队来帮助我。 我的问题是,当您在功能需求收集阶段有一些空闲时间时,就对这样的项目的低影响重构收集意见。有成千上万的编译器警告,几乎所有警告都未使用的导入,未读的局部变量,没有类型检查和不安全的强制转换。代码格式是如此的难以理解和草率,以至于编码人员患有帕金森氏病,无法控制在任何给定行上按下空格键的次数。通常会打开其他数据库和文件资源,并且永远不会安全关闭它们。无意义的方法参数,执行相同操作的重复方法等。 在等待下一个功能的要求时,我一直在清理低冲击力,低风险的物品,并想知道自己是在浪费时间还是在做正确的事情。如果新功能意味着删除我之前花费时间的代码怎么办?我将开始一种敏捷方法,并且我知道这在敏捷开发过程中不断重构是可以接受和正常的。 您能想到我要添加的任何正面或负面影响吗?

9
是否根据最佳实践检查冗余条件?
在过去的三年中,我一直在开发软件,但是最近我才意识到自己对良好实践的无知。这使我开始阅读《清洁代码》一书,这使我的生活变得更好,但我一直在努力了解一些编写程序的最佳方法。 我有一个Python程序,其中... 使用argparse required=True强制使用两个参数,它们都是文件名。第一个是输入文件名,第二个是输出文件名 具有readFromInputFile首先检查输入文件名已被输入的功能 具有writeToOutputFile首先检查查看输入的文件名的功能 我的程序很小,导致我相信#2和#3中的检查是多余的,应将其删除,从而将这两个功能从不必要的if条件中解放出来。但是,我还被认为“双重检查是可以的”,并且可能是一个程序的正确解决方案,在该程序中可以从不进行参数解析的其他位置调用函数。 (此外,如果读取或写入失败,我try except在每个函数中都有一个引发相应的错误消息。) 我的问题是:最好避免所有冗余条件检查?程序的逻辑是否应该如此扎实,以至于检查只需进行一次?有没有很好的例子说明这一点或相反的情况? 编辑:谢谢大家的答案!我从每个人那里学到了一些东西。看到如此多的观点使我对如何解决这个问题以及根据我的需求确定解决方案有了更好的理解。谢谢!

2
将清洁代码原则应用于功能语言
我目前正在阅读Robert Martin的Clean Code。我认为这很棒,在编写OO代码时,我会牢记他的课程。特别是,我认为他的建议是使用带有有意义名称的小函数,这使我的代码流程更加流畅。最好通过以下引用来总结: [W] e希望能够像读取一组TO段落一样阅读该程序,每个段落都描述了当前的抽象级别,并在下一层向下引用了后续的TO段落。 (清洁代码,第37页:“ TO段落”是一个以不定式表达的句子开头的段落。“要做X,我们执行步骤Y和Z。”“要做Y,我们...”等。 ) 例如: 对于RenderPageWithSetupsAndTeardowns,我们检查该页面是否为测试页面,如果是,则包括设置和拆卸。无论哪种情况,我们都以HTML呈现页面 我也为我的工作编写功能代码。马丁在书中的例子确实读起来好像是一段段落,而且非常清楚-但我不确定“读起来像一组段落”是否适合功能代码使用。 以Haskell标准库为例: maximumBy :: (a -> a -> Ordering) -> [a] -> a maximumBy _ [] = error "List.maximumBy: empty list" maximumBy cmp xs = foldl1 maxBy xs where maxBy x y = case cmp x y of GT -> …

5
如何避免过多的方法重载?
我们的应用程序源代码中有很多地方,其中一个类有许多具有相同名称和不同参数的方法。这些方法始终具有“上一个”方法的所有参数,再加上一个。 这是经过长期发展(遗留代码)和这种想法(我相信)的结果: “ 有一个方法M做A,我需要做A +B。好吧,我知道...我将向M添加一个新参数,为此创建一个新方法,将代码从M移到新方法使用一个以上的参数,在那儿执行A + B,然后使用新参数的默认值从M调用新方法。 ” 这是一个示例(类似于Java的语言): class DocumentHome { (...) public Document createDocument(String name) { // just calls another method with default value of its parameter return createDocument(name, -1); } public Document createDocument(String name, int minPagesCount) { // just calls another method with default value of its …

8
打破“完美程序员综合症”的方法
很难说出这里的要求。这个问题是模棱两可,含糊,不完整,过于宽泛或夸张的,不能以目前的形式合理地回答。如需帮助澄清此问题以便可以重新打开, 请访问帮助中心。 7年前关闭。 我可能不是唯一这样的人。但是我倾向于称之为“完美程序员的综合症”,许多人可能会说它与完美主义者相同,但是在这种情况下,它属于编程领域。但是,对于这种综合症,编程领域有点问题。 您是否曾经感到过,当您进行编程时,您对自己的代码是否干净,遵循大多数最佳实践的良好代码的信心不足或从来没有足够的自信?有太多的规则要遵循,我觉得有点不知所措。当然,我并不是程序员,我喜欢编程,我认为这是一门艺术,因此我必须遵守规则。但是我也喜欢它,我的意思是我想并且我喜欢遵守规则,以便对自己正在做的事情有个很好的感觉。有关最佳做法和良好代码的信息。 也许是缺乏组织?也许是缺乏经验?也许缺乏实践?也许缺少其他人可以指出的东西?有什么办法可以摆脱这种综合征吗?

5
如果有条件,则返回set.add()的布尔值?
set类的add运算符返回一个布尔值,如果元素(要添加的元素)不存在则为true,否则为false。在写字 if (set.add(entry)) { //do some more stuff } 在编写简洁的代码方面被认为是好的风格?我想知道既然您一次执行两项操作。1)添加元素,2)检查元素是否存在。

3
简洁的代码:使用较少参数的简短方法的后果
最近,在代码审查期间,我遇到了一个新同事写的代码,其中包含带有气味的模式。我怀疑我同事的决定是基于著名的《清洁法规》(也许还有其他类似书籍)提出的规则。 据我了解,类构造函数完全负责创建有效对象,并且其主要任务是分配对象的(私有)属性。当然,可能会通过类构造器以外的方法设置可选属性值,但是这种情况很少见(尽管不一定是错误的,只要类的其余部分都考虑了此类属性的可选性)。这很重要,因为它可以确保对象始终处于有效状态。 但是,在我遇到的代码中,大多数属性值实际上是由构造方法以外的其他方法设置的。计算得出的值被分配给属性,以便在整个类的多个私有方法中使用。作者似乎在使用类属性,好像它们是应在整个类中访问的全局变量一样,而不是将这些值参数化为需要它们的函数。此外,应按特定顺序调用类的方法,因为否则该类不会做很多事情。 我怀疑这段代码是受建议的启发而提出的,即应保持方法简短(<= 5行代码),以避免大的参数列表(<3个参数),并且构造函数一定不能工作(例如执行某种计算)这对于对象的有效性至关重要。 现在,如果可以证明当未按特定顺序调用方法时,可能会出现各种不确定的错误,那么我当然可以反对这种模式。但是,我预测对此的响应将是添加验证,以验证一旦调用需要设置那些属性的方法,就必须设置属性。 但是,我宁愿建议完全更改代码,以使该类成为实际对象的蓝图,而不是应按特定顺序调用(过程上)的一系列方法。 我觉得我遇到的代码有异味。实际上,我相信在何时将值保存在类属性中以及何时将其保存到参数中以供不同方法使用方面存在明显的区别-我真的不相信它们可以彼此替代。我正在寻找这种区别的词。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.