通常在我们的代码审阅期间,我们被要求减少代码中的行数。
这与删除冗余代码无关。 ,这是关于遵循一种专注于用更少的代码行来完成相同事情的样式,而我相信即使要增加行数也要保持代码的清晰。
您如何看待是正确的处理方法吗?
如果LOC(代码行)是一个小数字,它将如何影响代码?
如果LOC是一个大数字,它将如何对代码产生影响?
网站上的示例:“ javaranch”-
public static void happyBirthday(int age)
{
if ((age == 16) || (age == 21) || ((age > 21) && (((age % 10) == 0) || ((age % 25) == 0))))
{
System.out.println("Super special party, this year!");
}
else
{
System.out.println("One year older. Again.");
}
}
VS
public static void happyBirthday(int age)
{
boolean sweet_sixteen = (age == 16);
boolean majority = (age == 21);
boolean adult = (age > 21);
boolean decade = (age % 10) == 0;
boolean quarter = (age % 25) == 0;
if (sweet_sixteen || majority || (adult && (decade || quarter)))
{
System.out.println("Super special party, this year!");
}
else
{
System.out.println("One year older. Again.");
}
}
#1 楼
度量的问题,无论其意图如何,都在于度量项目的重要性,而必然的结果是,不度量项目的行为就变得无关紧要。衡量重要的是绝对重要的,而不衡量不重要的是绝对必要的。测量SLOC(实际上是您的评论正在做的事情),使SLOC很重要.... SLOC重要吗? -绝对不会,永远不会(在混淆编程竞赛之外),永远不会在商业组织中。
问一个简单的问题-“减少此例程的SLOC”如何使任何人的代码更好。在这种情况下可能发生的事情是,SLOC被用作衡量复杂性的幼稚方法。您必须不惜一切代价避免计数易计数的豆类-SLOC之类的客观指标,而不是计算重要但难以计数的豆类-例如可读性,复杂性等。
评论
虽然OP对复审的描述听起来有些毫无意义,但我想说代码行通常与您提到的较难的措施有关。长函数通常不那么易读,并且通常也具有较高的圈复杂度。因此,这实际上取决于审查是否实际上建议分拆/缩短将从中受益的代码,或者只是建议内联多个合法行。
–丹尼尔B
13年2月5日,13:25
我要说的是,减少代码行数很重要的原因是能够在单个页面上查看更多的功能。在无需滚动的情况下查看方法或类越容易,在上下文中维护上下文就越容易。
–CLandry
2013年2月5日14:14
@DanielB长函数通常更难缠头,不是因为它们长。但是,因为他们试图一次做很多事情。例如,它们通常从输入验证开始,然后进行一些处理,然后检查替代处理,再进行另一次检查以查看是否需要更新不相关的内容,然后执行与主操作无关的内联例程(例如检查月份超限并进行调整的日期逻辑)等等。到结束时,您已经不记得上课的责任了。
–埃德温·巴克
13年2月6日在21:07
@CLandry:通过使其适合一页来维护上下文是减少SLOC的非常不好的原因。当然,如果代码布置合理并且易于阅读,则更容易维护上下文。 -什么是2500或1000像素的“页面”?我有2 * 30“纵向监视器,但有时需要在笔记本电脑上进行开发。
–mattnz
13年2月11日在3:48
显示(参考)LOC ===错误的研究一毛钱。这是众所周知的事实。 (据我所知)尚未显示(参考b)“减少代码库中的LOC ===减少该代码库中的错误”。用外推(参考a)声明(参考b)是不科学的。发表证明或反对这种关系的论文将是。
–mattnz
13年4月17日在22:39
#2 楼
我同意您的代码审阅者的意见,但带有星号。您在代码中编写的每个语句都是技术责任–这是潜在的失败点。如果您用10条语句编写一种方法,而您的同事用5条语句编写实现相同功能的方法,则按问题可能性衡量,他的方法可能会“更好”(错误代码过多的地方是错误的两倍)复杂或有问题)。这是星号。这与想法中的实际代码行数无关,因为您可以通过以下方法减少行数:
void someMethod() {
someobject.doSomething(someSingleton.getInstance().with().a().lot().of().law().of().demeter().violations()).and().if().that().werent().enough().theres().more();
}
这是一行代码,但是在这个地方,很多事情都可能出错。因此,我想说的是专注于以最少的语句完成最多的工作-根据需要编写尽可能多的代码,而无需完成更多工作。至少,我认为这就是您的代码审阅者所追求的目标。
个人而言,我认为需要保持平衡。就像我说过的那样,您编写的每条语句都是一种责任,但是如果提取具有描述性名称的局部变量会使您的方法更清晰,更易读,那么也有理由这样做。我认为您可以轻松地进入人们对相对较小的美学差异感到困惑的情况,但是总的来说,我认为您的审稿人有正确的想法-希望将可能出错的内容减少到最少。
评论
同意-将语句的数量减少到一定程度可能会很有用,但是,如果代码审查想要减少语句的数量,他们会不会只是说“较少的语句数”而不是“较少的行数”码”。
–mattnz
13年2月5日在8:13
@mattnz仅用于确定他们是否正在做书。
–丹在火光中摆弄
13年2月5日,11:36
以我的经验,可以用更少的语句编写相同算法的人会:a)使用不太常见或不太了解的东西,以及b)引入更多需要单元测试的边缘情况,并可能引入错误。当然,这假设两个程序员的能力大致相同。
– Daniel A.A.佩尔斯迈克
13年2月5日在15:20
+1(幽默长的函数调用链),以及violess()之后的狡猾双括号。
–乔Z。
13年2月5日在15:44
100%+1,所以很多人不了解他们添加到代码库中每增加一小段代码的后果,这是人们真正需要知道的事情。
–吉米·霍法(Jimmy Hoffa)
2013年2月6日14:39
#3 楼
从字面上看,听取评论者的建议是无济于事的,因为显而易见的直接结果是促进了简洁的单线(尽管行长受到限制)。我相信,这里要吸取的教训是使您的代码执行更少的事情。换句话说,这是对简单性的要求。普遍认为代码是一种责任,而不是资产,因此在保留功能的同时减少其数量是一项艰巨的努力。这可以通过一种直接,更扎实的方法来直接解决该问题,并希望使用简洁的解决方案来实现。肯·汤普森(Ken Thompson)曾经说过:我最富有成效的一天之一就是扔掉1000条生产线代码。
#4 楼
我倾向于同意您的立场,即“即使在代码增加的情况下也要保持代码清晰。”我看到了太多的简洁代码,但并不是立即显然他们在做什么。可读性为王,因为其他开发人员将不得不维护您的代码。
我认为,针对较短的方法是更好的选择。因为几行代码而不是简短,而是因为它们只做一件事情,所以简短。
#5 楼
我目前在一家大型公司担任高级应用程序开发人员和项目业务分析师,而我的开发工作从未成为关注的中心。但是,我相信代码越简洁,BUT就越好,但它不会以快速分析和纠正(或添加)为代价。对我来说,当您负责关键业务应用程序时,必须具有广泛的可伸缩性,并且能够在不间断的不断变化的环境中进行即时更改,简洁,易于阅读的代码是开发中最重要的元素之一。值得埃里克·迪特里希(Erik Dietrich)的答复是:void someMethod() {
someobject.doSomething(someSingleton.getInstance().with().a().lot().of().law().of().demeter().violations()).and().if().that().werent().enough().theres().more();
}
对我来说是完全不可接受的,但是,我发现更改了所有公司现有代码:
if (boolean == true){
value.prop = option1;
}
else{
value.prop = option2;
}
至:
value.prop = boolean ? option1 : option2;
是一种出色的代码压缩选择,不会牺牲可读性。
至于它如何影响代码?我从来没有注意到性能提高或降低(例如100行代码)。一个简单的事实是,到达最终产品所用的过程比到达最终产品所需的生产线数更多。我看到一些编写的过程非常紧凑,但是效率低下,它们的执行效果与较长的代码不同,具有更好的代码流。
评论
你的意思是value.prop = boolean? option1:option2;
– ChristopherHammarström
2013年2月5日在18:49
我做! ...反正在“压缩代码”上。
–约书亚Volearix
13年5月5日在21:12
您的第二个示例特别好,因为它不仅更简单,而且还使您更加清楚,这是两个选项之一的赋值,没有副作用。 if-then-else掩盖了这一点;例如,在if的每个分支中分配一个不同的变量太容易了(这可能会或可能不会是一个错误,但是很难发现)。
– Andres F.
13年4月6日在20:43
我遇到了明确禁止使用三元运算符的环境。通常,它们是从PL / SQL过渡到Java或类似Java的环境,人们对此感到恐惧。关于您的声明,编写更多代码不会对性能造成影响,这可能取决于代码是什么。例如,如果用方法调用替换运算符,肯定会产生影响(并且可能会产生严重影响)。
– jwenting
16年1月6日在10:16
#6 楼
IMO,通过琐碎的LOC计数来衡量代码有效性是一个坏主意。编写正确的工程代码和有效代码的要素还有很多。以我的经验,有效的代码:
不违反任何SOLID原则
可读且不言自明
通过了爱因斯坦(Albert Einstein)对简单性的考验:“一切都应该尽可能简单,但不要简单。”
评论
爱因斯坦报价为+1。
–食盐
13年2月6日在21:03
#7 楼
这里有很多答案可以解决降低LOC的技术利弊,以及它是否是有意义的质量软件指标。这不是这个问题的意思。它的目的是如何处理那些坚持天真的教条主义遵守特定经验法则的管理。可悲的是,当人们在适当的上下文中使用并务实地应用好建议时,通常会抓住这些东西,将其从上下文中移出,并在教条化地应用它们,而又无法理解问题。首先存在缓解建议。
关于降低LOC的建议的目的是避免创建试图一劳永逸的方法,并阻止创建对方面了解太多的“神类”。设计的职责不是他们的直接责任,也不是系统中所有其他类所依赖的。较短的代码的另一个优点是它更具可读性,尽管正如您所指出的那样,您可以过度编写它,以至于实际上开始损害可读性。
低LOC计数有明显的优势(小方法比大方法更容易适应您的头脑,代码中更少的东西意味着更少的出错,等等),但是它也受制于收益递减法则。将150行方法重构为20行方法比将10行方法重构为7行方法要大得多。
当这种重构以良好软件设计的其他方面(例如可读性)为代价时,您就可以证明不这样做是合理的。删除赋予代码含义的上下文变量并将其替换为没有含义的文字是一件非常非常糟糕的事情。好的代码几乎没有文字。但是,这些变量(和命名的常量)是不直接对程序起作用的代码行,因此,如果LOC被视为某种上帝而崇拜,那么此类澄清行将面临极大的危险,无法获得快速的胜利。管理层的一些误导性表扬。
我相信您足够聪明,可以意识到这一点,实际上,这几乎就是您最初提出的问题的重点。问题不是您对什么时候代码精简是好的理解,不是对代码精简的理解,问题在于教条主义在不加选择地应用通常是合理的做法上。
我建议您花时间与您的管理层聊天,解释您的职位以及为什么您觉得被要求执行的操作会损害代码而不是帮助代码。尽量避免对抗,但在这样的讨论中要尽量保持理性和镇定。管理层必须了解编程是一项务实的活动,并且最佳实践建议仅在以务实的方式加以应用时才有用,这一点很重要。最佳实践写在书上,而不是刻在石头上,当发生冲突(短代码与可读代码)时,程序员应根据自己的判断来决定遵循哪种最佳实践。希望他们是喜欢这种输入的有理智的人。
您还需要有一点勇气,因为如果您被迫在您认为没有必要或不适当的地方降低LOC的压力,那么很自然,您还是会为了安静的生活而进行更改。您需要拒绝这样做,并且您必须“拥有”该决定。在管理层合理的情况下,您不必完全遵守他们的准则,但是您应能够辩解任何不合理的情况。
可悲的是,人们可能会变得不理智,尤其是当人们在啄食顺序较低的人群中质疑他们的决定和他们对您施加的规则时。他们可能选择不合理。您也需要为此做好准备。如果您可以证明LOC最佳做法与其他最佳做法直接冲突以及为什么这会损害产品的情况,并且可以在他们很少或根本没有个人参与的部分代码库中这样做(如果这样做,则不会)似乎不是对他们的工作或他们所监督的工作的人身攻击),那么这可能有助于加强您的论点。同样,您必须准备以一种冷静,理性的方式为自己辩护,并能够“拥有”您所做的论据。
只要您的管理层是有理智的人,那么他们必须感谢您所说的是有道理的,如果您能提供证据支持您的主张。
#8 楼
我认为您确实应该努力使具有少量SLOC的函数。如果LOC(代码行)很小,那么它将如何影响代码?理想情况下,一眼就能理解8行代码比一眼理解30行代码要容易得多。
这并不意味着30行LOC压缩成8行会更容易理解。
您认为正确的处理方式是什么。
通常在函数中,我尝试按抽象级别(“此处输入IO代码”,“此处验证”,“此处计算”等)将其分组。
然后,我将其分成块,并用空白行分隔。如果代码多于十行,我将每个块提取到一个不同的函数中(无论如何我都会对出现多次的代码执行此操作)。我曾经听说过有关以这种方式破坏性能(不必要的函数调用)的争论,但实际上,我从来没有遇到过由此而导致的性能瓶颈。
这就是说,我在提取过程中就有函数完成后,该函数的长度约为40行(C代码)。如果代码尽可能地分组,则较长的函数不会出现问题。
#9 楼
我认为,专注于干净,自动记录的代码比LOC更重要。不过,我真的不喜欢您的示例,因为它解释了代码在做什么,而没有说明原因。例如,这样:boolean sweet_sixteen =(年龄== 16);
非常多余。任何阅读“年龄== 16”的人都知道这一点。我宁愿这样写代码:
public static boolean companyShouldThrowABigParty(int age) {
return (age == 16) || (age == 21) || ((age > 21) && (((age % 10) == 0) || ((age % 25) == 0)));
}
public static void happyBirthday(int age)
{
System.out.println(companyShouldThrowABigParty(age) ? "Super special party, this year!" : "One year older. Again.");
}
决定何时举行聚会的逻辑与System.out是分开的,可以进行测试,它是容易明白。但是,更重要的是,阅读代码的人可以理解以这种方式编写代码的原因(“公司希望为某些人举办盛大的聚会”)。
评论
甜蜜的十六岁(和21岁)的意义是特定于文化的。短语“十六岁”比“年龄== 16”更容易搜索。因此,为某些布尔值命名可能很有用。不过,我同意您的一般观点:不要浪费时间解释不言自明的代码。
–乔纳斯·科尔克(JonasKölker)
2013年6月3日6:29
#10 楼
我认为更少的代码行=更具可读性的代码但是,当然,当您开始缩小/模糊代码以获取更少的行时,存在一些限制。
/** Pad a number with 0 on the left */
function zeroPad(number, digits) {
var num = number+"";
while(num.length < digits){
num='0'+num;
}
return num;
}
这是最小化,其逻辑保持不变,只是可读性较低。这不应该由人来完成,这种缩小是由机器来完成,以供机器读取。
function zP(e,t){var n=e+"";while(n.length<t){n="0"+n}return n}
如果您可以删除一些代码,并且算法仍然在做应该做的事情,好的,继续。只是不要缩减您的代码,有更好的工具可以做到这一点。
#11 楼
我认为更少的代码行==更具可读性的代码。但是,与理论有很大不同的现实是,经常在没有适当设计的情况下编写大量行代码。因此,对更少行的需求可能会迫使某些程序员在能力允许的情况下提出更好的设计。不同之处在于,许多程序员都不是,那么要求并没有太大帮助。#12 楼
在正常情况下,我认为行数不是问题,但是它可以指出问题。如果有人向您展示了一个包含1000行代码的类,则该类的完成或设计方式一定有问题。您的示例确实指出了一种情况,即行数较多代码很有意义。但这就是那个例子。每天我都会看到示例,其中行数与计划不足有关
#13 楼
我认为,LOC是项目开始时比实际实施中更有用的指标。了解每个功能点的LOC,您可以估算项目的工作量,并据此估算项目所需的时间以及开发人员的最佳数量。它还会影响设计和语言选择:减少功能点或切换到LOC / FP较低的语言应会减少项目工作,而其他所有条件都相同。
#14 楼
代码行本身不是很重要。一种查看方式是将其与散文进行比较。第一个认识是代码和散文(假定正确性)的重要属性是可读性。可读性(和易理解性)有助于诸如维护性和正确性之类的其他属性。能够在少量行中拟合函数具有优势。但是,文字不带段落会降低其可读性。使用困难的概念,困难(稀有)的单词和复杂的表达方式通常会减少表达一个想法所需的单词数量,但同时将文本的阅读级别从中学级别提升到专业学者(在一般情况下,在代码中添加抽象并使用助手等会很有帮助。但是同样,这些抽象可能会变得太多。还可能发生的是将复杂性转移到代码的另一部分。有时,就像当您作为专家来设计供初级程序员(或学生)使用的框架/库时一样,这样做是个好主意。但是,不要指望初级人员能够理解您的代码的工作方式,否则会使他们很难正确地使用它。
编写代码时,尤其不要回避添加代码中的空行。它们作为段落运行,可帮助您将函数的不同部分分开(即使它们尚不应该放入助手中)。
#15 楼
每种形式的代码评估方法的最大问题是,它肯定会在某些代码上失败。这是因为编程是一种艺术,因此,没有明确的评估标准。
当然会有不同种类的艺术-绘画的大量生产也存在,也许在这项业务中,在一张绘画上花费多少油漆很重要。 :)
#16 楼
老实说,我对LOC的测量不抱有任何疑问。当然,尽可能短的函数或过程很好,但是我一天中的任何时候都在短时间内读取可读的代码。#17 楼
我同意始终要求降低LOC会导致代码难以阅读。但是,您的编码风格可能太冗长,而您的审阅者认为,更简洁的方法更好。例如,仅注释了一个明显清楚的变量名称的注释是无用的。
评论
据我所知,评论不属于LOC。
–mhr
13年2月5日在11:08
根据您使用的定义,它不计数或计数。
– MatthieuW
13年2月5日,12:50
评论是评论。他们不是代码。因此,它们不适用于LOC计数。尽管自记录代码比注释良好的代码更好,但是从不那么明显的代码中删除注释对任何人都没有帮助。
–GordonM
13年4月7日在7:30
#18 楼
代码行只衡量一件事,那就是您拥有的代码行数。其他一切都是热空气,猜测和偏见。其他答案中有很多很好的例子,更少的代码行可以使事情变得更糟,而不是更好,但是一个核心点似乎是已经错过了,那就是:您实际上需要多少行来完成这项工作?
如果完成任务需要10行代码,那么就可以在10行中完成。如果完成它需要10,000行,那么同样地,您也需要10,000行。如果您使用1,000或2,000或其他代码,那么“更少的代码行”的崇拜将不会使后面的示例更好。这项工作需要10,000行,而这10,000行可能包含验证,错误检查,安全性等层,如果您花更少的时间就可能会错过这些层。
编辑
这引起了一些反对,我想我需要在这里说的更具体。任何人都应该做的第一件事就是读这篇文章-我要你摆脱的一点是,您编写的高级代码可能与实际执行的机器代码几乎没有相似。与此相关的是,在不了解底层实际内容的情况下,专注于高级代码是错误的。
现在考虑以下内容:
仅用一行就可以编写非常糟糕的慢速代码-请注意我提供的链接末尾对三元运算符的注释。
如果一行代码进行API调用(或其他调用一个外部库),那么按照定义,您几乎无法直接控制执行的内容或执行的效率。
错误检查,清理等都增加了额外的代码行,我敢肯定,即使最热衷于更少的代码行的人不会反对这些。
所以-代码行是一个坏指标。更少的代码行不能保证额外的性能-API或库调用是一行,并且可能超出您的控制范围。更少的代码行并不能保证额外的鲁棒性-错误检查和清除总是需要额外的行。更少的代码行甚至不能保证额外的可读性或可维护性-您只需要查看IOCCC即可知道。
那么,更少的代码行可以保证什么呢?只需更少的代码行。
专注于以2,000行而不是10,000行完成同一工作是完全错误的。相反,应将重点放在有效的,健壮的,在可接受的公差范围内执行且易于阅读和维护的代码上。有时,这意味着您可以以较低的LoC计数来执行此操作,有时这意味着您必须以较高的LoC计数来执行此操作,但此处的LoC计数不重要。
评论
根据定义,如果一项任务绝对需要N行代码才能完成(一开始很难确定),那么它就不能少于N行。因此,您的10,000行任务无法在2,000个周期内完成。我猜OP谈论的是存在一些回旋余地的情况,即“无论哪种方式都可以完全满足要求,那么哪个更好?”
– Andres F.
13年4月6日在20:47
#19 楼
减少代码中的行数有多重要?在大多数情况下,根本没有。实际上,在大多数情况下,通过将复杂的操作分解为更具可读性的步骤,并注释每个步骤以及总体上添加注释,以使其他代码更易于阅读和扩展,从而增加代码行数更为重要。追随您的开发人员。评论
为什么所有的反对票?
– Marko
13年2月6日在22:33
是的,为什么一个完全明智的答案被否决了?为什么还有其他完全明智的答案,所有这些都对减少代码行本身就是目的的观点提出了挑战,但也被否决了?
– Maximus Minimus
13年2月7日,0:06
@ mh01我猜是因为其中大部分错误?具体来说,在大多数情况下,通过将复杂的操作分解为更具可读性的步骤来增加代码行数更为重要,这并不是我的经验。通过使复杂的代码变得更小和更简单,通常可以使复杂的代码更具可读性,并减少错误,因为对于新来的语言/问题的新手/不确定他们在做什么,它变得很复杂。
–伊兹卡塔
13年4月7日在18:19
#20 楼
在较早的时期中,假设loc的代码行数较大,则该代码有效,并且可以完成它曾经执行的所有任务,但是一段时间后才意识到loc越少由于系统执行代码所花费的成本非常少,因此具有较高的效率。因此,为了使系统loc更好,应减少它的数量。从那时起,假定loc应当更少。为减少它,以下因素应该考虑在内。制作问题流程图
尝试使用尽可能少的循环次数
函数调用不应太多
在将堆栈或队列用于存储相关信息的情况下,应使用新的数据结构(如TRIE)。
并尝试用一种现实的方法来解决问题,而不是用一种想象的方法来解决该问题。非常大的数组中包含大量数字,然后尝试通过数组进行访问。]
用作ma尽可能使用ny宏
进一步的使用方法也取决于问题。如果确实很复杂,则有时使用简单的方法也等同于复杂的方法
评论
-1:哇!我认为您需要减少答案中的LOC!读起来很伤我的眼睛!
– Jim G.
13年2月6日在7:40
@JimG .:我同意答案会伤害我的眼睛,但认为最好通过增加LOC(例如,对每个编号的项目使用单独的一行)来解决。
–布赖恩
2013年4月6日下午2:36
这是自动格式的错误,在列表解决情况之前插入了一个空白行
–Balog Pal
2013年6月2日在1:35
评论
我可以将任何java文件转换为一行代码(s / \ n / / g),这并不意味着它甚至可以远程读取您的公司是否使用LOC来衡量生产力,因此他们正试图阻止您使用其编码标准“操纵系统”吗?
如果您可以提供每种样式的简短示例(不是摘自),那将真的有帮助,因此每个人都清楚我们在说什么。双向都有极端。答案将高度依赖于您的上下文。
曾经打扫过你的房间,然后你的母亲进来说“那不干净”,并指出了你没有收拾的十件事。这基本上就是他们在代码审查中告诉您的内容。
您给出的示例几乎是Introduce Explaining Variable重构的教科书版本,通常可以提高可读性和意图(这是一件好事)。有人认为您应该将变量进一步重构为短的单行函数,但这将其推向了极端。我想说您的版本优先于该评论推荐的短版本。