I recently posted a tidbit on Twitter which I thought was benignly unassailable:
Of course, Twitter being Twitter, I was wrong – and that’s one of the reasons why I love (and hate) Twitter. When your head gets too inflated, Twitter can deflate it as fast as a pin pops a balloon.
In recounting his obsession with quality, I recall an interview where Steve Jobs was telling a reporter about painting a fence with his father when he was a young boy. There was a small section in a corner of the yard, behind a shed and fronted by bushes, that was difficult to lay a brush on. Steve asked his dad: “Do I really have to paint that section? Nobody will know that it’s not painted.” His father simply said: “Yes, but you will know.”
It is pretty much a de-facto standard in the C++ (and Java) world that enum type names start with a capital letter and that enumeration values are all capitalized, with underscores placed between multi-word names:
Now, assume you stumble across some sloppy work like this in code that must be formally shared between two different companies:
Irked by the obvious sloppiness, and remembering the Steve Jobs story, you submit the following change request to the formal configuration control board in charge of ensuring consistency, integrity, and quality of all the inter-company interfaces:
What would you do if your request was met with utter silence – no acknowledgement whatsoever? Pursue it further, or call it quits? Is silence on a small issue like this an indicator of a stinky cultural smell in the air, or is the ROI to effect the change simply not worth it? If the ROI to make the change is indeed negative, could that be an indicator of something awry with the change management process itself?
How hard, and how often, do you poke the beast until you choose to call it quits and move on? Seriously, you surely do poke the beast at least once in a while… err, don’t you?
I was at a meeting once where a peer boasted: “It’s hard to schedule and convene code reviews when you’re writing 2000 lines of code a day“. Before I could open my big fat mouth, a fellow colleague beat me to the punch: “Maybe you shouldn’t be writing 2000 lines of code per day“.
Unless they run a pure software company (e.g. Google, Microsoft, Facebook), executive management is most likely a fan of cranking out more and more lines of code per day. Because of this, and the fact that cranking out more lines of code than the next guy gives them a warm and fuzzy feeling, I suspect that many developers have a similar mindset as my boastful peer.
Unsurprisingly, the results of cranking out as much code per day as one can, can yield legacy code before it actually becomes legacy code:
- Huge classes and multi-page member functions with deeply nested “if” constructs inter-twined within multiple “for” loops.
- A seemingly random mix of public and private member objects.
- No comments.
- Inconsistent member and function naming.
- No unit tests.
- Loads of hard-coded magic numbers and strings.
- Tens of import statements.
Both I and you know this because because we’ve had to dive into freshly created cesspools with those “qualities” to add new functionality – even though “the code is only a tool” that isn’t a formal deliverable. In fact, we’ve most likely created some pre-legacy, legacy code cesspools ourselves.
I get my blogging ideas from day-to-day observations, personal experiences, reading books and articles, and watching videos. There are two ways in which I proceed from idea to published post:
As the diagram illustrates, when I begin elaborating an idea with a picture first, I usually finish faster than when I start with words. I’ve also found that the picture-first process is usually more enjoyable. It just feels more fluid, less forced.
When I start drawing a picture, the act of sketching simultaneously draws forth some words that match the drawing as it evolves into being. Those words then beget changes to the drawing; and then the emerging drawing begets more yet more words associated with the changing picture. It’s an Escher-eque recursive process that drives me forward until at some point I simply decide to stop and queue up the post to be published. Unsurprisingly, when I write/test product code, I use the same picture-first process (sorry, but TDD is not for me).
I can’t count the number of times I started writing paragraphs of text and then stalled to a complete standstill when trying to concoct an accompanying picture. When that happens, I usually save the picture-less post to my drafts folder with the hope that when I revisit it again in the future a matching image will auto-magically appear in my mind. I have tons of picture-less posts in my drafts vault, but I refuse to publish a post without an associated picture. Some of those unadorned posts have hanging been around for years.
In the 1000+ post history of this blog, you’d be hard pressed to find a post that doesn’t have at least one picture in it. It’s simply just the way I operate. Maybe you should try it.
Revolution is glamorous and jolting; evolution is mundane and plodding. Nevertheless, evolution is sticky and long-lived whereas revolution is slippery and fleeting.
As the figure below from Neal Ford’s OSCON “Functional Thinking” talk reveals, it took a glacial 16 years for Object-Oriented Programming (OOP) to firmly supplant Procedural Programming (PP) as the mainstream programming style of choice. There was no revolution.
Starting with, arguably, the first OOP language, Simula, the subsequent appearance of Smalltalk nudged the acceptance of OOP forward. The inclusion of object-oriented features in C++ further accelerated the adoption of OOP. Finally, the emergence of Java in the late 90’s firmly dislodged PP from the throne in an evolutionary change of regime.
I suspect that the main reason behind the dethroning of PP was the ability of OOP to more gracefully accommodate the increasing complexity of software systems through the partitioning and encapsulation of state.
Mr. Ford asserts, and I tend to agree with him, that functional programming is on track to inherit the throne and relegate OOP to the bench – right next to PP. The main force responsible for the ascent of FP is the proliferation of multicore processors. PP scatters state, OOP encapsulates state, and FP eschews state. Thus, the FP approach maps more naturally onto independently running cores – minimizing the need for performance-killing synchronization points where one or more cores wait for a peer core to finish accessing shared memory.
The mainstream-ization of FP can easily be seen by the inclusion of functional features into C++ (lambdas, tasks, futures) and the former bastion of pure OOP, Java (parallel streams). Rather than cede the throne to pure functional languages like the venerable Erlang, these older heavyweights are joining the community of the future. Bow to the king, long live the king.
I’m on my second pass through Bjarne Stroustrup’s “The Design And Evolution Of C++“. In the book, which was published exactly 20 years ago in 1994, Bjarne discloses all of the “whys” and “hows” that drove the growth of C++ up to the time of the book’s publication.
In the beginning, before there was C++ there was the even-more-nerdly-named “C With Classes” (CWC). Bjarne’s motivation for creating CWC was, as many inventions are, rooted in frustration:
This was exactly the kind of problem that I had become determined never again to attack without the proper tools. – Bjarne Stroustrup
The problem Bjarne refers to in the above quote was: “the task of exploring if/how the UNIX kernel could be distributed over a network of LAN-connected computers“. The preceding “never again” problem was for achieving his Ph.D. thesis at Cambridge University: “to study alternatives for the organization of system software for distributed systems“. Notice how the word “distributed” appears in both problems – and this was way back in the 70’s when bell bottoms were in fashion and prior to the rise of multi-core processor technology.
Even though he didn’t say why he chose the tool for his Cambridge Ph.D. thesis project, Bjarne used Nygaard and Dahl’s Simula programming language to code up a program for “simulating software running on a distributed system“. If you already know the history of C++, you won’t be surprised at Bjarne’s feelings for Simula or why he imported some of its key features into CWC:
It was a pleasure to write that simulator. The features of Simula were almost ideal for the purpose, and I was particularly impressed by the way the concepts of the language helped me think about the problems in my application. The class concept allowed me to map my application concepts into the language constructs in a direct way that made my code more readable than I had seen in any other language. The way Simula classes can act as co-routines made the inherent concurrency of my application easy to express.
Class hierarchies were used to express variants of application-level concepts. The use of class hierarchies was not heavy, though; the use of classes to express concurrency was much more important in the organization of my simulator.
During writing and initial debugging, I acquired a great respect for the expressiveness of Simula’s type system and its compiler’s ability to catch type errors.
In the above book quotes, we see the “whys” for:
- The appearance of the “Classes” word in “C With Classes“.
- CWC’s’s support for an object oriented programming style
- CWC’s static type system.
In contrast to Simula’s elegant expressiveness, its compile time and runtime performance were abysmal (garbage collection + runtime type checking + built-in concurrency = slooow). The runtime performance was so poor that Bjarne had to rewrite his simulator in low-level BPCL at the last second in order to get any meaningful results out of the program to stuff into his Ph.D. thesis.
Although there were several other pragmatic reasons for the appearance of the “C” in “C With Classes” (flexibility, ubiquity of available compilers, direct mapping of data to the hardware, simple linkage and runtime systems), performance ultimately drove the decision to use the well known and proven C language as ground zero for CWC – despite its funky syntactic quirks and unsafe features.
Curiously, support for concurrency was provided in CWC’s very first library in 1980. Concurrency appeared in the form of a tasking library and built-in support for two special functions recognized by the preprocessor: call() and return(). If defined by the programmer for a class, these functions would get implicitly invoked prior to entry and prior to exit of every class member function except for the constructor/destructor. They were required by the monitor class in the tasking library to acquire and release a lock for precluding data races. Interestingly, the call() and return() functions were later removed because “nobody used them but me“. We’d have to wait until 2011 for concurrency to return to C++ in the form of new libraries.
On exiting this post, I’d like to show you this e-mail exchange with Bjarne regarding the possibility of a book sequel in the near future:
Why not join an e-mail campaign to get Bjarne started on D&E II? So, go ahead. E-mail Bjarne like I did and plead with him to start penning the sequel. The 20 year trek from 1994 to 2014 has got to be filled with as many great “hows” and “whys” as D&E I.
I’m currently taking an in-house course on Java programming. The material is being presented in standard lecture fashion where the instructor sequentially walks through a series of static powerpoint slides and explains what the code snippets on each slide are doing.
In parallel to the in-house class, I’m also taking an online Java video course taught by Paul Deitel in the comfort of my home. The 36 hour course is available to me through my pricey (but outstanding) safaribooksonline subscription:
Other than in the lesson video intros (e.g. the one above), you never see Mr. Deitel on the screen. Like many educational videos you can watch for free on YouTube and Kahn Academy, you see code and a yellow circle highlighter that Paul dynamically steers around the screen as he explains what the code is doing.
Even though the standard “live instructor” teaching method enables the student to ask a physically-present instructor questions in real-time, I find the video “live code” method much more flexible and effective for the following reasons:
- You can see the instructor dynamically interacting with the IDE (in this case Eclipse).
- You can learn at your own speed by replaying lesson snippets that you didn’t fully grasp the first time. (I’m not so smart, so I use this feature all the time).
- The instructor can compile/run the code in front of your eyes and connect the code with its output by switching between the console and the code editor as needed.
- The instructor can intentionally insert bugs in the code and step through the debugger.
- The instructor can switch between the code and detailed online documentation as needed.
Regarding this particular course, I’m thrilled with Mr. Deitel’s work. He’s very thorough, shows great empathy for the student, and he dispassionately points out the differences between Java and C++ as they emerge throughout his code examples.
As I learn more details about Java, I’m confirming what everybody has been saying about the language since its inception: it is a smoother and easier to learn language than C++. However, I (still) don’t like:
- Centralized garbage collection (I prefer C++’s RAII idiom and smart pointers for localized garbage collection).
- The fact that all methods are virtual by default.
- The fact that every user-defined reference type inherits from class Object.
- The fact that a whole other layer of software, the JVM, sits between user code and the operating system.
- The fact that Java” steers” programmers toward designing deep, complicated inheritance hierarchies regardless of whether that style fits the application.
Regarding the last point, the mental steerage toward a pure OO programming style is subliminally catalyzed in the way that the JDK library packages are designed and the proliferation of large frameworks in the Java community. The obsession with deep hierarchies reminds me of Microsoft’s horrendously complicated old MFC framework for writing Windows GUI applications.
I’ve personally seen the effects of a fixed OO mindset in Java programmers who subsequently learn and write C++ production code in my domain: distributed real-time event systems that are naturally “flat“. The code ends up being overly complicated, hard to understand, and very few methods in the deep trees end up being called. The end result is that the “smoothness” of the language is nullified, developer time is wasted on unnecessary code, and the code is hard to maintain.