Ask HN: How do you organize teamwork in C?
With OOP it's all about classes, abstractions, interfaces etc. and design patterns. But outside the object oriented programming, how actually is the teamwork organized? Could you please suggest any online articles to read?
I've tried googling it but I failed to find anything.
19 comments
[ 3.0 ms ] story [ 54.4 ms ] threadYou should do some searches to check how big C projects like the Linux kernel (or any of the BSDs kernels) is managed.
The ability to create abstractions is pretty much a part of any programming language, including assembler. They're a property of the structure of the code, not of specific language features. For example, in the Linux kernel, which is written in C, there's an abstraction called a file descriptor that represents a stream of bytes that your program can read/write, whether it comes from a file on a disk, a serial port, a pipe, etc.
Interfaces also exist in all languages: they're just a well-defined set of calls that one piece of code uses to communicate with another piece of code. For example, the C runtime library (or any library) has an interface (API), and callers of the library don't need to know about the internal structure of the library to be able to call its services. (There's a pretty good book called "C Interfaces and Implementations"[1] that talks about how to write reusable code in C.)
Classes are also possible to implement in C. A class is pretty much a data structure with a bunch of functions (the methods) that manipulate its data. In C, this can be represented by a structure and bunch of function pointers. The "constructor" function calls malloc() to create an instance of the class, sets its member variables from its parameters and returns a pointer to it. (Implementing inheritance is a bit tricky.)
To be able effectively split development tasks across a team, the same rules apply as in any other language: implement functionality behind well-defined APIs so that one part of the code can be used by another without having to know the details of how it works.
[1] http://www.amazon.com/dp/0201498413
If you understand how a large Java program is organized, you understand how it works on C projects. Just remove some of the fluffy Gang-of-Four stuff, and add back in a tiny veneer of DIY interface/object abstraction.
(The first 8 years of my career involved shipping C and C++ on 3 different large projects).
Have a good continuous integration (CI) system. Enforce that commits must not break the build. Have good commit messages. Have a culture of code review; no line of code should go in without someone other than the author reading it. Make sure that the culture of your company or team encourages people to review code carefully; someone who finds lots of issues (real issues) should be rewarded for a keen eye, not penalized for slowing down development.
Beyond that, if your codebase is sufficiently large than no one person could ever have all of the design in their head at once, then encourage people to become experts in diverse areas: "oh, for that subsystem you should ask Adela, she knows it inside-out". Everyone should have some areas they're an expert in, and more importantly, every area should have at least a couple of experts.
In C anyone sensible ends up with a pseudo-module system such that only a particular set of C files are allowed to contain functions that modify a particular set of data structures. Like OO encapsulation that you have to check yourself.
Should I assume that C projects are generally more hierarchical in nature, with one leader who orchestrates the entire production and where it would be rather difficult for team members to "freely" commit a module or a function here and there like you would with adding some sub-class in OO, because then it could ruin some other parts of the code?
Could this be also understood as a reason why Linus doesn't like C++, because it promotes higher flexibility and less carefully designed architecture, that in turn leads to security/performance issues?
Thinking about this, almost my entire career has been spent writing "C with classes": projects where the preferred subset of C++ is a very narrow one. The first one didn't even use the STL (it wasn't reliably portable enough at the time), instead defining a few container and zero-copy string classes of its own. It did however have overnight CI builds on dozens of different platforms including more than one non-GCC vendor compiler. We had an Itanium. We were living in the future.
The exceptions to this were C projects of size 1-2 people. Oh, and a glimpse inside a big multinational whose C products were the products of successive mergers lined up along side one another in the source control system. The sort of environment where it might take weeks to get anything committed without breaking some obscure corner of the test suite.
http://harmful.cat-v.org/software/c++/linus (2007) presumably?
"inefficient abstracted programming models where two years down the road you notice that some abstraction wasn't very efficient, but now all your code depends on all the nice object models around it, and you cannot fix it without rewriting your app. "
That sounds like he believes it's less flexible.
Blew my mind:
"...this new language had to divorce itself from Unix, by hiding all the system calls that bound the two together so nicely. This would enable guys who only knew about DOS to earn a decent living too.
"I believe most people have figured out for themselves that C++ is a waste of time but, I must say, it’s taken them a lot longer than I thought it would.
"It was only supposed to be a joke, I never thought people would take the book seriously. Anyone with half a brain can see that object-oriented programming is counter-intuitive, illogical and inefficient."