Showing posts with label question. Show all posts
Showing posts with label question. Show all posts

Monday, November 12, 2007

To Estimate or Not To Estimate

I have recently been spending a lot of time with two different "project management" applications: FogBugz and Team Foundation Server. FogBugz originally attracted my attention because I read Joel Spolsky's blog, Joel on Software, and he's the CEO of Fog Creek Software which makes FogBugz. TFS attracted my attention because it includes a new Source Control system which is a-w-a-y better than Visual Source Safe. I have been evaluating these products and trying to figure out which I'd rather use, its a harder task than it sounds.

The new version of FogBugz, 6.0, mainly consists of Evidence Based Scheduling. I have to be totally honest and say that EBS is not only very cool but makes total sense and I believe it would totally work. However it requires two things: 1) time tracking and 2) work item estimates.

Joel Spolsky recommends keeping your estimates under 16 hours, anything longer than that doesn't stand a chance of being accurate. That means you need a lot of very detailed tasks entered in the system (ex: develop function foo). Once you have estimates at this level you can start to get good predictions of when you'll ship AND you can start to pick and choose what tasks you want to do based on how much time you have left.

TFS doesn't really have any scheduling. It has Remaining Work and Completed Work fields (but only on the Task work item type, not on the Bug work item type...), but no reporting, no nice views, and no nice way to enter time (you have to subtract from the remaining work field manually when you add Completed Work...). The TFS developers seem unconvinced that estimating work at the level Joel recommends is at all worth while. Witness these articles on the Teams WIT Tools blog.

Personally I think estimating how long a task will take is a great idea. I think creating a list of tasks at that detailed level would not only help a developer think through what they're going to do before they dive into it but also help them get an idea of "where they're at" with all their work. I think it would make managing work loads a lot easier too. Not to mention the fact that the ship date estimates would make it possible for you to determine when your initial "blind" estimates were wrong or when scope creep is starting to get the best of you.

My question for all of you is, what do you do at your work? It doesn't even have to be programming work. Do you estimate work? At the detailed task level, or at a more abstract level? Is it helpful? And if you don't estimate work, do you wish you did?

UPDATE: I've posted a follow up post, Managing Projects

Wednesday, October 10, 2007

Where is UserControl.Text?

Creating UserControls is a very simple process from a high level. But as usual, the devil is in the details. Recently I was going through many of our controls here at work when I noticed that they were all using the “new” keyword to override the BackColor and Text properties. Somehow we’d managed to get by without this causing any problems until now. To correct this I had to override the OnBackColorChanged and OnTextChanged virtual methods.

After this was done I noticed that the Text property was no longer visible in intellisense for any of our UserControls. After looking closer at the object model I learned that UserControl inherits from Control which contains the Text property. So how come I couldn’t see the Text property? You can’t remove properties through inheritance.

It turns out there is a special designer attribute called System.ComponentModel.EditorBrowsableAttribute. This attribute can be placed on a property or method to determine change the visibility of that property or method in the designer. The possible visibility values (EditorBrowsableState) are Never, Advanced, and Always.

UserControl marks the Text property with EditorBrowsable( EditorBrowsableState.Never ).

I have no idea why Microsoft did this. I imagine there is some strange way of thinking which makes it make sense, but I haven’t figured it out yet.

To work around this, I had to override the Text property on a base class that all of our UserControls inherit from. Fortunately we already had a base class, otherwise I would have been forced to create one just so we could use the Text property correctly.

And for the record, yes, the Text property can be overridden. Why was it using the “new” keyword in the first place you ask? I don’t know. I think because whoever wrote the controls just didn’t know it was a virtual property.

Monday, September 3, 2007

How to Handle Control Events?

Object Oriented Programming is awesome. And it is no less awesome when working with User Interfaces. In fact, I find it can be amazingly helpful when you're dealing with a complicated UI that has many interacting components.

I'm going to make a up a really simple UI that has some interacting components so I have an example to work through. Say you have a grid on the left which displays a bunch of records, one per row. When a record is selected it displays the details of that record in a bunch of fields to the right of the grid. This is just your typical master/detail type of view.

One last thing to add. If the user changes one of the details, we want to visually indicate that the record has changed in the grid by adding a '*' at the beginning of the record name.

An OO approach to this might be to make the grid a custom user control and the details pane another custom user control. This allows us to abstract all the logic for managing each component into a separate object. That way its not scattered all over the Form class. I have done this in two different ways and I'm not sure which I prefer yet. For example, with the grid, sometimes I have done this by creating a control that inherits from the grid. Other times I have created a separate class whose constructor requires a grid. And other times I've created a UserControl that wraps the control and exposes the features I need. I really don't know which approach I prefer at this point.

But the title of this post is Handling Control Events, and I haven't talked about events at all yet, so lets get into that. To detect that the user has made a change to the details of a record we're going to have to register a ValueChanged event of some sort on each control in the details pane. We'll do this in the details pane user control. Then when any of those events fire we'll cause our user control to fire its own ValueChanged event. To add the '*' we'll simply have our form hook into the detail pane's ValueChanged event and call a method on our grid control to tell it to mark the selected record changed. Very simple.

But what happens when the user selects a record and we fill in all the detail controls? The value changed event of each control will fire, and our detail pane's ValueChanged event will fire multiple times, and we'll put the '*' on the record's name. But the user didn't actually change the record's details, they just loaded it.

How do we get around this? How do we handle control events? We need a way to tell the difference between the user interacting with the detail controls and us programmatically interacting with the detail controls. I know of three ways to handle this:
  1. Add a "suppress flag" which when true causes the detail pane's ValueChanged event NOT to fire. Set the suppress flag before doing something in code, then unset it when finished.
  2. Remove the events before doing something in code so they don't fire at all, then add them back when finished. This prevents the detail pane's ValueChanged from firing.
  3. Add a CausedBy parameter to the detail pane's ValueChanged event which indicates what caused the change, User or Program. Then the person consuming the event can decide how to deal with it.
Personally, I always go with the first method: suppress flags. This example is trivially simple (and yet I've seen many programmers have problems with it), but when the UIs get more components and more ways to interact these suppress flags can start to get out of control. Unfortunately, I don't know of another way to handle this very common problem.

Do you guys run into these situations?

Wednesday, August 1, 2007

Is WinForms DataBinding currently in progress?

I've recently been looking into WinForms DataBinding. We have an in house databinding solution that we use, but it is vary narrow in scope, so I wanted to learn how WinForms does it.

I started with an example where I have a very simple user control with 5 or 6 fields (combo boxes, text boxes). I wanted to bind these fields to data from a .NET class which has properties which exactly match the fields I'm displaying. Using WinForms databinding to accomplish this was startlingly easy. But then I hit a snag.

I've registered the ValueChanged event on all my controls (These are in house controls which implement an interface so they all have a ValueChanged. For the most part, all it does is forward the TextChanged and SelectedValueChanged events) and hooked it up to a single event handler. When this event handler fires I enable a "reset" link. Thus if the user changes any of the values, they can click reset to put the values back as they were.

The snag is that when the data binding initially loads the controls, the value changed events fire and I enable my reset link. But when its the data binding that has caused my value changed event to fire, I don't want to enabled the reset link. In other words, I need to know if the data binding caused the value changed or if a user editing the field caused the value changed.

Ideally, I'd like to be able to write something like this:

void Fields_ValueChanged( object sender, EventArgs e )
{
if ( !bindingSource.IsUpdatingControls )
resetLink.Enabled = true;
}


Unfortunately for me, nothing like this seems to exist. And even more infuriating, I can't find anyone else complaining about this on the web...

Now from what I've read I understand that if you're using data binding you're not supposed to depend on the controls. Instead you're supposed to use the object that contains your data. This is for MVC purposes apparently. This means: don't use the control's ValueChanged event. But this doesn't work in my case for 3 reasons: 1) I don't need two way binding here, so my underlying data object shouldn't even get updated. 2) To use two way binding I'd have to change the update mode to OnPropertyChanged instead of OnValidation, which I just don't want to have to do. 3) From an MVC perspective, this is View logic which should remain in the View layer and not be dependent on what update mode the underlying data binding is using.

Am I missing something huge here? Is there any way to do this? Or do I have to abandon WinForms data binding? Seems like such a silly thing to force me to write the binding code manually.

Tuesday, July 17, 2007

Shared Assemblies, Components, and Applications

Here's the situation:
You have a shared assembly which contains a lot of useful utilities called SharedAssembly.dll

You create a customized component that uses SharedAssembly.dll called ComponentA.dll

You create a full application which uses SharedAssembly.dll and ComponentA.dll called App1.exe

In VS2005 you setup your solution to include all the projects: App1, ComponentA, and SharedAssembly. You setup the references as Project references. Now, when you build the solution, VS figures out it needs to build SharedAssembly first, then ComponentA, then App1. The end result is App1 and ComponentA both use the same version of SharedAssembly. This is wonderful.

But what if you wanted to change it so that ComponentA wasn't included as a project in the solution file? Instead you want to release ComponentA as dll files that can simply be referenced by App1. The problem is that you now have two different versions of SharedAssembly.dll. If you set it up this way you'll get a runtime error because the framework detects that the version of SharedAssembly.dll is not what was expected by ComponentA.dll. Is there any way to get a setup like this working?

I want ComponentA to be like its own little mini-application, with its own versions of dlls, completely independent from App1.

My mind is immediately drawn to Java's jar files, but I don't really know how they work.

I've tried a little utility from MS Research called ILMerge which takes a set of dlls and combines them into a single dll. However, this didn't work. An exception was thrown at run time when the second SharedAssembly namespace was encountered.

I also tried installing the dlls in the GAC. However, it turns out you can't reference a dll in the GAC from Visual Studio: "This is because the GAC does not have full support for all design-time pieces of an assembly -- while you have access to the DLL itself, you will not have access to PDB symbols nor XML documentation files." (link)

Any ideas?

Wednesday, May 9, 2007

Blob performance concerns

Maybe someone can help me answer this question. I originally wrote about this on 3/2/2006 but never really found a good answer.

Suppose you are writing a program in C# that uses SQL Server 2005 and you'd like to store some files as Blobs (Binary Large OBjectS) in the database.

This is a very simple thing to do. Take the bytes, send them to SQL Server 2005 where you store them in a varbinary(max) column.

The code for this in C# looks like:

FileStream fs = new FileStream( "file" );
byte[] buff = new byte[fs.Length];
fs.Read( buff, 0, fs.Length );

SqlCommand sc = new SqlCommand(...);
sc.Parameters.Add( ...buff... );


My concern is that this code is going to read the entire file into memory. Then its going to send all that memory to SQL server in one shot. If this is a sufficiently large file I'd expect there to be problems on both the client and the server because of this.

If the client is somewhat lacking for memory, or if the file is really large, then I'd expect this code to cause a lot of disk paging. Possibly even paging out the beginning of the file you just read from disk to make room for the end of the file, just to turn around and page out the end of the file to make room for the beginning so it can send those bytes to SQL. I'm not clear such a thing could ever actually happen, but I do suspect some paging will occur.

What I'd really like to do is specify a stream as the parameter instead of a byte array. That way I could trust the driver was only loading a portion of the full file into a buffer at a time. It seems the JDBC driver supports this, but the SqlClient driver for ADO.NET doesn't.

So my questions are, am I blowing this way out of proportion? Is there a better way to insert a Blob in SQL from C#? Why does no one else on the internet address this concern?

Partly because of this problem, along with some other performance concerns, I ended up storing the files on a shared file server instead of as Blobs in SQL. This allowed to me to handle the transfer myself using the typical buffered approach.