I consider fluent interfaces very convenient for many tasks. But I feel uneasy when I end up mixing fluent methods and modifying methods in one class.
Just an example (it's a little contrived, please bear with me):
Assuming a string utility class, trimming seems good for chaining:
Str & Str::Trim() { return TrimLeft().TrimRight(); }
Other methods would naturally return a new object:
Str Str::GetFirstToken() const
{
// result = first token;
return result;
}
And there'sa 3rd type, that - by itself - would logically mutate the object and return a new one:
Str Str::SplitFirstToken()
{
result = GetFirstToken();
// this = remainder
return result;
}
When I use the signature that is most obvious for each method individually, I end up with these three types, and I am afraid it's not very intuitive for consuming the class which is which, especially since the return type is mroe or less the same.
I have already decided against making Str
immutable - since methods like SplitToken
provide core functionality. My main issue is mixing fluent methods What would you do?
do not use fluent methods in that interface
move them to a sub-interface (see below)
"If one is fluent, all modifying methods should be fluent"?
use a seocific prefix for fluent methods?
don't worry?
???
sub interface idea:
void CStr::Trim() { TrimLeft(); TrimRight(); }
CStrFluent & Str::Fluent() { return CStrFluent(*this); }
....
str.Fluent().TrimLeft().TrimRight();
I am undecided on this, I don't really like the extra "fluent" - especially that it's a method call in C++
What do you think?
[edit] I am using "fluent" here in the basic meaning of chaining method calls on a single instance, not in the advanced sense of creating english sentences in code.