Making Your Code Tidier With Fluent Interfaces
I'm not saying it's the best way, or anything, but my preference when coding is to write the least number of lines possible.
Going back to the OutputWindow class I talked about last month, you create and display it like this:
OutputWindow output = new OutputWindow(); output.show();
But that's two lines of code, where the following single line would feel more natural, to me at least:
OutputWindow output = new OutputWindow().show();
Maybe it's just me?
Either way, if you don't know how to write a class that allows "chaining" of methods, read on.
This approach uses a Fluent Interface and it's very easy to achieve. Here's the basic code for the class, written in such a way so as to allow "chaining":
class OutputWindow{ public OutputWinow(){ //construct it } public OutputWindow show(){ //show it return this; } }
Notice how the return type of the show() method is an object of the same class and that the method now returns the "this" object, whereas before the return type was void and it returned nothing.
That's all there is to it!
Taking it even further you could end up writing code like below if you change the setTitle and println method to also return "this".
OutputWindow out = new OutputWindow().setTitle("Test").show().println("Line 1");To lots of you this is probably a no-brainer, but then maybe there are other long-term Notes developers like myself who are only now venturing in to the real world of programming and still discovering little tricks like this.
Tim Tripcony used to be a big fan of chaining as well. But it's bad practice when you start testing complex code because it hides the point of failure in execution. If we take your last example, and that line resulted in a NullPointerException, how would you know whether it was the constructor, .setTitle(), or .show() that failed to return the correct object?
Restricting individual lines to single operation may bulk your code up a bit, but it makes it MUCH easier for a maintenance developer to come behind and diagnose a runtime error.
Reply
I'd only ever use it for simple cases like those shown above where it feels natural to do so (construct then display a window) and where there's very little complexity enclosed.
Reply
Doh, he outed me. Which amuses me, because I was about to leave essentially the same comment. If you're able to properly catch and handle all errors within each method, chaining is fine, but in general it does make debugging far more difficult. So, yes, when there's not much complexity enclosed, I suppose it's "safe", but what happens when the process evolves and suddenly one of those methods must become more complex? Do you then rewrite everything that calls it to remove the chaining and add null checks? We've found it saves more time in the long run to structure our code that way to begin with than we were previously saving by chaining methods, but, as Stephan would say, YMMV.
Reply
I add a debugging flag, sometimes with various verbosity levels. When the flag is on each object writes interesting values to a debug log. Then I can review the log and see what went wrong where.
Reply
Oh, and if you write unit tests for every method of every object that check the correct operation of each method, they there's only likely to be bugs caused by interface mismatches.
Reply
Chaining is a useful technique, but yes there are pitfalls. If you have a predictable chain / codebase, then it's a nice way of shortening things. If you're dealing with something like the godforsaken Domino Java API though, you're best off following Tim's advice, and keeping things in "long hand", if only to handle the proliferation of lame NotesExceptions and, even worse, the NPEs.
Summary? Chaining is good if you're using a good API.
Reply
(… Oh and decent unit tests are a must!)
Reply
Show the rest of this thread
Err, ben, what's an NPE?
Reply
Show the rest of this thread
I prefer something like
MyOutputWindow = new MyOutputWindow('Test', 'Line1');
Better "level" of chaining, code even more clean and readable, and in the MyOutputWindow class you can write code as you want, also taking care of debugging needs!
Reply
Actually, at risk of sounding like a Luddite, not only does the debugging issue make sense, there is also readability.
We are all tempted to make use of 'clever' aspects of any particular language, or oop, but the issue comes when you have to take over someone else's code (or even your own, 6 months later!) - readability wins every time.
Just my view!
Reply