Google’s Go Isn’t Getting Us Anywhere, Part 1

There’s buzz in the air about Google’s new language Go.  Naturally, I was excited hearing about it.  After all, Google has produced so many interesting tools and frameworks to date there’s almost automatic interest in any new Google software release.  But this wasn’t just a product, this was a Google language release.  My programmer brain pricked up immediately.

Language releases always catch my attention.  Since 1995, I’ve constantly wondered what is going to be the Great Java Killing Language.  Java’s release was the Perfect Storm of Language Timing–the rise of the internet, the frustration with C++, the desire for dynamic web content, a language bundled with a large series of useful libraries (UI, database, remoting, security, threading)  previously never seen.  Lots of languages have been released since, but none with quite the reception of Java.  But with that perfect storm came some serious fallout.

Java vs. C++
Java vs. C++

At the same time Java rose to prominence as the defacto web and enterprise language of choice, Moore’s Law was hard at work and hardware companies were creating new kinds of processors–not just faster ones, but also motherboards that supported multiple processors.  And then multiple cores on those processors.  Concurrency became the new belle of the ball, with every language making sure they added support for it.  Which gave rise to the widespread use of concurrency features in languages.  In essence, Java brought attention to the Great Concurrency Problem that has haunted us almost two decades now.

Before I address the Great Concurrency Problem, we have to agree that most people confuse Concurrency with Parallelism.  Let’s start with the definitions from Sun’s Multithreaded Programming Guide:

  • Parallelism: A condition that arises when at least two threads are executing simultaneously.
  • Concurrency: A condition that exists when at least two threads are making progress. A more generalized form of parallelism that can include time-slicing as a form of virtual parallelism.

Parallelism has only come about with multi-processor/multi-core machines in the last decade or so.  Previously, we used Concurrency to simulate Parallelism.  We program our applications to run as concurrent threads.  And we’ve been doing that for years now on multithreaded processors.  But the Great Concurrency Problem is really a problem about the differences between Human Thinking and actual Machine Processing.  We tend to think about things linearly, going from Breakfast to Lunch to Dinner in a logical fashion.  In the background of our mind, we know things are going on.  You might even be semi-aware of those yourself.  And occasionally, we get those “Aha!” moments from that background processing of previous subjects.  We use this mental model and attempt create a similar configuration in our software.  But the shared-memory concurrency model used by Java and other languages creates implicit problems that our brains don’t really have.  Shared memory is a tricky beast.  You have objects and data inside Java that multiple threads can access in ways that aren’t intuitive or easily understood, especially when the objects you share get more and more complex.

There are really two main models for concurrent programmingshared memory and message-passing communication.  Both have their ups and downs.

Shared memory communication is the most common of the two and is present in most mainstream languages we use today.  Java, C#, C++ and C all used shared memory communication in their thread programming models.  Shared memory communication depends on the use of memory locations that two or more threads can access simultaneously.  The main danger of shared memory is that we share complex data–whole objects on the heap for example.  Each thread can operate on that data independently, and without regard to how other threads need to access it.  Access control is granted through monitors, mutexes and semaphores.  Making sure you have the right control is the tough part.  Too little and you corrupt your data.  Too much and you create deadlocks.

Let me give a concrete example to show just how nasty this can get for shared memory communication:  Let’s say you’re handling image processing via threads in a shared-memory model–like Photoshop does for image resizing.  And let’s say you’re trying to parallelize this processing such that more than one thread handles a given image.  (Yes, I understand we don’t do that today and there’s a good reason for that.  This is an analogy, just keep your shirt on a sec.)  An image is an incredibly complex object:  RGB values, size, scale, alpha, layers if you’re in Photoshop, color tables and/or color spaces depending on the format, compressed data, etc.  So what happens when Thread A is analyzing the pixel data for transformation and Thread B is trying to display that information on the screen?  If Thread A modifies something that Thread B was expecting to be invariant, interesting things happen*.  Thread A may accidentally corrupt the state of the image if Thread B doesn’t lock the entire object during read operations.  That’s because Threads A and B are sharing the entire object.  Oh sure, we can break the image down into smaller, simpler data abstractions but you’re doing that because of the shared memory problem.  Fundamentally, Java objects can be shared between threads.  That’s just a fact.

Keep in mind this is just a TWO thread example.  When you write concurrent systems, two threads is like a warm up before the Big Game–we’re barely getting started.  Real systems use dozens, if not hundreds of threads.  So if we’re already having trouble keeping things straight with two threads, what happens when we get to 20?  200?  The problem is that modeling any system using concurrent programming tools yields a subtle mess of timing bugs and problems that rarely appear until you have mountains of production data or traffic hammering your system.  Precisely when it’s too late to do anything about it.

Even Java’s own documentation from ages ago cautions just how hard this problem really is:

‘‘It is our basic belief that extreme caution is warranted when designing and building multi-threaded applications … use of threads can be very deceptivein almost all cases they make debugging, testing, and maintenance vastly more difficult and sometimes impossible. Neither the training, experience, or actual practices of most programmers, nor the tools we have to help us, are designed to cope with the non-determinism … this is particularly true in Java … we urge you to think twice about using threads in cases where they are not absolutely necessary …’

Hey, what's behind that Runnable there?  Uh oh...
Hey, what's behind that Runnable there? Uh oh...

Harsh words (at the bottom) from a language that really opened Pandora’s Box in terms of giving us the tools to make concurrency an everyday part of our applications.

Message-passing communication is perhaps the safer of the two models.  Originally derived from Hoare’s Communicating Sequential Processes (CSP), message-passing communication is used in languages like Erlang, Limbo and now, Go.  In message-passing communication, threads exchange messages with discreet amounts of local data via channels.  I like to think of message-passing communication to be kind of algorithmic atomicity–you are performing some action, say transforming an image and at a certain step, you need the data from the image’s color table.  So you wait to get a message from another thread when that data is available.  And then continue processing locally in your own algorithm.

Because threads are restricted in what they can share, the risk of corrupt data and deadlocks drops considerably.  But this comes with a higher processing cost than shared memory communication.  With shared memory, there was no re-writing of the data before thread access.  Just the opposite is true for message-passing.  Until recently, message-passing communication was considered far to expensive to use for real-time systems.  But our multi-core, multi-processor world of the 21st century has finally broken down that barrier.

The question is, does Go really solve that problem in a way that overthrows Java as King of the Enterprise?  Tune in tomorrow for Part Two, where we look at Go’s features, whether Go really addresses any of these problems, and if Java is doomed.

* “Interesting” is the default programmer adjective we tend to apply when what we really mean is “incredibly BAD”.

It’s Official: Java Has Jumped The Shark

My favorite enterprise language seems to be running out of good ideas to implement.

From this post detailing the upcoming language features of Java 7, here is the list of completed features to date:

  1. Language support for collections
  2. Automatic Resource Management
  3. Improved Type Inference for Generic Instance Creation (the “diamond” operator)
  4. Underscores in numeric literals
  5. Strings in switch
  6. Binary literals
  7. Simplified Varargs Method Invocation

Now, keep in mind, usually the most critical, important, or difficult features are implemented first. At least if you’re trying to get something out that is meaningful.  But seriously, this is what Sun thought was the most important? Continue reading “It’s Official: Java Has Jumped The Shark”

Habit 7: Principles Are More Important Than Results

Our last installment today is about the Great Ivory Tower of Standards and Architecture.  In case you missed the previous bunch:

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Principles Are More Important Than Results

ivory_tower
Beware the Ivory Tower

Ever work on a project where some group (or some person) in your company espouses standards above all?

“You absolutely must follow our standards to the letter.  We’ll be having daily code and design reviews, anything out of compliance will of course, be refactored to meet the corporate standards immediately”

Principles and best practices are great things to engender on a project.  A highly respected architect friend of mine said to me over and over, “It’s better to be consistent than right”.  Consistency gives predictability to people looking at code for the first time.  They learn what to expect and it reduces up-to-speed time for new developers.  It also creates mini “code templates” in your work patterns to speed things up as you develop.

You can take this too far.  Projects where standards are used like a whip are demoralizing and turn action into motion purely for the sake of consistency.  Remember:  Your goal is to ship a finished product that meets the customer’s requirements, on time and under budget.  Following standards is part of that but creating painfully complex standards and then demanding absolute adherence in this fashion is just torturing your developers.

Have standards, but keep them simple.  Standards exist to create consistency, not some absolute right-or-wrong litmus test for code.  Balance is important–shipping a product ad-hoc without any standards is a recipe for disaster during your first bug fix or maintenance release, but following each and every standard down to the comma is just wasting cycles.  Don’t err on the side of extremes either way.

In summary:

A good developer knows that there is more to development than programming.
A great developer knows that there is more to development than development.

Got a habit that I missed?  Sound out below!

Habit 6: Reuse Is For Wimps

Today’s Habit is brought to you by the letter “R” and the number 1.

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Reuse Is For Wimps

recycle
Not Just For Plastic, Glass and Cans

Feeling that urge to rewrite qsort?  Convinced you can write a better Hibernate than Hibernate?  Positive that there is no XML parser out there that will suffice for your project?  Um.  Put down that Erlang compiler a sec and listen.

I completely understand why these urges come up.  We love to solve problems.  And sometimes, writing a billing application isn’t nearly as fun as say, creating a custom persistence layer that converts XML to binary ZIP and inserts it into a BLOB in the database.  But you won’t get a promotion because you reinvented the GOTO in your custom Haskell extension.  You might get a promotion because you shipped a working product on time, under budget that delighted your customers.

The goal of every software project is to launch.  Anything that gets you to launch quicker is good.  Previously developed libraries, even beta-grade ones, can be a win for you and your team.  That’s not to say you should create a Frankenapp by bolting every Open Source project together within reach.  But making judicious use of the right technologies can substantially reduce your time to market.

The one (and I do mean ONE exception) is creating something that is part of your core competency.  If you’re Intuit, then accounting software is your core competency and you’d better write some cool 401(k) prediction algorithms to help people use Quicken more effectively.  But what about a web framework?  Intuit isn’t in the business of creating frameworks.  Should they write a brand new one?  Probably not.  Understand what you’re in the business of doing, and write THAT.  Find help for everything else, as much as you can.

Habit 5: Fix It Later

We examine the power of procrastination in today’s post, and why you should never underestimate the impact on your future.  If you missed the early habits, they’re linked here:

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Fix It Later

How many times have you said to yourself,

“Bah…I don’t have time to do that now.  I’ll fix it later…

bug_costs
Anything is More Believable When It's Graphed

Yeah, I thought so.  I do it too.  But a disciplined developer will stop right then and there, think about the future cost of that mistake and then correct it on the spot.  It’s the difference between knowledge and wisdom.

Comp Sci majors are taught from basic coursework (usually in their ONE software engineering capstone course, sadly) that the cost of fixing errors goes up non-linearly as you move forward in a project to later phases–fixing a bug in the requirements during say, design, is cheaper than fixing the same bug in production.  A practiced engineer will apply that knowledge to fix problems BEFORE they get into the next phase by proactively understanding the consequences now and altering the course of history.

The temptation (and sometimes the stick that is whacking you on the backside) is to say you don’t have time because of The Schedule.  The Schedule will always be there.  You’ll almost never work on an open-ended project with infinite time to “get things right.”  You will have to ship, eventually.  That comes with compromises.  We defer changes out of fear.  Fear of impacting others.  Fear of being wrong.  Fear of having more work to do.  What’s that you say?  “I’m the exception!  I can’t just go changing that class because it’s already in production and I don’t know what it will break.”   Thank you, that’s the point.  THAT bug made it to production because someone said, “I’ll fix it later.”  So fix it now.

Habit 4: Never Share Information

Lessons from Lord of the Rings, why you really did learn all you needed to know in Kindergarten and the value of opening your kimono.

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Keep Important Information Secret And Safe

All that knowledge you’ve worked hard to acquire over the years…it should be jealously guarded, like a treasure in a cave.  Never shared.  My PREH-SHUSSSSS!

Filthy Colleagues-es!  They wants the Precious!
Filthy Colleagues-es! They wants the Precious!

Who are you, Gollum?  You may remember it didn’t work out so well for him.

The best developers actively share and disseminate their practices, tricks, tips and past pitfalls with everyone and anyone who will listen.  They teach and mentor new developers, write good documentation (OK, they at least write it…), send emails to the team letting them know about new tools and techniques for making things better.  They do Brown Bag seminars talking about the latest project and how it was useful to them, the company, or their peers.  They see problems in training and make up for it by creating Wikis for new team members.

There is no point in holding on to useful information that could make others better developers.  That is, unless you’re trying to stay in the same job forever.  Ask yourself, who do you want to work with on your next job?  The person who helped you write that complex algorithm on their lunch break, or the guy who hissed at you when you walked into his cube:  “Mine!  Stay away, filthy Hobbitses”.

Yeah, I thought so.

Habit 3: Complexity Demonstrates Intelligence

Smart people naturally create…chaos?  Today’s habit is about the value of parsimony in your work.  Previous habits linked here:

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Demonstrate Your Intelligence With Complexity

escher-relativity1
Ow, my head hurts...

Project complexity creeps in from two paths.  First, there’s accidental complexity.  As developers we love solving ALL kinds of problems–that’s usually why we choose this field.  Often times we start solving the problem before thinking about it first.  The result is stream-of-consciousness code, where even YOU won’t understand it in six months.  With comments.  As Mr. T would say, “I pity the fool”.

How about the developer that actively accidentally obfuscates their code by using counter intuitive algorithms, poorly named variables, or seven levels of indirection.  This intentional complexity is even more insane.  I’m not sure if this comes from some Napoleon complex in software, lack of training/experience or just a naive repertoire of coding tools.  Either way, it sucks for everyone else down the line from your code.

Simple code is easy to read, easy to maintain, and a joy to work on.  Sometimes, simple code will naturally evolve from complex code during the course of code reviews or pair programming efforts.  The best programmers I’ve ever worked with have one thing in common:  making complex things simpler.  And despite what I read about this Python library experience, simplicity pays for itself down the road.  Being afraid that a simple solution makes you appear less smart is crazy.  Want to prove how smart you are?  Try teaching some training class to your peers instead.

There are some easy ways to help fight both kinds of complexity:

  • Google the problem before you attempt solve it.  See if a solution already exists.  Understand that solution first.
  • If you only understand one solution to a problem, ask someone else for a different perspective, especially if you struggled with that answer.
  • Refactor if you don’t like it the first time.
  • Actively seek to reuse existing libraries.

Endeavor to make things easier for yourself and others.  The sanity you save may be your own.

Habit 2: Confuse Motion With Action

We explore the difference between work and heat in today’s habit.

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Confuse Motion With Action

Lots of people misunderstand the difference between motion and action.  Or in physics terms, the difference between work (energy put into a system that increases the potential of an object) vs. heat (energy expended but with no future value, like friction).   Steve Blank recently made a memorable post on it:

sisyphus
Sisyphus Enjoyed His Daily Routine...right?

Steve: Jim, how are we doing with getting Ansys ported?
Jim: Great, I have a bunch of calls into them.
Steve: How are we doing on the Nastran port?
Jim: Wonderful, they said they’ll get back to me next month.
Steve: How about Dyna 3D?
Jim: It’s going great, we’re on their list

Putting in the effort to look busy is not the same as making real progress towards a goal. I’ve sat in countless meetings listening to this sort of status reporting (at all levels, not just for developers either) and I’m sure you have too.  Oh, wait…you’ve given a status report like that?  Yeah, me too.  Next time you’re tempted to do that, look at the problem differently:

  • What goal do I need to accomplish?
  • What is in my way of doing that?
  • How can I get rid of those obstacles?
<li><a href=”http://www.lessonsoffailure.com/software/seven-habits-highly-dysfunctional-enterprise-developers”>Blame Everyone But Yourself</a></li>
<li><a href=”http://www.lessonsoffailure.com/software/habit-2-confuse-motion-with-action”>Confuse Motion With Action</a></li>
<li><a href=”http://www.lessonsoffailure.com/software/habit-3-complexity-demonstrates-intelligence”>Use Complexity To Demonstrate Intelligence</a></li>
<li><a href=”http://www.lessonsoffailure.com/software/habit-4-never-share-information”>Keep Important Information Secret And Safe</a></li>
<li><a href=”http://www.lessonsoffailure.com/software/habit-5-fix-it-later”>Fix It Later</a></li>
<li><a href=”http://www.lessonsoffailure.com/software/habit-6-reuse-wimps”>Reuse Is Overrated</a></li>
<li><a href=”http://www.lessonsoffailure.com/software/habit-7-principles-important-results”>Principles Are More Important Than Results</a></li>

Seven Habits of Highly Dysfunctional Enterprise Developers

With apologies to Steven Covey and Jack Ganssle, who have their own lists on the topic, I bring you the

Seven Habits of Highly Dysfunctional Enterprise Developers:

  1. Blame Everyone But Yourself
  2. Confuse Motion With Action
  3. Use Complexity To Demonstrate Intelligence
  4. Keep Important Information Secret And Safe
  5. Fix It Later
  6. Reuse Is Overrated
  7. Principles Are More Important Than Results

Blame Everyone But Yourself

finger-pointing2
Who me?

There’s always plenty of people on enterprise software projects.  Everyone shares the responsibility…and the blame.  Developers often use this situation to deflect the blame.  I call this the Code Kingdom Problem.  That’s not MY code, it’s YOUR codeI didn’t write that module, S/HE did…And so on.  Maybe this statement rings a bell:

“Hey Bob, since you wrote that parsing module and the bug that came up seems to be a parsing error, why don’t you fix it?

Tempting though this may be, consider the collateral damage caused by this causal remark:

  • Bob may resent you pointing out his failures
  • Bob may not want to collaborate with you on future work
  • Bob may not recommend you on future jobs
  • Bob may spit in your coffee when you’re not looking

Rather than risk Bob’s heinous salivary wrath, why not proactively fix the problem (Cooperative Code Sharing), or help Bob find it and suggest a fix if Bob is struggling with it? (Pair programming).  Bottom line:  Their is no MY code vs. YOUR code.  It’s OUR code. If you’re on the project, you share it all–failure, success, or mediocrity.  You can’t have pride of ownership without ownership.

Simplicity is the goal

My first day of Physics class in high school, we were given English homework:  find the definition of the word Parsimony.  My teacher was trying to underscore a point about the study of physics–while it explained the most complex of phenomena, the underlying theories and equations usually boiled down to a certain level of simplicity.  And as a corollary, if you found yourself trying to add in all kinds of complexity to an explanation, chances are you were running down the wrong road.  Which is not to say physics wasn’t filled with contradictions, despite my teacher’s mighty attempt to make it all seem elegant and grand.  I struggled with Quantum Mechanics because it violated every rule of simplicity learned to date in science.  And String Theory too.  Even Occam’s Razor is still one of my favorite things to trot out when folks are getting too mired in their own story.

Yet, we do the same things as developers all the time.  Brian Kernigan of C language fame has a famous quote:

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”

In other words, if you are at the limit of your skills in WRITING the code, you are far beyond your reach in debugging and MAINTAINING the code for the time to follow.  Where does the complexity come from?  That’s easy–we’re constantly trying to optimize the code.  That nagging voice pops up in my head when I start appending Strings in Java–”Ooooh.  That’s TERRIBLE.  That could be performance bottleneck!  You’d better optimize that…” 

Take a deep breath and step away from the StringBuilder. Donald Knuth said it best:

“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.”

Premature optimization is the root of all evil.
When Donald Speaks, You'd Best Listen.

Yes, we mean that string code, or that database query, or whatever you’re working on.  I mean MOST of code you write.  We code for the unexpected and then accidentally mire ourselves deep in complexity all for the sake of optimization. 

It’s easy to forget the 80-20 rule (80% of the program execution time will be spent in 20% of the code).  There’s also a 90-10 variant of the rule (which makes the point even more harshly).  Let’s put this rule another way.  Your optimizations and complexity are completely wasted in 80% of your code

Let’s figure out the real cost of this: Suppose you spent an extra 8 hours per week working, debugging and perfecting that kind of code for 3 months on the project (in addition to your regular work).  You spent 96 extra hours on the project (a whopping two+ weeks!) and of those hours, almost all of them were a waste since they didn’t lend any real value to the end product.

Ouch.

The Rules of Simplicity are quite simple (c’mon, you knew it was coming):

  1. Make your code as simple as possible.
  2. If you think it needs to be optimized, run it through a profiler.  And then see Rule #1.

Simple code yields clear benefits over complexity to everyone:

  • Quicker maintenance
  • Easier extension
  • Fast bug fix times
  • Shorter up-to-speed times with new developers
  • Lower frustration levels with support engineers

Think any of those isn’t important?  Try spending time as a support engineer of your product sometime and maybe you’ll feel differently.  Or sit with a support engineer for a day and see how they have to work with, explain, and sometimes apologize for problems in the product.    Or just wait six months and try, just try to fix that extra clever code of yours.

I can hear the whines coming already:  “But what about an extra layer of indirection for database portability?”  Or maybe “the communication layer abstraction so you could talk to an ESB in the future, surely I have to plan for it”?  The answer is NO.  Unless you need it NOW, you ain’t gonna need it.

Complexity is our mortal enemy as developers.  It makes all of us dumber in the end.