Monday, October 26, 2009

The Number One Rule Of Programming Is Leave Emotion At The Door

As programmers, we take pride in our work. We show this pride by doing the best work that we can. We show it by meticulously getting everything right, even down to variable and method names. We show it by choosing the right classes to get the job done, even though we know the user doesn't actually care whether we used List<KeyValuePair<Guid, string>> instead of Dictionary<Guid, string>. We show it by any number of neurotic perfectionisms that normal people think are OCD.

But what happens when a developer invests too much pride into the code that he or she wrote? What if that pride causes that developer to have an emotional stake in the code itself? What happens when a developer can no longer separate him or herself not just from his or her code, but his or her methodologies, decisions, and general behavior as a developer?

We've all dealt with this kind of developer before. This is the developer that always gets defensive when you ask a question about his or her code. This is the developer that gets into emotionally-charged arguments when you propose a slight tweak or suggestion to what the developer has already done. This is the developer that pouts when his or her way has been shown to be incorrect, and will probably harbor a grudge against you for showing it.

The thing is, we've all been this developer before, too. Especially when we were junior developers, we often were so gung-ho about getting out there and writing code while understanding so little about whatever technologies we were using that we inevitably wrote suboptimal code that we thought at the time was great. We've all known that sinking feeling inside when a more senior programmer shows you a better, more correct way to solve the problem you were trying to solve. We've all felt a little crestfallen when we found a built-in class that already does what we just spent half a week doing ourselves.

But as we gain experience, as we thirst for more and more knowledge of whatever technologies we use, most developers learn to separate themselves from their own work. Most developers learn finding a better way to do what you just did, even if it's from an intern or a fresh graduate, isn't any sort of commentary on our technical proficiency. Most of us reach a point where we really enjoy finding out those new and interesting things. As our proficiency with a specific technology increases, the more likely that something we don't already know will be an outlier that really eases our lives, and we like that. Unfortunately, not all developers make it to that point. Some developers stay at that immature stage and can't ever handle any kind of criticism.

What causes this kind of behavior? My guess isn't spitefulness, immaturity, or an actual belief that one is that much smarter than everyone else. If anything, I think it's borne out of insecurity. When I was pretty green, I always felt like being corrected or shown a better way to accomplish something in code meant that I was dumb. I think developers who get defensive about their own code secretly fear that their value is somehow diminished when their code is shown to be wrong or suboptimal.

Regardless of the why. there exists several ways to deal with this kind of developer. The first is to talk to him or her. Let the developer know that they're becoming too attached to their work and are starting to negatively affect the quality of shipping code. For many of these kinds of developers, this will be enough. No one wants to be responsible for bad code, and if you frame it such that the developer understands that his or her attitude is affecting production code, the developer will usually get their act together.

If that doesn't work? Well, you're left with less desirable means. If the developer never relents, then the next best thing is to get buy-in from the rest of the team. Unless that developer also happens to be a lead or manager of some sort, their bad code (and attitude) will not stand up to the rest of the team.

The next step is making all your suggestions to the manager or lead directly. This has a petty “backstab-y” feel to it unless you also have the developer in question in the room with you. Offer your suggestion to the manager, allow the other developer to defend his or her stance, then let the manager make the decision. It's out of your hands at that point, and it may not end up going your way, but at least you tried.

As developers, we all need to become a little less emotionally attached to our code. Remember that the next time you find yourself arguing against what is obviously a better solution than the one you used.

Sunday, August 2, 2009

The Advantages of User Controls

A practice I see used entirely too infrequently is the use of User Controls on webforms. User Controls provide some really great functionality to the ASP.NET programmer, and I think it's a real shame that they're so under-utilized.

The most obvious advantage of a User Control is that it provides a great deal of reusability. Once you've created the User Control, you're free to drop it on any webform or User Control that you want and instantly gain the functionality provided by the User Control. The more broadly-used the User Control becomes, the more you'll be able to tweak the User Control itself to provide really great functionality to consuming webforms. As you continue to develop User Control, you'll gain the ability to correctly predict what will and won't be useful properties and methods. This enhances your ability to provide robust controls with a minimum development/testing cycle.

Another great advantage of User Controls is the abstraction they provide. A User Control allows the programmer to create a self-contained, self-aware (but not in the evil robot way) set of controls that know how to receive a business object, bind the object to its controls, then rehydrate that business object from the controls for later retrieval from the parent form. The parent form is free to do whatever it wants with the rehydrated object, of course, including persistence in the data store.

That is of course a conceptual abstraction. User Controls also offer literal abstraction in that all the UI logic for the User Control is contained within the User Control itself. This removes several chunks of code from the parent form, thereby making it cleaner and easier to debug. As I said in my previous post, I really dislike big, ugly, complex webforms. With User Controls, there really is no need for webforms with overly complex and often very long code besides classes.

My next post will have some general tips when developing User Controls that I've found really make them useful.

Thursday, July 9, 2009

Overly Complex Webforms: Necessary Evil, or Complexity Problem?

One thing that I encounter quite frequenly are webforms that have very complex and involved logic. I'm thinking specifically of a page that I edited recently with over 2000 lines of code in the code beside. Two thousand lines! I have a hard time wrapping my head around that for a webform.

My honest belief is that a webform really shouldn't contain more than, say, 500 lines of code beside. Yes, that's a pretty arbitrary number, but really, what are you doing on a webform that requires more than 500 lines of code? Sure, there are some pages that require very complex business logic. Complex business logic I understand. What I don't like are webforms that have more than 500 lines of code beside which is almost exclusively GUI programming.

I think that if your code beside requires more than 500 lines of code, then you seriously need to reconsider what exactly you're trying to accomplish with the form. If you're continually adding GUI logic, making this control update that control, and that control updating these controls, then it may be time to start re-evaluating the page to see if there are GUI elements that can be broken out into their own forms.

I realize that it's a fine line that we draw when trying to decide what to show the user all at once and what to require the user to mouse and click to see. It is a bit of a moving target, I'll agree. However, you'll find that as the GUI complexity grows beyond 500 lines of code, the performance of the page starts to suffer. I especially see this on AJAXified webforms. The irony is that the responsiveness that the developer gleans by asynchronous AJAX calls are cancelled out by the amount of processing time required to perform such complex GUI logic.

So what does one do when one sees a webform growing to such monstrous proportions? As mentioned, my advice is to find ways to logically break down the webform into separate components that can be placed on their own forms. This will clean up the logic and increase per-page performance. Also, maintenance programming will be much easier. Nothing sucks like opening up the code beside and having to step through line after line of spaghetti logic just to fix one line of code.

There is another solution to this problem, and that is the use of user controls. I'm a big fan of user controls, but I'll touch on that subject on another post.

Saturday, June 27, 2009

Custom Exceptions: They'll Make Debugging Easier

One suggested practice that I read about over and over again in many software development books is the use of custom exceptions. The various books and blogs mention custom exceptions as a way to ease debugging and shorten development time. I recently made extensive use of custom exceptions in a console application that I wrote, and after a little trial and error, I came away impressed and will definitely vouch for the practice.

The first obvious advantage of using custom exceptions is the ability to add custom functionality to your derived class. Since you're designing the class yourself, you're able to totally customize the behavior of the class. You're also able to add detailed information about the application state that threw the exception. If you're logging exceptions (which you should be), then you can quickly check your logs to see detailed information regarding the exception and re-create the application state that threw it.

Another advantage of using custom exceptions is the more descriptive name given to your derived class. This much-touted advantage seems kind of petty when you first hear it. When I first read it, my thought was, “Ok, so?” However, it's a small feature that helps in a big way. When you're scanning over your exception log (the one you're logging your exceptions to, right?), it's actually a big help to look at the log and see a specifically-named exception. The extra descriptiveness helps more than you'd think.

The various books and blogs recommend using custom exceptions, even if all you do is derive from System.Exception and give the derived class a more descriptive name. My advice is to not go overboard with it. It is a trade off: You're adding a lot of extra code that doesn't really accomplish anything for the payoff of more descriptive exceptions. When simply deriving System.Exception and not adding any custom functionality, I recommend only doing so when you have a specific application state that you want captured.

Several caveats exist if you're writing custom exceptions. If your custom exception wraps another exception by catching the original exception and throwing the custom exception, make sure that you capture the original exception by setting your custom exception's InnerException property. The InnerException property can't be set directly, but you can set it by using the base.Exception(string message, Exception innerException) constructor overload.

The other caveat is the try/catch structure you've built. Keep in mind that in the above situation where you're catching a System.Exception and throwing your own, the stack trace of your custom exception will begin at the line where you threw the custom exception. If you aren't setting the InnerException as described above, you're going to lose the stack trace of the original exception that was thrown.

Also, remember if you're re-throwing an exception in a catch block, use the throw; statement without specificying the exception. This will preserve the stack trace, whereas throw [exception]; will begin the stack trace at the line where you're re-throwing the exception.