Agreed, and like I acknowledged in my article, when the class definition does not have too many frills, it looks great!
An aspect I did not touch on in the article though, is that I also think the development tools have improved a lot since the time the style was introduced. Code editors have gotten a lot better at highlighting. IDEs with code completion can go a long way in helping you find methods you need without having to open the header. Even the code formatting in the article illustrates how color and font choice help with reading the function declaration. Furthermore, we have the Haiku Book which quite literally puts all the methods a table (see BApplication as an example).
If I were to describe the style into plain English, I’d say we were going for the rules that for class member function declarations we (1) always want to break after the return type and (2) indent all lines by one extra tab against the baseline, except for the first line of the declaration. Note that my rule 2 would not indent the constructor and a non-virtual destructor.
For pragmatic reasons, I am looking at the options that are currently in clang-format
to see what we can do to come closer to the proposed style. As per the economic argument, I’d rather use something that already exists rather than modifying the clang-format
where possible.
For rule 1 (always want to break after the return type), there is the aptly named AlwaysBreakAfterReturnType option. It is currently set to TopLevelDefinitions
to get the desired style for function definitions according to our style guides. I think we would then go for the configuration All
in order to accomplish this, though the side effect is that this would also apply for function declarations outside of classes and structs.
For rule 2 (extra indention of subsequent lines), I think the one that we should use is IndentWrappedFunctionNames, which is currently set to false
.
Calling haiku-format -style="{BasedOnStyle: Haiku, SpaceAfterCStyleCast: false, IndentWrappedFunctionNames: true, AlwaysBreakAfterReturnType: All}"
then results in:
class BHandler : public BArchivable
{
public:
// The constructor doesn't have a return type and so it looks a bit strange. Is this a
// problem?
BHandler(const char* name = NULL);
virtual ~BHandler();
// BHandler guts.
virtual void
MessageReceived(BMessage* message);
BLooper*
Looper() const;
const char*
Name() const;
// Fictional very long member function declaration
// The parameters on next lines get indented one step further
status_t
Launch(const entry_ref* ref, const BMessage* initialMessage = NULL,
team_id* _appTeam = NULL) const volatile noexcept;
// NOTE: compared to the example in the article, I have separates the private methods
// from the private members. I think this is not part of the changes being discussed here,
// in both the current and new style, these should be kept separated
private:
friend inline int32
_get_object_token_(const BHandler*);
private:
// Do we want newlines also in the fields between the type and the name? or is it not
// needed?
typedef BArchivable _inherited;
friend class BLooper;
int32 fToken;
char* fName;
};
// Unintended side-effect: also definitions outside class declarations are affeced by
// IndentWrappedFunctionNames
void
Foo::FooFunction()
{
}
So clang-format
can somewhat accommodate these style changes, though it does not support making an exception for a break after a return type for non-member function declarations (which I am not sure is that bad), and it indents the function names also outside of class definitions (which I think is a departure of our current style).