Questions tagged «clean-code»

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

6
如何避免在次优设计中无休止地迭代?
因此,可能像许多人一样,我经常发现自己对设计问题感到头疼,例如,有些设计模式/方法似乎可以直观地解决问题并具有预期的好处。通常会有一些警告,如果没有某种工作就很难实施模式/方法,而这周围的工作否定了模式/方法的好处。我可以很轻松地结束许多模式/方法的迭代,因为可以预见的是,几乎所有的模式/方法在现实世界中都存在一些非常重要的警告,在这些情况下,根本没有一个简单的解决方案。 例: 我将给您一个假设的示例,大致基于我最近遇到的一个真实示例。假设我想在继承上使用合成,因为过去继承层次结构阻碍了代码的可伸缩性。我可能会重构代码,但随后发现在某些上下文中,超类/基类只是需要在子类上调用功能,尽管尝试避免这样做。 下一个最好的方法似乎是实现一半委托/观察者模式和一半组合模式,以便超类可以委托行为,或者子类可以观察超类事件。然后,该类的可伸缩性和可维护性较差,因为它不清楚应如何扩展,而且扩展现有的侦听器/代理也很棘手。同样,信息也隐藏得不好,因为人们开始需要了解实现以了解如何扩展超类(除非您非常广泛地使用注释)。 因此,在此之后,我可能会选择完全使用观察者或委托人来避免因混淆大量方法而带来的弊端。但是,这有其自身的问题。例如,我可能会发现我最终需要观察者或代表来应对越来越多的行为,直到我几乎需要针对每种行为的观察者/代表。一种选择可能是只为所有行为提供一个大的侦听器/代理,但是实现类最终会带有许多空方法等。 然后,我可以尝试另一种方法,但是与此同时存在很多问题。然后是下一个,然后是下一个,依此类推。 当每种方法似乎都存在其他问题时,这种迭代过程将非常困难,并导致某种设计决策瘫痪。无论使用哪种设计模式或方法,都很难接受代码最终同样会带来问题。如果我最终陷入这种情况,是否意味着问题本身需要重新考虑?别人遇到这种情况时会做什么? 编辑: 似乎有一些我想清除的问题的解释: 我将OOP完全排除在问题之外,因为事实证明它实际上并不是特定于OOP的,而且很容易误解我在传递OOP时所做的一些评论。 有些人声称我应该采取迭代的方法并尝试不同的模式,或者当它停止工作时我应该放弃一个模式。这是我首先要参考的过程。我认为这个例子很清楚,但是我可以更清楚一点,所以我编辑了问题。

1
难以掌握现实生活中的干净代码
我目前正在阅读和阅读Robert C. Martin撰写的“清洁代码:敏捷软件工艺手册”。作者讨论了一个函数应该如何仅做一件事情,因此比较简短。马丁特别写道: 这意味着if语句,else语句,while语句等中的块应为一行。该行可能是函数调用。这不仅使封闭函数保持较小状态,而且还增加了文档价值,因为在块中调用的函数可以具有很好的描述性名称。 这也意味着函数不应足够大以容纳嵌套结构。因此,函数的缩进级别不应大于一或两个。当然,这使功能更易于阅读和理解 这是有道理的,但似乎与我认为干净的代码示例存在冲突。以以下方法为例: public static boolean millerRabinPrimeTest(final int n) { final int nMinus1 = n - 1; final int s = Integer.numberOfTrailingZeros(nMinus1); final int r = nMinus1 >> s; //r must be odd, it is not checked here int t = 1; if (n >= 2047) { …
10 clean-code 

2
避免获取和设置方法,显示用户信息
背景 我正在阅读“清洁代码手册”,并且在并行中,我正在像银行账户那样从事诸如体操之类的身体对象卡塔(Kata)的研究: 健美操对象的第9条规则是我们不要使用吸气剂或吸气剂。 看起来很有趣,我同意这一原则。而且,在“清洁代码”的第98-99页,作者解释说,getters / setters破坏了抽象,并且我们不必询问对象,而必须告诉对象。 在我看来,这是完全合理的,我完全同意这一原则。问题出在实践中。 语境 例如,我有一个必须列出一些用户并显示用户详细信息的应用程序。 我的用户包括: -> Name --> Firstname --> String --> Lastname --> String -> PostalAddress --> Street --> String --> PostalCode --> String 问题 当我只需要显示一个简单的信息(并且我必须确认我不需要对该特定字段进行额外的操作)时,我该怎么办?或者如何避免吸气剂以简单的方式显示Firstname值(随机)输出支持? 我想到什么 一种解决方案是: user.getName().getFirstName().getStringValue() 这非常可怕,违反了许多健美操规则,并违反了Demeter法则。 另一个可能是这样的: String firstName = user.provideFirstnameForOutput(); // That would have called in the user object …

3
干净的代码和混合对象以及功能嫉妒
因此,我最近对代码进行了一些重大的重构。我试图做的主要事情之一就是将类分为数据对象和辅助对象。除其他外,这是由“ 清洁代码”的这一部分启发的: 杂种 这种混乱有时会导致不幸的混合数据结构,即一半对象和一半数据结构。它们具有执行重要功能的函数,也具有公共变量或公共访问器和更改器,它们出于所有意图和目的,将私有变量公开,从而诱使其他外部函数以程序程序将要使用的方式使用这些变量。数据结构。 这样的混合体很难添加新功能,但是也很难添加新的数据结构。他们是两全其美的。避免创建它们。它们表示设计混乱,其作者不确定(或者更糟,是无知)他们是否需要保护功能或类型。 最近,我正在查看我的一个工作对象(恰好实现了Visitor模式)的代码,并看到了: @Override public void visit(MarketTrade trade) { this.data.handleTrade(trade); updateRun(trade); } private void updateRun(MarketTrade newTrade) { if(this.data.getLastAggressor() != newTrade.getAggressor()) { this.data.setRunLength(0); this.data.setLastAggressor(newTrade.getAggressor()); } this.data.setRunLength(this.data.getRunLength() + newTrade.getLots()); } 我立即对自己说:“功能令人羡慕!这种逻辑应该在Data类中-特别是在handleTrade方法中。handleTrade并且updateRun应该始终一起发生”。但是后来我想到“数据类仅仅是一个public数据结构,如果我开始这样做,那么它将成为一个混合对象!” 有什么更好的,为什么?您如何决定该做什么?

5
纯功能的解决方案能否像当务之急一样干净?
我在Python中有一个练习,如下所示: 多项式作为系数的元组给出,因此幂由索引确定,例如:(9,7,5)表示9 + 7 * x + 5 * x ^ 2 编写一个函数以计算给定x的值 由于我最近从事函数式编程,所以我写了 def evaluate1(poly, x): coeff = 0 power = 1 return reduce(lambda accu,pair : accu + pair[coeff] * x**pair[power], map(lambda x,y:(x,y), poly, range(len(poly))), 0) 我认为这不可读,所以我写了 def evaluate2(poly, x): power = 0 result = 1 return reduce(lambda accu,coeff …

7
冗余检查条件是否不好?
我经常在代码中找到一些位置,一遍又一遍地检查特定条件。 我想举一个小例子:假设有一个文本文件,其中包含以“ a”开头的行,以“ b”开头的行以及其他行,而我实际上只想使用前两种行。我的代码看起来像这样(使用python,但将其读取为伪代码): # ... clear_lines() # removes every other line than those starting with "a" or "b" for line in lines: if (line.startsWith("a")): # do stuff elif (line.startsWith("b")): # magic else: # this else is redundant, I already made sure there is no else-case # by using clear_lines() …

4
处理响应的设计模式
大多数时候,当我编写一些代码来处理某个函数调用的响应时,我会得到以下代码结构: 示例:此功能将处理登录系统的身份验证 class Authentication{ function login(){ //This function is called from my Controller $result=$this->authenticate($username,$password); if($result=='wrong password'){ //increase the login trials counter //send mail to admin //store visitor ip }else if($result=='wrong username'){ //increase the login trials counter //do other stuff }else if($result=='login trials exceeded') //do some stuff }else if($result=='banned ip'){ //do …

6
抽象类应包含哪些代码?
最近,我对抽象类的使用感到困扰。 有时,会预先创建一个抽象类,并将其作为派生类工作方式的模板。这意味着或多或少地,它们提供了一些高级功能,但是遗漏了某些细节要由派生类实现。抽象类通过放置一些抽象方法来定义对这些细节的需求。在这种情况下,抽象类的工作原理类似于蓝图,功能的高级描述或您想要的任何名称。它不能单独使用,而必须专门用于定义高层实现中遗漏的细节。 在另一些时候,碰巧抽象类是在创建一些“派生”类之后创建的(由于父/抽象类还不存在,所以还没有派生出来,但是您知道我的意思)。在这些情况下,抽象类通常用作放置当前派生类所包含的任何常见代码的地方。 做出上述观察后,我想知道这两个案例中的哪一个应该成为规则。是否应该仅由于它们当前在所有派生类中都是通用的,而将某种细节冒充到抽象类?是否应该存在不属于高级功能的通用代码? 对于抽象类本身可能没有意义的代码是否应该仅仅因为它对派生类是通用的而存在呢? 让我举个例子:抽象类A有一个方法a()和一个抽象方法aq()。在派生类AB和AC中,方法aq()都使用方法b()。b()应该移到A吗?如果是的话,那么如果有人只看着A(假装AB和AC不在那儿),那么b()的存在就没有多大意义了!这是坏事吗?有人应该能够在不访问派生类的情况下浏览抽象类并了解发生了什么吗? 老实说,在提出这个问题时,我倾向于认为编写一个有意义的抽象类而不必查看派生类是一个干净的代码和干净的体系结构的问题。我真的不喜欢抽象类的想法,它像所有代码的转储一样在所有派生类中都很常见。 您如何看待/实践?

1
“ TILT”在评论中是什么意思?
我正在阅读Robert C. Martin的Clean Code,该短语TILT在某些代码示例中莫名其妙地出现。示例(顺便说一下,它是在Java中): ... public String errorMessage() { switch (status) { case ErrorCode.OK: // TILT - Should not get here. return ""; case ErrorCode.UNEXPECTED_ARGUMENT: return "Unexpected argument"; case ErrorCode.MISSING_ARGUMENT: return "Missing argument"; ... } ... 从上下文来看,我猜测是TILT指定一个无法访问的状态,并且仅包含该状态以满足编译器的要求(例如,在上面的代码中,TILT出现这种ErrorCode.OK情况是因为如果状态为OK,则不会出现错误消息),但是我不确定。 有人知道TILT代表/意味着什么吗?

7
我是否使我的课程过于细腻?单一责任原则应如何应用?
我编写了许多涉及三个基本步骤的代码。 从某处获取数据。 转换数据。 将该数据放在某处。 我通常最终使用三种类型的类-受它们各自的设计模式的启发。 工厂-从某些资源构建对象。 调解员-要使用工厂,执行转换,然后使用指挥官。 指挥官-将数据放在其他地方。 我的班级往往很小,通常是一个(公共)方法,例如获取数据,转换数据,执行工作,保存数据。这导致类的激增,但总体上效果很好。 我在进行测试时遇到的困难是,我最终会紧密耦合测试。例如; 工厂-从磁盘读取文件。 指挥官-将文件写入磁盘。 没有其他人,我无法测试。我可以编写其他“测试”代码来进行磁盘读/写操作,但是随后我要重复一遍。 看看.Net,File类采用了不同的方法,它将(我的)工厂和指挥官的职责结合在一起。它具有“创建”,“删除”,“存在”和“全部读取”功能。 我是否应该遵循.Net的示例并将我的类结合在一起(尤其是在处理外部资源时)?它仍然耦合了代码,但是它更具故意性-它发生在原始实现中,而不是在测试中。 我在这里是否过于狂热地应用了“单一责任原则”?我有负责读和写的单独的类。当我可以拥有一个负责处理特定资源(例如系统磁盘)的组合类时。

6
如何在switch语句中减少switch?
因此,我正在基于数据库中的两个人创建一种称呼行的方法。 有四个参数:两个名称(name1和name2)和两个性别(gender和gender2)。 对于每种性别组合,我都有不同的输出。 例如:如果性别1为M(man)且性别2也为M,则输出应为: Dear Sir name1 and Sir name2, 此时,我的开关如下所示: switch(gender1){ case 'M': switch(gender2){ case 'M': printf("Dear Sir %s and Sir %s", name1, name2); break; case 'W': printf("Dear Sir %s and Madame %s", name1, name2); break; case 'R': ... } break; case 'W': switch(gender2){ case 'M': printf("Dear Madame %s …

3
我应该在哪里放置发出Http请求的方法以从iOS开发中的Web服务获取数据?
我的iOS应用程序中有一个Model Car,其中从网络服务中获取了诸如名称,年份,值等参数,以便用汽车数据填充列表。 我应将异步发送到服务器并返回汽车数组的方法放在哪里(该方法已将JSON转换为汽车数组)? 我当前的方法是Car类中的静态方法,该方法接收HttpClient(这样我就可以模拟客户端对它进行单元测试)并返回NSArray的汽车,这样好吗? 你们在这种情况下做了什么? 我很担心,因为我最近开始阅读干净的代码,该代码说一个类只能做一件事,而现在我拥有它的方式似乎可以做两件事(保存有关汽车的信息并获取汽车列表)。

7
检查方法是否返回false:将结果分配给临时变量,还是直接将方法调用置于条件中?
调用在if语句中返回true或false值的方法是一种好习惯吗? 像这样: private void VerifyAccount() { if (!ValidateCredentials(txtUser.Text, txtPassword.Text)) { MessageBox.Show("Invalid user name or password"); } } private bool ValidateCredentials(string userName, string password) { string existingPassword = GetUserPassword(userName); if (existingPassword == null) return false; var hasher = new Hasher { SaltSize = 16 }; bool passwordsMatch = hasher.CompareStringToHash(password, existingPassword); return …
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.