关于语言不可知:Allen Holub写道“你永远不应该使用get / set函数”,他是否正确?

Allen Holub wrote “You should never use get/set functions”, is he correct?

本问题已经有最佳答案,请猛点这里访问。

艾伦wrote Holub the following,P></

You can't have a program without some coupling. Nonetheless, you can minimize coupling considerably by slavishly following OO (object-oriented) precepts (the most important is that the implementation of an object should be completely hidden from the objects that use it). For example, an object's instance variables (member fields that aren't constants), should always be private. Period. No exceptions. Ever. I mean it. (You can occasionally use protected methods effectively, but protected instance variables are an abomination.)

它听起来合理,但他会去网上说,P></

You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public (though access functions that return full-blown objects rather than a basic-type value are reasonable in situations where the returned object's class is a key abstraction in the design).

which,坦率地说,他只是对我的声音。P></

《信息隐藏原理的理解,但你不能没有被访问和使用Java豆t at all。不,你会在后续的诀窍. MVC设计模型没有茶,since the can not be for负责渲染模型视图。P></

不管一个人多,AM在年轻的程序员和更多的面向对象的设计everyday learn about。也许有人可以在网上与更多的经验weigh this的问题。P></文章holub' Allen s for reference

  • 为什么extends是邪恶的
  • 为什么是邪恶的getter和setter方法

相关问题:

  • Java: Are Getters and Setters evil?
  • Is it really that wrong not using setters and getters?
  • Are get and set functions popular with C++ programmers?
  • Should you use accessor properties from within the class, or just from outside of the class?


Holub告诉您,通常应该避免改变对象的状态,而应该使用集成的方法(行为的执行)来实现这一目的,这一点我并不介意。正如Corletk指出的那样,对于最高级别的抽象进行长时间的、艰苦的思考是明智的,而不仅仅是用getter/setter进行无思想的编程,这样做只会让您围绕封装做一个最终的运行。

但是,如果有人告诉您应该"从不"使用setter或"从不"访问原语类型,那么我会遇到很多麻烦。事实上,在任何情况下,保持这一级别的纯度所需的努力都可能并且最终会导致代码比使用适当实现的属性更复杂。你只需要有足够的判断力就可以知道你何时会以牺牲长期痛苦为代价而违反短期收益的规则。

Holub不相信你知道区别。我认为,了解这些差异才是你成为专业人士的原因。


我认为艾伦·霍尔布在这篇文章中所说的话如下。

Getters and setters can be useful for variables that you specifically want to encapsulate, but you don't have to use them for all variables. In fact, using them for all variables is nasty code smell.

程序员们遇到的问题,艾伦·霍尔布正是指出了这一点,他们有时会对所有变量使用getter/setter。封装的目的也就不复存在了。


仔细阅读那篇文章。Holub强调getter和setter是一个邪恶的"默认反模式",这是我们在设计一个系统时陷入的一个坏习惯,因为我们可以。

思考的过程应该沿着直线;这个物体是做什么的?它的职责是什么?它的行为是什么?它知道什么?对这些问题进行长时间的认真思考会自然地引导您设计类,这些类将公开尽可能高级别的接口。

汽车就是一个很好的例子。它公开了一个定义良好、标准化的高级接口。我不关心我自己和setSpeed(60)…是英里/小时还是公里/小时?我只是加速,巡航,减速。我不需要考虑setSteeringWheelAngle(getSteeringWheelAngle()+Math.rad(-1.5))中的细节,我只是turn(-1.5),细节在引擎盖下处理。

它可以归结为"您可以并且应该弄清楚每个类将用于什么、它做什么、它表示什么,并公开尽可能满足这些需求的最高级别的接口"。getter和setter通常是一种逃避,当程序员只是懒得去做分析,从而精确地确定每一个类是什么,而不是什么,所以我们走上了"它能做任何事情"的道路。能手和二传手是邪恶的!

有时对一个类的实际需求提前是不可知的。这很酷,现在只需避开并使用getter/setter反模式,但是当您通过经验了解类的用途时,您可能会希望返回并清理脏的低级接口。基于"你希望你在一开始就写傻子的时候就知道的东西"的重构对于这门课程来说是很正常的。你不需要知道所有的事情才能开始工作,只是你知道的越多,在工作的过程中需要的返工就越少。

这就是他提倡的心态。吸气剂和二传手是容易掉入的陷阱。

是的,bean基本上需要getter和setter,但对我来说,bean是一种特殊情况。bean表示名词、事物、可识别的(如果不是物理的)有形物体。事实上,并不是很多物体都有自动行为;大多数情况下,物体都是由外力(包括人类)操纵的,以使其具有生产力。

daisy.setColor(Color.PINK)完全有道理。你还能做什么?也许是一个秃鹰的思想融合,使花想要粉红?六羟甲基三聚氰胺六甲醚?

能手和二传手有他们的吗?邪恶?地点。这只是,就像所有真正好的OO事物一样,我们倾向于过度使用它们,因为它们是安全和熟悉的,更不用说简单了,因此,如果没有人看到或听到它们可能会更好,至少在他们掌握了心灵融合的东西之前。


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

好吧,简单地说——我不同意他的观点;他对返回类型的属性非常挑剔,因为它会破坏调用代码——但同样的参数也适用于方法参数。如果你也不能使用方法?

好的,方法参数可以更改为加宽转换,但是……为什么…另外,请注意,在c中,var关键字可以减轻许多这种感觉到的痛苦。

访问器不是实现细节;它们是公共API/契约。是的,如果你违反了合同,你就有麻烦了。那什么时候变成了一个惊喜?同样,访问器也是非常重要的——即它们不仅仅是包装字段;它们执行计算、逻辑检查、通知等,并且允许基于接口的状态抽象。哦,还有多态性等等。

访问器的冗长特性(第3页?4??)-在c:public int Foo {get; private set;}中-作业完成。

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


我在Allen Holub上做了一些谷歌搜索,好像他在Java社区里有他的对手。

  • Allen Holub是邪恶的
  • 邪恶的裁判员
  • Holub又来了

最后一个是特别指出的。评论员的文字是斜体。

Though getIdentity starts with"get," it's not an accessor because it doesn't just return a field. It returns a complex object that has reasonable behavior

哦,但是等等……那么,只要返回对象而不是基元类型,就可以使用访问器了?这是另外一个故事,但对我来说也一样愚蠢。有时需要对象,有时需要基本类型。

另外,我注意到,自从艾伦上一篇关于同一主题的专栏文章"从不使用访问器"没有出现任何一个例外以来,他已经从根本上软化了自己的立场。也许几年后他才意识到,配饰毕竟是有目的的……

Bear in mind that I haven't actually put any UI code into the business logic. I've written the UI layer in terms of AWT (Abstract Window Toolkit) or Swing, which are both abstraction layers.

好的。如果你在SWT上写申请书呢?在这种情况下,"抽象"到底有多大?直面现实:这个建议只是引导您在业务逻辑中编写UI代码。多么伟大的原则啊。毕竟,至少十年前,我们才将这种实践确定为项目中最糟糕的设计决策之一。

< /块引用>

我的问题是作为一个新手程序员,有时会在网上的文章上绊倒,给他们更多的信任。也许这就是其中之一。


getter和setter仅用作一个掩码,使私有变量公开。

没有必要重复Holub已经说过的话,但关键是类应该表示行为,而不仅仅是状态。


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

例如,尽管有些人不同意,但我喜欢Java标准API。我也喜欢弹簧框架。查看这些库中的类,您会发现很少有setter和getter只是为了公开一些内部变量。有一些方法名为getx,但这并不意味着它是传统意义上的getter。

所以,我认为他有一个观点,那就是:每当你在Eclipse(或者你选择的IDE)中按下"生成getter/setters"时,你应该后退一步,想知道你在做什么。公开这个内部表示真的合适吗,还是我在某个步骤中弄乱了我的设计?


getter/setter的问题在于它们试图伪造封装,但实际上它们通过暴露内部来破坏封装。第二,他们试图做两件不同的事情——提供访问和控制他们的状态——结果都做得不好。

它破坏了封装,因为当您调用get/set方法时,首先需要知道要更改的字段的名称(或有一个好主意),然后必须知道它的类型,例如,您不能调用

1
setPositionX("some string");

如果您知道字段的名称和类型,并且setter是公共的,那么任何人都可以像调用公共字段一样调用该方法,因为这只是一种更复杂的方法,所以为什么不首先简化它并使其成为公共字段呢?

通过允许访问它的状态,但同时试图控制它,get/set方法只是混淆了事情,结果要么是无用的锅炉板,要么是误导性的,实际上并没有做它所说的事情,而是产生了用户可能不期望的副作用。如果需要进行错误检查,可以将其称为

1
2
3
4
5
6
public void tryPositionX(int x) throws InvalidParameterException{
    if (x >= 0)
        this.x = x;
    else
        throw new InvalidParameterException("Holy Negatives Batman!");
}

或者,如果需要额外的代码,可以根据整个方法所做的工作,例如,将其称为更准确的名称。

1
2
3
4
tryPositionXAndLog(int x) throws InvalidParameterException{
    tryPositionX(x);
    numChanges++;
}

我认为需要吸气剂/设置器才能使某些东西工作通常是不良设计的症状。利用"告诉,不要问"的原则,或者重新思考为什么一个对象首先需要发送它的状态数据。公开更改对象行为而不是状态的方法。这样做的好处包括更容易维护和更高的扩展性。

你也提到了MVC,并且说一个模型不能对它的观点负责,因为在这种情况下,Allen Holub给出了一个例子,通过拥有一个"give-me-a-jcomponent-that-representative-your-identity类"来创建一个抽象层,他说这将"隔离身份与系统其他部分的表示方式"。我没有足够的经验来评论这是否可行,但从表面上看,这听起来是个不错的主意。


(P)当阶级没有真正的一致性,或者当事实上存在差异时(作为一个点类别),公共变量就可以使人感觉到。总的来说,如果在一个类别中有任何变量表明,你认为可能不应该是公共的,那就是说,这个类别有一些一致性,而且变量有一些相关的因素,应该保持不变,那么所有变量都应该是私人的。(p)(P)Getters and setters make sense when they reflect some sort of coherent idea.In a polygon class,for example,the X and y coordinates of given vertices have a meaning outside the class boundary.It probably makes sense to have getters,and it like makes sense to have setters.在一个银行账户类别中,资产负债表作为一个私人变量可能存在,而且Almost certainly should have a getter.如果这是一个问题,它需要有logging built以保持可审计性。(p)(P)在一些公共变量方面,Getters and Setters有一些优势。They provide some separation of interface and implementation.Just because a point has a EDOCX1 plography 0 communal function doesn't mean there has to be an X,since EDOCX1 commercial 0 and EDOCX1 commercial 2.Can be made to work just fine with radial coordinates.Another is that it's possible to maintain class invhariants,by doing whatever's necessary to keep the class consistent within the setter.Another is that it's possible to have functionality that triggers on a set,like the logging for the bank account balance.(p)(P)然而,为了更抽象的分类,会员国的可变因素失去了个人的意义,而只是在上下文中产生了感觉。You don't need to know all the internal variables of a C++stream class,for example.You need to know how to get elements in and out,and how to perform various other actions.If you counted on the exact internal structure,you'd be bogged down in detail that could arbitrary vary between compilers or versions.(p)(P)So,I'd say to use private variables almost exclusively,getters and setters where they have a real meaning in object behavior,and not otherwise.(p)(P)仅仅因为获得者和定居者经常不被人利用。(p)


我不相信他是说永远不要使用g e t/set,而是说对字段使用get/set并不比将字段公开(例如,公共字符串名称与公共字符串名称get;set;)更好。

如果使用get/set,它将限制OO的信息隐藏,这可能会将您锁定到一个错误的接口中。

在上面的示例中,name是一个字符串;如果我们希望以后更改设计以添加多个名称,该怎么办?接口只公开了一个字符串,因此我们不能在不破坏现有实现的情况下添加更多字符串。

但是,如果最初没有使用get/set,而是使用了add(字符串名称)等方法,则可以在内部单独处理名称或添加到列表或不处理的内容,并在外部调用add方法,尽可能多次地添加更多的名称。

OO的目标是设计一个抽象的层次;不要暴露出比你绝对需要的更多的细节。

如果你刚刚用get/set包装了一个原始类型,那么很可能你已经打破了这个原则。

当然,这是如果你相信OO目标的话;我发现大多数人,不是真的,他们只是使用对象作为一种方便的方法来对功能代码进行分组。


(P)如果这些机构提供了执行细节的机会,公共采购/定居者就很糟糕。Yet,it is reasonable to provide access to object's properties and use getters/setters for this.For example,if car has the color property,it's acceptable to let clients"observe"it using a getter.如果某些客户需要有能力回收汽车,那么分类可以提供一个定居者(`回收'是更清洁的名称思考)。这对我们来说很重要,因为我们不让客户知道在目标中有多少财产,这些财产是如何维护的,以及它们是如何维护的。(p)


(P)I think that getters and setters should only be used for variables which one need to access or change outside a class.That being said,I don't believe variables should be public unless they're static.这是因为使公共变量能够引导他们实现变化中的发展。让我们来告诉你,谁是没有根据的公共变量。He then accesses a variable from another class and without meaning to,changes it.现在他在自己的软件里已经犯了一个错误那是我为什么相信有人会使用这些技术,但你不需要这些技术来保护任何私人或可变因素。(p)


嗯……他没听说过封装的概念吗?getter和setter方法用于控制对类成员的访问。通过使所有字段公开…任何人都可以编写他们想要的任何值,从而完全使整个对象无效。

如果有人对封装的概念有点模糊,请在这里阅读:

封装(计算机科学)

…如果他们真的很邪恶,.NET会把财产概念构建成语言吗?(getter和setter方法看起来有点漂亮)

编辑

本文确实提到了封装:

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

使用这种方法将导致从长远来看极难维护代码。如果您在一个跨越数年的项目中发现需要封装一个字段,那么您必须更新软件中该字段的每个引用,以获得好处。在前面使用合适的封装,在以后的头痛中保护自己,这听起来更聪明。