Allen Holub写道"你永远不应该使用get/set函数",他是否正确?

Jam*_*hon 50 language-agnostic oop getter setter immutability

Allen Holub写了以下内容,

如果没有一些耦合,你就无法拥有一个程序.尽管如此,您可以通过盲目地遵循OO(面向对象的)规则来最大限度地减少耦合(最重要的是对象的实现应该完全隐藏在使用它的对象之外).例如,对象的实例变量(非常量的成员字段)应始终为私有.期.没有例外.永远.我是认真的.(您可以偶尔有效地使用受保护的方法,但受保护的实例变量是令人厌恶的.)

这听起来很合理,但他继续说,

你不应该出于同样的原因使用get/set函数 - 它们只是过于复杂的方式使字段公开(尽管返回完整对象而不是基本类型值的访问函数在返回对象的情况下是合理的class是设计中的关键抽象).

坦率地说,这对我来说听起来很疯狂.

我理解信息隐藏的原理,但是如果没有访问器和更改器,你根本就不能使用Java bean.我不知道如何在模型中没有访问器的情况下遵循MVC设计,因为模型不能负责渲染视图.

但是,我是一名年轻的程序员,而且我每天都在学习更多关于面向对象设计的知识.也许拥有更多经验的人可以在这个问题上权衡.

Allen Holub的文章供参考


相关问题:

Mar*_*ham 38

我不知道Holub告诉你一般应该避免改变一个对象的状态,而是采用集成方法(执行行为)来实现这一目的.正如Corletk所指出的那样,对于最高级别的抽象而言,有很多智慧在思考,而不仅仅是使用getters/setter进行编程,而只是让你在封装中进行最终运行.

但是,对于那些告诉你应该"永远不会"使用setter或者"永远不会"访问原始类型的人来说,我遇到了很多麻烦.实际上,在所有情况下保持这种纯度水平所需的努力最终会导致代码比使用适当实现的属性更复杂.你必须要有足够的知识来了解你何时以牺牲长期痛苦为代价来制定短期利益规则.

Holub不相信你知道差异.我认为了解差异是什么让你成为一个专业人士.

  • 我喜欢这一点:专业人员知道何时(和如何)有效地应用技术......黑客"只是让它工作". (6认同)

cor*_*ttk 32

仔细阅读该文章.Holub正在强调吸气剂和制定者是一种邪恶的"默认反模式",这是我们在设计系统时陷入的坏习惯; 因为我们可以.

思想过程应该是一致的; 这个对象做了什么?它的职责是什么?它的行为是什么?它知道什么?对这些问题进行长期和艰苦的思考会使您自然地设计出可以展示最高级别界面的类.

汽车就是一个很好的例子.它公开了一个定义明确,标准化的高级接口.我不关心setSpeed(60)......是MPH还是km/h?我只是加速,巡航,减速.我不需要考虑细节setSteeringWheelAngle(getSteeringWheelAngle()+Math.rad(-1.5)),我只是turn(-1.5),细节是在引擎盖下处理的.

它归结为"你可以而且应该弄清楚每个类将用于什么,它做什么,它代表什么,并暴露最高级别的接口,以满足这些要求.吸气剂和制定者通常是一个警察,当程序员只是懒得做分析,以确定每个类是什么和不是什么,所以我们沿着"它可以做任何事情"的道路走下去.吸气剂和制定者是邪恶的!

有时,课程的实际要求是不可知的.这很酷,只是拷打并且现在使用getter/setter反模式,但是当你知道,通过经验,这个类被用于什么时,你可能想要回归并清理脏的低级接口.基于"当你在第一时间写傻瓜时希望你知道的东西"的重构是课程的标准.你不需要知道所有事情就可以开始,只是你知道的越多,在途中可能需要的返工就越少.

这是他正在推广的心态.吸气剂和制定者是容易陷入的陷阱.

是的,bean基本上需要getter和setter,但对我来说bean是一个特例.豆类代表名词,事物,有形可识别(如果不是物理)对象.实际上并没有很多对象具有自动行为; 大多数时候,外部力量(包括人类)操纵东西,使它们成为富有成效的东西.

daisy.setColor(Color.PINK)很有道理.你还能做什么?也许是瓦肯人的心灵融合,让花成粉红色?嗯?

吸毒者和二传手有他们的邪恶?地点.就像所有非常好的OO一样,我们倾向于过度使用它们,因为它们是安全和熟悉的,更不用说简单了,因此如果没有人看到或听到它们,可能会更好,至少在他们'之前d掌握了思想融合的事物.

  • "但是官员我正在编程到一个不明确的界面!" (6认同)
  • 不知道setSpeed(60)是以英里/小时为单位还是以公里为单位会让你入狱.不好的例子. (5认同)
  • 是的,我认为最初的陈述是轰动效应.使用正确抽象级别的文章,大多数人都同意,可能会获得较少的点击,然后发出煽动性声明. (3认同)

Suv*_*apa 31

我认为艾伦·霍尔布独醒,改写在文章中,如下.

getter和setter对于您特别想要封装的变量很有用,但您不必将它们用于所有变量.实际上,将它们用于所有变量都是令人讨厌的代码味道.

麻烦的程序员和Allen Holub指出的是,他们有时会为所有变量使用getter/setter.并且封装的目的丢失了.

  • 预先使用Getter/Setter方法可确保在整个软件生命周期中使用它们.如果你先把它们混合起来,然后再找出需要封装的道路......你需要重新编写任何引用该公共值的代码. (15认同)
  • +1拥有带getter/setter的容器类是合理的.任何有大量getter/setter的课程都可能是代码味道. (3认同)
  • @Justin Niessner,他没有说要用公共领域替换访问者.事实上,他唯一清楚的是访问者返回类型应该是接口. (3认同)

Mar*_*ell 10

(注意我是从.NET"属性"角度来看这个)

嗯,简单 - 我不同意他的意见; 他对返回类型的属性做了大惊小怪,因为它可以破坏你的调用代码 - 但完全相同的参数将应用于方法参数.如果你也不能使用方法?

好吧,方法参数可以改变为扩大转换,但......就是为什么......另外,请注意,在C#中,var关键字可以减轻很多这种感觉到的痛苦.

访问者不是实现细节; 它们是公共API /合同.是的,如果你打破了合同,你就会遇到麻烦.什么时候成为一个惊喜?同样地,访问者并不罕见 - 即它们不仅仅包装字段; 它们执行计算,逻辑检查,通知等.它们允许基于接口的状态抽象.哦,多态性 - 等

重新说明访问者的详细性(p3?4?) - 在C#中:public int Foo {get; private set;}- 完成工作.

最终,所有代码都是表达我们对编译器的意图的手段.属性让我以类型安全,基于契约,可验证,可扩展,多态的方式做到这一点 - 谢谢.为什么我需要"修复"这个?


cle*_*tus 9

使用getter和setter只是一个掩码来使私有变量公开.

没有必要重复Holub已经说过的内容,但其关键在于类应该代表行为,而不仅仅是状态.


Jam*_*hon 8

我在Allen Holub上做了一些额外的谷歌搜索,看起来他在Java社区中有他的对手.

最后一个是特别尖锐的.评论员的文字用斜体字表示.

虽然getIdentity以"get"开头,但它不是一个访问者,因为它不仅仅返回一个字段.它返回一个具有合理行为的复杂对象

哦,但是等等......只要你返回对象而不是原始类型,那么可以使用访问器吗?现在这是一个不同的故事,但它对我来说同样愚蠢.有时您需要一个对象,有时您需要一个原始类型.

此外,我注意到艾伦已经从他上一篇关于同一主题的专栏中彻底软化了自己的立场,其中"永不使用访问者"的咒语没有遭受任何一个例外.也许他在几年后意识到存取器确实起到了一个目的......

请记住,我实际上没有将任何UI代码放入业务逻辑中.我用AWT(抽象窗口工具包)或Swing编写了UI层,它们都是抽象层.

好的.如果您在SWT上编写应用程序怎么办?在这种情况下,"抽象"是如何真正的AWT?只需面对它:这个建议只会让您在业务逻辑中编写UI代码.多么伟大的原则.毕竟,自从我们将这种做法确定为您可以在项目中做出的最糟糕的设计决策之后,至少已经十年了.

我的问题是,作为一个新手程序员有时会绊到互联网上的文章,并给予他们更多的信任,然后我应该.也许这就是其中一个案例.


wax*_*ing 5

当这些想法呈现给我时,我想看看我使用的库和框架以及我喜欢使用的库.

例如,虽然有些人不同意,但我喜欢Java Standard API.我也喜欢Spring Framework.查看这些库中的类,您会注意到很少有setter和getter只是为了暴露一些内部变量.有一些名为 getX的方法,但这并不意味着它是传统意义上的吸气剂.

所以,我认为他有一个观点,就是这样:每当你按下Eclipse(或你选择的IDE)中选择"Generate getters/setters"时,你应该退后一步,想知道你在做什么.是否真的适合公开这种内部表示,还是我在某个步骤搞砸了我的设计?