5 ms·
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.
- RoboSeldon 11y agoThere is no pre-made recipe. You define the scope of the project, you split it in a few "modules" with a well defined interface (functions headers in this context) and data structures and you start coding. You should do some searches to check how big C projects like the Linux kernel (or any of the BSDs kernels) is managed.
- greenyoda 11y ago"With OOP it's all about classes, abstractions, interfaces etc. and design patterns." 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 http://www.amazon.com/dp/0201498413
- ectoplasm 11y agoYou don't need function pointers without inheritance, just take an instance pointer as the first parameter to each class member function.
- tptacek 11y agoIt's exactly the same way in large C projects (minus the "design patterns" bit). The project is divided into libraries and programs that are clients of those libraries, each team member gets a couple of them. 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).
- DaveVoyles 11y agoJavaScript teams face a similar issue, due to its dynamic nature. I find that strict coding standards (ex: making sure code aligns) goes a long way.
- JoshTriplett 11y agoThe organization of your code should not necessarily reflect the organization of your team. Well-organized code does help your team scale, but beyond that, you shouldn't have a three-pass compiler just because three teams wrote the code, and you shouldn't have object-oriented responsibility align with team responsibility; that can get adversarial very quickly. 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.
- segmondy 11y agoFigure our your data structures as a team first. Decide what operations you will perform on those structures and the results. Use header files as your contract/interface, and divide up the work. Then your team works can work on the implementations/code.
- kozukumi 11y agoYou can OOP in C so just treat it the same as you do other languages. Have a read of http://www.cs.rit.edu/~ats/books/ooc.pdf http://www.cs.rit.edu/~ats/books/ooc.pdf
- pjc50 11y agoThe Linux kernel is probably the largest and best known example. The process actually resembles (or used to) Brooks's pilot-copilot system quite a lot, with Linus Torvalds and Alan Cox making the decisions on what actually got included. The vast army of contributors submits patches, but they would generally be localised to a particular driver or subsystem. Bigger changes (such as rewriting the IO system, or the original addition of the hotplug system) require advance coordinated planning. 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.
- dorfuss 11y agoThank you, precious remarks. 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?
- pjc50 11y agoC projects are generally subject to more code review as the compiler is no help at all with allocation issues and someone has to check ownership semantics manually whenever a function has a pointer return type. 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 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.
- felixangell 11y agoYou can do OOP with C, I've used this for a lot of my projects and it usually works out really well, the code is readable and it's quite easy to scale.
- taf2 11y agoC has the same abstractions and the same OOP capabilities. You just have to type more to get there. Take a look at gtk+ and its supporting libraries for examples. The gist of the idea is a struct is the same as a class but public by default. Your this pointer, constructors and destructors must be called explicitly and error handing as well is explicit. In terms of how you can manage this among a larger team, would be to expose strict interfaces through methods that expect a struct pointer if it's an object. Next you can separate the concerns of the application in the same way you would in any OOP language. IMO this is probably a bad idea as the amount of typing necessary for a marginal performance win is probably not worth the effort. I like to think of it as a whole lot of dirt you will need to move with you fingers. Languages like golang and rust are perhaps better options to explore first?