I've been recently assigned for a new high-performance C++ project (finance) together with 3 other guys who, like, me, refer to themselves as "primarily C/C++ programmers", meaning, all of us have also done Java & other stuff, we all have comparable experience (8 to 10 years) and have successfully collaborated for the making of other projects (not C/C++).
I soon found out we have such different mindsets when it comes to our "mother programming tongue" that it risks not only the good delivery of the project but also the general well-being of the team/office. Specifically:
They come from an electrical engineering/automation/polytechnic type of background, so their reasoning is intimately related to how hardware works, how bytes move around, processor workings, instruction caching, generally everything at the lower layers. They did embedded programming, ARM programming (I barely know what those are). I soon found out their practical experience is with mostly C, not C++. They think procedurally, not OOP.
I, on the other hand, have trained myself to think in a more abstract way, to apply principles such as encapsulation, low coupling/high cohesion for creating reusable, modular software. My speciality is the C++ programming language, with an accent on language constructs that help you get both fast and reusable, generic code. I think design patterns, idioms, concepts. Throughout 9 years of developing software I consistently witnessed how poor maintainability of software systems is by far the #1 burden of teams. I generously document my code, write careful interfaces. I embrace template meta-programming as a way to obtain fast and reusable products. I embrace the new C++11 standard features.
Where I see reusability and loose coupling, they see "complication". They want to "see it all there". They want to see char*
, not some buffer class in interface methods. At one point one even said "I don't care how simple your interfaces are if your implementation looks complicated". The trouble is, we really are trying to transition from a monolithic style of systems to a reusable one - we are writing a library. Yet they don't wish to see their C-style structs being polluted with templated methods, typedefs and c-tors, even if neither makes their structs non-POD. They also don't wish to see static_assert(std::is_pod<...>). They love memcpy and pointers and generally stay away from references. They tend to think typedefs are somehow evil.
I really tried to make them see an abstraction for what it is. It is code together with data it operates on. By necessity, a library needs to define some interfaces for the user to be able to plug it into a larger product. They tend to see these interfaces as ways in which my code requires their code behave/look as I wish and doesn't allow them to do things their way, but without actually telling me a specific functionality they can't obtain.
Make no mistake, I'm no ignorant when it comes to performance. I know about cache lines, branch prediction, the overhead of method virtualization, heap allocation, hash lookups. I'm good with complexity of algorithms (though that doesn't matter so much here), data structures, inlining and some other compiler optimizations such as RVO. I believe with a modern compiler a reusable, layered OOP C++ product can get within 10% of the performance of a C-only monolithic product, when carefully written and optimized.
I honestly believed we would complement each other in our thinking.
What are your thoughts? Please don't be too harsh, we need to make this work.