@ayende You ought to try Mercurial. in reply to ayende 1 week ago
04
Feb

Catching Exception is almost never justified and almost always harmful

I was doing an ad-hoc review of another developer’s code not long ago when I saw something like this:

try {
    return bool.Parse(GetSomething());
}
catch (Exception) {
    return false;
}

I gently pointed out to him that this is a bad practice. Apart from the fact that you can use bool.TryParse() instead of bool.Parse(), your GetSomething() method may be throwing exceptions indicating a rather more serious problem, such as your database being down.

Catching Exception is one of my pet peeves, but sadly it’s far too common, even among smart developers that I’d have expected to know better, cropping up in commercial products and open source projects alike. Part of the problem is the code samples in the MSDN documentation itself, which are littered with completely unnecessary try ... catch (Exception) blocks, that people copy and paste without thinking about it. But it’s also a quick and dirty hack — it’s easier to simply catch Exception and cross your fingers than to look up the documentation to find out exactly what you should be catching.

But this is reckless and dangerous. Catching exceptions inappropriately can lead to some very serious bugs in your code — serious, because you are deliberately ignoring them while they wreak havoc with your data. In one instance, I was asked to troubleshoot an application where a database upgrade had been botched and nobody had noticed for several days until the users started complaining that their changes weren’t being saved. You may also be ignoring misconfiguration, missing assemblies, external services being offline, and so on. And even if the effects aren’t serious, the bugs can still be particularly difficult to track down, as your logs will likely contain misleading error reports, if indeed they contain any error reports at all.

Catching general exception types without re-throwing them is almost never justified, and almost always harmful.

The correct approach to exceptions is to allow them to bubble up to the topmost level of your code, and handle them there by logging them and presenting an approriate error message to the user. For ASP.NET applications, this is the Application_Error event handler in your global.asax file, or perhaps an error logging framework such as ELMAH. For console applications, it is your Main method. For separate threads, it is the topmost method of the thread. And so on.

Well written code has very few try ... catch blocks. The most common case where you would have a general exception handler is when you need to roll back a transaction or otherwise leave your application in a consistent state when you re-throw:

try {
    BeginTransaction();
    DoStuff();
    Commit();
}
catch {
    RollBack();
    throw;
}

Aside: when you re-throw the exception, always use throw; here (which preserves the stack trace), not throw ex; (which doesn’t).

Apart from that, you should only catch specific exception types that you are both able and willing to handle meaningfully. Certainly, catching Exception should be treated as the nuclear option — and if there really is no alternative, you should always log the exceptions and rigorously justify your decision both in comments and in a code review. And next time you are tempted to write catch (Exception), ask yourself this question:

What would this code do if the exception were due to a botched deployment, an out of memory error, or a misconfiguration?

26
Oct

How to validate a URL in .NET

System.Uri.TryCreate.

You don’t need to use regular expressions.

More generally, if you are trying to do something extremely common, the chances are that whatever framework you’re using, there’s a method or function somewhere in there which will do it for you. And it will almost certainly do it much better than your home-brewed solution will.

29
Sep

Book review: The Art of Unit Testing

Unit testing is one of the programming disciplines that, to my mind at least, sets apart the reputable developers from the cowboys. Test driven development has become increasingly popular over the past few years, and for many teams, it’s becoming as fundamental a discipline as using source control. It’s an idea that sounds almost like a no-brainer at first: you write a bunch of methods that feed test data into your code and examine the result, and they report either success or failure. Then when you start extending and modifying your code, you can re-run your tests to check that everything still works as it’s supposed to, and you haven’t broken any dependencies.

Yet of all the programming disciplines that I’ve had to get to grips with over the years, unit testing has probably been one of the most difficult. Setting up your project to facilitate automated testing involves quite a lot of groundwork. You have to configure a test environment, perhaps with a test database or other form of test data source, and you also have to completely re-think the way you write your code. It requires greater discipline — it’s all too easy to think “Stuff that,” and slip into the old mindset of just slapping down your code and testing it manually. Some legacy code may seem almost impossible to test, especially if it is a Big Ball of Mud with long, multi-purpose methods and no clear separation of concerns. Then there is the question of what to do with external dependencies — components that are beyond the control of your unit tests, such as third party web services, input devices, and even the current date and time.

The Art of Unit TestingIf you’re wrestling with problems such as these, Roy Osherove’s book, The Art of Unit Testing, is a must-read. Most treatments of unit testing that I’ve come across only cover the topic at a fairly basic level, but this one picks up where they leave off. I was pleased to see some good solid chapters on stubs, mocks and dependency injection, for instance: these are essential tools needed to break external dependencies. I was also pleased to see a whole chapter devoted to working effectively with legacy code; another whole chapter is devoted to the political and organisational implications of introducing unit testing into your organisation.

The book assumes a basic familiarity with object oriented programming and design patterns (which every working developer should understand properly anyway) but it isn’t a difficult read, and it explains things very clearly. Code samples are given in C#, but developers working with other languages will also find much in it of benefit. There are plenty of suggestions that may not have occurred to you, and you’ll end up much more aware of the “tricks of the trade.”

My only disappointment was that four major, and potentially thorny, aspects of the subject — database, UI, web and thread-related testing — were only given a brief overview in the second half of Appendix B. Of course it could be argued that these were outside the scope of this book — indeed, Osherove argues that unit testing in some of these areas in particular have a relatively low return on investment — and in others, unit testing frameworks and methodologies are still very much in their infancy. However, I was hoping for a somewhat more extensive treatment of these aspects of the subject and it was a little bit disappointing that they only got six pages.

But this doesn’t detract from the value of the book. Whether unit testing is your “thing” or not, it is very much a must-read for every working .NET developer, and indeed for developers working with other languages too. It deserves to be as much a classic as books such as Code Complete, Design Patterns, or Martin Fowler’s Refactoring.

25
Sep

Joel Spolsky, cowboy coder

Some people at work think I’m a bit of a Joel Spolsky fanboy. I’ve certainly got a lot of useful hints and tips out of his blog, Joel on Software, and I’ve been recommending it as a must-read for fellow developers and managers alike.

Until now.

What’s really, really annoying me about Joel these days is that he’s started preaching cowboy coding. And I don’t like it.

His latest post, The Duct Tape Programmer, illustrates this perfectly. He has yet another dig at Architecture Astronauts who come up to you when you’re racing to get an upgrade ready for deployment and tell you that you need to refactor your core code to use multi-apartment threaded COM. Not unreasonable. But then, he goes on to wax lyrical about Jamie Zawinski, who is, to use Joel’s words, the Pretty Boy of Software Development. He wrote Netscape Navigator in the 1990s and is Joel’s hero because—get this—he didn’t write unit tests:

Zawinski didn’t do many unit tests. They “sound great in principle. Given a leisurely development pace, that’s certainly the way to go. But when you’re looking at, ‘We’ve got to go from zero to done in six weeks,’ well, I can’t do that unless I cut something out. And what I’m going to cut out is the stuff that’s not absolutely critical. And unit tests are not critical. If there’s no unit test the customer isn’t going to complain about that.”

Now perhaps Mr Zawinski is brilliant enough to get away with a “duct tape programming” approach, but it is not something that we should be encouraging, not least because it is deeply unprofessional. Besides, what he says about unit testing is just WRONG.

Here’s the score with test-driven development. Once you know what you’re doing, it doesn’t slow you down overall. Yes, it takes longer to write the code in the first place, but this is offset by a decrease in time spent debugging, and on top of that, you get a dramatic increase in confidence in your code, a more robust design, and a reproducible, easy to run way of verifying that your code does what it’s supposed to. Every professional developer who is concerned about quality these days writes unit tests insofar as they can. If you don’t like the idea, you are a cowboy coder. Period.

Joel’s sentiments such as these have been bugging me since the start of this year, when he crossed swords with “Uncle Bob” Robert C Martin on the Stack Overflow podcast over the SOLID principles. Back in January on the Stack Overflow podcast, he made this observation:

Joel revisits the SOLID principles, and compares them to designing replaceable batteries, or a headphone jack, into your product. Appropriate in some narrow cases, but not all the time. Imagine a consumer product where every single part of it could be plugged in and replaced with another compatible part. Is that realistic?

Actually, Joel, I can perfectly well imagine such a consumer product. In fact I own one such consumer product myself where this kind of design pattern is very important. It’s called a car.

Let me explain. On the journey up to Faith Camp in August, another driver ran into the back of said car and left it looking rather sorry for itself. The repairs took three weeks, and involved replacing the rear bumper, the rear hatch, and various panels. Ford makes appropriate parts that can be slotted and bolted into place with relative ease as replacements for the damaged originals.

Imagine a car built the way Joel’n’Jeff seemed to be suggesting, where it was just one monolithic structure, with non-interchangeable parts. One ding like that and it’s a writeoff. When the tyres wear thin, or the bulbs go, you have to scrap it. Is that realistic?

Architecture astronauts are a straw man here. We’re not talking about highfalutin over-engineered ProviderSingletonVisitorAdapterMediatorRepositoryFactory design patterns, nor are we talking about more layers of abstraction than The Princess and the Pea, we’re talking about a common sense approach to software development. It’s the kind of thing that you’re either doing anyway but you just don’t know what it’s called, or else you get that kind of “aha!” moment when you first encounter it that makes you think, “Now how come I never thought of that before?”

One other thing. When you’re repairing a car after an accident, you most certainly do NOT just use duct tape and WD-40. No matter how much of a Pretty Boy you think you are.

16
Sep

If you are saving passwords in clear text, you are probably breaking the law

The Christian dating website that got hacked by 4chan back in August was a textbook illustration of why you should not store users’ passwords in plain text. Most of the users of the site had re-used their user names and passwords on Facebook and their e-mail accounts, which were compromised as a result, in many cases in extremely embarrassing ways.

Reading about this (and a similar event somewhat closer to home a week later) has got me thinking about the whole issue again. A couple of years ago, Mats Helander proposed on his blog that saving plain text passwords should be illegal. (Unfortunately he lost his domain name to squatters a few months later, but the post is still up in the Wayback Machine.) His post was in response to some of Jeff Atwood’s readers, who pointed out that many web developers have bosses and clients who insist on them storing passwords in clear text so that they can e-mail password reminders to their users. To be sure, you can try explaining to them that there are alternative approaches that don’t compromise usability, but if your boss is an “I’m not a computer person” type, or just doesn’t care, you might as well try to strike a match on jelly, or you may even find your job on the line. However, if you could tell your boss or clients that they were asking you to do something illegal, you’d be in a much stronger position to push back.

Now I am not a lawyer, but the other day, I took a close look at the Data Protection Act 1998, and if I understand it correctly, saving passwords in clear text is indeed illegal here in the UK.

The relevant part of the Act is Schedule 1, Part I, paragraph 7, which states the seventh of eight Data Protection Principles:

Appropriate technical and organisational measures shall be taken against unauthorised or unlawful processing of personal data and against accidental loss or destruction of, or damage to, personal data.

This is expanded on in Schedule 1, Part II, paragraphs 9-12, which tells us how to interpret this principle. Paragraph 9 in particular says:

9 Having regard to the state of technological development and the cost of implementing any measures, the measures must ensure a level of security appropriate to—

(a) the harm that might result from such unauthorised or unlawful processing or accidental loss, destruction or damage as are mentioned in the seventh principle, and

(b) the nature of the data to be protected.

It should be noted that these restrictions apply to “personal data” as well as to “sensitive personal data.”

As Mats argued, and I would reiterate, and the Christian dating website/4chan incident illustrates dramatically, losing people’s passwords has the potential for immense harm. Defacing Facebook profiles can cause serious embarrassment and possibly even wreck careers, but if the attacker then gets access to your e-mail account, they can obtain or request new passwords for even more sensitive websites such as your bank, your credit cards, and so on.

It seems obvious to me that storing plain text passwords in a database most certainly does not “ensure a level of security appropriate to the harm that might result from such unauthorised or unlawful processing or accidental loss” as required by the law. The state of technological development provides us with a much better solution — a one-way salted hash, which is computationally infeasible to reverse engineer — and since there are still perfectly adequate solutions to the login recovery problem, the cost of doing so is negligible.

I’d be interested to hear from anyone who specialises in the legal issues surrounding computer security whether my understanding of the Data Protection Act is correct here. Do you concur with my conclusions? Or do you think that the law need to be made more explicit on this matter?

29
Jun

Why SQL Server 2005 database projects in VSTS are a bad idea

I’ve been working a bit lately with a project that uses SQL Server 2005 database projects in Visual Studio 2008 Team System. These are different from the conventional database projects that you get in Visual Studio Professional, since they have extra features that allow you to do schema and data comparisons, and, in theory at least, manage database deployments and migrations.

The idea is that you should be able to design your database using visual designers rather than having to write all that nasty SQL code to script it for you. Visual designers make things so much easier at the planning and initial design stage, and once you are done, you can use the various schema comparison and script generation tools to generate your production database.

The problem comes when you want to manage your database’s entire lifecycle. I’m sure that many developers will have scratched their heads at some stage about this problem. You chop and change your database on your development server, most likely using the visual tools—but how do you reliably replicate these changes on your live server?

The Microsoft approach here is to rely on the schema comparison tools to generate change scripts that you can then run against your database. Some people think it’s a silver bullet. I beg to differ.

The first problem is that while schema comparisons can make a good starting point, the scripts they generate don’t always work properly out of the box, if at all. Some database refactorings simply can’t be done using schema comparison tools. Examples include normalisation refactorings such as moving data from one table or column to another; introducing constraints or changing a column’s data type when you need to do some data cleanup first; or modifying reference data. Even relatively straightforward refactorings—or even, in some cases, no refactoring at all—can be problematic: if your production and development databases get their collation orders out of sync, for instance, the script may refuse to run at all. And the thought that anyone would blindly use this option on the project properties page makes me shiver:

Perform "smart" column name matching when you add or rename a column

In other words, you’re asking it to guess what’s changed.

Testability—and when you’re dealing with an abstraction as leaky as this one, testability is vital—is another issue. Unfortunately, SQL Server 2005 database projects have serious shortcomings in this area too. They do offer unit testing features, but these only apply to the final database. There doesn’t seem to be any way of integration testing your migrations themselves: you don’t have a consistent record of what’s changed in a format that can easily be applied to a blank or reference database, so there’s no way of verifying that you’re getting the expected results when you’re going from “before” to “after.”

Then there are the change scripts generated by schema compare itself. They are a morass of long winded, convoluted, hard to maintain, spaghetti code. Adding a column to a database table involves dropping and re-creating the table: this is understandable if you need to put the column in the middle of the roster, since SQL Server does not have an AFTER clause in the ALTER TABLE statement like MySQL does, but even if you add a column on to the end, it still drops and re-creates the table. A task that needs only one or two lines of code ends up taking eighty. If you rely on schema comparison tools, sooner or later you are going to need to edit your scripts, and when that happens you’ll find that you’d have been quicker just writing the change that you needed by hand in the first place.

All in all, this seems far too leaky an abstraction to give me any confidence in it to manage a database lifecycle. There is simply no substitute for scripting every database migration, checking it into source control, and having your unit tests run them all on a blank, or reference, database, and having some record in your production database of which scripts have been run and which haven’t. And while schema comparison tools may be a life saver if you lose track of things for any reason, they are a very poor alternative to generating your migration scripts by hand.

01
Jun

Why would anyone not use source control?

There’s a question over on Stack Overflow that asks if there are any good reasons for not using source control. It’s a question I’ve been racking my brains over for a while now, especially since you do occasionally encounter people who claim they have good reasons not to. The most common such reason that I come across is that they’re a lone developer — an excuse that simply shows that they haven’t a clue what source control actually is.

One person pointed out that physicists are particularly unlikely to use source control:

For the casual programmers – those to whom programming is just a tool, such as many of the people I work with (scientists) – much of the work is hackish and small scale, there may be a dozen other things that are more likely to fail outside the code which could also be eliminated with better practices.

As a colleague put it, “we don’t get published for writing beautiful code”.

Interesting point that. Most programs written by physicists tend to be no more than a few hundred lines long, or even just a Microsoft Excel spreadsheet, and once they’re debugged and working, they usually don’t change. This is of course the exact opposite of business and web programming, where requirements change faster than you can keep up with them. However, you can’t really generalise here. I’d be very surprised, for instance, if NASA doesn’t use some from of source control for the Mars rovers.

Another person gave an answer that was especially worth commenting on:

“For the first 10 years of kernel maintenance, we literally used tarballs and patches, which is a much superior source control management system than CVS is” –Torvalds

If you’ve got quick/easy/automatic backups, you’ve already got 95% of what most of us use VC for. Somebody with a local DVCS repository on his HD but no backups is actually in much worse shape.

Using a VCS does have a real cost, and it’s usually a small one but not always. Every VCS I’ve ever used, I’ve had days where I had to fight with it for hours just to get it to do something that should have been simple.

To those that think “There are no good reasons not to use version control”, where does it end? Must every project have 100% unit test code coverage? Must every project have code reviews? Coding standards? A complete functional spec?

There’s a whole spectrum of programming projects in the world. Not everybody is writing code for the space shuttle. Sometimes being able to diff my code from 11:00am and 11:30am is simply not that important.

Some are merely managing globally-distributed teams of thousands writing operating system kernels.

This is another interesting point — if the Linux kernel managed fine without source control for ten years, why should we use it? In actual fact, the commenter is not entirely correct: the Linux kernel has been under source control since 2002 and Linus Torvalds even wrote his own source control system because he was dissatisfied with all the others that were available at the time. But this is an indictment of CVS in particular, not of source control in general — at the time the choice that you had was between that and something costing an arm and a leg.

This highlights another fairly common reason why people shy away from source control: they perceive it as being more trouble than it’s worth. In recent years, most developers’ first experience of source control has been Subversion. Once you get used to it, Subversion is pretty powerful and works very well, but unfortunately it is not a good example to throw at beginners when telling them they need to use source control. Getting your project under source control in the first place with it is a faff, and I’ve lost count of the number of times that it’s gotten so confused with itself that I’ve had to do a fresh checkout just to get it working properly again. And all those extraneous .svn directories that pollute your project’s filespace can be a major irritation at times.

So what is the best option to convince the naysayers? In a word: Mercurial.

Recently I’ve been playing with some of the new distributed source control systems such as Git and Mercurial, and I get the impression that they are much better suited to new and casual developers than Subversion. They’re a lot easier to use for starters — in combination with visual front ends such as TortoiseHg, you can get your entire project under source control with only three or four mouse clicks. They also have fewer pitfalls and gotchas — you can rename and delete files and directories much more easily without creating a whole lot of confusion, for instance.

Another big advantage of modern distributed source control systems such as Mercurial is that they scale down as well as up. Mercurial creates a single .hg directory in your project’s root which acts as a complete repository in and of itself. For a lone developer this is probably all you need, in tandem with a decent backup strategy, and it even makes it entirely reasonable to get your throwaway scripts under source control. After all, throwaway scripts have a rather nasty habit of not being as throwaway as we first thought they would be.

For development teams, you can have a central repository in addition to the developers’ personal ones, and push the changes to the central server once you’re done. For really big projects, you can have a whole hierarchy of source control servers, with changes being pushed up to the next level once they have passed quality control and whatever other processes you may have in place.

There may have been reasonable excuses for not using source control five years ago on small, trivial projects. But with the latest generation of tools, these excuses are getting flimsier and flimsier every day. Even for physicists.

11
May

Reinventing the wheel, badly

A few years ago, I inherited a VB.NET application in which every method (many of which were four hundred lines long, copied and pasted all over the place, and peppered with vague sounding variable names such as blnRunIf and blnRunElse) contained this boilerplate code:

Sub MyMethod()
    Try
        '
        ' ** snip ** '
        '
    Catch ex As Exception
        Throw New Exception ("MyClass.MyMethod::" + ex.Message)
    End Try
End Sub

Those who do not understand Exception.StackTrace are doomed to reinvent it, badly.

06
Apr

When technical debt becomes technical bankruptcy

When clients and managers insist on a quick and dirty fix, they usually think that this means we only implement the “must-have” functionality, and leave aside the “nice-to-have” and even some of the “should-have” stuff. Okay, so we might need to reboot the server once a month or so, or we might need to go directly into the database using SQL Server Management Studio whenever prices change, but we can live with that, they think.

However, there is an unseen and potentially much more damaging effect of the quick and dirty fix, that developers, managers and clients all need to be aware of: technical debt.

Martin Fowler explains it like this:

You have a piece of functionality that you need to add to your system. You see two ways to do it, one is quick to do but is messy – you are sure that it will make further changes harder in the future.The other results in a cleaner design, but will take longer to put in place.

Technical Debt is a wonderful metaphor developed by Ward Cunningham to help us think about this problem. In this metaphor, doing things the quick and dirty way sets us up with a technical debt, which is similar to a financial debt. Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice. We can choose to continue paying the interest, or we can pay down the principal by refactoring the quick and dirty design into the better design. Although it costs to pay down the principal, we gain by reduced interest payments in the future.

Now there are times when technical debt is an appropriate strategic decision. Often, you need to get to market quickly with your website in order to obtain a competitive advantage. Sometimes, there are hard deadlines to meet. However, just as with financial debt, you need to be aware that you are taking on a certain amount of technical debt, because it will need to be repaid sooner or later.

Consequently, when you make the strategic decision to accrue some technical debt, you should always allow for some time to repay it at regular intervals — refactoring, adding more unit tests, documenting the system, and maybe even rewriting some components from scratch a second time if they are particularly messy. If you don’t, and the situation is allowed to get out of hand, you can end up with technical bankruptcy.

Technical Bankruptcy is the point at which levels of technical debt become so overbearing that the project is effectively doomed. This is due to two serious and crippling effects of technical debt:

1. Making changes becomes much harder.

One of the quickest ways to build up technical debt is to copy and paste large sections of your code. Programming purists rightly regard copy and paste as evil — it violates the “once and only once” rule and makes it much harder to make changes later on. However, it can add extra functionality into your program much more quickly than doing things the “correct” way. Many of the other programming anti-patterns, such as magic numbers, meaningless method names such as “do_it”, and so on, fall into the same category — shortcuts which involve a trade-off between getting things done now and getting things done in the future.

However, these are the less complex cases. More serious are the higher-level shortcuts: poorly designed database schemas, tight coupling between the tiers of the application, a lack of preliminary analysis and design, and so on. Nevertheless, whatever the cause, the result is that by asking for quick and dirty hacks today, you are potentially blocking yourself off from asking for quick and dirty hacks tomorrow.

2. Finding developers to work on the project becomes much harder.

Make no mistake about it: working on a project that has an excessive amount of technical debt is a depressing, discouraging, and disheartening experience. It can mean going for days or even weeks on end banging on the keyboard with little to show for it and getting shouted at by your boss for not delivering on time. It saps morale and by extension productivity, and this can spill over onto other projects and pull the rest of the team down. And what do developers do in that kind of situation? If they’re any good, they go and find somewhere else to work.

This compounds the problem even more. When a developer leaves, you have to recruit someone else to fill their place. This means placing an ad wherever you normally place ads, spending time filtering CVs, conducting phone screens, technical tests (you do give potential hires a technical test of some nature, don’t you?) and interviews, and then once you find a suitable candidate, there is the ramp-up time where they are actually getting to grips with the system — and no prizes for guessing what technical debt does to the length of this ramp-up time.

Although we are in the throes of a recession, there is still a massive shortage of good developers. It’s amazing just how many working programmers there are out there who can’t even handle the most basic challenges such as the FizzBuzz problem, and who get by merely by copying and pasting SQL injection vulnerabilities from ten year old PHP tutorials, or by pestering their more talented and knowledgeable colleagues for help at every step of the way and proving to be a net drain on the company’s resources. These are the kind of developers who have no concept of technical debt in the first place, and will just make things worse faster.

I would say that when you start to find it difficult to get good developers to work on a project for any length of time, it is a sign that your project is in serious trouble.

Is a total rewrite the answer?

Managers are invariably suspicious whenever a developer recommends a complete rewrite. Joel Spolsky wrote an article a while ago asserting that complete rewrites are a bad idea, and every time I say that X needs to be rewritten, this article is quoted back to me as a stock excuse for declining my suggestion.

Now the managers have a point here. A total rewrite from the ground up is the nuclear option: you run the risk of throwing away a whole lot of undocumented business rules, corner cases and bug fixes, and a complete redesign of the administrative interface means staff re-training and a deluge of support calls. Besides, developers can be a bit trigger-happy when calling for a total rewrite. We tend to be a pretty opinionated bunch, and very often we will call Someone Else’s Code complete garbage simply because we don’t understand it properly. But given a bit of time, most developers will manage to settle down into a new code base and will be able to start improving it and cleaning it up by a process of small, incremental refactorings as they go along.

Nevertheless, once you reach the point of technical bankruptcy (where technical debt becomes so overwhelming that the project is effectively doomed), a total rewrite might save the day, and maybe even provide some added value by clearing out certain business rules and systems that were put in place only as workarounds for bad design decisions in the first place. However, it would take a brilliant and determined developer, probably working on it as a skunk works project, to pull it off. Best to avoid getting into the situation in the first place, by paying down your technical debt sooner rather than later, and only hiring developers who know what they are doing to work on the project.

26
Mar

OO: the lingua franca of modern software design

There is no excuse whatsoever these days for working professionally as a developer and not being thoroughly familiar with object oriented programming.

Occasionally I meet people who have some crazy idea that it isn’t necessary, claiming that it leads to over-complicated code that is difficult to understand. Indeed, there are some software packages — WordPress springs particularly to mind — that make very little, if any, use of OO, yet they do pretty well. Furthermore, I wouldn’t necessarily expect new junior developers to be completely up to speed with it — after all, we all need to start off somewhere, and it’s perfectly reasonable to cut them some slack right at the start of their programming careers.

However, if you are working professionally with code, whether as a web developer or as any other kind of developer, then regardless of whether or not you are actually using it, getting to understand OO properly needs to be right at the top of your list of priorities.

Why? Because OO is the lingua franca of modern software design.

OO has been mainstream for nearly twenty years now, and before that it had been knocking around in academic circles and research labs since the sixties. In fact, it’s now pretty pervasive — nearly every framework out there is built round OO principles, and you can’t work as a developer for long without running into it.

More importantly, OO is a communication tool for discussing your application architecture and design decisions with your fellow developers. If you don’t understand it properly, or if you misunderstand it, you will not be able to hold a meaningful discussion with your colleagues about the structure and high level architecture of your code. You will not be able to understand why computer programs are designed the way they are, or why frameworks work the way they do. You will not be able to design your code to be easily extensible, nor will you be able to build usable, stable service interfaces. And you will be the one writing convoluted spaghetti code that is almost impossible to maintain.

You need to understand it correctly, though. A lot of developers think that they understand OO, but in actual fact, have numerous weird, fuzzy conceptual misunderstandings as to what it’s all about. Just wrapping a bunch of procedural code in a class doesn’t make it object oriented any more than going into McDonald’s turns you into a hamburger. Not knowing the difference between static methods and instance methods is a dead giveaway here — if you are creating instances of a class consisting entirely of helper methods, you’re doing it wrong. I’ve come across numerous examples over the years of this kind of thing:

public class Helper
{
    public int SumOfSquares(int a, int b)
    {
        return a * a + b * b;
    }
}

/* elsewhere */

var objHelper = new Helper();
return objHelper.SumOfSquares(a, b);

which could just as easily be written as:

public class Helper
{
    public static int SumOfSquares(int a, int b)
    {
        return a * a + b * b;
    }
}

/* elsewhere */

return Helper.SumOfSquares(a, b);

Now this is a relatively trivial example and one that is fairly easy to fix, though I have come across variations on this theme with the potential to introduce resource leaks or other obscure, hard to track down bugs. Much more serious, however — and harder to fix — are the maintenance nightmares, such as methods taking dozens of arguments, all of them primitive types such as int, char or string. Or very long methods containing a lot of complicated copy and paste code. Or huge, ten thousand line classes with more responsibilities than the Secretary General of the United Nations. These are the kind of problems that OO, design patterns and the SOLID principles are designed to solve, people.

Well designed OO code may be difficult for novice developers to understand, but it is not a problem to experienced OO practitioners. On the other hand, poorly written code, written by people with vague, woolly ideas about how code is supposed to be written, is a huge problem to novices and experts alike.