Joe Eames

Arbitrary Randomness


News


The great lesson of the Titanic was hubris, right?

Perhaps. I don't know. What I do know is that there is another valuable lesson from the Titanic that is very applicable to software engineering: A failed implementation does not invalidate the concept.

Titanic was designed by experienced engineers, using some of the most advanced technologies and extensive safety features of the time.  It was built to be luxurious and safe.  The cost of a first class ticket is equivalent to $100,000 accounting for inflation.  It was an amazing ship.  But for all that it still sank.  Why?

If I told you it was because sailing is an impossible venture, you'd laugh.  The titanic didn't sink because the idea of sailing is a flawed concept.  The reason it sank is because a healthy dose of bad luck and human error.

Now compare that to software development methodologies.  Let's pick something with a little controversy behind it.  Pair Programming.  If you try pair programming, and it goes poorly.  Let's say what you work on fails, or the code is obviously less effective, or you feel that you were wasting your time, or perhaps it ended up in a fistfight.  Does that mean that pair programming is a flawed concept?

No.  Like all things in life, we get better as we practice.  Things take time to learn.  Not every two developers in the world can work happily together for 8 hours.  Not every programmer bathes regularly.

Whether it's pair programming, TDD, agile, WIP, Code Reviews, or anything else, you can't take anecdotal evidence as proof that something doesn't work.

A failed implementation does not mean the practice is bad. 

 



I'm going to say this a few times.  Look for it.  Local Optimizations do NOT equal increased productivity.

Everyone wants their development to succeed. 

The policies of a team are an important element to successful development.  As teams gel together, decide on things like pairing frequency, WIP limits, check in policies, testing practices, Done Definitions, etc, they have the opportunity to change behaviors that otherwise would detract from that success.

One of the big advantages of these policies is the ability to do something that can seem counterintuitive from a myopic viewpoint, but will actually result in increased performance in the long run.  WIP is a great example of this.  As a developer, if I'm done with a story, and because of a WIP limit, I can't hand that story over to the QA engineer, I have to either sit on my hands, or help clear out their queue.

Now maybe I'm not good at whatever task I'll have to do to contribute.  So it seems inefficient.  But if I just keep piling on work to the next person in the line, the only thing I will be doing is causing a log jam.  Software chock full of untested and unapproved features isn't releasable.  If I help out, I'm probably less efficient.  And I'm probably not going to do as good of a job.  But local optimizations do not equal increased productivity.  Just because I'm going faster doesn't mean the team is, and can often mean the team is slowing down.

Automated testing is another great example.  It takes time to run those tests before I check in.  I can get more work done if I don't bother.  But local optimizations do not equal increased productivity.

Sure that last example should seem silly.  But the moral of the story is no less true. 

So next time you're balking against a policy that seems to hold you back personally, try to truly consider if ignoring it will make your team more successful.

And while you're at it, say this to yourself, "Local optimizations do not equal increased productivity."



I previously blogged about technical wisdom here.  Here's the my definition of that:

Technical wisdom: Knowing why a particular solution is a bad idea even if you are technically capable of implementing the solution.

So today I want to discuss one of the best ways to get technical wisdom.

I read a great article about the benefits of maintaining bad code here davybrion.com/blog/2011/09/maintaining-bad-code-can-be-a-great-experience/ and I was in complete agreement with his thoughts.  And that led me into a discussion where eventually David Adsit commented on the value of job hopping (codeobsession.blogspot.com/).

After some thought, I felt as though I was struck by en epiphany.  Job hopping truly is one of the best ways to gain technical wisdom.  You get to work with more people with more ideas, you get the chance to work on greenfield and brownfield projects, you get to maintain other people's crappy code, so that you know not to inflict that on the next guy, you get to see more industries, see multiple team practices, and see what makes teams work well, and see more of what makes employees happy, and more of what makes them unhappy.  You get to hear new complaints about the mistakes of the past at your company.

You get to be excited more often for new opportunities, practice your interpersonal skills more (although that may make some people shudder) as you convince new people that you are not only good to work with, but also know what you're doing, and you get to get out of that rut you're in and do something new.  

And best of all you can reset you.  Were you a little too negative in your last job?  Too timid? Too complacent?  Too uncommitted?  Much easier to change that with a new environment.

So.  Should you switch jobs every 6 months?  No.  You should definitely not do that.  But if you've been at your current company in your current role for 5 years, and you've been doing the same thing with mostly the same people on the same product building/maintaining the same code base, then it's probably time to make a move. 

 

 

 



What is technical wisdom?


Recently I implemented a rather complex page allowing the user to input pairs of colors and quantities, with some relatively "odd" validation rules.

I knew that I probably wanted to implement the page entirely with javascript and probably jquery templates, but for a demo I just needed a quick prototype of the page, so to get that done I threw together a quick and dirty webforms page using the telerik radgrid to display the data, but not save & validate.  Took me maybe 2 hours including some basic styling.

Then I added a few more display features.  That took another hour or two.

A little later the product owner said that the prototype was correct and we needed to implement the actual saving of the data.  At that point I figured that redoing the whole page in javascript was going to take me 10ish hours, and since we were still in prototype mode I thought I'd just throw together the ability to save using the existing page I had already built.  I figured I'd have the basic saving to db done in an hour and then the page could sit until the project was approved.

After a couple hours of struggling to get telerik to show all the rows of a datagrid in edit mode, I had that conquered, but saving the changes wasn't happening because the shape of my tables didn't match the shape that the radgrid wanted.  But I thought I could make a small change and get that to work

Two hours later that hadn't happened, so I came up with a new idea.

Two hours later THAT idea hadn't produced results either.   I was banging and banging away at this heavy server control and throwing logic around into all kinds of differnet events in the code behind trying to figure out the magic combination that would make it work correctly.

Suddenly I realized that I was 10 hours into the page, and it wasn't working, and I had no idea how much more work would be required to get the page to go.  So I finally did the right thing and scrapped it, taught myself knockout.js and had a slick clientside implementation done in < 12 more hours of work, that not only did all the stuff I was trying to get in the original page, but tons more client-side validation and the ability to easily add a ton more features that were on the list for eventual implementation.

Server roundtrips were 200 bytes for the request, 350 bytes response.  The postbacks from the telerik component were 80-100k both ways.  Much superior solution by far.

But here's what got me.  At every point along the original path, going just one more step farther seemed completely reasonable, and indeed the most responsible step, since doing what I knew was eventually the "right" thing would take a very large chunk of work.  Yet every step took me deeper and deeper into a mire of maintenance and problems.

I now realize that this was truly a microcosm of technical debt.  At my job we are running the new app we're building (v2.0 of the main internal application) out of the exact same database as the v1.0 application.  Same structure, same data.  v1.0 was architected about 8 years ago and was a direct translation from an old foxpro db that was the "previous" v1.0 application. 

Now unless you have a severe head injury you understand that this structure can be a bit of a problem.  Want to change how some data is stored?  Well, if you can't make that change by tacking a view or two on top of the old tables, then you have to duplicate the data into a new set of tables.  Application all of a sudden throwing exceptions?  Come to find out one of the other groups supporting the legacy application has inserted some data that you weren't expecting and have broken your application.  Now you may say "well, whoever made the decision to run out of the same database must have been criminally insane when they made that decision" well guess what?  That decision was the most logical and "responsible" decision at the time it seemed.  The product needed to be launched by a certain date (which was missed, btw) and the dev team realized that there was no way they could rewrite the import application and write a conversion component in the time allotted.  So retrofitting to run off the current db was the only "responsible" solution.

But we're not talking about 10 hours of work to fix the problem and move to a separate db.  We're talking hundreds of thousands of dollars of development.  Meanwhile development is hampered by our inability to refactor the database, the crazy dependencies on existing data, and the fires that crop up as the foundation of our application are shaken by changes made by other groups.

These gradual dead ends we take ourselves down by doing what's responsible, what's expeditious, instead of what we know is right for our applications are the hell we make for ourselves.



We interviewed a new hire today.

One of our senior engineers conducted a technical interview first, then a different engineer paired with the candidate for about 40 minutes.

The result was quite suprising.

The technical interview didn't go well.  The interviewer basically said that the guy was a definite no.  He got defensive when he didn't know the answer, he rambled, and he got too many questions wrong.

Yet the pairing interview went well.  Although the engineer didn't say he was a "definite yes" he did say that he was impressed with the guy's ability to solve problems quickly, identify viable solutions and implement them.

Why the disparity?  Which interview should bear more weight?

I've interviewed quite a bit and never gone to a pairing interview myself, but have read about them which is why as tech lead I implemented pairing interviews at my current place of employment.

Has anyone else seen pairing interviews and how well did they work?



 

 

 

 

I was recently visiting a friend of mine at his office, and while I was there he introduced me to his coworkers.  When my friend told the office's resident PHP programmer that I was a .NET programmer, he responded with "I'm sorry" and a half-hearted chuckle.  I merely smiled and flipped the  bozo bit  as my friend uncomfortably changed the subject.

After I left his office and was driving home I was considering his statement and the naturally resulting discussion of a development platform lineup and the pros and cons of the different frameworks.  Every time I have been asked “Why .NET?” by either a peer or a potential customer, I have always tried to return a measured response, indicating that most arguments come down to differences in flavor.  Yet I have always had difficulty relaying that position, and conveying the concept that the programmer is far more important than the platform.

As I was thinking over this recent encounter, an analogy came to me that I think I’ll file away for the next time this discussion comes up.  If you’ll give me a few spare CPU cycles, I’ll do my best to articulate it here.

We're not engineers, we are hunting guides.

As a hunting guide, when a hunter comes to me and asks to engage my services, I let him know in which geographical areas I have experience as a guide.  But if I were to tell him that I’m an experienced Yukon guide, and he responds with “Why not Siberia?  I hear there’s tons of bears there, and I want to hunt bear” how would I respond?  Well, I would tell him that the Yukon has plenty of bears, and as an experienced guide I can nearly guarantee him a bear if he comes with me to the Yukon.  Every other person I have taken hunting for bear has gotten one.  I know the places the bears go, the places they like to feed, etc.  But I know those places in the Yukon, not in Siberia.  If he’s sold on hunting in Siberia, then he should find a Siberian guide. 

But it would be a HUGE mistake for him if he were to go find a very poor or inexperienced Siberian guide and expect to have better luck than coming with me to the Yukon.  Likewise if he were to hire a poor or inexperienced Yukon guide and fail to kill a bear, the fault is not in the place he went hunting, it’s with the guide.

And if he were to want to choose Siberia as the place to hunt because the licenses for bear hunting are cheaper, well, compared to all the other risks & costs of going on a guided hunt, choosing your area based on the license fees is just plain silly.

Now in reality there may actually be more bears in Siberia, but there are still plenty of bears in the Yukon.   Deciding where to hunt based on that and not based on the guide you are going to use is a mistake for anyone.  A good guide will get you your prize, and a bad one likely will not. 

So the next time someone asks me “Why .NET?” I’m going to respond, “There’s plenty of bears in .NET”