Tuesday, January 27, 2009

Making sure that your application is disposing of any unwanted resources has always been part of the ugly plumbing work of writing software.  Although .NET "helps" with this - by providing a non-deterministic Garbage Collector - it can actually muddy the waters a little.  Now, instead of having to implement a Destructor in each class, most of the time you can let the framework deal with it. 

The tricky part - and the reason I'm writing this blog - is remembering the specific scenarios when you need to, and when the framework will take over.

The general guidance is that you only need to implement IDisposable when dealing with unmanaged resources.  This is because the framework has no way of tracking this, and you need to do it yourself.  However, there are other scenarios where you might need more control.

A specific scenario would be if we had a class which had hooked into events provided by a global static or singleton class.  This singleton would likely not be disposed of until the application is shut-down (although obviously every case is different).  Because the delegate keeps a reference to our class, it would keep it alive until the singleton is disposed.  It is highly likely we want to free our class before this.  Whether we do this as part of implementing the IDisposable pattern, or use Init() and Unit() methods, is still up for debate.

In the following scenario, only ListForm and NavBarControl is required to implement IDisposable (because it is a Form):

Because this is a self-contained object graph, once we free our reference from ListForm, the GC will be able to free all the objects within this graph.

HOWEVER, if, say, ListFormController were to hook up an event handler to an object outwith this graph, then we would be in trouble - because it would not be freed and therefore keep it's referenced items alive.

You can find out more about the IDisposable pattern here.

 

Tuesday, January 27, 2009 12:24:23 PM (GMT Standard Time, UTC+00:00) | Comments [1] | c# | Patterns#
Wednesday, January 21, 2009

If you're ever having trouble with Assembly binding failures, then the Fusion log can help to resolve the problem.

Check out this blog for more information.

Wednesday, January 21, 2009 9:17:21 PM (GMT Standard Time, UTC+00:00) | Comments [0] | c##
Thursday, January 08, 2009

Our new project is off and running, but we have hit a few snags.  Before we get too alarmed, it is important to remember that it is Sprint 1, and if ever you're going to hit problems this is the time to do it, so they are sorted out by the end of the project.  Incidentally, this is what I see as one of Agile's best features - because each sprint is considered a mini-project in its own right, we get the chance to stand back and assess the situation before moving to the next phase of the project, rather than just ploughing on and hoping for the best.

Towards the end of this sprint, the burn-down seems to have flatlined - for every hour of work that seems to get done, someone experiences a problem elsewhere which causes production to seize up. 

My own analysis of the situation is just that there were too many unknowns at the beginning, and the tasks identified at the beginning of the sprint quickly became out-dated.  This can happen on any sprint, but normally it would only affect one area - this time it seemed to affect the majority of task lists and that's why it's had such a dramatic effect. 

What are the unknowns? 

For me, it's three things:

  1. Developers being assigned to domains and/or codebases they are not familiar with.  Although there is some documentation available, it is easy to forget how complex the current system has become, even at a conceptual level.  Sometimes with the resources available then putting developers in unfamiliar areas can't be avoided - besides, learning is always a part of this job.
  2. Unfamiliarity with new third party controls or tools.  Until you have looked at the control documentation in-depth and played around with it in your sandbox, you can only take a real guess as to how you would accomplish something with it, and therefore hazard an estimate.   Some controls might implement the entire feature just by calling a method, in others something you would EXPECT to be there, just isn't.  We tend to ask A LOT of our third-party controls, rarely do we find it acceptable to use just out-the-box, so this sometimes requires communication with the vendor support teams.
  3. Software Development in general.  I don't think there's anything we can do about this.  It happens.  People will make the odd mistake - underestimating, overestimating, perhaps identifying the wrong approach to a problem.  The only thing you can do is learn from it and move on.

What are we going to do about it?

Well, if you want a highly accurate result then before we estimate ANYTHING, we should have a good, firm understanding of EXACTLY what you'll be doing over the next 3 weeks.  For this, you'd need to design the components and complete any prototyping - effectively implementing the feature - before this would be achieved.  This also is trapped in BDUF world, as opposed to the flexible, feature-driven delivery of the agile paradigm.

Personally, I don't think this is the way to go.  In fact, there are a couple (or more) arguments out there that question the usefulness of task level estimation full stop.  I'm not sure if I'd go that far, although it is an interesting argument.

My own proposal is one that I half-introduced in my last task breakdown, but didn't have the conviction to stick to it, although it made an appearance again in the retrospective.  The basic idea is that you identify as many tasks as you can that you're confident of, and estimate these as normal.  For those areas that you're unsure of - be it the domain, an area that you know will require significant design/architecture, or even familiarisation with a third-party control or codebase - then there should be two 'types' of task identified: Investigation & Implementation.

Investigation tasks are brief descriptions of work that you're just unsure of, for example "Investigate how to bind Control X to data", or "Investigate how to use this new tool" or "Investigate the refactoring approach I need to take".  An estimate is provided for these. 

The Implementation task is a traditional rough guess, probably based on the story points assigned, of how long you think it would take to implement the feature.  A rough guess.  This differs from normal breakdown estimates as you aren't identifying the tasks yet, and people should expect this estimate to be high-risk.

During the sprint, when the investigation tasks have been completed, the developer should then be at a stage where they have a much better idea what is going on.  'Proper' Tasks can then be identified, which take the place of the Implementation placeholder.  In addition, further Investigation tasks may be identified at this stage, and the cycle continues.

A Brief Example

In the above example, we start with an Investigation task at 7 hours and an Implementation task estimated at 14.  Once the first Investigation has been completed, Tasks 1, 2 and 3 will be identified and estimated with some degree of certainty, where Task 3 is another Investigation task from which Task 4 and 5 will be identified at a later stage.  As you can see, the first Implementation estimate had delivery of the feature within 14 hours - but the reality is it took at least 4 + 7 + 3 + 4 + 2 = 20.  A third more than the initial estimate. 

This gives the SCRUM-master (and other stakeholders) a much clearer visibility into the state of the sprint.  They can tell at-a-glance where the 'red-flag' areas are, and have confidence that when the implementation phase begins there are no more 'brick-walls' where a developer can lose days without realising it.

Honesty really is the best policy, even if sometimes the truth hurts.

But with this approach, how is time-boxing possible?

Calculating the exact number of tasks to fit into any given sprint isn't going to happen.  The estimates will either be under or over - the key here is to be agile.  With this approach, I would propose that no more than 50% of the tasks on the sprint should be Must-Haves - this allows us breathing space by letting tasks of a lesser priority slide to the next sprint, if necessary.  50% may seem like a large margin, but the rule of thumb for planning is always to double your initial estimates (and the very worst case scenario is that if a developer finishes early then the sprint can be ended or more work added from the backlog)

 

 

This approach also has the advantage that sprint turn-arounds are much quicker - you really shouldn't spend more than an hour or so planning for a 2 or 3-week sprint. 

Based on experience, I'm fairly confident the above approach could resolve a lot of the estimation and task identification issues that we have from time-to-time.  The important thing is that we have realised this early, and taking action to resolve it.

Thursday, January 08, 2009 7:17:53 PM (GMT Standard Time, UTC+00:00) | Comments [0] | Agile#
Tuesday, January 06, 2009

It takes a while to get going after the holidays, but once I had dusted the mince pie crumbs from the thinking cap it was business time.

As you may be aware from previous posts, I'm a regular user of the various flavours of the MVC pattern (MVC, MVP, Supervising Presenter etc.  I'll just refer to it as MVC from now on, even though the exact pattern I'm using may not be that).  The software might take a little longer to construct, but this will pay back in maintainability, testability, legibility and other -bilities.  

The task for today was to apply a user-defined 'mask' over a datasource that was bound to a grid.  In this specific case, we apply the mask to the grid instead of the datasource, but the principles would be the same if our requirements were to modify the datasource in some way.

We have 3 MVC-triads involved, and the associations between which (and classes) are illustrated below:

 

The 'Super' triad, shown in green, is where it will begin.  The Window will receive the click event to show the Top N dialog, which will notify the WindowController.  The WindowController will then create the concrete TopN View (the dialog), passing this into the TopNController.

When the user clicks the 'Apply' button on the Top N dialog, this will communicate the specified values to the TopNController, which will then modify the PivotViewDef.  Note: The PivotViewDef is stored by the Document, and bound to the GridView by the GridController on instantiation.  We use a simple Observer pattern for this, which means that whenever PivotViewDef is modified, we broadcast this change to any interested parties, which can then take action.

Therefore when the PivotViewDef is modified, it will automatically refresh the GridView.

This is a clean and elegant design, as it removes any logic from the forms.  The inter-dependencies between the various components are also limited, which reduces the complexity.  And because the TopNController only communicates to the view via an interface, it is inherently unit-testable.

 

 

 

 

Tuesday, January 06, 2009 8:46:42 PM (GMT Standard Time, UTC+00:00) | Comments [0] | c# | Patterns | TDD#
Search
Archive
Links
Categories
Admin Login
Sign In
Blogroll