The Danger of Assumptions

Just spent an hour trying to work out why the resources in my "en-GB" satellite assembly weren't being loaded, but instead I was getting the default "es" resources.  Of course, the problem was my assumption that my login had "en-GB" as its culture.  Turns out I was actually running as "en-US".  "en-US" != "en-GB", and there was no "en" fallback, so the Resource Manager, quite correctly, went for the default.

Grr.  Note to self:  Don't make assumptions. Check the basic things first. 

Assumptions.  The mother of all f**k ups.

Weekly digest of interesting stuff

My regular Friday slot for this seems to have gone completely awry these last couple of weeks.  Normal service may be resumed at some point.  Anyhow, here's the list of things that have caught my eye over the last few days:

  • For those doing MVC stuff, or for fans of Thomas the Tank Engine, a good post on the dangers of Fat Controllers.  Ok, it's not so good if you're just a fan of Thomas.  Sorry.
  • Some interesting stats for solid state drives for standard development tasks.
  • Another post on MGrammer
  • A clear description of the Single Responsibility Principle.  If you don't get this, stop coding and read stuff until it makes sense.  Seriously.
  • This one I like.  It's discussing the purpose of value stream maps, but I think it applies to a number of the activities that are undertaken during development. 
  • Code coverage.  Why 100% is a false safety net.  But do take note of the very last sentence - having a line covered doesn't mean it's properly tested, but having a line not covered for sure means that it's not been tested at all.  I tend to aim for around 80% coverage - getting more than that can start getting hard with extremely contrived test setups, and just because I get to 100% doesn't mean the job is done.  The lines that don't get covered tend to be extreme edge cases, which should be reviewed.
  • Design and testability - worth a read.  My take is that no amount of testing will make up for poor design skills, and that just writing tests won't necessarily make you a good designer.  I think that's also what Jeremy is trying to say, he just used a lot more words :)
  • This could be a first - a digest post that references another digest post.  All worth a read for anyone struggling to adopt or explain Agile. 
  • OpenCL goes to version 1.0.  It'll be interesting to see what comes of this, and in particular whether Microsoft will join the party or not.
  • For anyone interested in F#, here a good post showing some transliterations from C#.  As the author says, doing transliterations between different languages is not necessarily a good thing, but it does have its place.

What's interesting at the moment is the number of posts on design - the basic principles that are needed to develop good software are having a resurgence, which can only be a good thing.  All the new shiny technologies that are out there don't help much if you start out with a poor design.

On Agile

Following a couple of other posts relating to agile (here & here), I thought I'd give my thoughts on the subject. 

There are numerous books and posts on the subject of Agile - searching for "Agile Development" on Google gives well over 1 million hits.  As someone who is hugely interested in how to improve software development, I've read a good deal of material on the subject (although, being fair, it would only be a fraction of a percent of those Google hits!).  What I've found very interesting is the number of different opinions as to what Agile means - it's pretty hard to find two books on the subject that agree on a definition of the term.

One thing that is for sure - Agile (whatever definition you may have) is no silver bullet.  Just being "Agile" does not guarantee success.  It does not guarantee the early delivery of rock-solid software to delirious customers. It does not guarantee that your staff will become highly motivated software ninjas overnight. Given that, what's all the fuss about?  The fuss is that previous software methodologies have got a woeful delivery record.  I'm not going to quote some specific number here, since there are a ton of research articles available which give differing statistics depending on exactly what is defined as failure.  However, the general range is anything from 30% - 85%.  Even if you take the best number there, it's clearly an unacceptable state for a multi-billion dollar industry.

Given the lack of consistency for what Agile means, and given the proliferation of processes that claim to be Agile (XP, SCRUM, Crystal etc.), what is the best way for you to move forward?  Alas, I don't have a silver bullet here either.  The best I can do is describe the process that I have gone through to get this stuff clear in my head.

The first step is to clearly understand what the key requirements are for your business.  Ignore software, ignore the process, just focus on what matters to the business.  For me, I came up with a single overriding principal:

To make a decent, long term, sustainable profit

I'm guessing that's not particularly contentious - any business for which that isn't a key principal is unlikely to last long.  However on it's own that's not really enough.  So I then pondered what aspects of the business would best support the primary principal.  This gave the following, in no particular order:

  • To create solutions that give the customer the solution that he needs, when he needs it, and at a cost he is happy with
    • Happy customers mean repeat business and referrals, which are the best and most profitable form of sales. Plus I'd much rather be working with a customer who's happy rather than one who's not.

  • To have control over the costs and timescales for each customer project
    • Not having control means that the customer doesn't know how much he is paying or when he's going to receive the goods.  Given that the software is probably only a part of a bigger project, the timescales in particular are critical - without confidence on delivery dates, how is the customer meant to schedule other aspects of the wider project such as training, marketing, manufacturing etc?  In addition, if we don't know when projects are due to complete it makes it very hard to commit to start dates new customers.

  • To have a motivated, skilled team that share the same values
    • Motivated staff take care and pride in their work, which gives rich rewards in terms of the quality of the product.  They also tend to enjoy their work which reduces expensive staff turnover, and just makes the workplace a more enjoyable place to spend what amounts to a significant percentage of your life.

 

From this, I could then extract the aspect of Agile from the mass of books that I've read to provide, in effect, the essence.  These are the areas that I consider important, and why:

  • Accept and embrace change.
    • Anyone who thinks that they can prevent change from occurring during a project of any size is, quite frankly, living on another planet.  Accept that change is essential to enable the software to meet the needs of the customer, and adopt a process that makes change as painless as possible.  The change may be requirements, it may be technical, it may be staffing, but whatever it is, it's going to happen.
  • Develop in short iterations.
    • There's a load of important things about the iterative approach, so I'll expand on this below.
  • Don't attempt up-front detailed design
    • Again, there's lots of empirical evidence that this doesn't provide any benefit.  By all means, do up front high-level architectural design - indeed, for the key structural aspects of the project (scalability, security, disaster recovery etc.), this is pretty much essential; getting those wrong or trying to reverse them into an existing code base can be very expensive and not something the "right click / refactor" is going to help with.  But the low level stuff is best done with the compiler.
  • Make sure that testing is a first class citizen
    • Testing should being as soon as coding begins (indeed, if you want to do TDD, then it starts before the coding).  As far as possible, make the tests automated so that you can frequently run the full test suite.  It's inevitable (regardless of whether you attempt up-front detailed design or not) that, at times, you'll need to refactor parts of the code base to support new functionality.  At times like this, a large test suite gives a great safety net.  In addition, the tests (if well written) also act as a form of executable (and hence up to date) documentation.  Finally, and most importantly, testing as early as possible tends to promote a testable code base and gets quality in there from day one. 
  • Empower your team to use their brains.
    • If you've any sense, you spend a lot of time recruiting the very best staff.  Recognize that, and let them shine.  If they are committed to the business, then trust them to make sane choices and don't try to micro-manage tem.  If they're not committed to the business, politely but firmly point them in the direction of the door.

Expanding on iterations, I think the following aspects are essential:

  • At the start of an iteration, plan in detail what you are going to achieve.  For that plan to have any teeth, it is essential that changes are not allowed during an iteration.  For this reason, iterations should also not be too long - my experience suggests that between 2 and 4 weeks works well.
  • During the iteration planning, ensure that the tasks being worked on are the most important to the project at this moment in time.  Don't do the trivial stuff whilst there are important things to be done (important can either be those items that give most business value, or those items that present the most technical risk)
  • At the end of each iteration, deliver demonstrable, working software.  This keeps the team focused and gives a clear view of progress to date.  In addition if, god forbid, you fail to complete all the development tasks you will at least have a system that the customer could take.  And, since you worked in priority order, it should include most of the stuff that the customer considers important.  Telling the customer that you're not finished is never an easy conversation, but "We're not done, we estimate that we're about 80% of the way there, but here's a system in which all of the following function is complete and ready to go" is a much better chat than "We're not done, we estimate that we're about 80% of the way there.  Sorry, but there's nothing you can take yet because until we've done the other 20% nothing will work"
  • At the end of each iteration, tasks are either done or not done.  It's notoriously hard to determine how much work is left on a task when it's not yet complete (how often have you heard the phrase "it's 80% done", only to then find it takes another 100% of the elapsed time so far to finish?).  In addition, done needs to be done.  Code written, all functionality complete, all tests written and passing.  Anything less is not done, and should hence be deferred to a future iteration.
  • At the end of each iteration, evaluate what has gone well and what has gone badly.   Do more of the good things, and make changes to prevent the bad things from happening again.  I have seen a number of teams running iterations who recognize that they are not getting things done as quickly as they need, and whose response is "ok, we recognize that things aren't going well.  We'll try harder in the next iteration".  Trying harder at something that isn't working is unlikely to yield the results that you want.
  • Don't queue up bugs.  The tasks that you've worked on to date are, by definition, the most important ones.  Bugs mean that they are not finished.  Fix the bugs.  If you don't, then at the end of the project you'll have a pile of important stuff that's not done.  The customer is not going to like that.

The key thing that I've observed with well-run iterations is that they tend to surface problems early in the project.  Pain is going to happen (what - you really think that nothing will go wrong?), and Early Pain is considerably more desirable than Late Pain.  Early Pain means that there's time to take corrective action. Late Pain is what kills projects.

Those are the things that I see as the essence of agile - it's not rocket science, it's just working smarter.  It's understanding that change happens, and making sure that you can handle it.  It's understanding that things go wrong, and making sure that they can be spotted and fixed as early as possible.  It's understanding that you have a hugely talented team, and using them.  It's no silver bullet though.

What else can I add?  Well, there are a few things that spring to mind:

  • Requirements - up-front or iteratively?
  • Contracts - fixed price or T&M?
  • What methodology?  SCRUM?  XP?  Lean?
  • We're not Agile, but want to be - how do we change?
  • My customer doesn't want Agile - what are my options?

This has been a pretty long post, so although I've got things to say on those, I'll leave them for another day.

As a final remark, all of the above is just my opinion.  I've intentionally not put in references to books etc. - for each reference I find that says one thing, I've no doubt you can find a reference that says the opposite.  Such is the nature of our imprecise world.  I hope, however, that this does give some food for thought, and perhaps helps you through your own thought processes around how (or indeed if) to adopt Agile.

I would certainly appreciate any comments that folk might have...

Weekly digest of interesting stuff

 

  • For those remote workers, here's a useful TFS proxy.
  • 2 posts here and here on how to handle large models in Entity Framework. This is an area that's pretty week right now, and hopefully will get improvements in V2.
  • Another post related to the code contracts in .Net 4.0, and how they play with TDD.
  • Martin Fowler on the gradual emergence of non-relational databases.  This is an interesting area, particularly with the emerging cloud OSs - the core data stores that these make available tend to be non-relational since scaling a relational model across a cloud is a challenging problem, to say the least.
  • Another post from Rico on VS2010, this one focuses hard on the new WPF editor, which has raised a lot of "interest".
  • These guys need a course in UI design.  Really, this is just a peach. No idea if the app is any good; judging from the main screen, I don't think I'd be smart enough to use it.
  • And one more from Rico - this time, it's a Channel 9 video on VS2010.  I've been snowed under this last week, so no idea if it's worth watching or not :)
Weekly digest of interesting stuff

A relatively quiet week:

  • Contracts in .Net 4.0

  • A whole pile of stuff about Silverlight 2.0, most of which you probably know already, plus some sniipets of info about Silverlight 3.0

  • Another great post from Mark Russinovich, this time on virtual memory

  • Rico Mariani on VS2010. And he should know what he's talking about, being the Chief Architect. One of Rico's passions is performance, so let's hope he brings a good deal of that to Visual Studio :)

  • REPL loops in C#. You've really got to be interested in this sort of thing to bother following the link, but for those twisted folk out there, here it is.

  • A glimpse of the plans for N-Tier Entity Framework

  • Finally. A good, clear explanation of Oslo. The first half is, imho, spectacularly good.
Weekly digest of interesting stuff

It's been quite a week, certainly as far as things that interest me go:

  • A much under-rated app - here's the low-down on the new Calculator in Windows 7. Now, don't mock, it's actually rather good!
  • A load of posts on Azure (no surprise there!):
    • ASP.NET MVC on Azure. It's all good stuff - I'm current using the AspProviders that this article talks about, but in conjunction with WCF REST rather than ASP.NET MVC. They work real well, except for one little detail around getting HTTP 401 errors returned back to the client. More on that in a later post...
    • Links to useful sites in the Azure community.
    • How to retrieve the logs from your Azure services. This will be essential if you're doing anything more than trivial stuff! I'm guessing (hoping!) that at some point features like log viewing will be available through the developer portal.
    • A good intro to the Table Services part of Azure
  • M has been getting a whole pile of traffic this week. Here are the good bits:
    • A neat M grammar for modeling user stories. Even if you're not interested in M, it's worth reading since there is great value in this approach to gathering requirements.
    • Generating code using M and T4. This is really in depth - I think it's fair to say that the language that he generates code from is of limited us, but the approach would be applicable to any DSL that you care to put together.
    • Writing WPF using M. Of course, it's only a toy language, but it sure is cool.
    • Consuming MGrammar output from C#. Suspect this is how most of us will use it for some time.
    • The complexity in language design, and how M doesn't really change that. This link is the response - be sure to click the Frans Bourma link to see the original point (although be prepared to have your Compiler Design course from college come back and haunt you!)
    • MrEPL. Lots of stuff is starting to do the old REPL thing again, brings back happy memories of BBC BASIC :)

Weekly digest of interesting stuff

This should have been sent last Friday, but other stuff got the better of me. Anyhow, here's last weeks "interesting stuff":

  • The reason why we have iterations: Early Pain

  • An example of a simple TODO language implemented in Mg. For those use to parsers, BNFs etc, this will be an easy read. For those that haven't come across such things, it's a nice introduction.

  • How SanDisk's ExtremeFFS works. Bets on how long it is before Joe gets one :)

  • A nice summary of PDC. Thanks, John - saves me writing it!

  • Access to the ETW APIs from .Net using NTrace. Not used it yet, but suspect this is worth keeping an eye on.

  • A new TFS Power Tools release. Surprised that Obama got quite so much press coverage considering that this came out the same week.

  • Code Contracts in C# (well, any .Net language in fact). It's due out with .Net 4.0, but it also looks like it works with VS2008. Getting into the habit of declaring the intent of your code in this way can only be a good thing - it helps out with documentation, static analysis, runtime checks and gives Pex something to get its teeth into.

  • A good reality check on some of the hype going on about Oslo right now.

  • Hadi is twittering. Hell has also frozen over.

  • For those of you with a media center and an iPhone / iPod touch, this is cool. I've been running it for a week or so (before this review came out), and although at $6 it's one of the most expensive iPhone apps I've bought, it's a load cheaper than the wireless mouse / keyboard that I would have bought otherwise.

  • Should we put comments in our code? Neal Ford has shares his views here - not sure I entirely agree with him, but I do respect his opinion and it's hard to refute his reasoning. Some of the comments are pretty decent, so it's worth reading the whole page.

Weekly digest of interesting stuff

This one is about 2 weeks late due to my trip to PDC.  Some of the "interesting" things from the week prior to PDC have been superseded by announcements made since then, so this is probably shorter than normal...

Live from PDC: Dublin

Just come out of a Dublin talk, and I've got to say that I'm very impressed.  Dublin is a set of extensions to Windows Server / IIS to improve the ability to host and manage WCF and WF services.  It's initial release is planned to be a web download, and should come out sometime soon after Visual Studio 2010.

So what's new?  Once I get time to run the samples I'll go into some of this in more detail, but for now here are the highlights:

  • Basic statistics available on Completed, In Progress and Suspended (i.e., in error) workflows
  • Additional tracking information available to keep detailed information on a workflow instance
    • From this, can see exactly why a suspended workflow is in that state, which will help no end in problem diagnosis
  • Ability to resume workflows from the suspended state
  • A new forwarding service that can perform routing and filtering of inbound requests to specific endpoints
  • A worflow instance restart service that automatically resumes orphaned workflows
  • Additional scalability features
  • And everything can be programmatically accessed via PowerShell cmdlets

Now none of this is rocket science, and indeed much of it could (and has been) be done by hand.  However, it's tedious to keep writing such plumbing code, and it's of very little (apparent) value to the end customer.  It's great to see stuff like this making it into the base products.

Live from PDC: C# 4.0
Just been to the excellent talk from Anders on the new features coming in C# 4.0, plus a glimpse of the stuff coming further in the future. I’ll try to get some samples up over the next couple of days, but for now here’s a brief summary of the key features.

The main focus for C# 4.0 is on Dynamic features. This largely means some great interop with some of the newer .Net language implementations, such as IronPython or IronRuby, plus improved interop with COM, which will come as a great relief to anyone who regularly talks to the Word or Excel object models.

The way in which this has been done is with a new static type, called “dynamic” (lots of laughs in the room about that!). A type declared as dynamic is of type System.Object, but with an additional attribute that causes dynamic dispatch at runtime to properties, methods etc - i.e., you’re not restricted to the normal 4 methods that are on System.Object (ToString() etc), but can instead call anything you like. Of course, if at runtime the underlying type doesn’t implement the property / method that you call, then they’ll be a runtime exception thrown. And equally, there’s no intellisense support for dynamic types - no surprise there, since without the static typing, intellisense is somewhat harder to implement. Usage looks like this:

dynamic calc = GetCalculator();// Statically typed to be dynamic
int sum = calc.Add(10, 20);// Dynamic invocation with dynamic result conversion

where GetCalculator() could be returning a Ruby object or a javascript object (or, indeed, a regular C# object, although in that scenario you’d probably be best off keeping the static type information!).

In addition, there´s an interface called IDynamicObject that allows you to create a regular C# object that gets dynamic behavior, such as the ability to add properties and methods at runtime. Once I get the CTP running (hopefully tomorrow), I’ll get a sample of this up and running. It will open up a whole new way of doing certain things in C# that would be very difficult to achieve today. It’ll also open up a whole new way of making your applications completely unmaintainable, but I don’t see that as a bad point, just a good reason to continue to use good software practices in your developments.

Another new area is named and optional parameters. This will help out when calling methods that have a large number of parameters, and finally gets C# something that VB has had for some time. Next new one is Co- and Contra- variance of generic types. Again, once I’ve got the CTP I’ll do a couple of samples that show the syntax, but essentially this now lets you do things like:

void Main()
{
IEnumerable<employee> employees = GetEmployees();
DisplayPeople(employees);
}

void DisplayPeople(IEnumerable<people> people)
{
// Do the display logic
}

Lovely! Being able to cast the IEnumerable variable is going to be so useful.

And finally, one snippet from the future. Currently, the C# compiler is written in native code, which limits the ability to make use of it from within C#. In particular, there’s no particularly clean way to create an Eval method today, but there are a number of places where being able to do so would be extremely useful. Well, MS are currently re-writing the compiler in C#, and whilst doing so are making it’s functionality available as an API. This opens up the ability to do Eval properly, provides new ways for doing dynamic code generation, and news ways for tooling or runtimes to perform inspection and modification of the abstract syntax trees during the compilation process. All very cool, let’s just hope it’s not too long before we can get our hands on it!