Wednesday, April 23, 2008

Bug Reports

It turns out many people really struggle with writing bug reports. What I'm going to recommend here is exactly the same thing you'll find in the Joel on Software article, Painless Bug Tracking.

What I've found is if you go to someone and say, "What's the bug?", they'll have no problem describing it to you. But when they write the bug report, it comes out all confusing.

The difference is when I asked them "What's the bug?", they were happy to describe the bug to me. But when I ask them to report it, they feel like they need to tell me what the bug IS. Subtle difference, but it has a large effect. The result is typically a mangled sentence or two about how something didn't work. But it doesn't clearly tell me what they were doing or what they expected or even in what way it didn't work. Its like they are suddenly afraid to give me the context in which they found the bug.

So how do you write a bug report?
Just tell me these three things:
  1. Steps to reproduce the bug
  2. What should have happened
  3. What happened instead
  4. Provide extra details (exception text, error message screen shot, stack trace, etc)
The fun part about this is for many people they will save both time AND keystrokes reporting bugs this way because they no longer have to stress about "How do I communicate this bug?!"

For example,
1. Go to this form
2. Click on the "S'Okay" button
Error box should pop up, but instead the app crashes.

Crash report: blah blah blah blah blah...

You can use this method to report any kind of bug, you will save yourself time writing it, and you will save time trying to figure out what the bug is and how to fix it. Everyone wins, everyone is happy.

Sunday, April 6, 2008

TFS Source Control

The source control system that comes with TFS is pretty good. It's absolutely fantastic when compared with Visual Source Safe (what was so Visual about it anyway?).

It has "Path Space Branching," meaning you can create branches by creating new folders. It follows the Checkout, Edit, Merge pattern by default, meaning many developers can work on the same file at the same time (no locks). It integrates beautifully with Visual Studio, and all of its dialogs and wizards are really straight forward and intuitive.

That said, it is not without its issues...

Anyone who has ever tried to organize a branching strategy for an office of developers knows that branches add complexity, and complexity adds confusion, and confusion slows stuff down. On the other hand, the isolation that branches provide can make life much easier for individuals and individual teams as well as the whole office. This is mainly because you can focus on developing new stuff and not worry about breaking other people or integrating you changes until you're done. Sounds minor, but its a huge help.

However, once you're using branches in this way, you're making the majority of your changes on the "development" branches and then merging back to the "public" branches when you want to release your changes. Enter TFS issue #1.

Merges result in a single changeset, they do not reproduce all the changesets made on the source branch on the target branch.

This means, if you have 5 changesets on your dev branch, with associated checkin comments, and work item associations, and user identification, NONE of that information will appear on the target branch. So when you're trying to figure out:
  1. Who made this change?
  2. When did this change?
  3. What has changed recently?
you. are. screwed.

In my opinion, this is so severe it almost makes branches in TFS completely worthless.

But wait, there's more! TFS has branches, and TFS integrates really well with Visual Studio, but its not as perfect as it seems...

Using branches can screw up your project and solution files

It all looks like it should work well. You've got your references set up as project references. You branch everything and the relative paths are all setup the same (..\..\myproject). And yet, somehow VS still gets confused. You start getting errors where the version numbers arn't right. Or it wants to check out all your project and solution files. It's terribly annoying.

And what happens if the relative paths arn't the same? In the branching environment we've setup this happens in some scenarios because branch our project's shared dependencies into the same directory as the main project to isolate the project from all outside changes. When you do this, you have to completely rebuild your project references and solution files because VS gets confused. This isn't the end of the world, but it is a huge annoyance.

It also means, any time you perform a merge, you have to merge the project files by hand because VS will think there are changes (the relative paths) even though there aren't any real changes.

Ready for the next issue?

There is no simple way to rollback a changeset.

The TFS power tools comes with a rollback command, but it's command line only and it's not terribly easy to use (since you need to know the changeset numbers). The absence of this feature in the GUI proper just makes no sense. This is one of those features people always use to sell why you should be using a Version Control system, and TFS doesn't even have it.

I should stop and mention that these are the downsides. The rest of the Version Control that I've used is really great. Workspaces are cool, though only moderately useful. And Shelves are a decent concept, though again, only moderately useful.

The funny part about branching is that when you learn about distributed source control systems, your first reaction is, that would never work, and your second reaction is, that's perfect! Many of the problems you were trying to solve with branching just go away and get replaced with simple communication problems. As in, you have to tell other people when they should pull from you and that kind of thing. However, there are no distributed systems that I currently know of that integrate with Visual Studio like TFS's source control does, nor that are nearly as user friendly. However, I would still encourage you to check them out as it will give you a whole new perspective on versioning.

Thursday, March 27, 2008

Powershell Rename with Regex

I had a little more fun with Powershell today and I thought I'd share.

I used Visual Studio to generate a bunch of SQL Scripts into a Database Project. (In Server Explorer, right click -> Generate Create Script To Project).

This is very slick and works wonderfully. Only thing I didn't like is it puts the database name at the front of the file name:
Database.Schema.Objectname.SQL

I'm creating this project because I know I'm going to be executing these scripts against many databases, so I don't want the database in the name. I couldn't find a way to configure VS so it would generate the scripts with different names, so I'm stuck with them. That being the case, how do I easily rename all the files?

Powershell to the rescue!
dir | rename-item -newName { $_.Name -replace '^Database.', '' }

This command will rename every file in the current directory, removing the "Database." prefix from the name (if it has one).

You can use the shorthand version of the command and parameters as well:
dir | ren -new { $_ -replace '^Database.', '' }


I'm just so happy to finally have a powerful command line in Windows.

Tuesday, March 25, 2008

MVC and MVP

In two previous posts I discussed the Model View Controller pattern and the various flavors of it: MVC is What Exactly? and MVC in Windows Applications.

In this posts I presented my understanding of MVC that I had gained from various books, articles, blogs, and thought experiments. Shortly after I encountered the term MVP: Model View Presenter. Then I found some articles that described passive MVC differently than I had described it. Then I found some articles about PAC: Presentation Abastraction Control.

In short, I discovered that there doesn't seem to be one definitive definition of MVC, nor of MVP.

From what I can tell, MVP is just MVC where the Controller is allowed to do more work. In that regard, it is more similar to what I described in my posts on MVC. I have also seen arguments that the way I described Passive MVC is actually MVP.

In the end all the issues I discussed then still apply. I just wanted to clarify that this area of design is full of lots of slightly different ways of accomplishing the same goal, and everyone seems to use a different word to describe it.

Update 9/11/2008: Follow up post on MVC and MVP with more details

Friday, March 21, 2008

Varbinary and Service Broker, a story

Today I was working on a very simple SQL 2005 Service Broker service. It was to work like this: someone executes a stored procedure passing in some meta data and a varbinary(max) which contains a document. The stored procedure inserts a record into the database with the meta data, then builds a service broker message containing the varbinary and some other required information. A windows service is monitoring the service broker queue for messages. When one arrives it parses it out and creates a file out of the bytes.

This took me about an hour to get through this morning (I already had written a nice service broker library, which is why it was so easy). However, I spent the rest of the day fighting with setup, data types, and encodings.

Problem #1: Windows installer service can't start. Error 193: 0xc1

A very helpful error message which popped up immediately after I tried to start my service. It was clear the OnStart method was never invoked. Apparently this error can be caused by a random "program" file in C:\ on occasion. In my case that wasn't the problem.

Nope, my case was much dumber than that. C# Services, like most programs, require a main method, usually in a program.cs file, to execute. I didn't have one because I started with the visual studio class library template instead of the windows service template... Once I realized what was missing this was easy to fix. But realizing it took longer than you might think.

Problem #2: Invalid XML Document (1, 256)

It turns out that when you define a SqlCommand and setup a bunch of Parameters on it and you tell the parameter that its length is 256, it's actually going to truncate anything you pass into it to 256 characters... In this case, my xml message was longer than that. Duh.

Problem #3: Invalid XML Document (1, 1)

This one is weird and I can not explain it. Say you create an XML variable in SQL and use it as your service broker message like so:
declare @msgX XML
Then in C# you define the message_body parameter as an nvarchar(max). The types are mismatched, but we know XML is just a string, so everything should be just fine, right?

Wrong. I don't know why. But the string you get out will have some random byte as the first byte. If you print it to the Windows Event Log it will look like a little box. This byte causes C#'s XML parser to blow up. If you change the SqlCommand parameter to XML(max) (so the data types match) the byte goes away...

Problem #4: Encoding the varbinary data into XML from SQL

You can't build your xml message just by concatenating strings together if you're dealing with varbinary. You can't cast the varbinary variable to a string either. What you need to do is encode the varbinary. In SQL, the easiest way to do this is:
declare @encoded xml
set @encoded = ( SELECT @varbinary FOR XML, TYPE )
This will automatically encode your binary into base 64 text.

Problem #5: Decoding the varbinary out of the XML in .NET

It took me awhile to find the right way to do this. At first I was trying to use the static Encoding class like
Encoding.Unicode.GetBytes( encodedData );
But this was just giving me the encoded string back.

Finally I found the right way to do it:
byte[] b = Convert.FromBase64String( encodedData );


Moral of the Story or What I learned:
Debugging Windows Services is hard. You have to print messages to the Event Log to figure out what is going on. And every time you make a change you have to: uninstall the service, rebuild the solution, rebuild the setup file, reinstall the service, go to computer management services, set the Run As permissions on the service, start the service, and check the event log to be sure it started correctly. THEN you can do whatever you need to test it.

This takes time. And it sucks.

So what I learned is, take the time to build a test, or refactor the code, or copy and paste the code if you have to. Even though you think, "oh! I just have to do this and it will work" take the time. Cause it's not going to work after you do that. And then you're going to have to do it all again. So just create a nice little testing environment for yourself. Its a one time expense, and then everything will go much faster from there. You'll be much happier, and if you're lucky, you wont have to spend all day debugging something that had basically been done at 11am.

Wednesday, March 19, 2008

IoC and DI

Inversion of Control Containers and Dependency Injection.

A coworker of mine gave me an MSDN article called Loosen Up which goes over Dependency Inversion, Dependency Injection, Inversion of Control containers, and 3rd party IoC tools. It's an excellent article, I highly recommend it.

In an early post I talked about Dependency Injection and referred to it as a slippery slope. I still feel this way to some extent, but its the only way to do good unit testing, so we're stuck with it.

First I want to point out something obvious I got from that article that I hadn't thought of somehow. In Dependency Injection I mentioned how my classes defaulted their dependencies in the constructor and used Properties to allow different instances to be passed in.

This sucks for two reasons:
  1. If someone does actually pass in a different instance of a dependency, the default will have been newed up for nothing
  2. There are ton of properties on the object that it is likely no one will ever use
What's the obvious way to fix this? Create a constructor that takes in the dependencies. Create a default constructor that calls the other constructor:
public LessStupidClass( depA, depB, depC ) {...}
public LessStupidClass() : this( new depA(), new depB(), new depC() ) {...}
Solves both the problems of the stupid way I was doing it.

On to IoC. The idea behind Inversion of Control Containers is basically that you don't like the fact that the class has a way of specifying its default dependencies. You'd rather have the class lookup what its defaults should be in a "Container of Default Dependencies" that has been pre-configured. This can easily be done by performing the lookup based on the interface type of the dependency. The third party tools (like Spring.NET and Castle Windsor) take this even further and allow you to setup the default dependencies in configuration files.

That's the idea at least. Personally, I'm not a fan. I can see how this might be useful if you actually anticipated swapping in different dependencies frequently, or even at all. However, I'm just doing it so I can unit test. So introducing this container layer just makes it harder for me to figure out what the hell is going on in my code. Its bad enough depending on an interface because I can't "right click -> go to definition" any more. And it only gets worse when you move it into a configuration file...

Maybe I'm missing something here. If so, please let me know. But as far as I can tell, for the ways in which I've been using dependency injection, in which there is only 1 concrete dependency class and there is likely only going to be one, EVER, IoC just adds unneeded complexity. It moves the stuff I need to know further away from the places where I need to know it.

And it "centralizes" my dependencies... In my experience, "centralizing" things is only good when it makes sense that everyone share from the same source. It doesn't make sense to centralize when you're either A) forcing things to match that otherwise wouldn't have to match or B) moving things away from where they are used just so they can be "centered." Centralizing also has the unwanted side effect of causing things to get all tangled together. Now that everyone is sharing the same thing, defined in the same place, I have to be really careful about changing that thing... Because if I change it, it will change everywhere, even if I didn't know everywhere it was used.

Aside: Sometimes you want things to be centralized. But make sure you REALLY want it before doing it. Like consistency, it's not a good idea in and of itself.

UPDATE 6/27/08: for more on complexity, read this followup post

Monday, March 17, 2008

Demoing

When you're in the business of creating software, demoing your software is very important. If you're in a consulting type of business, then its even more important.

In college, I had the opportunity to give a number of presentations on some research I was doing at conferences. The research involved Mobile Agents, Evolutionary Computation, and Swarm Programming. Obviously, the audience was mostly professors and graduate students. I absolutely loved giving those presentations, and apparently it showed. After I gave a talk on Swarm the chair of the session came up to me and said he really wished his students could have been there to see it, not only because they were playing with swarm too, but because he'd been trying to tell them that research presentations could be fun.

I also had to give a couple of really stupid presentations in my Marking and Management classes. Both of these were completely devoid of any kind of meaningful content. They were just an exercise in... well, who knows. Fortunately, I got lucky and did pretty well. In fact, in both courses the teachers actually told the class that what I had done was what they were looking for from everyone. I actually found this horribly embarrassing. I still tastefully rubbed it in my friends' faces of course, but still.

Now, I didn't put any kind of special effort into those presentations. My slides didn't have animations and sound or funny jokes. In fact, I put about the minimum amount of effort into those slides as I possibly could. No one would call them pretty. So that certainly wasn't why it was "fun." I also didn't practice what I would say, I didn't work on any clever phrases. All I did was create a basic outline of what I would talk about, and then turn that into slides. Then I went and gave the talk.

Turns out the reason why I was getting such good responses was simply because of enthusiasm. I learned this from my research presentations, where the enthusiasm was genuine, and applied it to my business presentations, where it was totally contrived. All I did was:
  1. Behave a little less formally than everyone else
  2. Allow myself to get excited about the exciting parts
  3. Explain things from the bottom up (so people wouldn't get confused)
And that was it. All this positive feedback had me thinking I was really good at this stuff. And then I started working full time and I had to start giving software demos to relatively non-technical users.

Suddenly, my 3 steps to success didn't work anymore. Behaving less formally (which for me translates into acting somewhat silly) still got people's attention, but it didn't translate into them understanding or enjoying what I was demoing. Getting excited actually seemed to just cause them to get confused (and it wasn't because I started to talk fast, or about things that were only exciting to me either!). And I couldn't explain from the bottom up, because the audience didn't care about the software bits, and I wasn't involved in the business analysis so I couldn't talk about the why very well.

Finally, I realized there were a couple other factors that had contributed to why my college presentations went over well, and none of them had anything to do with what I was doing:
  • I had an interested and invested audience
  • The audience was knowledgeable about my topic
In the research presentations, everyone was smarter than me to start with, and what I was working on wasn't really complicated, it was more just fun. So they paid attention and played along.

In the business presentations, the other students didn't give a damn what I was talking about, but the professors did. The professors paid attention and played along.

Now, in these demos, the users really just don't care. You'd think they would... After all, its their software. But they don't. So they get distracted by any little thing and they can't follow the thread of what you're trying to demo to them. You'll say a word, which causes them to think of something, and they'll ask about that thing, even though its completely unrelated to the day's demo, but since they're the client you'll try to answer it, and during your answer they'll think of something else, so you'll have to try to answer that...

It's like a program with an infinite number of nested function calls, you never manage to return all the way up the call stack. And even if you did, no one would remember what was going on before the call.

Also, my demo audience members don't really relate well to computers. Its not that they get confused easily, and its certainly not that they're stupid. Its more that they're just nervous they're going to get confused I think. So as soon they start to slip, even a little bit, they seem to give up and stop following.

So the difference is the audience. I still believe that my enthusiasm mixed with the slightly silly relaxed style will work. What needs to change is the way the demo is presented. So here are the guidelines I've worked out that have had good results so far:
  1. Start every demo with a picture or flow chart of the overall process you're about to perform in the software
    1. This will help avoid questions like, "When will we do this?" "I'm going to show you that next."
    2. This will help avoid some of the side tracks as well, because everyone knows what we're trying to show
  2. When you first open a screen, start slowly describing what's on it
    1. This will give people an opportunity to read it and and try to figure it out for themselves, which they will do even if you try to dive it to explaining it
  3. Before you do anything (click anything), say what you're about to do
    1. "Now I'm going to add a new Employee"
  4. When you're doing it, repeat what you're doing
    1. "I'm going to click "New" *click* to do that"
  5. After you've done it, describe what happened
    1. "I can now type in the information about my new Employee"
  6. If you don't feel like a broken record you're doing it wrong
    1. Your audience doesn't know the software like you do, so it wont feel as repetitive to them
  7. Make sure you don't sound like you're insulting their intelligence, this is mostly a tone of voice issue
  8. If one person gets lost or confused, they could start seriously side tracking everyone else, so don't let anyone get lost
Has anyone else out there had these kinds of experiences?

Friday, March 7, 2008

To Empower or Restrict

Software Developers frequently work on things that will affect other people. It could be as simple as the behavior of your application, or an API other developers will use, or a standard on how to do something either in code or in practice.

There are two ways to approach these kinds of activities:
  1. Attempt to empower the people your work will affect
  2. Attempt to restrict the people your work will affect
Obviously, given the terminology I'm using, I think empowering is better. By empower I mean give flexibility, simplicity, and in general, leave room for people to use their brains and do what is right for them.

By restrict I mean force everyone to do everything exactly one way. Restricting has its benefits. It will have a much smaller learning curve. It will keep everyone consistent. It will frequently work very well for the one thing it was designed for.

"Obviously a small learning curve is good!" exclaims Joe Q Designer. Everyone recognizes this, especially Joe. But in this case, Joe is getting a small learning curve because he's eliminated (restricted) many options and abilities. Clearly, you'll learn faster if you have less to learn. But Mr. Designer has traded flexibility for ease of learning. Unless J.D. has been both very careful and very lucky, this will come back to bite him in the end when someone needs to do something slightly different. Even though its only slightly different, Joe wont be able to accommodate it.

"I'll handle the slightly different cases as they arise. In the meantime, at least everyone is consistent!" Yes, Joe. But is this just consistency for the sake of consistency? Where Joe sees consistency, I usually see lost flexibility. Unless Joe can show a real benefit of the consistency, it's just a cop out.

"Well, I still think consistency is good. Plus, look at how little work has to be done with my solution to accomplish <a>!" Joe protests. I must say, I like how simply your solution handles <a> Joe. Who doesn't like simple solutions? I'm just concerned that <b>, <c>, and <d> are ridiculously hard now! If we'd made your solution less restrictive, <b>, <c>, and <d> would be easier. <a> would be a bit harder, it's true, but everything would be easier on average! Plus, when <e> comes along, we might actually be able to accommodate it.

I think its usually better to err on the side of empowering people rather than restricting them. And I definitely think its better to have a mindset of empowering people when you're designing things that will affect other people.

Don't get me wrong. You have to draw the line somewhere. You'll always be restricting something. Otherwise we'd all just give our clients C compilers and say, "off you go!" It's really a question of degrees and of what's important.

For example, if you know the users who will be using your system have no experience with computers, you're going to want to make things really simple. Like, iPod simple. However, your product is going to be better if your mindset is one of empowering, not restricting. It's not that I'm removing features because my user is stupid. I'm designing the set of features my users will most benefit from in a way that they will understand and enjoy. The guy who is thinking the second way is going to make a much better iPod than the guy thinking the first way.

So, Joe Q Designer, please stop trying to restrict everyone and start empowering us. We'll all love you for it.

Monday, March 3, 2008

#if DEBUG

C# allows you to use various Preprocessor Directives (the things with the # in front of them).

One of these is #if, and there is a DEBUG symbol you can use to determine if the program is currently running in debug mode or release mode. In general, using this is an awful awful thing to do. Why would you want to modify the behavior of your application when it was in debug mode vs. release mode?

Well, you might want to do this if you needed to add some code in debug mode to make debugging easier for yourself. But I can't imagine a case where you would want to use it to actually change the behavior of your application.

Why? Do you really need me to tell you why? Okay, fine. Its because now you can't trust debug mode. Any testing you perform in debug mode no longer applies to release mode. You might as well never run the app in debug mode, its a complete waste of your time.

"Surely you're overstating the issue!" protests John Q Programmer. "Like, what if I wanted to throw an exception if something was misconfigured or misused, but I only wanted it to blow up in Debug mode. In release mode, I don't want the application to blow up!"

Not wanting the application to blow up in release is very noble of you, John. I commend you. You are truly wise beyond your years. But I'm assuming you, Mr. Programmer, are throwing the exception because something has gone wrong. NOT throwing the exception in release mode is not going to change the fact that something has gone wrong. In fact, it is likely to make it worse. J.Q.'s application may now be in an inconsistent state! There's no telling what might go wrong. John hasn't avoided a problem in his application. Far from it! He's just potentially made the problem 100% times worse.

So J.Q., please don't do that.

Now, if you really must use preprocessor directives for some reason, at least make sure you're VERY careful with them. It may look like an if statement, but it's not. It is literally changing what code the compiler gets to see. If the #if doesn't pass, it will be as though the lines of code within it never existed.

That means you can get some really nasty behavior if you're not careful:
if ( iNeedToDoSomething)
DoSomething();
else
#if DEBUG
DoSomethingElse();
#endif

DoTheMainThing();

See what's wrong with this?

If we are in debug mode, this code looks like:
if ( iNeedToDoSomething)
DoSomething();
else
DoSomethingElse();

DoTheMainThing();

If we are NOT in debug mode, this code looks like:
if ( iNeedToDoSomething)
DoSomething();
else
DoTheMainThing();

Holy crap! DoTheMainThing just got moved into the else! But only when we're not in debug mode.

To fix this you could simply add curly braces, but I think this example demonstrates how easy it is to get preprocessor directives messed up. And also why you should try just about anything to avoid using them.

Tuesday, February 26, 2008

Source Control Branching

Source Control systems have a number of purposes:
  1. Track every change made to the source
  2. Help multiple developers work together
  3. Help multiple teams work in parallel
Different source control systems are better at each of these. For example, Microsoft's Source Safe works fine for #1 and #2, but sucks at #3. This is because it doesn't really have branching support.

Microsoft's TFS, on the other hand, is quite good at all these things. It is every bit as nice as Subversion or Perforce or Vault. This is mainly because it has real branching.

However, unless your company consists of only 2 or 3 people you can't just start randomly branching things. You need a basic plan of some sort. A kind of branching strategy.

There are lots of resources out there that provide this kind of information. One of the best I have found, which is specific to TFS, is the Microsoft Team Foundation Server Branching Guidance. There have also been articles in the IEEE about branching, such as The Importance of Branching Models in SCM. And of course there are many blogs which touch on the subject such as Top 10 Tips On Version Control for Small Agile Software Teams.

All of these resources are helpful, but what they indicate is that what kind of branching strategy you use is really dependent on the structure of your organization. There does not seem to be a one size fits all method. For example, at Microsoft "Feature Teams" reign, and therefore Feature Branches are the way to go. At other big companies the development teams may not even be aware of the branching strategy. They just work in the environment provided for them and other people promote their changes for them. Its also possible that small teams have no need for branching at all.

What I find fascinating in all of this though is the lack of any discussion about Shared Components. I've talked about this in past posts like Two Versions of the Same Shared Assembly. In that series I was trying to find a way to support two different versions of an assembly in the same "Solution" at the same time. Ultimately I determined that there is just no solid way of doing this that is worth the effort.

Now I'd like to look at how having Shared Components affects a branching strategy. All the reference's I've linked to so far only consider a single project at a time. They don't talk about how a project's dependencies on other projects should be handled in source control.

Let's start by looking at what we want to gain from branching:
  1. Keep untested changes from being released
    1. To clients
    2. To dependent internal projects
  2. Allow projects to decide when to make changes available to other projects
  3. Allow projects to decide when to integrate changes from other projects
The first question: Should you depend on source (project references) or dlls?
The answer depends on your environment. If you need to be able to work on a dependent project and an application hand in hand, at the same time, you have to use source. If you want to be able to perform one step refactorings you also have to use source.

You might think that you could could switch between dlls and source as needed, but if you work out the details of this you'll see it doesn't work. Mainly because you end up working on a "release" source branch, which you shouldn't be making changes to.

So, if you have distinct teams that work on different projects with little overlap, you can probably reference dlls. But if you have people who work on a little of everything, you probably need to reference source.

The second question: What branching strategies should we consider?
  1. On Demand Application Isolation: Applications branch their code and all dependent code into a TEST or RELEASE folder when they want to isolate themselves, or "freeze" their dependencies. When they are not frozen they simple reference the since source control store of their dependencies.
  2. Team Promotion: Shared components do development work in a DEV branch and when the changes are ready for the wild they merge them into a PUBLIC branch. Applications reference their dependencies public branches.
  3. Team Promotion/Application Isolation: Combination of the other two. Applications reference their dependencies' PUBLIC branches. Then branch everything into TEST and RELEASE.
  4. Distributed Projects: Shared components have DEV and PUBLIC branches. Applications branch from PUBLIC into all of their branches, DEV, TEST, and RELEASE.
  5. Distributed Individuals: Use a source control system like Mercurial, or Git...
Of all of these Distributed Individuals is the most intriguing and flexible. However, it can't be done with a standard centralized source control store, so I have to disregard it for now.

Distributed Projects is the next most flexible. In this model Applications decide when to merge changes from the projects they depend on into their own branches of those projects. Then those applications push changes from DEV -> TEST -> RELEASES. The down side of this model is the huge number of branches and the long path to push changes from Module DEV -> Module PUBLIC -> App DEV -> App TEST -> App Releases and back the other way.

Because Distributed Projects has so much overhead I prefer the Team Promotion/Application Isolation model. This model is practically the same. It only differs in that the Application's DEV branch doesn't contain dependency branches. It references them directly. The downside of that is that the Application can't decide when to integrate changes from dependencies into DEV. However, it still decides when to integrate into TEST.

Note that all of these models would still take advantage of Feature Branches when it was helpful.

Hopefully this has made some sense to you... I was strongly tempted to create some diagrams to go along with all of this and make it easier to comprehend, but I simply didn't have time.

Do you work on projects that employ branching? Do you have to deal with shared components?

Thursday, February 21, 2008

Restore the Master Boot Record

When I got my laptop about 1.5 years ago one of the first things I did was install Linux on it. I can't remember now if I installed SUSE first, or went straight to Ubuntu. I'd been through Slackware, Debian, Suse, OpenSuse, SLED10, and Ubuntu in the past on other computers. In any event, I stopped with Ubuntu.

I've always had a few reasons for playing with linux
  1. To learn
  2. To feel cool, in a super nerd kind of way
  3. To not pay for software
Probably more or less in that order. My adventures with Linux ultimately ended with me deciding that I just wasn't that impressed. I wont go into the details here, because that is not what this post is about. The short list is:
  1. the file system is stupid (unless you're using GoboLinux),
  2. package managers are a double edged sword,
  3. the battery life on my Thinkpad in Linux sucked,
  4. it didn't have any apps that were far and away better than what I was using in Windows.
Keep in mind, I spent about 4 or 5 years coming to this conclusion, and I frequently still find myself drawn to the Open Source world. And for what it's worth, I don't personally view myself as a Microsoft fan boy. In any event, I retain the right to change my mind at any point and for any reason!

So I've had Ubuntu installed on my laptop, but I haven't used it in a year. Every now and then I would use it to pull songs off an iPod, that's about it. So it was just sitting there wasting 20Gb of my Hard Drive. This post is about how I removed it and restored the MBR. (really? you'd better get to the point then!)

Problem #1: Get rid of GRUB and replace it with the Windows boot loader

I'm pretty sure you do have to start here. If you remove the partitions first, GRUB will complain and refuse to let you boot into the remaining partitions... That happened to me once before, it wasn't nice.

How do you do this? It's easy, insert a Win XP disk and boot into the Recovery Console. Once there, execute fixmbr. When it warns you that "all hell will break loose, are you sure you know what you're doing?", tell it yes.

Problem #2: Umm... The Recovery Console wants an Administrator password. Leaving it blank doesn't work, and none of my passwords work... How do I get into the Recovery Console?

The first thing I tried was to go into Control Panel -> Performance and Maintenance -> Administrative Tools -> Computer Management -> Local Users and Groups -> Users. Once there, I right clicked on the Administrator and selected "Set Password..." then entered a password. Sadly, after rebooting back into the Recovery Console (and waiting forEVER while it loads...) it still wouldn't take my password.

So how do you fix it? Go back to Administrative Tools and this time go to Local Security Policy -> Local Policies -> Security Options. In the list, scroll to the bottom and find "Recovery Console: Allow automatic administrative logon." Double click and switch it to Enabled. Now you wont have to supply a password to get into the Recovery Console and you'll be good to go.

Problem #3: Remove the linux partitions and resize the windows partition.

I tried to use Partition Magic to do this, but it blew up with an error when I ran it, something about how some partition didn't have a drive letter. I think it was afraid of the IBM recovery partition.

How do you do this? I downloaded an Ubuntu install/live CD and used the gnome partition manager (gparted). First unlock the swap partition. This crashed gparted... But when I ran it again the unlock had succeeded, so everything seemed good. Then I deleted the swap and the linux partitions. Then I resized my windows data partition (fat32). Click Apply and go take a shower cause its gonna take a while.

After all that, I now have my drive space back and GRUB is gone. I still have two windows partitions C (ntfs) and D (fat32)... I wish I could convert D to ntfs but the only way I know to do that would be to copy all the data on D to some other drive, format D to ntfs, then copy all the data back. Maybe I'll do that when I get my backup solution in place. Actually, I'd like to get rid of D altogether. It made sense to have an applications partition and a data partition when I wasn't backing up my drive. But once I have a backup I'm not sure I still need two partitions.

How do you have your drive space setup?

Wednesday, February 20, 2008

.NET structs

.NET has structs and classes. Structs are allocated on the stack instead of the heap and can't participate in inheritance. However, because they're on the stack, they are faster. Check out this article on MSDN for some details, scroll down to the ValueType section. As it says there,
The flexibility afforded by objects comes at a small performance price. Heap-managed objects take more time to allocate, access, and update than stack-managed ones. This is why, for example, a struct in C++ much more efficient than an object. Of course, objects can do things that structs can't, and are far more versatile.

But sometimes you don't need all that flexibility. Sometimes you want something as simple as a struct, and you don't want to pay the performance cost. The CLR provides you with the ability to specify what is called a ValueType, and at compile time this is treated just like a struct. ValueTypes are managed by the stack, and provide you with all the speed of a struct. As expected, they also come with the limited flexibility of structs (there is no inheritance, for example). But for the instances where all you need is a struct, ValueTypes provide an incredible speed boost. More detailed information about ValueTypes, and the rest of the CLR type system, is available on the MSDN Library.

So, it would seem, if you found yourself doing some very C-like tree or list type of coding, you should use a struct instead of a class.

So it would seem. Unfortunately, it turns out this doesn't really work out so well for one very simple reason: structs are Value Types!

Take a look at these two code samples. I'll tell you in advance, the first one fails, the second one passes.
struct Node
{
public int Value;
public string DisplayValue;
}

void Test()
{
List l = new List();
Node n;
n.Value = 5;
n.DisplayValue = "display this";

l.Add( n );

n.DisplayValue = "Display This";

Debug.Assert( n.DisplayValue == l[0].DisplayValue );
}
That one fails.

class Node
{
public int Value;
public string DisplayValue;
}

void Test()
{
List l = new List();
Node n = new Node();
n.Value = 5;
n.DisplayValue = "display this";

l.Add( n );

n.DisplayValue = "Display This";

Debug.Assert( n.DisplayValue == l[0].DisplayValue );
}
That one passes.

The first one fails because "Display This" is not equal to "display this". That is, l[0].DisplayValue returned "display this", not "Display This" as you might have expected.

What went wrong? Its simple. Structs are value types. You passed your struct into the List's Add method as a parameter. Parameters are passed by value. Therefore value types get copied when they are passed as parameters. With reference types the underlying pointer is copied, but the object is not. Thus the first code sample copies the Node and the second code sample doesn't.

update: I had stacks and heaps backwards in the first paragraph... So I flipped them.

What you need is a pointer to the struct. But C# doesn't have pointers (well, not really), so you have to use classes instead. Because of this, I think you'll find that the utility of structs is pretty limited. That probably explains why you never see anybody using them.

Monday, February 18, 2008

The Elements of Design

In the world of software design, there are 3 distinct classes of "pattern" to be aware of:
  1. Smells
  2. Patterns
  3. Principles
The focus of each of these is primarily on enabling code to be changed and understood.

Smells are symptoms that are frequently demonstrated by code which has not been well designed. These are good to be aware of as they indicate you should probably consider doing something to fix the code so it doesn't smell so bad anymore.

Patterns are common OO design techniques for accomplishing certain behaviors. They were originally captured in the "Design Patterns" book by the "Gang of Four." These are very helpful, less for how they can improve your code, and more as a communication technique between developers. Personally I've found Singleton, Strategy/State, and Mediator to be the most far reaching. These are about as close as Computer Science has come to having terminology that can be used to describe abstract code design concepts. In general, you might fix a code smell with a Design Pattern.

Principles are a cross between smells and patterns except instead of telling you what is bad they tell you what is good, and instead of giving you precise designs to accomplish tasks they tell you what, in general, good looks like in Object Oriented languages. Of all of the three classes, Principles are probably the most useful because they describe design in general. Interestingly, they seem to be less known. Probably because they are both newer and slightly harder to understand. Of these, I have found the Single Responsibility Pattern and the Dependency Inversion Principle to be the most far reaching.

Thursday, February 14, 2008

Goz-Inta

I've referred to one of my college professors in past posts. He had a way of presenting lessons in simple packages. One of these was a word he used: Goz-Inta.

He said, "Many new programmers have the Goz-Inta problem, they don't know what should Goz-Inta what!" New programmers write programs that consist of one gigantic function. It doesn't occur to them that some of that code should goz-inta separate functions. They don't have any experience with reasoning about what should goz-inta what. And more than that, it doesn't even seem to be an important issue. After all, working programs is the most important thing, right? HA!

From the time that I emerged out of the "new programmer" phase, I have found that all the major problems of "Software Architecture" can be reduced to questions of Goz-Inta. People seem to progress through the following stages:
  1. 1 big function
  2. 1 big class
  3. 1 big assembly
  4. 1 source control branch (as in, no branches)
All of these can be expressed in terms of Goz-Inta.

And that's not all! Take a look at design smells/patterns/principles. What are they all doing? They're either describing symptoms of Goz-Inta mistakes, common Goz-Inta techniques, or big picture Goz-Inta concepts. GOZ-INTA.

Ever heard people say that its important to name your methods and classes well? That's because a good name helps the author remember what should and shouldn't goz-inta those methods and classes. A good name also helps people using the methods and classes understand what's gonez-inta them.

Why do I think that unit testing helps you design better code? Its because unit testing forces you to think about the Goz-Inta problem.

Furthermore, in my experience, the best programmers are the ones who are the best at working through the trade offs created by the Goz-Inta problem.

Thursday, February 7, 2008

"This is a Capacitor"

In college I took a Physics II course. I had been looking forward to that class since early High School. It was basically an introduction to circuits. I was eager to learn about resisters and capacitors and voltage and how circuits were built and designed. I thought I'd gain some knowledge that I'd be able to use in everyday life.

You wont be surprised to hear that I didn't gain any of that kind of knowledge. Sadly, I doubt I retained any knowledge from that course whatsoever. In truth, I barely made it through! Of course, it was one of those classes where a 60% test score can set the curve...

Anyway, there was one lesson in that class that I will never forget. The professor started class and turned to the board and said,
"This is a capacitor."

Then he wrote "C=Q/V" on the black board.

Yep, those 3 letters and 2 symbols are definitely a capacitor...

Now, maybe its just me, but when someone says "This is a capacitor," I sort of expect to glance up and see him holding one, or displaying a picture of one. I don't expect to see an equation. We never talked about what a capacitor DID, or why you might NEED one. In fact, it wasn't until I had a phone conversation with my dad that I learned a capacitor "stored charge". And I'm not even going to get into the fact that C=Q/V describes capacitance, which is a measurable quantity, and not a capacitor which is a physical device...

So what lesson did I learn from this? Different people learn and think in different ways. I'm a practical applied type of learner. That is, I need to understand and not just memorize. Thus giving me an equation or showing me a graph just isn't quite enough. I need to see steps and logic and explanation. In other words, I have to start from something I know and build up.

Other people certainly aren't this way. I've known lots of people who could simply see an equation and understand. I've known other people who could see an equation and then spit back and pass the class, but maybe not understand.

Fortunately for me, my learning style works great for computer science. Unfortunately for me, it's not how Math is taught. And only rarely how Physics is taught.

I've always believed that calculus and physics should be taught hand in hand. After all, the majority of calculus was developed trying to solve problems in physics. Add in a dash of History and you've got a thoroughly engrossing class in my opinion. But anyone who's been through college knows that isn't how its done most places.

Instead physics is taught with algebra, because the kids don't know calculus, even if they've taken it. And that means you have to memorize and spit back more equations for more circumstances. If it was calculus the number of equations would drop and the amount of logic to handle different circumstance would rise. Great for me! But again, not how its typically done.

Given all this, I guess I can't really blame my Physics II teacher. He was just teaching the way he thinks. Turns out a lot of people think and learn that way just fine. Even the Wikipedia article on Capacitance is written in much the same way. Of course, Wikipedia makes a distinction between a Capacitor and Capacitance and does a great job of describing Capacitors in English...

Still, I've never been convinced that people who were able to learn the equation and solve the "word problems" and ace the tests really understood any of it. Some of them did. But most of them? I find it hard to believe.

I have to end this by pointing out that there are certain topics to which my style of thinking and learning just doesn't help. Things like Quantum physics, for example. Where no matter how you look at it, you can't reduce it to common sense. In these circumstances you have to settle for memorizing the "way things are". Chemistry is like this. And yes, lots of Physics is like this too. But I still claim that after you've internalized the "way things are", you can start to reason logically about it.

Thursday, January 31, 2008

Objects vs SoC Objects

Object Oriented Programming rocks the house. The reason why it is good can be summed up with a single word: Abstraction.

I had an awesome professor in college who said that a person is only so smart. They can only keep so many things in their minds at one time and can only fully understand some of those already limited things. The only way, then, that a person can do anything complicated is to abstract out the details. This frees up more space in their limited heads for other things.

This is true. And because it's so enormously true I'm going to provide some examples of abstractions people use all the time.
  1. Language
  2. Money
  3. Time, Dates
  4. Math
  5. Physics
Language is certainly the most powerful example. I say "Dog" and you know what I mean. I could also say say "Golden Retriever." Or I could try not to be so abstract and say "Four legged animal with ears, eyes, tail, nose with extremely sensitive smell, hair all over, and isn't a cat." Of course, now I'm wrong, because there are Dogs that have no hair... So, obviously, language is a very powerful abstraction.

In computer programming, we have programming languages. "Modern" programming languages are typically considered modern because they allow more powerful abstractions. Object Orientation is one such abstraction. Though I'm not sure it really qualifies as "modern" anymore...

It's important that programming languages have good abstraction techniques. Software development is complicated. So for a person to do software development they must be able to abstract things. Its not enough to just abstract things on paper either. Things have to be abstracted in code. What are these things? Algorithms and data. That's about all there is in programming. You have data that has some meaning and you have algorithms that manipulate that data in meaningful ways.

Objects allow us to abstract both data and algorithms. Typically the algorithms are still quite detailed, but we can abstract the details into an object so we don't have to think about them. (Aside: Functional programming allows you to make your algorithms more abstract with fewer details.)

Objects let us abstract things by grouping a set of data and algorithms together into a single named container. And then it goes one step further and lets us create many instances of those containers. So now I can have a Dog object. And I can create many of them. And they can have names and colors and weights and heights and any other data they need. They can also bark and whine and soil the carpet and any other actions (algorithms) they need.

Objects also let us represent commonalities and relationships between things through fun words like inheritance and polymorphism. That just makes the abstraction that much more powerful.

So that's why Object Oriented programming rocks the house: Abstraction. But everyone (who is reading this) knows that. So why did I waste all my time writing it and your time reading it? Because I couldn't stop myself.

What I actually want to talk about is what these objects should actually abstract. As far as I can tell there are two schools of thought. I'm pretty sure the one has already mercilessly beaten the other and kicked it to the curve. But in my schooling I wasn't taught about either, so I'm gonna teach myself about them both here.

The two schools:
  1. Objects should represent "the thing" and everything about it
  2. Objects should do exactly one "thing"
Or if you'd prefer,
  1. Objects represent real world objects
  2. Objects manage "concerns" and concerns are separated between objects
In the first you have one big object that knows everything about dogs and manages everything about dogs. Wanna draw a dog on the computer screen? Dog.Draw(); Want to make puppies? Dog.MateWith( Dog );

In the second you have lots of much smaller objects which together, collectively, know all about dogs. DogDisplayer.Draw( Dog ); DogMating.Mate( Dog, Dog ); Note however that this doesn't preclude you from hiding all the various classes behind the Dog class so that a user of the Dog object could still say "Dog.MateWith( Dog )".

As far as I can tell, current industry thinking is that Separation of Concern Objects are the way to go. However, when object oriented programming is taught it inevitably starts with the Real World Objects because that approach is just easier to understand.

MVC is an example of three Separation of Concern Objects. Just about every Design Pattern depends on Separation of Concern Objects (Observer, Strategy, State, Factory). And the point of just about every Design Principle I've learned is that you should write Separation of Concern Objects, the principles are just defining what Separation of Concern actually means (Single-Responsibility, Open/Closed, Liskov Substitution, Dependency-Inversion, Interface Segregation)!

There are a couple things you have to get over when you start creating these kinds of objects though. First, having lots of objects is not a bad thing. Second, having simple objects that only do one thing is a Good Thing. This often feels like overkill before you do it. After you do it you realize it has the potential to make your life seriously easier.

Okay, but why create many objects? Why not just put all the code in the same object? How is this going to make my life so seriously easier? The biggest reason is that if you put all that code in the same object it will get tangled. That is, two algorithms that really have nothing to do with each other (except that they apply to the same object) will start to affect each other. They'll use the same variables, but in different ways, they'll make assumptions that the others will break. This will become a problem when you need to change one of them and you suddenly and accidentally break the other.

The second reason is that you may want to allow for reuse. If everything is all packaged into one object, you can't reuse only a portion of it without the other parts. The final reason is that you may want to swap out the details of how something behaves for different details.

What would this mean for our Dog? Well, we can still have a Dog. But when we tell him to bark, he'll delegate the actual details of how to bark to a DogBark object. And when you tell him to soil the carpet, same thing.

Now if you decide that he should always bark when he soils the carpet, you can do that. And when you later realize that its bad enough that he's soiling the carpet, but now he's waking you up in the middle of the night barking, you can change it again so he doesn't bark when he soils the carpet. And you wont have to worry that soiling the carpet and barking got all tangled.

Moral of the story: SoC Objects add more abstraction to our abstraction. So when I told you that Unit Testing would improve your code design, this is why.

Wednesday, January 30, 2008

Unit Testing: MVC

So I've talked about what MVC is and looked at MVC in Rich Client Applications.

In those posts I mentioned that MVC was pretty helpful when it comes to unit testing. This is because, as I pointed out in Unit Testing and TDD, you can't test GUIs. Of course, you can if you really set your mind to it... But at this point I'm not convinced its worth the effort.

So how does MVC help us Unit Test? Well, once you have a controller that manipulates a view, you can mock out the view and unit test the controller. So MVC gave us something in our GUI layer to test!

Here's an example. Suppose you're creating an interface in which there are three combo boxes, each one is dependent on the one before it. So, when you select a value in the first, the second one gets populated with certain data. When you select a value in the second, the third one gets populated with certain data. Change the first one, the second one loses its value, gets filled with different data, and the third one loses its value and its data is cleared. Pretty simple little UI and not all that uncommon.

So, the view is simple, it's three combo boxes. Lets ignore data binding to keep this example even simpler. So what does our view's interface look like?
  • ClearComboBox2Value
  • ClearComboBox3Value
  • SetComboBox2DataSource( data )
  • SetComboBox3DataSource( data )
Now our controller can cause the view to change state by calling the methods on the view. How does the controller know when values have been changed on the view? This could be done in two ways.
  1. Add events to the view that fire when the values of ComboBox1 and ComboBox2 change
  2. Simply put methods on the controller to indicate the values have changed and have the view call the controller
Personally I prefer the second approach. This approach makes it easier to test and easier to read the view's code. Also, it doesn't violate the dependency chain of MVC because the controller still doesn't depend directly on the view. The view depends on the controller, but that's OK. If you need to provide different controllers to the same view you can do this with Dependency Injection. So, if you're willing, lets go with the second approach.

Now we have a view and a controller. Can we unit test the view? You can, but I'm not. Can we unit test the controller? YES!

Why does this matter? Well, the controller now contains the actual behavioral logic of the form. By testing the controller we guarantee that that logic is correct. Now we just have to test that the view updates its state appropriately. You could do this manually by clicking around, or you could use a visual scripting framework to click around for you, or you could write code to click for you... I'm still just doing it manually.

Again, no silver bullet, but we're 80-90% there (depending on how complicated the view is).

The post on MVC in Windows Applications ended without an answer. However I think this post clarifies that the benefits of unit testing a controller likely out weigh the complexity that comes from MVC.

Have you tried it? What do you think? Why not leave a comment? Josh always does! Is he really that much better than you?

Thursday, January 24, 2008

MVC in Windows Applications

In the last post I looked at what, exactly, MVC really is. Now I want to look at how it applies to Windows applications.

Windows Forms with data binding is basically Active MVC! The data binding keeps the view and the model up to date automatically. When the user performs an action (like clicking a button) an event is fired. Some code executes in response to the event, updating the model and causing the view to be updated. Just like in Active MVC. The only difference is we did it all in two classes, the form class (view & controller here) and the data class. We could separate the controller into its own class if we wanted to, and then we'd have the M, the V, and the C.


Are we comfortable with this? The only problem is that in Active MVC the Model takes on more responsibility because its responsible for keeping the view up to date. But if we're data binding to the model, it has to be 1-1 with the controls we're displaying. There is some potential for this to get complicated if we need our Model to do more advantaged state management. This could cut two ways and could be a great thing, or could become really hairy very quickly.

We could convert this to look more similar to Passive MVC by creating two models. One model will be independent of the view and managed completely by the controller. The other model will be the class we use to data bind into the View. This second model will be updated by the controller to cause values of the view to change and be read/monitored by the controller to respond to user events. With this setup we've moved more of the responsibility to the controller but we've also increased the amount of data passing that has to go on.

And there in lies the rub. On the web, the data passing is required, there is no way around it. But in a windows application, we don't have to pass data around like this. We can write code that gets the data directly from the controls and writes them to the database if we want to. There is no need to have a model class for housing data.

So what are we gaining by using MVC in a Windows Application? We've separated the data from the GUI and we've also separated the "controller" logic from the GUI. This will be nice if we ever want to make changes to the GUI like swapping one control for another. Its also nice because we can now write unit tests for the controller and mock out the GUI (and the model if needed).

So the big question is, are the benefits of an MVC design worth the overhead that comes with an MVC design?

To start with, its certainly not good to have a single form class that contains EVERYTHING. In Windows Forms this is how nearly everyone writes, at least when they're starting out. It seems like the simplest option: 1 form, 1 file, 1 class. Everything is in one place!

But as the form gets bigger (more controls, more rules, more behavior) the number of event methods just keeps rising and before too long you're looking at a 2,000 line class (not including designer code...). You can't remember where anything is and you can't find anything either. It feels like being lost in a jungle.

So we need to come up with a way of breaking this into pieces, no question. We just have to decide what pieces we want. MVC provides us with three pieces. They are nice logical pieces in theory. In practice, you really have to commit to "shoveling data around."

If you were hoping I'd end this by telling you what the best practice is, I'm sorry to disappoint, because I don't know. I'm still experimenting and researching. I'd love to hear your take, or your best practice, or even approaches you've tried and despised.

Update 1/25/08: Added chicken scratch images
Update 9/22/08: Follow up post about MVP and MVC which may be more applicable to Windows Applications and talks about View State.

Wednesday, January 23, 2008

MVC is What Exactly?

MVC (Model, View, Controller) is a design pattern or application architecture, depending on how you want to look at it, used to separate the storage of data from the presentation of data from the processing that takes place when the user interacts with the software.

It's also a huge buzzword in software development that everyone has heard about and thinks they understand but that very few people have ever actually researched or read about.

The concept of MVC was first introduced in the Smalltalk language. The Model stores data, the View presents a user interface, and the Controller handles user interaction.

It was recognized that MVC typically took one of two general forms, Passive or Active. Each form differs based on how the controller and the model behave.

Active Form:
  1. Controller handles user iteration events and updates model
  2. State changes in the model cause the view to update (observer pattern keeps model independent of view)

Note: This means the model can be changed by things other than the controller and the view will still updatePassive Form:
  1. Controller handles user interaction events and updates the model and causes the view to update
  2. Model is completely independent of view and controller
Clearly the Model must carry a lot of responsibility in the Active Form by maintaining state or whatever else is needed to keep the UI up to date. In the Passive Form the Model isn't required to do anything more than house the data. The Controller can manage the state changes.

MVC also appears in a slightly different form called the Document-View pattern used by the MFC (Microsoft Foundation Classes) framework which combines the controller and the model into one object, the Document.

MVC as seen in Ruby on Rails is basically the passive model. The controller is invoked by a user interaction. The Controller builds the model (or tells it to build itself) and/or modifies it as needed, the controller then picks what view to render and passes it any data it may need.

ASP.NET's new MVC framework works almost exactly the same way as Ruby on Rails in terms of MVC (surprise surprise!).

Passive MVC makes tons of sense on the web because the Request/Response nature of HTTP requires a very structured data passing model. Ultimately, that's all MVC is, a standard for how to pass data around:

Data is housed in the Model, accessed and modified by the controller, passed to the view to be displayed, passed back to the controller from the view w/ changes made by the user, etc...

So, MVC is a great thing on the web. It simplifies the code, makes it obvious where to go for what, standardizes the flow of data and rendering of web pages, and exactly matches the behavior of HTTP.

That being said, there are still some variations:
Does the Model match the database schema and just house data (as in .NET Typed Datasets or the new LINQ to SQL objects)? Or does the Model present data in an intelligent (problem domain specific) way and contain high level logic for modifying the Model? I'm not sure it actually matters, honestly. Its just a question of where you want to put your logic, all in the controller or spread between the controller and the model?

So, now we've surveyed MVC, talked about some frameworks that use it, and decided that it works really well for the web. In the next post I'll look at if MVC makes sense in a Windows Application.

Update 01/25/08: Added chicken scratch images

Monday, January 21, 2008

Web UIs vs Rich Client UIs

Nearly every application has a User Interface of some sort. It could be a configuration file, a command line, a Windows Form, or a web site. A software application's User Interface is the part of the software that effects the user the most because its the only part that the user has direct interaction with. Unfortunately the UI is also the hardest part of the software to quantify and measure, so its hard to determine if one UI is better than another. And further complicating it, a user might like a UI that they don't work as efficiently with and hate a UI that actually helps them get their work done faster. Its very subjective.

Before I go any further I ought to point out that having a good UI doesn't mean you have good software. The primary function of software is to fullfill a user's goals.

In any event User Interfaces are clearly important. So where do you find the best user interfaces? I think most people these days would say that Rich Client UIs are the best. They're more consistent, easier to develop, have shortcut keys and menu bars and toolbars, and have fast response times. Meanwhile, web apps are all different and inconsistent, are very difficult to develop, arn't as easy to interact with, and have high latency.

At least, that's what everyone seems to be thinking. Even in articles where very smart people like Joel Spolsky and Jeff Atwood are discussing how web apps are going to replace desktop apps you can still see those underlying assumptions.

Of course, AJAX is changing things. Now we have Gmail and Google Calendar and 30 boxes and Jott and Remember the Milk and Fog Bugz and Scrybe and Google Maps and Yahoo Maps...

Maybe its just me, but I like the UIs of these web apps better than what Outlook has to offer, or iCal, or Thunderbird (and Sunbird) or TFS or Microsoft's Streets and Trips. Why? It comes down to three reasons:
  1. They are more dynamic
  2. They are easier to read and understand
  3. They are prettier

By more dynamic I mean, when you hover over something, information is displayed in a nearby panel. Or when you click a row, it expands to show you more detailed information and give you links to perform actions. Also, the display of data is usually customized so that, for example, if you're seeing a list of todos and one is longer than another they both take up whatever space they need making them easier to read. In a rich client they're typically forced into the same amount of space in some kind of Grid control.

They're easier to read and understand because everything isn't displayed in static grids and panels. Instead, it's displayed more how you'd display the same information in a report. That is, it's laid out like a Flow Document. This makes it easy for your eye to find the information you're looking for and remember where to find that information in the future. Also, things tend to be broken into display and editing in two different interfaces. This way you're not staring at a grid of labels and text boxes, some with data in them and some without.

And finally, they're prettier. They have color and logos and icons. Most rich client apps are either a sea of grey, or washed out white, with black text over top.

So from a strictly functional standpoint, these Web UIs are better than any Rich Client UIs I've used to accomplish the same tasks. Now when you add in cross browser compatibility problems and the steep development cost and the potential for high latency things become less attractive. And this inevitable leads me to ask, "Why don't my Rich Client Applications behave as well as these Web Applications?"

The answer is its actually harder to do this kind of stuff with the existing frameworks in Rich Clients. For example, there is nothing in Windows Forms which will let you create an html style layout. You can simulate it by creating a custom control for every item and state you may need to display and throw those into a Flow Layout Panel, but the overhead involved in developing this and the performance costs when it's completed makes it too prohibitive. Ultimately you'd have to just perform your own custom GDI drawing or use an HTML rendering engine and write in HTML. Neither of these is really a very good solution.

WPF may offer a solution to this. I haven't actually done any development in it yet, though I've done plenty of reading. For now, I'm hopeful and looking forward to finding some free time to experiment with it.

Ideally I'd love to see Rich Client applications which took a more flow document layout style approach like you see on the web as well as more dynamic interfaces capable of showing the most pertinent information in the "report" view and allowing the details to be displayed through a web style progressive disclosure model.

And I'd love to see tab controls replaced with web style Navigation bars that toggle the "report page" or navigate to "anchors" in the page. These are simple but powerful UI patterns that you rarely see in a Rich Client environment.

How do you edit data? Either allow users to click and open a pop up to perform edit tasks (like Properties Windows) or dynamically display an edit control when the user clicks on the read only data. These two patterns both allow you to perform very simple spot editing or display more complicated edit UI when needed.

The fun part of all this is that none of it is new. You use it every day when you browse the web. Its time designers started incorporating the good ideas from the web in Rich Clients. And its time Rich Clients were developed with a Framework that makes dynamic UIs possible!