这绝对是主观的,但我想尽量避免它变成争论。我认为如果人们恰当地对待它,这将是一个有趣的问题。
这个问题的想法来自于我对“你最讨厌的语言的哪五件事?”问题的回答。我认为c#中的类在默认情况下应该是密封的——我不会把我的理由放在这个问题上,但我可能会写一个更完整的解释来回答这个问题。我对评论中的讨论热度感到惊讶(目前有25条评论)。
那么,你有什么有争议的观点?我宁愿避免那些基于相对较少的基础而导致相当宗教的事情(例如,大括号放置),但例如可能包括“单元测试实际上并没有多大帮助”或“公共字段确实是可以的”之类的事情。重要的是(至少对我来说)你的观点背后是有理由的。
请提出你的观点和理由——我鼓励人们投票给那些有充分论证和有趣的观点,不管你是否恰好同意这些观点。
getter和setter被过度使用
我见过数百万人声称公共字段是邪恶的,所以他们将它们设置为私有字段,并为所有这些字段提供getter和setter。我相信这与公开字段几乎是一样的,如果你使用线程(但通常不是这样)或如果你的访问器有业务/表示逻辑(至少有些“奇怪”),可能会有点不同。
我不赞成公共字段,但反对为每个字段创建getter/setter(或Property),然后声称这样做是封装或信息隐藏……哈!
更新:
这个答案在评论中引起了一些争议,所以我会试着澄清一下(我不会动原文,因为这是许多人点赞的)。
首先,任何使用公共场地的人都应该坐牢
现在,创建私有字段,然后使用IDE为每个私有字段自动生成getter和setter,几乎和使用公共字段一样糟糕。
很多人认为:
私有字段+公共访问器==封装
我说(自动或非自动)为字段生成getter/setter对有效地违背了您试图实现的所谓封装。
最后,让我引用Bob叔叔在这个主题中的一句话(摘自“干净代码”的第6章):
我们保持沉默是有原因的
私有变量。我们不想要
没有人可以依靠他们。我们想要的
自由地改变他们的类型或者
心血来潮地执行
冲动。那么,为什么要这么多呢
程序员会自动添加getter
和对象的setter,暴露
他们的私人领域,就好像他们是
公众吗?
对象不应该处于无效状态
不幸的是,许多ORM框架要求所有实体类都使用零参数构造函数,使用setter填充成员变量。在这些情况下,很难知道为了构造一个有效的对象必须调用哪些setter。
MyClass c = new MyClass(); // Object in invalid state. Doesn't have an ID.
c.setId(12345); // Now object is valid.
在我看来,一个对象不可能发现自己处于无效状态,类的API应该在每次方法调用后主动强制它的类不变量。
构造函数和突变方法应该原子地将对象从一种有效状态转换为另一种有效状态。这个好多了:
MyClass c = new MyClass(12345); // Object starts out valid. Stays valid.
作为一些库的使用者,在尝试使用一个对象之前跟踪是否调用了所有正确的setter是一件非常痛苦的事情,因为文档通常没有提供关于类契约的线索。
默认情况下,数组应该基于1,而不是基于0。系统实现语言不一定是这样,但是像Java这样的语言吸收了更多C语言的奇怪之处。“元素1”应该是第一个元素,而不是第二个,以避免混淆。
计算机科学不是软件开发。毕竟,你不会雇佣一个只学过物理的工程师。
尽可能多地学习数学。您不会使用大部分的知识,但是您需要能够以这种方式思考才能擅长软件。
目前标准化的唯一最好的编程语言是Common Lisp,尽管它很冗长并且有从零开始的数组。这很大程度上是因为它被设计成一种方式
来写计算,而不是抽象的冯·诺依曼机器。
至少90%的对编程语言的比较批评可以归结为“语言A有C特性,而我不知道如何在语言B中实现C或类似的功能,所以语言A更好。”
“最佳实践”是我所见过的“平庸”最令人印象深刻的拼写方式。
现代c++是一门美丽的语言。
我说出来了。很多人真的很讨厌c++,但说实话,我发现现代c++与STL/Boost风格的编程在大多数时候是一种非常有表现力、优雅和令人难以置信的高效语言。
我认为大多数讨厌c++的人都是基于使用OO的糟糕经历。c++在面向对象方面做得不是很好,因为多态性通常依赖于堆分配对象,而且c++没有自动垃圾收集。
但c++真正的亮点在于泛型库和函数式编程技术,这使得构建难以置信的大型、高度可维护的系统成为可能。很多人说c++试图做所有事情,但最终什么都做不好。我可能同意它在面向对象方面不如其他语言,但它在泛型编程和函数编程方面比任何其他主流的基于c的语言都要好。(c++ 0x只会进一步强调这一事实。)
我也很欣赏c++如何让我在必要时获得底层,并提供对操作系统的完全访问。
加上RAII。认真对待。当我用其他c语言编程时,我真的很想念析构函数。(不,垃圾回收不会使析构函数无用。)
详细的设计是浪费时间,如果一个工程师需要它们来做一份体面的工作,那么就不值得雇佣它们!
好的,这里有几个想法:
1) the old idea of waterfall development where you supposedly did all your design up front, resulting in some glorified extremely detailed class diagrams, sequence diagrams etc. etc., was a complete waste of time. As I once said to a colleague, I'll be done with design once the code is finished. Which I think is what agile is partly a recognition of - that the code is the design, and that any decent developer is continually refactoring. This of course, makes the idea that your class diagrams are out of date laughable - they always will be.
2) management often thinks that you can usefully take a poor engineer and use them as a 'code monkey' - in other words they're not particularly talented, but heck - can't you use them to write some code. Well.. no! If you have to spend so much time writing detailed specs that you're basically specifying the code, then it will be quicker to write it yourself. You're not saving any time. If a developer isn't smart enough to use their own imagination and judgement they're not worth employing. (Note, I'm not talking about junior engineers who are able to learn. Plenty of 'senior engineers' fall into this category.)