4

I am thinking of using the builder pattern in C++ unit tests, to streamline the creation of input data for the code being tested.

In Java the common idiom seems to be to have the setters of the builder class return the (reference to) the builder object itself, so that multiple setters can be chained in a single line. E. g. the builder class could be defined like this:

// class builder 
public class Builder
{
  private Part1 part1;
  private Part2 part2;
  public Builder withPart1(Part1 p1);
  public Builder withPart2(Part2 p2);
};

And then used like this:

Builder b;
Part1 p1;
Part2 p2;
b.withPart1(p1).withPart2(p2);

The same effect can be achieved in C++ by having the setters return a reference to the builder object. However, I have not been able to find any examples of that on the web. Is this kind of "chaining" a common practice in C++? And if no, then why not?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Dima
  • 38,860
  • 14
  • 75
  • 115
  • I think my question is more specific. The question you cited seems to be about using the Builder pattern in general. Mine is about the "chaining" of setters. But I did get my answer, so thanks! – Dima Aug 01 '11 at 20:32
  • because it's an anti-idiom, getters and setters should be avoided, as they blow up encapsulation; constructors should be used to construct objects. – Gene Bushuyev Aug 01 '11 at 20:34
  • 2
    @Gene: A builder object effectively allows named arguments for construction. – Ben Voigt Aug 01 '11 at 20:40
  • 1
    @Gene, the whole point of the builder pattern is to make it easier to create an object of a class that has a complicated constructor with lots of arguments. It is hardly an anti-idiom. And getters and setters should be used to establish a reasonable policy for accessing the members of a particular class, not simply avoided. But that's a separate topic. – Dima Aug 01 '11 at 20:42
  • @Ben -- yes, and why would I destroy class design to do that? – Gene Bushuyev Aug 01 '11 at 20:43
  • @Gene you don't. You have your class A, and the class ABuilder, which helps you construct an object of A. – Dima Aug 01 '11 at 20:45
  • @Dima -- easier? why? and why would it matter if it's a bad design? lot's of arguments? -- again design issues. Getters/setters must be avoided, it's not a matter of personal taste, it's a bad design. – Gene Bushuyev Aug 01 '11 at 20:46
  • 2
    @Gene If you have a class `Rectangle`, it is perfectly reasonable for it to have getters like `getWidth()` or `getHeight()`. However, you would probably not provide setters for width and height, but instead have functions like `stretch()` and `shrink()`. If your rectangle is meant to be displayed, it might have a data member `color`, for which there would be both a getter and a setter. This is called a policy of member access. Some data members are readable, some are writable, and some are completely hidden. Saying "getters are bad" is not a technical argument, but a religious one. – Dima Aug 01 '11 at 20:52
  • @Dima -- these are bad design decisions, which unfortunately leaking into C++ from GUI frameworks. – Gene Bushuyev Aug 01 '11 at 21:01
  • @Gene You seem to live up to your name. :) – Dima Aug 01 '11 at 21:07
  • @Dima -- you're violating SO rules now! – Gene Bushuyev Aug 01 '11 at 21:23
  • @Gene: Why don't you tell the language committee what a bad design [setters](http://www.cplusplus.com/reference/iostream/manipulators/setiosflags/) are? [2](http://www.cplusplus.com/reference/iostream/streambuf/pubsetbuf/) – Ben Voigt Aug 01 '11 at 21:34
  • @Ben -- I don't think ios flags are relevant to this discussion. – Gene Bushuyev Aug 01 '11 at 21:53
  • @Gene: You claimed "getters/setters" must be avoided, apparently the C++ standards committee disagrees, because they use them. Although getters and setters in the C++ standard library are admittedly rare, compared to e.g. the .NET BCL or Java's library. – Ben Voigt Aug 01 '11 at 23:12
  • @Ben - no, I simply don't think stream manipulators have anything to do with this discussion: similarities are coincidental, differences are fundamental. And I believe Stroustrup and Sutter and might be others publicly expressed dislike for getters/setters. – Gene Bushuyev Aug 01 '11 at 23:30
  • Possible duplicate of [Builders in Java versus C++?](https://stackoverflow.com/questions/2294746/builders-in-java-versus-c) – Cœur Jul 13 '18 at 13:56
  • @coeur This question is related, but not a duplicate. I was asking specifically about chaining of builder getters, not a general question about the differences between Java and c++ builders. – Dima Jul 13 '18 at 14:30
  • @Dima close vote retracted: note that old links to a wrong duplicate need to be manually removed. – Cœur Jul 14 '18 at 05:56

1 Answers1

5

Yes it's a common practice, it's called a "Fluent API".

The canonical example:

while ((std::cin >> std::setbase(16) >> i >> s).getline(s2)) { ... }
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • what is common practice? chaining operators? -- why not when necessary; creating builders with setters? -- not by a long shot; it's simply bad design. – Gene Bushuyev Aug 01 '11 at 20:48
  • 2
    @Gene: There's no real difference between operators and other member functions (in my example, `getline` is not an operator). I understand your distaste for builders, but the question was 'Is this kind of "chaining" a common practice in C++?' and clearly fluent chaining is common, even though the builder pattern isn't. – Ben Voigt Aug 01 '11 at 20:52
  • @Ben why the distaste for builders? I have lots of unit tests with complicated and largely duplicated code which sets up the input data. Using builders seems like a good way to clean that up. – Dima Aug 01 '11 at 20:56
  • @Ben -- while operator chaining is quite common, function call chaining smells bad and probably is an indication of a design problem, especially when there are setters involved. – Gene Bushuyev Aug 01 '11 at 20:57
  • @Gene: I originally included `getline` (and used its return value) in my example specifically to counter the argument that operator chaining is good but function call chaining is bad. – Ben Voigt Aug 01 '11 at 21:36