您是否发现编程中有任何过度使用(IE过度使用的技术)或滥用技术,或者对所有事物都使用了一点技术,而又不能很好地解决人们试图解决的许多问题解决它。
它可以是正则表达式,某种设计模式或算法,也可以是完全不同的东西。也许您认为人们滥用多重继承等。
您是否发现编程中有任何过度使用(IE过度使用的技术)或滥用技术,或者对所有事物都使用了一点技术,而又不能很好地解决人们试图解决的许多问题解决它。
它可以是正则表达式,某种设计模式或算法,也可以是完全不同的东西。也许您认为人们滥用多重继承等。
Answers:
代码注释
我只是希望大学教授能够理解,他们不需要教学生写10行注释,说下面的代码是一个for循环,从1到x的数量进行迭代。我可以在代码中看到!
先教他们编写自我记录代码,然后再对不能充分自我记录的内容进行适当的注释。软件世界将是一个更好的地方。
Clean Code
,Fowler清楚地指出,过时的文档比没有文档更糟糕,并且所有注释都趋向于过时并从其文档中迁移出来。整本书都是关于如何编写自我记录代码的。
单例设计模式。
当然,这是一个有用的模式,但是每当新程序员了解此模式时,他便开始尝试将其应用于所创建的每个类。
$this->
。PHP是一种烂语言,所以我不能指望这些框架是优秀的。
保护愚蠢的编程是最邪恶的事情。将所有内容放入尝试捕获区,不进行任何处理
try
{
int total = 1;
int avg = 0;
var answer = total/avg;
}
catch (Exception)
{
}
当我看到一个不执行任何操作且旨在处理愚蠢逻辑的try catch时,我会发抖。通常,尝试捕获已被过度使用,但是在某些情况下非常有用。
依靠StackOverflow解决您的问题,而不是想办法。
新的程序员(经常)发现关于SO的丰富知识,然后再进行思考和尝试。
在我这一天,我们不得不从书籍,没有互联网,没有SO进行编码。现在下车我的草坪。
面向对象 它非常有价值,但是如果使用不当,它很容易掩盖否则会清除清晰的代码(让我想到R中的S4编程的一些示例),并且会产生不必要的巨大开销,并且会花费大量时间在性能上。
另一件事是,(例如,在Perl中)OOP通常归结为用另一种方式编写相同的东西:有时这result = $object ->function(pars)
不是result = function(object, pars)
很有意义,但是当与过程编程混合使用时,它会使阅读代码变得非常混乱。除此之外,您只会引入更多无法改善设计的开销。这也取决于关于单例模式的说法:应该使用,但不能在所有内容上使用。
我本人确实使用OOP,但是在我的领域(科学计算)中,性能非常重要,并且由于当今所有学生都在使用Java,因此OOP经常被滥用。这对于处理更大的问题,概念化等等非常有用。但是,如果您在BioPerl中使用DNA序列,那么每次使用对象并与吸气剂和吸气剂保持一致可以使计算时间增加十倍。当您的代码运行几天而不是几个小时时,这种区别确实很重要。
Foo.DoX().DoY().DoZ()
)很好,但是,它绝对不是解决问题的唯一方法。功能组合物(像doZ . doY . doX $ foo
是完全有效的替代方案。
在ASP.NET Webforms中使用了数年之后,我必须明确地说:
尽管完全有可能在Web窗体中创建可测试的分层应用程序,但Visual Studio使开发人员仅需单击即可轻松地形成与数据源紧密绑定的窗体,而应用程序逻辑则遍布所有UI代码。
史蒂夫·桑德森(Steve Sanderson)的反模式比我在其Pro ASP.NET MVC书中所能解释的要好得多:
要构建智能UI应用程序,开发人员首先通常通过将一系列UI小部件拖到画布上来构建UI,然后为每个可能的按钮单击或其他UI事件填写事件处理程序代码。所有应用程序逻辑都位于以下事件处理程序中:用于接受和验证用户输入,执行数据访问和存储以及通过更新UI提供反馈的逻辑。整个应用程序由这些事件处理程序组成。本质上,当您将新手放在Visual Studio的前面时,默认情况下倾向于出现这种情况。在此设计中,没有任何关注点分离。一切都融合在一起,仅根据可能发生的不同UI事件进行排列。当逻辑或业务规则需要在多个处理程序中应用时,通常会复制并粘贴代码,或某些随机选择的段被分解为静态实用程序类。由于许多明显的原因,这种设计模式通常称为反模式。
我偶尔会看到这种情况,这通常是由于不完全了解布尔表达式引起的。
if (someCondition == true)
bool
以is
或开头的has
,则无需使用来使代码更明确= true
。
重新实现核心(或以其他方式提供)的功能,可能是由于对其存在的无知或自定义的需求。
遗产。
不要在没有意义的地方执行is -a。
定制现成的软件。
虽然我可以承认这样做很有用,但我确实想知道为完成可疑收益而花很少的钱做些小事情。在这里,公司可能会花费数十万美元(如果不是数百万美元)来购买某些软件,然后对其进行定制,因为它具有可配置性,可编辑性和灵活性,以至于默认情况下它实际上并不会做很多事情。最后,这是一个自定义应用程序,因为所有新代码都添加了最初购买的内容。
使用编译器作为调试器。
忽略编译器警告或将其完全关闭。
全局变量。
所有设计模式。
它们就像盐或糖。食物中的一些使食物变得很棒,许多食物使您的食物变得糟透了。
不要误会我的意思。设计模式是很棒的技术。我经常使用它们。但是有时候,我发现程序员(其中有些是我的前任老板)拥有这些“您必须使用设计模式”,即使与问题不符!!!
一个示例是“访客模式”,它更直接地针对“线性/顺序集合”。我不得不一次使用树数据结构。为了“访问”每个项目,我编写了一种非设计模式的方法,并且前任老板坚持使用或改编“访客模式”。然后,我浏览网络,以征询第二意见。好吧,其他程序员也有相同的情况和解决方案。并将其称为“树/分层访客模式”。
我希望在“设计模式”书的新版本中将其作为现有模式的新模式添加。
使用异常作为流控制。有点类似于此答案,但有所不同。
吞咽异常是一种不好的形式,因为它引入了代码中难以发现的神秘错误。另一方面,将异常用作流控制是不好的,因为它使代码效率大大降低,并且从概念上讲是很草率的。
异常处理仅应用于处理真正的异常(duh),不可预见的情况,而不是诸如用户在期望数字的字母字符中键入之类的东西。这种异常滥用在Java世界中的不良程序员中非常普遍。
公开内部数组
public class Data {
int[] x;
public void setArray(int[] x) {
this.x = x;
}
public int[] getArray() {
return x;
}
}
根据http://www.oracle.com/technetwork/java/seccodeguide-139067.html
除非打算共享状态,否则在返回之前复制可变对象。
可变状态和循环。您几乎永远不需要它们,并且没有它们几乎总是可以获得更好的代码。
例如,这是直接从StackOverflow线程获取的:
// ECMAScript
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
thing = things[i];
if(things_by_type[thing.type]) {
things_by_type[thing.type].push(thing);
} else {
things_by_type[thing.type] = [thing];
}
}
# Ruby
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
他们俩都在做同一件事。但我不知道是什么,他们在做什么。幸运的是,该问题实际上解释了它们在做什么,因此我能够如下重写它们:
// ECMAScript
things.reduce(function (acc, thing) {
(acc[thing.type] || (acc[thing.type] = [])).push(thing);
return acc;
}, {});
# Ruby
things.group_by(&:type)
// Scala
things groupBy(_.type)
// C#
from thing in things group thing by thing.Type // or
things.GroupBy(thing => thing.Type);
没有循环,没有可变状态。好吧,好的,没有显式循环,也没有循环计数器。
代码变得更短,更简单,更像是对代码应该执行的操作的描述(特别是在Ruby情况下,它几乎直接说出“按类型对事物进行分组”),并且不易出错。由于没有循环索引和终止条件,因此不会出现循环末尾,栅栏错误或循环索引和终止条件出现一对一错误的危险。
(acc[thing.type] || (acc[thing.type] = []))
,而不是, unless you want to add
两次将“ = [thing] thing” 放到列表中……还是我错过了什么?
嘲笑。当过多的过程或功能设计可能是您的问题的更简单解决方案时,它为代码中的过多解耦引入了过多的人为要求,导致过度设计的馄饨代码并迫使OO风格的设计陷入困境。
属性。我知道这是有争议的,但是我觉得.net中的属性被过度使用了。
这两行有什么区别?
public string Property { get; set; }
public string Field;
对于开发人员而言,区别在于:绝对没有。编译形式是一点点不同,所以如果你正在写一个库,并且该库将在程序进行升级,并且如果你正在写一个接口插件不能重新编译程序本身(例如该应该可以在您的软件的各个版本上使用),那么您不应使用公共字段,因为您不能将它们替换为属性。在任何其他情况下,使用字段或不带修饰符的自动属性之间绝对没有区别。
YAGNI
但我觉得偏离在这种情况下,没有任何费用)
;
以{ get { ... } set { ... } }
任何不是改变更多的工作{ get; set; }
来{ get { ... } set { ... } }
?