james mckay dot net

because there are few things that are less logical than business logic
20
Jun

Keep the number of projects in your solution to a minimum

There are a lot of common practices among .NET developers that get touted as “best practices” although they are nothing of the sort. A lot of them seem to be leftovers from the days about ten years ago when there was a lot of hype about n-tier although the people promoting n-tier didn’t properly understand the problems that n-tier was supposedly trying to solve. I’ve mentioned the repository-as-a-pointless-abstraction antipattern before, for example. Another related antipattern is too many projects in a single solution.

In general, you should always aim to keep the number of projects in your solution to an absolute minimum. For a simple web application, your solution requires exactly two projects: the application itself and your unit tests. For an application with a web front end and a console application, your solution requires four projects: the shared components, the web front end, the console application, and your unit tests. Products that deploy different applications to different servers may need one or two more for shared components, for instance, but the number should still be kept as small as possible.

Your solution does not — I repeat, does not — require separate projects for your controllers, your model, your business services, your repository, your shared components, your interfaces, and your wrappers round third party web services.

Your solution does not require multiple unit test projects. Some people create a separate unit test project for every main project in their solution. This is completely unnecessary: why not have a single unit test project for all of them? Of course, it may be worth having one project for fast unit tests, and another one for slower tests that need to run against a database, but over and above that, reasons for creating extra test projects are few and far between.

Your solution does not require multiple front end applications of the same type for deployment on the same server. You may need a back-end admin application on one server and a front-end public facing website on another, but you don’t need two back-end admin web applications for the same solution.

There are three reasons why too many assemblies are harmful:

1. Too many assemblies slow down compilation. When you have to compile a single project that references thirty external dependencies, the C# compiler only has to pull in these referenced assemblies once. When you have to compile thirty projects that reference thirty external dependencies each, the C# compiler has to pull in all thirty dependencies every time — a grand total of nine hundred referenced assemblies. This adds a lot of time onto your edit-compile-test-loop, which in turn knocks you right out of the zone and makes the whole development process feel like wading through treacle.

2. Too many assemblies make dependency management a pain. If you have to add a third party reference to thirty different projects, it is a massive, painful violation of DRY. If you have to swap out one reference for another, it is painful. If you have to add a third party reference to only a subset of those thirty, it is even more painful because you have to work out which assemblies require it and which don’t. And don’t even get me started on the problems you might face if you end up with two different projects referencing the same assembly from two different places within the bowels of your third party dependencies directory.

3. Too many front-end projects in particular make configuration and release management a pain. If you have two web front end projects for deployment on the same server, you have to configure them both together and deploy them both together. The more configuration you have to manage, the greater your risk of making a mistake. When you add a new configuration option, you have to update several different applications, and you increase the risk that you might miss one. If you have to change Copy Local from False to True for some assembly or other, you have to go through all your front end applications to make sure this is done correctly. Again, it’s a violation of DRY.

The main reason why people advocate a lot of projects in their solution is to attempt to keep the different logical parts of their code separate, so, for instance, they aren’t referencing System.Web from within the data access layer, or the data access layer directly from the UI, and they aren’t introducing circular dependencies. In practice, it simply isn’t worth it. If dependencies between your classes and namespaces really bothers you, a far simpler alternative is to buy a licence for NDepend instead. Certainly, you should have a very, very good reason to add a new project to your solution, and you should look to see what you can consolidate wherever you can.

03
Jun

Silverlight is dead. Long live HTML 5.

It seems that Microsoft has announced that HTML 5 and JavaScript, rather than Silverlight, will be the basis for front-end applications in Windows 8. The Silverlight community is up in arms.

This decision is hardly surprising. Silverlight was pretty much doomed from the start. It was a rival to a well-established, if flaky, technology — Flash — and pretty late to the party, so to developers not wedded to the Microsoft ecosystem (and that means 90% of web developers and designers), it was a great big yawn. And its prospects were effectively killed off when Apple decided to ban non-approved programming languages and frameworks from the App Store — therefore, no Flash, and by extension, no Silverlight. The iPhone and iPad are a huge market — if something doesn’t run on them, it isn’t cross-platform.

In the meantime, HTML 5 has come to the fore as a standard that looks set to render both these technologies obsolete. It is (partially at least, and increasingly) supported natively by web browsers without requiring any additional extensions. It’s an open W3C standard with a history spanning two decades, so it’s here to stay, as well as being a skill that can easily be transferred to other environments. XAML may be nice, but it has little or no traction outside of .NET.

For what it’s worth, this illustrates the risk of limiting your experience and skills to the Microsoft ecosystem. A lot of people have invested a lot of time and effort in becoming Silverlight specialists, and now they’re scared because it looks like those skills are set to become pretty much worthless over the next few years. I wouldn’t advocate ditching Microsoft altogether, but it’s always a good idea to be attentive to what’s going on elsewhere and not put all your eggs in one basket. Besides, if you’re familiar with what’s going on elsewhere, it can help to give you a better feel for which of Microsoft’s frameworks and technologies are likely to be a good long-term investment and which aren’t.

28
Mar

The great .NET productivity killer

A couple of blog posts caught my attention over the weekend. The first was from Robert Scoble, attributing MySpace’s woes, at least in part, to their choice of technology stack. The second was from David Barrett, the CEO of Expensify, explaining why he doesn’t hire .NET programmers.

Now there is the saying that a bad workman blames his tools, but there is such a thing as a bad tool (would you want to use a hammer whose head keeps flying off?) and having had fairly extensive experience of both .NET and other technologies, I could say that they both have a point, and it’s a point that I’ve personally found increasingly frustrating over the years. Specifically, I’ve noticed the following:

  1. I find it significantly easier to be productive with Python or PHP than with .NET.
  2. When I’m working with .NET, I find it significantly easier to be productive with client-side JavaScript and HTML than with C#.
  3. By far the biggest productivity killer in .NET is the edit/compile/test loop.

Here’s the difference. When you’re working in an interpreted scripting language such as PHP, Python or JavaScript, making changes is simple and fluent. You edit some code. You run your tests, or hit F5 in your browser. You see the results of your change almost immediately. Lather, rinse, repeat.

On the other hand, in .NET, once you edit your code, you have to re-compile your project. If your change is to the front end of your code, such as a tweak in your .aspx page, this might not take long. But if you are making changes in the back end, it can take a sizeable fraction of a minute. Then you have to re-load your project, with all its dependencies, into memory. For a large project, with a lot of dependencies, this can take a minute or more. And of course, that’s assuming that Visual Studio doesn’t freeze altogether in the process, which it very often does.

Now here’s the killer. Increasing the feedback time from ten seconds to over a minute knocks you right out of the zone. When you get quick feedback, you remain fully engaged, and fully focused on the task at hand. On the other hand, when you have to sit and twiddle your thumbs, it becomes increasingly difficult to resist the temptation to go and get yet another cup of tea, or switch to something else and get distracted. Even if you don’t, you still have to pick up the threads of what you were thinking about before you started. It can easily make a difference of an order of magnitude in productivity if you’re not careful, and even if you are, it’s still pretty wearying.

Incidentally, Joel Spolsky makes exactly this point in the Joel Test when advocating quiet working conditions and the best tools that money can buy.

However, it isn’t always possible to avoid .NET altogether: to do so would be to cut yourself off from a lot of opportunities, and I’m certainly not ready to throw in the towel yet and switch completely to Ruby on Rails, as some people do — noisily. So, that being the case, what can you do to alleviate the situation?

Here are some suggestions worth considering:

  • Use a lightweight text editor such as Notepad++ or vim alongside, or perhaps even instead of, Visual Studio. Yes, you lose IntelliSense and integrated debugging, but this forces you to rely more on test-driven development, commit the APIs that you use to memory, and get into the habit of paying more attention to detail, and that only benefits you in the long run. Besides, that’s how we code in other languages, and we’re none the worse for it. As long-time Windows programming expert Charles Petzold will tell you, IntelliSense and integrated debugging dumb you down.
  • Have as few projects in your solution as possible. Lots of projects mean lots more dependencies have to be loaded, and that can dramatically increase compilation times. Also, keep your layers of abstraction to a minimum.
  • Alternatively, if you genuinely need a lot of projects, use more than one solution. That way, you reduce the risk of accidentally triggering an unnecessary “Rebuild all.”
  • Resharper is great, but I’ve found it uses a lot of IDE resources and increases the risk of freezes. Unless you have plenty of memory (like, 8GB or more) at your disposal, consider turning it off.
  • Disconnect from the Internet when you need to focus on what you’re doing.
14
Feb

Team Foundation Server is the Lotus Notes of version control tools

tl;dr: Advocates of Team Foundation Server, Microsoft’s ALM suite, respond to criticism by saying that TFS is not just source control but an end-to-end integrated ALM suite. This completely misses the point of our criticism of TFS in the first place: that we find it restrictive, bureaucratic, unreliable, and extremely difficult to use. End to end integration does not justify unreliability or a poor user experience.

About a year ago, Martin Fowler conducted a survey of ThoughtWorks developers to find out what they thought about various source control tools. Not surprisingly, Git came out top. The one that came out bottom? Team Foundation Server. In fact, TFS was unique in getting no positive responses at all: out of 54 respondents who had used it, every single one of them rated it as either “problematic” or “dangerous.”

Team Foundation Server advocates claim it’s unfair to compare TFS to other source control tools, since it’s not just source control, but an integrated end-to-end application lifecycle management solution. Comparing TFS to, say, Subversion, is like comparing Microsoft Office to Notepad, so they say.

Now where have I heard something like that before? Oh yes, Lotus Notes:

The main focus for frustration is Notes’s odd way with email, and its unintuitive interface. But to complain about that is to miss the point, says Ben Rose, founder and leader of the UK Notes User Group (www.lnug.org.uk). He’s a Notes administrator, for “a large automotive group”.

“It’s regarded by many as an email program, but it’s actually groupware,” Rose explains. “It does do email, and calendaring, but can host discussion forums, and the collaboration can extend to long-distance reporting. It will integrate at the back end with huge systems. It’s extremely powerful.”

The thing is, it wasn’t the detractors who were missing the point. It was the Lotus Notes guys. You see, e-mail is right at the heart of any groupware application. It’s the part of the application that users interact with the most. It’s where usability matters the most. And it’s what Notes got wrong the most.

It’s exactly the same with ALM tools. Source control is the part of your ALM tool that is most visible to developers. It’s source control rather than, say, work item tracking or continuous integration, that can make or break your workflow. It is source control where a zero-friction experience is most important.

Team Foundation Server is not zero-friction. Not by a long shot.

I guess if you have only ever used TFS, Visual SourceSafe, and perhaps exclusively trunk-based development in merge-paranoid Subversion teams that use if statements and configuration settings to avoid branching, you would be happy enough with it, since that’s all that you know source control to be capable of. But once you’ve actually used one of the alternatives that offers you fluent, unrestricted branching and merging, a local sandbox, flexible workflows, self-consistent best practices, and source control as an extension of your undo button, the limitations of TFS become so massive that it’s not even funny any more. (Incidentally, if you tot up the figures in Fowler’s survey, you’ll find that his respondents had, on average, experience with six different tools.)

But even if you’ve never used a DVCS and are only comparing it to Subversion, it’s still a usability disaster. Subversion may have pitfalls and gotchas and limitations of its own, but once you know your way around it, you can at least work as fluently with it as is possible with a primarily trunk-based, centralised tool. In TFS, even the simplest tasks become Herculean undertakings. How do you back out a changeset that isn’t the latest, for instance? Why can’t I have a check-in screen that shows only the files that have actually changed since my last commit? Why does it take me half a dozen mouse clicks for each file in my check-in screen to find out that it doesn’t have any changes? Why is it asking me to check in files that don’t have any changes in the first place? Why does it turn Visual Studio into a Berlin Wall around my code with these awful read-only files? Why does it lobotomise the branching and merging experience with baseless merges, making feature branches — pretty much a must-have for a pain-free ALM experience these days — impractical for all but the largest tasks? Why can’t it cache my login credentials to a server on a different domain like Subversion does? Why does the command line interface bring up dialog boxes? Is it a command line interface or isn’t it? And that’s barely scratching the surface of its usability problems. It doesn’t even have a search tool to speak of.

Furthermore, the source control component is the one part of TFS that you can’t swap out for something else. You can use TFS source control with Trac, Mantis, FogBugz or Jira, or with TeamCity or FinalBuilder, but you can’t use TFS work items or TFS build servers with Subversion, or Git, or Mercurial. As far as TFS is concerned, source control is their way or the highway.

End-to-end integration is all very well, but it is hardly a killer feature, and when the most visible component that it integrates is difficult to use and gets in the way, it ceases to be an asset and it becomes a liability. It’s far better to have a selection of separate tools, each of which is designed to do its job well, than a single monolithic application that does everything badly.

09
Dec

How to host WCF services in ASP.NET applications without bloating your web.config

If you add a WCF service to a web project in Visual Studio, it will dump a whole lot of garbage in your web.config file to make it work. If you want to keep your web.config file slim and clean (and you should), there is an alternative. You can of course create the services programmatically in a console application, but how do you do it in a web application?

Simply open the .svc file itself (not the .svc.cs codebehind file) in a text editor (you can right-click on the file and choose “Edit markup” on the context menu), and add the following attribute to the <%@ServiceHost %> tag:

Factory="System.ServiceModel.Activation.WebServiceHostFactory"

This will give you something like this:

<%@ ServiceHost
    Language="C#" Debug="true"
    Service="My.Wcf.Service"
    CodeBehind="Service.svc.cs"
    Factory="System.ServiceModel.Activation.WebServiceHostFactory"
%>

You can then remove all the extraneous cruft that Visual Studio adds to the <system.serviceModel> section in your web.config, thereby keeping it cleaner and more manageable.

10
May

Introductory videos on IOC containers

Dependency injection is one of those concepts in computer programming that looks weird and complex when you don’t understand it, but once you do, you wonder how you managed without it. A bit like distributed source control. Unfortunately, if you don’t understand it properly and implement it incorrectly, you can end up losing the benefits of it and end up wondering, “What was the point?”

For developers new to the concept, David Hayden has a series of video tutorials that provide what’s probably the best introduction to it that I’ve come across. He uses Microsoft’s Unity Container for most of his examples, but the concepts can easily be adapted for other libraries such as Ninject, Autofac, or Castle Windsor. He explains in some detail how to use them properly within both ASP.NET and WebForms, and demonstrates what kind of things they can achieve:

26
Mar

On web deployment

Scott Hanselman says that if you’re using XCopy for deploying web applications, you’re doing it wrong. He is talking, of course, about the web deployment features of Visual Studio 2010, which constitute Microsoft’s attempts to solve a problem that is a lot less trivial than it looks.

It’s a bit of a strong statement, and I’m not sure that I agree with it. For the past four years or so, I’ve used a variant of XCopy deployment that I’ve found to be very effective. I put each release of the website into a separate folder, numbered after the version reported by Subversion, Mercurial, CruiseControl or TeamCity, depending on which of the above I’m using, and I just switch the directory in IIS, or on Linux it’s just a case of changing a symlink. This all but eliminates downtime for the vast majority of upgrades, as well as allowing you to roll back in seconds to any previous version that you still have available if things go pear shaped.

I’d like to see how Web Deploy handles upgrades like this. My experience of software upgrades is that they are rarely that seamless and usually involve several seconds of downtime, though having said that, if your website is so busy that half a minute of downtime is a serious problem, the chances are that you have failover servers that you can bring in while you upgrade.

A more serious issue, however, is rollback. Some of the sites I work on are pretty high profile, and the ability to roll back in seconds if things don’t work out is a deal breaker as far as I’m concerned. That’s why I’ve found the XCopy/IIS settings switchover approach to be such a winner.

I am not impressed with the approach that Visual Studio 2010 adopts to managing web.config files, however. This approach sets your connection strings etc at build time, which can be pretty painful since you have to have different builds for development, integration, test, production and so on, and once you start branching and merging, and have to have separate connection strings for separate branches, it can completely blow up in your face if you’re not careful. No, configuration is a deployment time operation and needs to be treated as such. The best place for your configuration settings is outside your application root, in a common location easily accessible to every version of your site.

Finally, one last tip. Never deploy on a Friday. There are two reasons for this: first, it’s the end of the week, you’re tired, you just want to go home, and you’re much more likely to make a mistake than on a Monday when you’re fresh. Second, if something does go wrong, it will really, really, really ruin your weekend.

23
Mar

NAnt and MSBuild are completely pointless

I mentioned this in passing in a recent blog entry, and I thought I’d expand on it a bit.

I do not like NAnt.

I do not like MSBuild either.

I’ve used both of them, and quite frankly, I don’t see the point of either of them. To be sure, MSBuild allows you to build Visual Studio solutions from the command line, but that’s MSBuild the program. MSBuild the language, on the other hand, is a completely, utterly pointless reinvention of NAnt, which itself is probably the most completely, utterly pointless domain specific language in widespread use that I’ve ever come across.

Neither language does anything that you can’t do in Python. In fact, most of the time, Python does it better, with a cleaner syntax because it isn’t XML-based. XML is fine for some things, but the foundation for a scripting language is not one of them. When you’re using XML as the basis for your scripting language, you’re getting dangerously into “all you have is a hammer, so everything looks like a nail” territory.

Besides, neither of them are used anywhere for anything other than writing build scripts. If you use Python, at least you can leverage your knowledge for other domains, such as web development, game development, OS scripting, and much, much more.

I say Python here purely because I happen to know it. There are other decent, popular, multi-purpose languages that you can use to write build scripts. There’s no reason why you can’t use Ruby, or PowerShell, or even good old fashioned batch files, for instance. But having to learn and use a fiddly, awkward new language solely for the purpose of setting up or changing your build scripts—something that you only do relatively infrequently—simply doesn’t make sense.

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.