"Software quality isn't really getting 90% code coverage, test cases for the domain, formal proofs or conforming to APIs and specs. Software quality is defined by the sustained rate of change a codebase can support through the promotion of clarity of thought and fluency of execution."
Monday, March 21, 2016
I love to create beautiful things with elegant code. I particularly like low-level optimisation for bare metal performance and systems programming, but I also enjoy high-level functional programming. I prefer a strong type system over excessive unit testing and I prefer common sense over agile development methodologies. I am mildly allergic to buzzwords. Data should be immutable.
-- Ruud van Asseldonk,
Sums up my feelings completely.
-- Ruud van Asseldonk,
Sums up my feelings completely.
Wednesday, March 09, 2016
As some of you might know from my last post, I've recently joined LinkedIn after 4 years at Google. LinkedIn is a Java company through and through. It's not a bad thing: it allows the company to consolidate its efforts and spend its resources wisely. The flip side is that everything assumes that Java will be around. I've spend the past month ramping up on the tooling, infrastructure and code. Coming from C++, I've been pleasantly surprised by a few things:
Java has a mature IDE ecosystem. IntelliJ is an awesome IDE, *much* better than Eclipse. Even though I'm coming from the Vim / Emacs world and I'm used to high productivity editors, there are things that IDEs can do for you much faster than you can do yourself (the big one is of-course extracting, moving and renaming methods). C++ needs to get its act together and expose ASTs for C++ code. There's a dire need to write tools that can automatically refactor parts of C++ code (string-replace should not cut it anymore in 2016). Even though I'll never give up Vim / Emacs, I do want to be able to do automated code refactoring with 100% guarantee of 1:1 transformations across the entire C++ project.
Dependency management and Build Systems
Java dependency management is more robust. There's a clear ecosystem of versioned build artifacts that you can drop into your application and a uniform way of referencing third party code (I'm talking about JAR files).
The C++ build landscape is a mess. Including third party code involves setting up an entire build environment corresponding to your dependency and then building it with your compiler and with your compile flags to maintain compatibility. Static and Dynamic libraries exist (.dll, .so, .a files) but the requirement to have header files compatible with the exact version of the library that you're linking against pretty much means that it's more reliable to build with all your dependencies present in your source tree (partial binary + source builds are impossible).
People in the C++ ecosystem try to avoid this mess by shipping header only libraries that cuts a few steps out of the way at the cost of increased compile time. Make + Autotools don't cut it anymore these days, Bazel and Buck aren't well adopted yet (but are the future), CMake's ghastly language is currently filling the gap as the "state of the art" but we really really need a standard build system for all of C++.
Uniform Instrumentation, Profiling, Debugging
Java's instrumentation profiling and debugging is fairly uniform. The JVM handles several aspects of profiling and debugging for you. This means that there's a uniform way to get information about the currently running threads, the memory structure and code hotspots *regardless of the running application*. There's also structure in the J2EE specification on how "web-applications" are expected to expose internal metrics to the outside world. There's also an active community around Java profilers and debuggers since these tools end up being widely used in a uniform manner across enterprises.
If anyone's done C++ profiling extensively, you'd know how hard it is to get a C++ application to disgorge metrics about its internal state (call-counts, hotspots, memory allocations etc.) and the things that get in the way. The Google Profiling Tools are amazing for C++ code and provide a lot of what you'd need but they're not used uniformly across the community.
The killer feature that Java has here is that you can simply pass in a command line argument to any modern JVM and it can load up specific profiling code (either inbuilt or provided as a native library) that instruments *all* the running code and exports debugging information from a "debug-port" that you can simply attach a debugger or profiler to. You can then proceed to put your application under load and see changes to its metrics (gc, threads, hotspots, allocations) in real time (this takes a ton of time to do correctly for each C++ project and works magically in Java). Call me impressed.
C++ today has its blind spots just as it has its strengths. We're now reaching the point where the actual language structure isn't the most important thing, it's the ecosystem and the developer productivity tools that are starting to matter. The C++ ecosystem just needs to get its act together and it doesn't look like we're going far enough with new proposals. I'd like to see this level of maturity in the C++ tooling system and I hope I see it sooner rather than later.
If you've read so far, I'd like to leave you with a small nugget: try out Go. It's got horrible syntax at first glance but the underlying principles are excellent. It's still an immature language but it's worth taking a look. Let me know what you think about it in the comments.