我看到很多人抱怨编程语言的冗长。我发现,在一定范围内,编程语言越冗长,就会越容易理解。我认为冗长程度也加强API
了为该特定语言编写更清晰的。
我能想到的唯一缺点是,它会使您键入更多内容,但是我的意思是,大多数人都使用IDE为您完成所有工作。
那么,冗长的编程语言可能有哪些弊端?
我看到很多人抱怨编程语言的冗长。我发现,在一定范围内,编程语言越冗长,就会越容易理解。我认为冗长程度也加强API
了为该特定语言编写更清晰的。
我能想到的唯一缺点是,它会使您键入更多内容,但是我的意思是,大多数人都使用IDE为您完成所有工作。
那么,冗长的编程语言可能有哪些弊端?
Answers:
“详细”的意思是“使用太多单词”。问题是什么“太多”。
好的代码一目了然。如果大多数字符直接用作代码的目的,则这会更容易。
如果语言是冗长的,则您的代码更多是杂音。比较Java的“ Hello World”:
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
...使用Ruby:
print "Hello World!"
噪音浪费了精力。
另一方面,语言过于简洁也会消耗精力。比较Common Lisp中的这两个示例:
(car '(1 2 3)) # 3 characters whose meaning must be memorized
# vs
(first '(1 2 3)) # 5 characters whose meaning is obvious
一目了然,它会影响您可以看到和解析多少代码
x++
而不是 set(x,Integeradd(get(x),1))
ps。这不仅仅是阅读代码的问题。在40x25的屏幕时代,APL类型语言(或Perl)比Cobol或Fortran有用,因为它可以读取/分页显示的代码量很大。但是,现在更多的是关于您自己的内部缓存的-如果一条语句只有一个运算符,那么比起带有3个符号和4个函数调用的语句,我的大脑更容易解析。
set
方法在这里做什么呢?它实际上设置了什么(即第一个x
参数)还是返回了什么(即x
,调用后的赋值)?我要说的是,冗长的示例中发生了一些奇怪的重复。
+
比有意义plus
。 =
比更好equals
。这当然可以走得太远(并且已经被多种语言使用),但是当适度使用时,它非常强大。
如果语言的冗长性降低了代码的可读性,那就不好了。
某些语言的语法过于冗长,以至于掌握代码的含义需要更长的时间(我在考虑VB.NET与C#的比较):
If something Then
End If
if(something)
{}
真正归结为编码人员所熟悉和熟悉的东西。
If .. Then .. End If
只阅读了重要的内容。
看一下AppleScript,这是我认为可以认为是最新的最冗长的语言之一,尝试在其中编写一些琐碎的东西,然后再回过头来争辩说,冗长是语言的一种很好的特征。
如果您每天都不做这些,要记住关键字去向和含义的所有语义都是很重要的。
只要看一下这个简单示例中的所有关键字噪声:
tell application "Finder"
if folder "Applications" of startup disk exists then
return count files in folder "Applications" of startup disk
else
return 0
end if
end tell
bash
对于大多数OSX用户而言,使用传统的Unix工具获得相同的东西虽然很简单,但却很神秘,所以必须取得平衡。
return the 0
输入时不想吗?AppleScript是我所知道的唯一一种可以让关键字困扰您的对手的语言……我的意思是同事。
我认为您需要首先提出一个问题,然后问:为什么有些人认为简洁的代码是好的?
我的回答是,有两个基本原因:
简洁可以变得更好的原因
这些包括更具可读性,就像短句子比华丽冗长的句子更易于理解。通常,尝试模仿英语语法的编程语言最终会费时费力,需要大量的代码才能执行最简单的操作。通常,您会发现一种语言模仿一种书面语言的次数越多,就越难以诱使它执行逻辑上复杂的操作。
简洁可能会变得更糟的原因
某些语言(我正在考虑Perl)使用了一系列奇怪的符号(它们似乎几乎是任意选择的)作为其语法的一部分。对于不熟悉这些象形文字的任何人,该语言将变得难以理解。犯下不容易发现的错字错误也变得容易。正则表达式可能是这种简洁的缩影。
另外,有些人喜欢通过编写简洁的代码来炫耀,因为坦率地说,他们认为这使他们看起来很聪明。您有时会在StackOverflow上看到这一点,人们通常会以非常易读的方式提交非常紧凑的答案。这是一种“使您的同伴印象深刻”的知识,但是优秀的程序员意识到“ 编码高尔夫 ”并不是创建可维护软件的方式。
terse
反义词verbose
(反之亦然)。/鸭子
@frowing,我建议研究冗长性问题的一种方法是认识到编程始终是找到和表达解决方案的两种截然不同的样式的某种组合。
第一种也是更冗长的样式是面向语言的(语言)编程。这种风格在句子结构中结合了类名词词和动词类词,旨在以与编写良好段落相同的方式阅读和理解。语言编程是最通用的编程风格,因为语言本身是通用的。出于同样的原因,长期的程序支持始终需要强大的语言组件,因为新程序员首先要寻找的是对正在做的事情的概念性理解。通常,离您创建程序的环境越远,语言的编程风格就越重要,这是为了确保下一个尝试理解您的代码的人不会误解您的假设和概念。 。
第二种更简洁的样式是面向数学的(数学)编程。这种推理方式也依赖于语言,因为例如变量类似于名词,而运算符类似于动词。但是,数学推理可以利用我们的大脑惊人且高度并行的能力对视线范围内的对象进行复杂的空间变换。通过将名词和动词表示为紧凑,独特的符号,可以将它们安排在结构良好的虚构对象(方程式)中,然后我们可以使用高度平行的视觉功能对这些虚构对象进行旋转,替换,移动,倒置和其他转换对象。结果是极大地放大了我们一次可以处理的案例数量,因为每个符号都可以代表紧密相关对象的整个类别。
请注意,要有效地应用视觉处理,您需要使虚构对象的大小和特征与真实对象尽可能相似。如果所需的视野太宽,或者不能像在对象上使用可移动标记那样使用符号,或者如果您必须“阅读字母”并将其转换为单词,则可靠地执行复杂转换的能力将下降即使是非常好的数学家,也很快。
因此,如果方程式以他们所谓的“冗长”的语言风格展开和表达,那么沉迷于编程的数学风格的人们会变得非常不高兴。这不是因为方程式已发生重大变化,而是因为这样展开方程式几乎可以使视觉理解方式几乎不可能。但是,与此同时,根本不熟悉短符号的新程序员可能会更喜欢冗长的版本,该版本提供更多的语言信息,以初步了解代码的作用。
那我会推荐什么呢?
使用这两种风格,但仔细注意为什么您使用的每一种风格。
例如,任何有可能与外界交互的东西都应在某种程度上强化冗长,即使仅以内联注释的形式与代码混合,也应包括对正确用法的自动检查。隐秘的符号,尤其是定义不完整的符号在这种界面上毫无用处,因为几乎可以肯定它们在某些时候会被误解。在1999年损失火星气候Obiter的,由于没有认识到无论是软件接口设备是在磅或牛顿表示是软件或硬件接口依靠太随便对原始数据的危险的特别指出的例子。
相反,本质上具有深厚算法和数学意义的任何形式的编程,都是支持推理的数学风格的优良简洁编程。如果新来的人必须维护这样的代码,通常让他们学习数学符号而不是尝试将代码转换为更详细的形式会更好。当然,应该始终有容易获得的文档来解释这些开发人员可以使用的代码的数学部分,但这是一个单独的问题。
在这两种极端之间,程序员有很多酌处权。我建议您看一下如何长期维护代码,并设法满足最有可能长期维护代码的人们的需求。
许多人暗示了我认为应该明确指出的内容。
详细程度倾向于在微观层次上进行理解-它通常导致单个陈述易于阅读和理解。详细程度还趋于降低对理解它所必需的语言的熟悉程度(至少在某种程度上)。即使是完全的非程序员,最冗长的语言(例如COBOL)也可能至少具有一定的可读性。
压缩趋向于相反:它有助于从宏观上理解,特别是对那些对特定语言最熟悉的程序员。同时,对特定语言的不熟悉甚至会阻止甚至是初级的理解,即使对于那些本来很有经验的程序员也是如此。
因此,可读性会因目标受众的不同而有很大差异。一方面,考虑一个由几乎专门从事该项目工作的人编写和维护的大型复杂项目,其中大多数人具有丰富的编程背景和受过教育(例如,许多博士学位)。这将倾向于使用更简洁的语言。
在或多或少相反的极端情况下,考虑一个相当简单(尽管可能仍然很大)的项目,该项目主要由真正专门从事与软件相关的业务而不是软件本身的人员维护。这几乎肯定会支持一种更加冗长的语言。
归根结底,任何“不同”的事物都会引起人们的how叫。我对C样式的语法很满意,因此对其他使用相似语法(C ++,Java,C#)的语言也很满意。所以我倾向于这种特殊风格。
语言往往会在描述性和非冗长性之间找到平衡。
Perl是可以编写非常简洁的代码的示例。对于没有经验的人,Perl忍者编写的代码简直就是魔术。
COBOL就是一个过于冗长的例子。
我曾在某处读到过,冗长的辩论大部分来自新程序员还是老手。使用的类比是,当我们学习新东西时,我们会告诉自己一个“故事”来通过它(想想您何时在HS中学习代数)。随着经验的积累,我们不再需要一个故事来解释各个组成部分,而是获得了更多的理解。我们的代码变得更紧凑,更简洁,注释仅解释了必要的内容,而不是重复代码的内容。
我发现我和同事之间确实如此。她编写的代码带有很多注释,这些注释解释了代码行以及空白。如果我正在阅读,就会发现我只能在一个屏幕上放几行代码,因此。这使理解每条线变得容易得多,但是使整个功能复杂化变得困难得多。
我倾向于编写没有多余空格或注释的代码。这使得查看整个过程变得容易得多,但是您必须能够简单地“获取”单个代码“ words”。如果您尝试在每个单词都单独出现的情况下阅读此答案,并且有很多空格/注释/多余的单词,那么理解每个单词会容易得多,但难于理解整个单词。
i++; //this is adding one to var i
这是多余的。
爱因斯坦说对了:“使事情尽可能简单,但不要简单。”
这也适用于代码。如果您可以通过删除重复的和不必要的冗长元素来简化代码,那将是一件好事。
同样,一些案例研究表明,以代码行衡量的程序员生产力或多或少是一个常数。每个LOC的错误数量也是如此。因此,如果所有其他条件保持不变,那么切换到一种允许您在每行代码中执行更多操作的语言可以被认为是生产率的提高。
话虽如此,该行业中有一种过度设计和使本应简单的事物复杂化的趋势。在关系数据库中填充联系人详细信息等简单的事情。我已经看到了针对该特定问题的一些荒谬的,错误的解决方案(咳嗽 MDA)。诸如Scala和Ruby之类的语言就是功能强大的工具的典范,这些工具在某些人的手中导致难以理解,过于复杂且难以维护的代码。仅仅因为您可以通过几次按键操作就可以使用多个间接级别,但这并不意味着您必须用那个特定的锤子敲打每个钉子。
如果使用得当,您将获得简洁易懂的简洁代码。如果使用不当,则最好将相关人员限制在使用Visual Basic或类似限制的语言中,以防止进一步的损害。
真正的技巧在于以简单的方式制作复杂的事物,而不是以复杂的方式制作简单的事物。
没有人碰到的东西就是您可以在一个屏幕中容纳的代码量。它的帮助有以下几个原因:
因为更多的代码意味着更多的开发时间和更多的错误。
如果您编写100行代码而不是300行代码。这意味着您需要将近1/3的开发时间,并可能遇到1/3的潜在错误。
在大多数情况下,您需要兼顾效率和简洁性,因为编写更少的代码意味着机器需要做更多的事情,这会降低效率。
通常,人们喜欢可读/冗长的语言,而不喜欢神秘/简短的语言。但是,我认为大多数人将“冗长”和“混乱”混为一谈,但这不是同一回事。
例如: while(<>){print if($.==2 || $& && !$x++); $.=0 if (/^--+$/)}
是一个非常简洁的声明。它包含您想知道的所有内容。但是,由于它的简洁性,很难理解。另一方面,同一程序的稍微冗长的版本将很容易理解,因为它更具可读性。当然,这不是语言本身的特性,但是某些语言倾向于更加冗长,而另一些语言倾向于更加简洁。
详细程度的另一个极端是http://en.wikipedia.org/wiki/Literate_programming ,我认为这是一个非常有趣的概念。
另一个方面是“不必要的冗长”,也称为“混乱”。由于技术原因,语法语法不足,API膨胀等原因,您必须添加的内容。
我认为清晰直观的语法非常重要。它也必须足够冗长以便于阅读。包含太多逻辑的简短语句通常会导致比其他稍长的语句花费更多的时间来解密。另一方面,满是样板行的无用的plate肿代码却使事情变得非常简单,这同样令人讨厌。
详细程度倾向于使用大量文本,而Terseness倾向于使用很少的文本...
详细程度不好是因为:
一定程度的冗长程度对于保持清晰是必不可少的,但是...
最低程度的Verbosity是好的,因为:
对于许多人来说,过于简洁的命令的一些奇妙示例包括,和... 的旧BASIC备用代码val(x$)
,它从其字符串表示形式返回一个数字,为一个数字返回一个字符串,并返回一个具有ascii值x的单个字符作为字符串。str$(x)
chr$(x)
或C / C ++指针和通过参考运营商&
和*
相对于BASIC byref
关键字。在C / C ++中,我可以有一个变量X,并传递一个指向该变量的指针,但是我必须记住,哪个是指针,哪个是“使用指针作为它所指向的变量”。从根本上讲,我只是在函数调用中使用byref关键字传递引用,这更加清楚,但灵活性较低:
def fn Foo(x byref as float) foo= (x += x+1)
...
Foo(x)
在此代码中,x的内容由于byref标志而被修改。某些样式允许在调用时使用byref,而其他一些定义则允许。
对于临时程序员来说,冗长的语言很重要,因为它能够更轻松地使用符号。与C / C ++相比,BASIC或python更具人类可读性和冗长性,因此对于休闲程序员而言更有用。C / C ++的简洁性使它对于经验丰富的程序员来说要好得多,他们需要一次查看更多的代码和更复杂的代码,但必须学习各种符号结构约定。远端是APL,几乎完全是人类无法理解的。
密切相关的问题是清晰度-简洁的代码通常不清楚,而过于冗长的代码(如AppleScript中的代码)也可能不清楚。熟悉给定语言会提高该语言中简洁代码的清晰度-面对C ++代码的原始初学者很可能只能解析公式,甚至很多功能性的BASIC或Python代码也太简洁而无法理解,但是applescript可以通常,不使用语言词典就会感到困惑。我在没有故意混淆的情况下遇到的最不清楚的问题是Inform 7 ...
在过去的日子里
过去的另一个重要考虑因素是操作和存储空间,但对于业余编码员而言,这不再重要。(它在高端仍然很重要。)请记住,许多语言都被解释了,尤其是BASIC风格,并且有更多语言是运行时编译的,代码空间非常重要,尤其是当磁盘仅容纳128KiB且单个穿孔卡仅80B时。
存在几种解决方案-令牌化在BASIC中非常普遍;单个语言关键字在高位128或控制字符空间中被减少为1或2字节的单词。令牌化还导致字节码编译(如Inform和Z-Machine中一样)。
多目标文件的编译和链接也用于解决空间限制。100KiB Pascal代码段可能仅编译为5KiB;通过链接多个编译文件,一个人可以构建大型应用程序而无需访问大型驱动器(记住10MiB是如此之大,并且购买一辆昂贵的新车)。
但是,更多简洁的语言将更多代码放入磁盘和ram的给定块中,从而一次编译了更大的块。请记住:1970年代初期的“微型计算机”可能只有64KiB的ram(Honeywell 800的基本安装是4个银行,每个银行2048个字,每个8B)。APL和类似的符号语言每个指令加上它的操作数达到1B,而每条指令加上操作数的3B-10B要大得多。(在打孔卡上键入文字是一场噩梦,特别是因为符号本质上是打字球上的一种字体,而且很多卡片打孔的按键上都没有符号...)
另外,请记住,无法删除卡...并且在卡上输入了许多程序。虽然并不是很昂贵,但是代码在卡上的压缩程度越高,所需的代码就越少,程序可能就越大,或者价格越便宜。这是BASIC在大多数情况下每行具有多条指令串联的部分原因-引入它是为了节省打孔卡。(或者说我的Vax Basic编程文本如此。)虽然我没有为读卡器进行编程,但是我已经用FORTRAN,BASIC,APL和其他几种高度象征性的语言对Honeywell 800进行了打卡。
就像许多事情一样,答案取决于“详细程度”的具体定义。如果定义是冗长意味着多余,那么我认为这总是不好的。请注意,使用这种定义,经常被引用的Java hello world程序将不符合“冗长”的条件,因为其中没有多余的东西。
程序员倾向于喜欢具有表达能力的语言,因为它允许他们用小段代码编写简单的事情,而这些事情通常必须经常执行。详细的语言往往意味着必须使用许多行代码来一遍又一遍地执行相同的操作。但是,表达性语言可能要付出一定的代价,因为它们执行起来可能不像更简单的高级语言那么快。如果我可以举一个C和C ++之间的对比示例。C ++为代码编写者提供了更具表达力的功能-他们可以将现实世界对象的思想封装在类中。C程序员可以实现相同的目的,但是他们确实具有类构造的表达能力来帮助他们-常常他们必须编写更长,更复杂的代码(以理解)。但是该代码可能运行得更快(尽管这在很大程度上取决于编译器的质量等等),因为它不使用C ++的“后期绑定”(即运行时重构)来执行代码。C只是执行已编译和链接的代码,C ++必须在运行时(在某些情况下)决定要执行哪些代码段。
我认为,这个问题的答案根源于比可读性更根本的理论问题,并且该答案与Gregory Chaitin建立的算法信息理论有关:http : //en.wikipedia.org/wiki/Algorithmic_information_theory。简而言之,“字符串的信息内容等于该字符串的尽可能短的自包含表示形式的长度”,这意味着最短的程序(即按照其词典长度)紧密地解决了给定的问题匹配解决方案所要解决的问题的内在复杂性,因此,它更多地取决于问题的性质而不是问题的表示形式。