Tuesday, July 10, 2012

Verdict

For the last few years, I've been vaguely and increasingly dissatisfied with my field of software development; however, it's been very difficult to put my finger on WHY. So far, that's been the whole point of this blog - gathering my thoughts to try to figure out what about the industry (or about myself) has changed, to cause this dissatisfaction. Here's my conclusions:

"Successful software products can be built from mediocre (or even bad) code."
If you've been in the industry for more than a few years, you've almost certainly seen it: source code so bad that entire websites have been created to showcase its horror - and yet the product created from that source code is sold by someone, bought by someone, loved (or at least tolerated) by some users, and is generating a profit for some company. I wish I was wrong about this, but it seems undeniably true.

"A commitment to high-quality code has tangible upfront costs, and less-tangible long-term benefits."
It requires a commitment to hiring (and retaining) skilled personnel, and resisting the urge to just throw something together any-which-way, in order to get it done faster. The benefits come later (and more theoretically), in the form of fewer bugs, faster product enhancements, faster ramp-up for new employees, etc.

"Companies want mediocre code."
That's not precisely true: companies want the benefits of high-quality code - but they aren't willing to pay the costs. They want to be able to hire mediocre people, and offer them mediocre compensation. They want the option to deliver certain functionality by a certain deadline, by throwing code quality out the window, and / or by shoving more and more inexperienced man-hours at the project.

I've come to believe that is the dirty little secret of our industry: the "strive for mediocrity" business model actually works. This is not inherently a bad thing, nor is it a good thing - it is simply business 101: maximize profit. If a sell-able, "good enough" quality product can be produced via mediocre code, why pay the costs of a commitment to high-quality code? There are plenty of developers comfortable working within this paradigm:
  • Inexperienced developers not yet able to produce "craftsman-quality" code.
  • Ambivalent developers who aren't interested in learning to produce "craftsman-quality" code.
  • Pragmatic developers who can produce "craftsman-quality" code, but are comfortable with the fact that much of the time they won't be allowed to. These people will be the true MVPs of a company's development team - able to focus on the end-product (regardless of underlying code quality), and with the skills to make it happen.
However, I'm not any of those developers. I'm no longer inexperienced; I know how good code can be (beautiful even, in its own way). I've never been ambivalent; I've always wanted to learn and understand the development platform, and create elegant designs within it. Finally, I haven't been able to become the "pragmatic developer", focused on the end-product and comfortable using whatever code necessary (good, mediocre, or bad) to reach it.

Thus, it's time for me to leave the industry - a love of and dedication to well-crafted code doesn't really fit in with corporate software development. The industry isn't what I'd like it to be; but as I said above, that's not inherently good or bad, it's just business.

I'm glad I went through the time and effort for this blog. Leaving behind 20 years of work and experience is a difficult decision. Doing so based on nothing but a vague feeling of dissatisfaction would have been a stupid decision. But doing so because you know the profession holds nothing more for you except disappointment and frustration, is probably a wise decision. Or at the very least, it's one I can live with.


Edit: a friend pointed out that I missed a category of developer: "mature developer, capable of quality code, but beat down by many years in the business." While these people undeniably exist (quite possibly in large numbers), I don't think they actually fit the description of "developers comfortable working in this paradigm". Nevertheless, they are definitely worth a mention (thanks, Sharon!).

Tuesday, June 5, 2012

The allure of mediocrity

In my previous post, I outlined the costs and benefits of making a commitment to well-crafted code.  I lamented how almost no companies are willing to make that commitment, even though the benefits far outweigh the costs.

Or do they?  I'm trying to put on my corporate hat: "profit above all".  It doesn't fit me very well, but here goes...

The costs of being committed to well-crafted code:
  • Commitment to hiring "craftsman-level" developers:  There is a time-cost associated with every candidate searched, evaluated, and interviewed.  Finding someone who is "good enough" takes much less time (money) than finding someone "really good".
  • Commitment to keeping skilled developers:  This incurs many costs: above-average benefits and above-average salaries.  Investment in infrastructure to support remote-work. Also, it limits my ability to demand 60-hour weeks / weekends (remember, for my salaried employees, I logically only pay for the first 40 hours per week - any work beyond that is free).  Really good developers are more likely to leave under those conditions, as they are less afraid of looking for a new position elsewhere.
  • Staying away from "bargain" developers:  There's hundreds of development firms (many of them offshore) who can give me developers at an hourly rate that is about 1/4 of what I would pay a full-time employee.  Even if it takes them twice as long to develop and debug the desired functionality, I'm still paying half the cost of my own locally-based development staff.  Their code can't be THAT bad, right?
  • Taking the time to think before you code: You have 10+ years of software development experience - you shouldn't have to research things anymore - you should already know the best way to approach every possible problem in every possible system in every programming language for every possible set of requirements.  Thinking costs time/money, but doesn't provide any measurable benefit to the bottom line.
  • Refactor code which fulfills the system requirements: if it ain't broke, don't fix it.  You should be spending your time developing new features or fixing the bugs our clients are complaining about.
  • You must be open to the possibility of sacrificing some functionality in order to meet a deadline: this is a huge cost!  If FeatureXYZ isn't 100% implemented and bug-free in the next version of the software,we won't be able to sell it at all.  If cutting corners will get FeatureXYZ implemented by the deadline, then do it.  We can deal with the fallout from it in a later release.
Many of those costs are invisible or inconsequential from a developer's perspective, but they all impact the company's profitability to some extent.  Perhaps there were spots where I was a little sarcastic or over-simplistic, however, I think the overall assessment is accurate: every one of those is a real cost, and would probably give me pause if it were my responsibility to keep a company's books in the black.

However, from a pure profitability standpoint, costs aren't inherently evil.  If the costs buy us benefits which result in a net profit, I'll happily pay them.  The benefits of a commitment to well-crafted code:
  • Gives the developer a sense of accomplishment and pride: seriously?  Go paint happy little trees on your own time, hippie.
  • Well-crafted code is more easily understood by other developers ... New employees can be productive sooner: I like it - improved productivity is a real benefit.  How much sooner?  How much more productive?
  • Well-crafted code generally has fewer bugs.  Bugs which do occur are quicker to repair: I like this one, too - bugs make for unhappy customers; fixed bugs make for happy customers and increased revenue (I never understood how a 10-year-veteran of software development still writes code with bugs, but I've stopped asking since it seems to offend them for some reason).  So how many fewer bugs?  None?  And how much more quickly can you repair them?
  • Well-crafted code is easier to extend.  Future enhancements can be made more quickly: I'd like this one better if it meant faster development now.  But nevertheless, it's a good benefit.  How much faster?
You can probably see a trend here: many of the benefits of well-crafted code are realized in the future; contrast that with the costs, which are mostly incurred immediately.  The benefits are difficult to quantify (and in some cases difficult to even describe in layman's terms); contrast that with the costs which are more concrete and easier to quantify. 

So from a pure profitability standpoint, we have very real, immediate costs that provide somewhat foggy, future benefits.  Again, if I were in charge of a company's books, I don't think I'd want to make that tradeoff either.

So where does that leave corporations?  A commitment to consistently well-crafted code doesn't seem profitable, but they're not stupid - they know they need SOME degree of code quality and developer expertise.  I assume they'll do the same thing I do when I'm purchasing something: try to find the best bang-for-the-buck.  I'm not going to buy the most well-crafted, reliable, brand-new car on the market, but I'm also not going to buy the bondo-coated, 200,000-mile jalopy.  Similarly, I suspect corporations are looking for a developer who's skilled enough to write "good enough" code, but is unskilled enough to be content doing so.

So where does that leave me?
(to be continued...)

Tuesday, April 24, 2012

The costs and benefits of well-crafted code

Over my career, I've worked with several different companies, none of which were able to truly make a commitment to well-crafted code.  A few were very close, but the majority of companies paid it lip-service at best (and completely ignored it at worst).  That's because a commitment to quality code does not come for free:
  • You must limit your development team to those people with the experience and capability to consistently write well-crafted code.
    • Because this talent pool is smaller, losing an employee is a greater cost.  Thus, you must be willing to compensate your "craftsmen" at a level which minimizes turnover.
    • If you choose to hire junior employees who show the skill and interest in becoming "craftsmen", you must commit the time to mentor them, and accept the fact some of their development efforts (especially at first) will not "make the cut" for inclusion into the codebase.
    • You will not be able to take advantage of "bargain" developers.  If a body-shop (on-shore or offshore) promises craftsman-level work at college-grad-new-hire prices, you should probably treat them the same as you would someone selling you a 1-year-old Porsche for the blue-book price of a 10-year-old Volkswagen.
  • You must take the time to think before you code (or design).  Research - are there commonly-accepted approaches to meet your requirements?  Consider your design at an abstract level -  does it mesh well with the framework in which it will run?  This means initial development takes a little longer (compared to the "just do it the first way that comes to mind", or the "this is the only way I know how to do this" approach).
  • You must be willing to refactor code which fulfills the system requirements, but is poorly-written.
  • You must have the discipline to maintain these ideals, even when deadlines loom near.  You must be open to the possibility of sacrificing some functionality in order to meet a deadline.

For much of my career, I was too busy learning my craft to really think about things at this level.  However, once I had progressed to the point where I could recognize and produce well-crafted code, it really made me angry: why were there no companies who were willing to make that commitment to high-quality code, in order to reap the benefits?
  • Well-crafted code has its own "beauty", and gives the developer a sense of accomplishment and pride.
  • Well-crafted code is more easily understood by other developers (if they have a comparable level of expertise).  New employees can be productive sooner, and existing employees can maintain each others' code with less knowledge-transfer time.
  • Well-crafted code generally has fewer bugs (I'm not sure whether that is a factor of the quality of the code, or the experience of the developer).  Bugs which do occur are usually quicker to diagnose and repair.
  • Well-crafted code is easier to extend.  Future enhancements to the product can be made more quickly, and the product will be able to "withstand" more enhancements before its overall stability / reliability / performance takes a hit.
It's a no-brainer - well-crafted code is the way to go!  Of course I want a sense of pride in what I create.  Of course I want to understand new code more easily, fix bugs more quickly, and create future enhancements more easily.  Of course I want to work on a development team comprised of "craftsman-level" developers, committed to helping junior developers improve their skills.  Of course I want to take the time to learn and understand the best ways of building code, and not just rush ahead with the first approach that comes to mind...

... Wait a minute...  Those last couple of things are from the list of "costs", not "benefits".  What happened here?

That's when I realized - I've been looking at this purely from my own perspective - that of a developer who loves crafting code that works in concert with its environment, understanding design patterns, and thinking about and discussing the best ways to approach certain abstract problems.  From that perspective, the costs of well-crafted code are very small - so small that I viewed many of them as benefits!  And of course, the benefits are very large - "a sense of accomplishment and pride in what you do" - Abraham Maslow would agree.

If I'm going to try to understand why well-crafted code isn't a corporate priority, I'm going to have to look at this from a corporate perspective.  I've never been much of a business-person, so that perspective doesn't come easily to me.  But I'll give it a try in my next blog post.

PS: if you currently work for a place which is truly committed to well-crafted code, that's terrific - I'm jealous of you.  You're in an extremely rare situation.  Keep that in mind if you consider leaving for "greener pastures" - you're already about as green as it gets!


Tuesday, April 10, 2012

Craftsmanship

There's something beautiful in a well-built dovetail joint.  It works with the wood, relatively strong in all directions without any nails or screws to risk splitting.  It looks terrific, but that's ancillary - especially since these joints are often hidden out-of-sight, in the back corner of a drawer.  The real beauty is in how cleanly it works - as if the wood was intended to be joined that way.

By contrast, you can hold two pieces of wood at a right angle, and just pound nail after nail through them until they basically hold together.  It takes less time than a dovetail joint and will generally serve the intended purpose: the drawer will hold together (for awhile, at least).

Dovetail joints can be very challenging (almost impossible) to create if you don't know the right technique, have the right tools, and some degree of skill and experience.  They're one of the things that sets an experienced craftsman apart, and one of many things that makes truly well-crafted furniture harder (and more expensive) to build.

There's also something beautiful in well-crafted code.  Sometimes it's building classes which follow the expected paradigms of the platform on which they run.  Sometimes it's execution of a proven design pattern to solve a relevant problem.  (Stress "relevant" there - overuse or misuse of design patterns makes for ugly code, masquerading as elegance.)  It often follows the tenet, "Things should be made as simple as possible, but no simpler" (generally attributed to Albert Einstein).

I've been working primarily with ASP.NET for the last few years, so I'll use it as an (admittedly over-simplified) example.  Most ASP.NET development centers around a Page.  Each time a Page is requested, the framework follows a consistent series of steps to execute/construct the page: this is the "page lifecycle".  The framework incorporates a "view state" to track user-entered data, supports re-usable components called "controls", and supports event-based communication between the page and its controls.  Understanding these elements and how they work together are vital "tools and techniques" for building a well-crafted ASP.NET system.  If you understand them, you'll likely write code which integrates well with them, and you'll feel how the whole just seems to be "meant to work that way" - like a dovetail joint in wood.

By contrast, it is possible (I've seen it many, many times) for developers to build a fully-functioning ASP.NET system with only the barest understanding of those elements, and no concept at all of how they interact.  It's ugly and difficult to maintain, and usually results in a lot of "whack-a-mole" fixing of bugs (and causing more bugs in the process).  It's the software equivalent of "just pounding nail after nail into it".  But if you keep pounding at it, it will eventually work - like the nailed-together drawer - at least for awhile.

A furniture craftsman is perfectly capable of haphazardly nailing a drawer together - but he (or she) won't.  He takes pride in his work, and doing a "good enough" job simply isn't fulfilling.  Perhaps more importantly, he knows just how beautiful and fulfilling a well-crafted piece CAN be, and that knowledge makes doing "good-enough" work all the more painful.

In my younger, less experienced days, it gave me great pleasure just to get a piece of software working.  Often, my code was of the nail-after-nail variety - but that's to be expected.  I didn't have the skill, tools, or technique to write "dovetail joint" code.  Heck, at that time I probably didn't have the experience to fully appreciate the difference between the two!

However today, at the risk of sounding pretentious, I am a software craftsman.  I know how good software CAN be, when it is built with an understanding of its platform, and of common best-practices for using it.  Simply "getting the software working" no longer holds any excitement for me; designing and writing well-crafted code is the fulfilling aspect of my job.

So that's great, right?  Experienced craftsmen are MVPs of their professions, right?  When it comes to software development, I'm not convinced that's true.  I need to mull that over a bit - it will probably be my next post.

Monday, March 5, 2012

Does good code make good software?


(what is "good" code and "good" software?  See my previous post.)

In most areas of life, using bad materials results in a bad product.  Cheap lumber?  Your deck will look warped and/or need to be replaced in 5 years.  Bad ingredients?  The meal isn't going to taste good (though I imagine a skilled chef could mitigate that somewhat).

However, over the years I've been very surprised at the connection (or lack thereof) between code quality and software quality.

  • I worked on an ASP.NET project which discouraged the use of the ViewState, and instead stored everything in the Session.  This resulted in bloated memory usage, poor performance when marshaling the session to / from the state server, and a myriad of hidden (and untestable) dependencies among classes which required certain Session data to be set or updated at certain times, by other classes.
     
  • Once, my development manager forbade the use of common, re-usable helper classes / functions; he wanted all logic copied into every function that used it, because he "didn't like looking all over the code for the implementation".
     
  • Another project was composed of two completely separate systems (even though both systems were being developed simultaneously by the same team).  Almost every operation required multiple communications between the two systems.  Each system retained its own copy of data; if the data ever became out-of-sync between the systems, it caused numerous subtle errors.  There were no automated or periodic checks to ensure data was in sync.  Out of sync data could only be repaired by one of the system experts manually adjusting the data using SQL.  But that's ok because "the systems will always work perfectly, once we pass QA".
     
  • I worked at a company that had a nicely-encapsulated software platform... then started every new client project by copying the entire codebase.  Bugs fixed for one client never made it to the other clients' systems - unless / until those other clients complained about them too.  Platform enhancements were very slow to roll out, as they had to be implemented for each client individually.
     
  • On one very "enterprise-y" project, the home-grown framework required creation of 4 classes, 3 config file entries, and 3 database entries - just to implement a simple "are you sure" dialog.  It took several seconds to execute, as it necessitated two postback operations to open the dialog.  The same behavior could be achieved with sub-second execution time and 1 line of javascript code; however use of the home-grown framework was mandatory.

The above approaches would be considered laughable in any conversation among experienced developers, and would probably result in a failing grade on any professional certification test. Yet all of the companies above are successful, have been in business for years (in some cases, decades), have a large following of loyal customers, and have products which are widely regarded as effective and reliable.

In other words, in all of the cases above, bad code and development practices have produced good software.

I'm not so jaded as to believe that code quality has NO impact on software quality.  Every one of the systems above could have been improved by well-crafted code and better methodologies and design.  However, as much as I wish it weren't true, it's clear that very good software CAN result from very bad code.  This is even more true when you measure software quality by the only metric that truly matters to a company: profitability.

Tuesday, February 28, 2012

"Software" and "code"

As I suspect most developers do, I make a distinction between "software" and "code":

  • Software is the end-product: a website or web-application accessible by the end user, an installable GUI program, a long-running installable service, etc.  The point is: software is the product which customers purchase and use.
     
  • Code is the source code - the building blocks from which the software is made - including "raw" code (C#, Java, Ruby, Javascript, HTML, SQL, etc), configuration files, publicly-accessible APIs, and even the designs which govern how the subsystems are built and interact.  Most significantly, customers never see the code or directly interact with it.

Considering this distinction between software and code, it's not surprising that quality of software and quality of code are measured differently:

  • "Good" software is generally measured by number of bugs found during QA, number of issues found "in the field", function points implemented,, etc.  Sometimes it is measured using more "business-y" factors, such as customer satisfaction with the product, quantity of sales, etc.  And ultimately, by the only business yardstick that really matters to the company: profitability.
     
  • "Good" code is generally measured by its adherence to industry-standard best-practices (appropriate use of design patterns, appropriate use of the language / platform's idioms, adherence to "DRY" concepts, encapsulation and code reuse, etc.).  And sometimes by more quantifiable measures (completeness of code comments, unit test coverage, etc.).  In my experience, those quantifiable measures rarely reflect the actual quality of the code, but that's a discussion for another day.

So even though code is the building material from which software is made, the two are surprisingly distinct.  With that in mind, what is the relationship between code quality and software quality? 

I think I'll mull that over, and make it my next post.
 

Saturday, February 25, 2012

First

I've been developing software for about 20 years.  Lately I've been doing a lot of ruminating about the industry, my perspective on it, and my place in it.

When I'm trying to gather my thoughts on something, writing them down is often helpful.  So that's what this blog is - me gathering my thoughts on software development.

It's quite possible the only one who will find this remotely interesting or useful is me.  But just in case others do, I figured I'd throw them out here.