你曾经喜欢过什么样的编程习惯?
在我们的计划中,我们都在开发我们使用和依赖的实践和模式。 然而,随着时间的推移,随着我们的理解,成熟,甚至技术使用的变化,我们认识到我们曾经以为伟大的一些做法是不(或不再适用)。
一个我曾经经常使用的实践的例子,但最近几年改变了,是使用Singleton对象模式 。
通过我自己的经验和与同事长时间的争论,我意识到单身并不总是可取的 – 他们可以使testing变得更加困难(通过禁止像嘲笑之类的技术),并可能在系统的各个部分之间产生不希望的耦合。 相反,我现在使用对象工厂(通常带有一个IoC容器)来隐藏系统中不关心或者需要知道的单件的性质和存在。 相反,他们依靠工厂(或服务定位器)来获取对这些对象的访问。
我本着自我完善的精神向社会提出的问题是:
- 您最近重新考虑过哪些编程模式或实践,现在试图避免?
- 你决定用什么replace它们?
//Coming out of university, we were taught to ensure we always had an abundance //of commenting around our code. But applying that to the real world, made it //clear that over-commenting not only has the potential to confuse/complicate //things but can make the code hard to follow. Now I spend more time on //improving the simplicity and readability of the code and inserting fewer yet //relevant comments, instead of spending that time writing overly-descriptive //commentaries all throughout the code.
单一返回点。
我曾经更喜欢每个方法的单一返回点,因为我可以确保程序所需的任何清理都不被忽略。
从那时起,我已经转移到了更小的程序 – 所以忽视了清理的可能性减less了,事实上清理的需求也减less了 – 发现早期的回报降低了代码的表面复杂性(嵌套级别)。 单一返回点的工件 – 保留“结果”variables,保留标志variables,还没有完成情况的条件子句,会使代码看起来比实际复杂得多,使其难以阅读和维护。 早期退出,更小的方法,是要走的路。
- 尝试在第一次尝试时完美编码。
- 在编码之前试图创build完美的OO模型。
- devise一切灵活性和未来的改进。
用一个词来形容工程 。
匈牙利符号(forms和系统)。 我曾经以一切为前缀。 strSomeString或txtFoo。 现在我使用someString和textBoxFoo。 对于一个新来的人来说,它更具可读性,更容易上手。 作为一个额外的好处,它是微不足道的,以保持一致 – 骆驼控制和追加一个有用的/描述性的名字。 forms匈牙利有一个缺点,那就是匈牙利体系并不总是一致的。 将所有variables分块在一起并不是很有用 – 特别是对于现代IDE。
“完美”的架构
几年前我就提出了这个架构。 尽我所能地从技术上推动自己,所以有100%松散耦合的层,广泛使用代表和轻量级对象。 这是技术天堂。
这是废话。 架构的技术纯度让我的开发团队为了完美而放慢了速度,几乎完全失败了。
我们现在有更简单的技术上不太完美的架构,我们的交付速度飞涨。
使用caffine。 它曾经让我保持清醒,并以一种光荣的编程心态,代码从我的手指飞出,带有高热的stream动性。 现在它什么都不做,如果我没有,我会头疼。
评论代码。 我曾经认为代码是宝贵的,你不能只删除你制作的那些美丽的gem。 我现在删除我遇到的任何注释掉的代码,除非附加了一个TODO或NOTE,因为它太冒险留下了。换句话说,我遇到过很多老的类,有很多注释掉的部分,它真的让我困惑在那里:他们最近被注释掉了吗? 这是一个开发环境的变化吗? 为什么它做这个无关的块?
认真考虑不要评论代码,而只是删除它。 如果你需要它,它仍然在源代码控制。 YAGNI虽然。
#region指令的过度使用/滥用。 这只是一个小东西,但在C#中,我以前会使用#region指令到处,组织我的类。 例如,我会将所有类属性分组在一个区域中。
现在我回头看看旧的代码,大多只是被他们搞惹了。 我认为大多数时候这并不会让事情变得更加清楚,有时候他们只是简单地拖慢了你的速度。 所以我现在已经改变了主意,觉得在没有地区指令的情况下 ,上课的课程大多是清洁的。
总的来说,瀑布的发展,特别是编写完整和全面的function和devise规范的做法,这些规范在某种程度上被认为是规范的,然后期望这些规范的实施是正确和可接受的。 我已经看到它取代了Scrum,并且很好的解决了它。 简单的事实是,客户需求和需求的变化性使得任何固定的规格都无效; 真正正确地处理这个问题的唯一方法是用迭代方法。 当然,Scrum并不是一个银弹。 我已经看到它滥用和滥用了很多次。 但它跳动瀑布。
永远不会崩溃。
这似乎是个好主意,不是吗? 用户不喜欢程序崩溃,所以让我们编写不会崩溃的程序,用户应该喜欢程序,对吗? 我就是这样开始的
现在,我更倾向于认为如果不行,就不应该假装它正在工作。 尽快失败,并出现错误信息。 如果你不这样做,那么你的程序会在稍后的几个指令中更加难以解决,但是会带来一些不明白的空指针错误,需要花费一个小时来debugging。
我最喜欢的“不崩溃”模式是这样的:
public User readUserFromDb(int id){ User u = null; try { ResultSet rs = connection.execute("SELECT * FROM user WHERE id = " + id); if (rs.moveNext()){ u = new User(); u.setFirstName(rs.get("fname")); u.setSurname(rs.get("sname")); // etc } } catch (Exception e) { log.info(e); } if (u == null){ u = new User(); u.setFirstName("error communicating with database"); u.setSurname("error communicating with database"); // etc } u.setId(id); return u; }
现在,您不必要求您的用户复制/粘贴错误消息并将其发送给您,您必须深入查看日志以查找日志条目。 (因为他们input了一个无效的用户ID,那么就不会有日志条目。)
我认为每当我认识到它们就应用devise模式是有道理的。
我不知道我实际上是从外国的编程语言复制样式,而我正在使用的语言允许更优雅或更简单的解决scheme。
使用多种(非常)不同的语言打开了我的眼睛,让我意识到,我不必错误地将其他人的解决scheme应用于不属于我的问题。 现在当我看到像Ruby这样的语言应用工厂模式时,我不寒而栗。
强迫testing。 我曾经是testing先行发展的狂热支持者。 对于某些项目来说,这是很有道理的,但是我意识到,这不仅是不可行的,而且对于许多项目来说都是不利的,坚持为每一项function编写unit testing的准则。
真的,任性地坚持任何事情都是有害的。
这是一件小事,但是:关心大括号的位置(在同一行或下一行?),build议的代码的最大行长度,variables的命名约定和样式的其他元素。 我发现每个人似乎都比我更关心这个事情,所以我现在就跟随我一起工作。
编辑:当然,这是一个例外,当我是最关心的人(或者是设置一个组的风格的人)。 那样的话,我做我想做的!
(注意,这与不一致的风格是一样的,我认为代码库中的一致风格对于可读性来说非常重要)。
也许,自从我改变主意之后,最重要的“编程实践”就是我的代码比其他任何人都好。 这对程序员(特别是新手)来说很常见。
实用程序库。 我曾经带着各种各样的辅助方法和类来进行汇编,理论上我可以在某个地方的某个地方使用它们。
实际上,我创build了一个巨大的命名空间,其中有很多function不佳的组织。
现在,我只是把它们放在我创build它们的项目中。很可能我不需要它,如果我这样做,我总是可以将它们重构成稍后可重用的东西。 有时候我会用一个TODO标记它们,以便将它们提取到一个普通的程序集中。
devise比我更多的编码。 一段时间后,它变成分析瘫痪。
使用DataSet来执行业务逻辑。 这将代码绑定到数据库太紧密,DataSet通常是从SQL创build的,这使得事情变得更加脆弱。 如果SQL或数据库发生更改,它往往会扯到DataSet触及的所有内容。
在对象构造函数中执行任何业务逻辑。 通过inheritance和创build重载构造函数的能力往往会使维护变得困难。
缩写variables/方法/表/ …名称
我曾经一直这样做,即使在使用不限制名称长度的语言(很可能是255或者其他)的情况下也是如此。 其中一个副作用是在解释(非标准)缩写的代码中散布的很多评论。 当然,如果名称因任何原因而改变,
现在我更喜欢用很好的描述性名称来称呼事实。 仅包括标准缩写。 不需要包含无用的注释,代码更具可读性和可理解性。
使用自定义的辅助方法层包装现有的数据访问组件(如企业库)。
- 这不会让任何人的生活更轻松
- 它有更多的代码可以有它的错误
- 很多人知道如何使用EntLib数据访问组件。 除了本地团队之外,没有人知道如何使用内部数据访问解决scheme
我在1984年的时候第一次听说过面向对象的编程,但是直到1992年我使用cfront C ++编译器才得以使用oo语言。我终于在1995年使用了Smalltalk。我非常期待oo技术,并且认为它会节省软件开发。
现在,我只是把oo看作一种有一些优点的技术,但它只是工具箱中的一个工具。 我在Python中完成了大部分工作,而且我经常编写不是类成员的独立函数,而且我经常在元组或列表中收集数据组,这些数据在过去我将创build一个类。 当数据结构复杂时,我仍然创build类,或者我需要与数据相关的行为,但是我倾向于抵制它。
我真的有兴趣做一些Clojure的工作,但是我没有提供oo工具,但是如果我理解的正确的话,它可以使用Java对象。 我还没有准备好像oo已经死了一样,但是我个人并不是我以前的粉丝。
在C#中,私人成员使用_notation
。 我现在觉得这很丑。
然后, this.notation
为私人成员更改了this.notation
,但是发现我在使用它的时候并不一致,所以我也放弃了这一点。
在实施之前,我停止了由大学推荐的devise方法。 在混乱和复杂的系统中工作迫使我改变态度。
当然,我仍然在进行代码研究,特别是当我要触摸我以前从未碰过的代码时,通常我会尽量关注尽可能小的实现,以便先行一步。 这是主要目标。 然后逐渐完善逻辑,让devise本身出现。 编程是一个迭代过程 ,并且在敏捷方法和很多重构方面效果很好。
代码不会看你最初以为它会是什么样子。 每次都会发生:)
我曾经在合同devise方面做大。 这意味着在我的所有function开始时进行大量的错误检查。 从关注点分离的angular度来看,合同仍然很重要,但是不是试图强制执行我的代码不应该做的事情,而是尝试使用unit testing来validation它的function。
我会在很多方法/类中使用静态,因为它更简洁。 当我开始写testing,实践变化很快。
检查exception
纸上的一个奇妙的想法 – 清楚地定义合同,没有错误的余地或忘记检查一些exception情况。 当我第一次听到这个消息的时候,我被卖了。
当然,在实践中变得如此混乱。 为了让今天的图书馆像Spring JDBC一样隐藏遗留检查的exception作为其主要function之一。
有价值的东西只能用一种特定的语言编码。 在我的情况下,我相信C是有史以来最好的语言,我从来没有任何理由用任何其他语言编码任何东西…永远。
从那以后,我开始体会到许多不同的语言和他们提供的好处/function。 如果我想快速编写一些代码 – 我会使用Python。 如果我想在一个大型项目上工作,我会用C ++或C#编写代码。 如果我想开发一个脑肿瘤,我会用Perl编码。
当我需要做一些重构时,我认为直接开始实施新的devise,修复连接直到它们工作起来更快更干净。 然后我意识到最好做一系列小的重构,以缓慢但可靠地向新devise前进。
也许在我的编码实践中以及在其他编程实践中发生的最大的变化是接受从互联网下载的外部类和图书馆作为应用程序行为和function的基础。 在上大学的时候,我们被鼓励去学习如何通过我们自己的代码来改善事情,并依靠语言来解决我们的问题。 随着用户界面和服务/数据消费的各个方面的进步,这不再是一个现实的概念。
有些东西在语言中永远不会改变,并且有一个库将代码封装在一个简单的事务中,而我需要编写的代码行数很less就是一个祝福。 连接到数据库将始终是相同的。 在DOM中select一个元素不会改变。 通过服务器端脚本发送电子邮件永远不会改变。 不得不一次又一次地写这些东西,浪费了我可以用来改进应用程序中的核心逻辑的时间。
初始化所有class级成员。
我曾经显式初始化每个类的成员,通常是NULL。 我已经意识到这一点:
- 通常意味着每个variables在被读取之前被初始化两次
- 是愚蠢的,因为在大多数语言自动初始化variables为NULL。
- 实际上在大多数语言中实施轻微的性能下降
- 可以在更大的项目上膨胀代码
和你一样,我也接受了IoC模式来减less我应用程序各个组件之间的耦合。 这使得维护和部件交换更加简单,只要我可以保持每个组件尽可能独立。 我还利用了更多的对象关系框架(如NHibernate)来简化数据库pipe理杂事。
简而言之,我使用“迷你”框架来帮助更快更高效地构build软件。 这些小型框架节省了大量的时间,如果做得好,可以使应用程序超级简单,以保持下去。 即插即用赢得胜利!