9

I am working on some C++ code that uses several libraries, including some C libraries, that all have different coding styles. It will be open sourced once it reaches a usable stage. Which would cause the least confusion for a short-term contributor who checks out the code to fix one bug or add one feature?

  • Have one consistent coding style throughout the entire application, even if it occasionally doesn't match the typical coding style of the libraries used.
  • When a library is heavily used in a certain module, conform to the typical coding style of that library (i.e. the coding style used in the library's own code and documentation) in that module.

My thought is that the latter will make it easier for experts in that particular library to make one-off contributions, and make it easier to incorporate tutorial/example code during development. However, it also makes the coding style inconsistent throughout the application. What are the pros and cons of each approach?

  • 4
    Would it be possible to avoid this problem by wrapping all the libraries in your own custom abstractions? Your own code and abstractions could then follow a single coding style. – MetaFight Dec 6 '13 at 17:26
  • A lot of what I'm doing is abstracting those libraries. The question is what coding style to use inside the abstraction. – Karl Bielefeldt Dec 6 '13 at 17:28
  • 6
    Ah. I'm no expert here, but it seems like you'd be best to use the convention of the library itself. Using a mismatched convention sounds like a maintenance nightmare. And as long as the library's style is contained to the class/module that abstracts it I assume it would be OK. Again, I'm no pro here, but this seems like a good balance that grants you easier maintenance in your abstractions and also allows you to have your own style in the rest of the application. – MetaFight Dec 6 '13 at 17:32
  • 1
    Sometimes abstractions like that can get a little ugly, do your best to keep it clean regardless of conventions used, but above all else just make sure that the API you present from the abstraction is of sufficient quality that you won't need to go back into the abstraction meddling and consumers will be able to work consistently with your abstractions easily to ensure their code doesn't become a mess like what may be in your abstractions. So in short, there's no good answer but as long as your abstractions present good APIs at least you're stopping the problem from spreading past them. – Jimmy Hoffa Dec 6 '13 at 17:44
  • 1
    What exactly do you mean by "coding style" - simple stuff like using_underscores/camelCase/PascalCase and brace location, or more complex things like class/method/function layout and imperative/functional style? – Izkata Dec 11 '13 at 3:33
10
+200

I think it kind of depends upon how big the overall project will end up being.

At one extreme, let's say you have a 1 Mloc project. For that large of a project, it's unlikely that a single individual would be an "expert" in all of the areas involved. So in this case, I would stick with existing code styles for each major component. New developers will pick an area, learn that, and it's unlikely they'll see many other components that may have different code styles.

If the project is a lot smaller, where it is likely to have individuals understand the entire code base, then I would pick a dominant code style and stick with that. In this case, I think consistency across the entire project makes more sense because new developers will be likely to work in all areas of the project.

Medium sized projects are perhaps the hardest to make this decision for. In this case, you have to weigh out the costs for each approach and decide upon the one you think will be least expensive long term. The challenge is that medium sized projects have usually grown just enough to where a complete style refactoring looks prohibitively expensive. You may want to have a second look at the code tree structure to see if things can be arranged to group particular code styles together.

Either way, the final decision should rest with the team you're on that's putting this package together.


Some of the outliers that might shift my reasoning from above:

  • If one or more of the modules has an atrocious style, then there's no sense in keeping that around, even on a larger project. Yes, style is subjective, but if you and your fellow project participants really, really don't like the way particular areas flow then nuke the old style and give it a better one.

  • If all of the styles are reasonably close to each other, it might be just as easy to declare "here's the new way" and use that for all new code and significant refactorings. This can make reviews a bit of a pain, but in my experience most folk are pretty capable at adapting to this approach. It also provides a telltale sign where the old code is.

  • Sometimes style is shifted based upon new functionality added to the language. C++ has picked up a number of features over the years. It may make sense to refactor as needed the older style to a newer style that takes advantage of those features.

  • Some libraries may have a particularly idiomatic approach or style. If so, I would stick with that style for that library even if it may conflict with the rest of the project. The intent here is to increase the odds that someone who works on frobnosticators on other projects will also work on your project.


Some of the comments mentioned imperative and object-oriented styles as being a consideration.

Modules that are "heavy" in a particular style probably ought to stay that way if the module is medium sized or larger. I have worked with the three major styles (imperative, objective, and functional), and I have refactored heavy imperative styles into an OO style. With a medium or larger amount of code, the refactoring can be (exceptionally) difficult. My experience was confounded because I didn't have any tooling support to assist in the refactoring.

I would imagine there is a high correlation between the heavily imperatively styled modules and those modules being idiomatic for particular development niches, which goes back to the last point I raised with outliers. So any module you would find for that functionality is going to look like that, and you want the experts of that domain to easily be able to work on your project as well. But if there are options and your team doesn't like the style of that module, then I would investigate the options.

Likewise, I have worked with a heavy-OO styled module where the OO principles were taken too far and used incorrectly. As an example, interfaces were being used as a substitute for multiple inheritance. And as you might expect, it was a crude implementation. I was able to make reasonable progress in refactoring that module, but I ultimately abandoned that approach as I found better packages to use instead.

  • That's a good way to put it. Similar projects are around 300 KLOC. – Karl Bielefeldt Dec 6 '13 at 18:29
3

Sounds like there are multiple layers to consider, at least:

  1. The existing libraries and any modifications to them.
  2. New unit test code for those libraries.
  3. The abstraction layer.
  4. The API presented by the abstraction layer.
  5. Example and test code using the abstraction layer.

I'm going to assume that it does not make sense to just refactor all code to a common style up front - if it did you would not have asked the question.

Taking in each in turn:

  1. For the existing code-base, then you'll likely want to stick to that style.
  2. New unit test code for existing code stands in a grey area, particularly depending on how much it is integrated with older code. But most likely, I'd try to make it in the 'preferred style'.
  3. The new code in the abstraction layer. By ensuring that this is really a separate code layer, there should be no difficulty in using a preferred style even it the code is doing a lot of interfacing with a legacy style or styles. Most code needs to interface with other styles, and I have never found this a problem.
  4. Obviously the API itself needs the most thought and meet maximum usability needs.
  5. Any example or test code should likewise be able to be be written in the preferred style. Depending on the completeness of the abstraction (i.e. whether is completely hides the lower layers), this may be easy or difficult. Of course, making sure that future client code is readable will be one of your key objectives.

Some things I have found personally is that with a large legacy code base:

  • Setting a preferred style and enforcing for code changes it does not magically result in the all old code migrating to the new style.

  • Most engineers tend to like to code in (more or less) the existing style in a given library. Requiring otherwise results in a lot of enforcement.

  • Requiring a preferred style in a legacy library tends to result in a lot of inconsistency in style in that library. So for standards which are purely around presentation, as opposed to code robustness it's hard too see a lot of benefit in requiring them.

As a final issue (slightly off topic but I think relevant), the truth is that some engineers struggle to stick to any style standard other than they one they know best. I strongly recommend engaging the team in style decisions and making sure there is buy in. Having done so you are in a much better position to actually apply a standard in mixed code.

0

I will agree with @MetaFight here in case you are developing a big size project with lot of third party modules.

Lets map your problem with a real word problem: "Suppose you have quiet lifestyle in your house. You like your place to be quiet, you never speak louder and never like any member of your family to do so. But you interact with lot of different people outside everyday to bring in something for your house. Not necessarily they will also speak with lower voice, in that case you mold yourself accordingly while dealing with such people. Thus interface or wrapper for these people is highly flexible just for the sake of your work to be done." Dumb example...lol

But my point is to create wrapper for such libraries as per their coding standard in such a way that you use these libraries through these wrappers maintaining your original coding style inside.

+1 for MetaFight.

  • Exactly the right solution imo. I use wrappers to tie up code that other people write for my projects as well. Define an interface up front, and then when they implement it, you can wrap it and black-box test it. – Kieveli Dec 13 '13 at 14:05
  • 1
    Why is this getting downvoted? I clearly think it's the best solution :) – MetaFight Dec 13 '13 at 17:02
0

It would clearly cause the least amount of confusion to use a single coding style throughout your project. The very point of using a coding style in the first place is to make code easier to read and modify.

As for the code style used internally in a library, I don't think it's relevant. If the library is too imperative, then writing an OO wrapper around is fine, but that doesn't require that you use the same code style as in the library's examples or internals.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.