自引用方法链接有任何实际缺点吗?


14

我最近建议为某个项目中的某个类实施链接方法,以便可以提高代码的可读性。我得到了一个“流畅的接口,不应该只是为了方便而实现,而是为了语义”,并拒绝了我的建议。我回答我不是在建议使用流畅的界面,而是将方法自身链接(可以相互混淆,请在底部阅读)以提高可读性和编码舒适度,但该建议再次遭到拒绝。

无论如何,这让我想到也许总是以不应该返回任何内容的方法(例如,setter)返回“ this”,这可能会导致一种不好的做法。

我的问题是:可以将先前的惯例视为不良做法或滥用吗?为什么?我认为没有任何性能缺陷,还是存在?


2
看看这个问题的一个很好的讨论programmers.stackexchange.com/questions/48419/...
KeesDijk

@KeesDijk谢谢,我编辑了我的问题,使其与那个问题不太相似,因为我对同一类的链接方法更感兴趣
dukeofgaming 2011年

1
在SO,他们告诉我,链接不适用于C ++- stackoverflow.com/questions/5760551 / ...-您如何看待?
kagali-san 2011年

1
@mhambra看起来您只需要在实现方法链并为之定义明确的标准时要小心。
dukeofgaming 2011年

Answers:


10

没有

正如肯特·贝克(Kent Beck)指出的那样,代码读取的频率远远超过其编写的频率。

如果方法链接使您的代码更具可读性,请使用方法链接。


1
很棒的书.. +1
Rein Henrichs

5
但是,如果您是唯一一种链接起来更具可读性的查找方法,该怎么办?如果这是一个关于语法问题的问题,那么您将遵循一组编码约定:这意味着为了保持一致性,以与现有代码相同的方式编写。
coredump 2014年

@coredump听起来好像OP已经被告知要这样做,但是我认为Steven只是说这是因为方法链接使其更具可读性。
Panzercrisis

1
@Panzercrisis OP由于便利性和语义而被告知不要使用方法链接。史蒂文(Steven)的回答基本上说“无论如何都要做”,并且仅考虑OP代码本身的可读性,而不考虑团队的意见或一致性。如果OP想要重写项目中的每个现有类,以使其适合他的代码可读性,该怎么办?这就是我对方便/语义论点的理解:应该有一个“技术上”的理由来进行方法链接(顺便说一句,这个论点听起来也好像是另一个人为其自己的偏好提供了借口)
coredump

9

是的,有缺点

易于阅读的代码是好的,但也要注意代码所传达的内容。当一个对象的方法总是返回该对象时,它传达了两件事:

  1. 我要求不一定要按顺序设置或配置的高级配置
  2. 后续的每个方法调用均基于最后一个

有效用例:临时数据库查询

类库几乎以每种语言存在,可让您查询数据库而无需求助于硬编码的SQL。以.NET实体框架为例:

DBContext db = new DBContext();
List<Post> posts = db.Posts
    .Where(post => post.Title.Contains("Test"))
    .OrderBy(post => post.DateCreated)
    .ToList();

这是一个流畅的接口,每个后续方法调用都建立在前一个方法上。在查询数据库的上下文中,从逻辑上读取这些调用很有意义。

无效的用例:用于设置属性的语法糖

现在让我们对Post类使用相同的模式:

public class Post
{
    public string Title { get; set; }
    public DateTime DateCreated { get; set; }
    public string Body { get; set; }

    public Post SetTitle(string title)
    {
        Title = title;

        return this;
    }

    public Post SetDateCreated(DateTime created)
    {
        DateCreated = created;

        return this;
    }

    public Post SetBody(string body)
    {
        Body = body;

        return this;
    }
}

现在让我们看一下如何使用此类:

Post post = new Post()
    .SetTitle("Test")
    .SetDateCreated(DateTime.Now)
    .SetBody("Just a test");

当我看到此代码时,我立即问这个问题:“调用后SetBody,它查询数据库吗?我需要调用另一个方法来说'我完成了吗?'”

链式方法调用使用类与代码进行了哪些通信Post

  1. 我有一个复杂的设置
  2. 每个方法调用均基于前一个方法

真的吗?号的Post类并没有有一个复杂的设置。设置标题,创建日期和正文并不能相互建立更复杂的最终目标。您已将一个方形钉捣成一个圆孔。

自引用方法链接的缺点是,您必须传达需要进行多个方法调用才能执行某项操作,并且每个调用都建立在最后一个方法的基础上。如果不是这样,则方法链接可能会将错误的信息传达给其他程序员。

当您的同事说:

流利的接口不应该只是为了方便而实现,而是为了语义

他们是绝对正确的。流利的接口或方法链接本身可能在传达某些不正确的信息。


这假定方法链接和复杂的配置总是齐头并进。它们是不同的实体,一个实体的存在不应使您假设另一个实体。
2014年

这不仅是“复杂的配置”,而且是“从前一个方法构建的后续方法调用”。方法链接具有关于它的元通信,这种通信并不总是符合类的目的。
Greg Burghardt 2014年

1
从先前的方法构建的后续方法调用也与方法链不同,并且我认为将方法链的语法视为对依赖顺序的一系列副作用操作的语义的强通信是可靠或有用的。这是一个语法简写,仅此而已。在它使事情更短,更易读的地方使用它。
2014年

1
我知道你想方法链是分开的,但我说,谁没有在你的头,并使用其他类库其他程序员实现方法链接这些原因最终可能使你的代码是不真实的假设。请注意,方法链接可能暗示您(代码作者)不希望这样做。清晰通信的代码与易于阅读的代码一样重要。不要为另一个牺牲。
格雷格·伯格哈特

1
When an object's methods always return the object, it communicates a couple of things-我认为这是个人观点;很难断言,每个查看链接方法的人都会承担相同的事情。
Sam Dufel 2014年

1

主要缺点是清晰度不够。例如:

x.foo();
x.bar();
x.baz();

由于这些语句都不返回值(或者如果返回,则将其忽略),因此只有在产生副作用时它们才有用。与此相反:

x.foo()
 .bar()
 .baz();

首先,它目前尚不清楚,barbaz在同一类型的对象进行操作x,除非你知道一个事实x的类是这些方法的唯一类。即使是这种情况,也不清楚方法在x或新对象上运行的方法。

突出显示代码中具有副作用的部分很有用,因为您需要跟踪这些副作用以对程序进行推理。您必须权衡潜在的清晰度损失与易于编写代码的潜在收益之间的关系,而且还要考虑对代码的读取比对代码的读取要多。


0

考虑编程语言的所有风格元素(与手工编码机器语言相对),这削弱了“语义而非便利”的论点。

我们作为工程师所做的很多事情都是围绕语义提供便利。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.