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.

Monday, November 3, 2008

Work With Someone Who Knows More Than You

Of late, I've had the privilege of working with a developer with much more experience than me. Of course, being a junior developer means that pretty much everyone has more experience than me. That actually works out in my favor, because it gives me lots of opportunity to learn. The person I've been working with lately, however, has much more experience than me.

Working with someone with more experience than you provides some really great opportunities to improve yourself as a programmer. The first benefit is probably the most obvious one: You'll learn programming and productivity shortcuts that the senior developer has already figured out. These are little nuggets of wisdom that are a result of the senior developer's years spent doing some of the more repetitive programming tasks. For instance, you might learn a handy keyboard shortcut or code snippet that saves time. These are things that while not earth-shattering, can add a lot of convenience to your life.

The second benefit goes a little deeper conceptually than the first: Exposure to different problem-solving techniques and general design methodologies. Watching someone else solve problems or design a software solution can give you tremendous insight into other ways of thinking. It can also help you identify gaps in your own knowledge and areas where your skills need improving. While watching others solve problems, I'm fascinated by watching them unravel the problem, formulate a solution, then make small adjustments here and there. Once the encounter finishes, I'll often apply the situation to myself by asking two questions: What part of my normal problem-solving methodology is much less efficient than what I just saw, and what part of my normal methodology could have improved upon the solution? By asking these questions, I try to identify my strengths and weaknesses.

A third big opportunity for improvement when working with a more experienced developer is the advice and guidance that he or she can provide. My main mission at my job is twofold: To always be adding value to the company and to constantly be improving. Like all developers, I can get pretty wrapped up in whatever I'm working on. Sometimes I can become so absorbed in what I'm doing that I can't see the forest for the trees, and having that objective guidance from someone who's made similar mistakes really helps me get rid of that tunnel vision. That applies not only to a specific solution, but also to my proficiency in general.

Note that working with someone who knows more than you requires a quality that some developers don't possess in large quantities: Humility. You have to be humble enough to realize that you don't know everything and that other people can have more insight into development-related problems than you. While this presents no problem for most of us, we all know those programmers that wouldn't take advice from another developer if their lives depended on it.

Sunday, September 7, 2008

My Number One Hurdle: Fear

This blog post makes me uncomfortable, because it's going to be about something fairly personal.  I'm going to be talking about my biggest weakness, my biggest personality flaw, that which keeps me from becoming a great developer:  Paralyzing fear of failure.  It's a personal subject to me and I'm uncomfortable talking about it, but I think it's a good thing to get out of our comfort zones, so here goes.

Of late, I've been meditating on my job quite a bit.  I'm not dissatisfied with my job at all; rather, I'm dissatisfied with my performance at my job.  I find throughout the day that I hesitate to get projects started, I hesitate to finish them, and I hesitate to work on already-begun projects.  I'll get distracted and work on something else.  These acts of hesitation and distraction have become more pronounced of late, either because they've actually become worse or because I've just begun noticing them more.  Regardless, I knew it was time I figured out what was going on, so I thought about and meditated on the subject.

The conclusion to which I came startled me:  Deep down, I'm afraid that I'm not smart enough, that I don't know what I'm doing, and that those things will lead to failure.  I'm afraid to start a project because I'm afraid that I won't be able to figure out some part of it and I'll look like an idiot.  I'm afraid to make big decisions about the projects on which I'm working because I'm afraid they might be the wrong decisions.  I'm afraid to finish up my projects because I'm afraid that when I let a superior look over my work, he or she will say I was wrong.

This fear would manifest in the deadliest of ways, by causing me to hesitate at each part of a project.  I would put off each part of the project to avoid the confrontation with myself, the questioning of my ability and intelligence to solve the problem.  This fear would also cause me to distract myself from my current project.  Once I'd get to a part of the project that I was afraid I might screw up, I'd say, "Oh, hey, here's this other thing I need to do," and I'd again put off that confrontation.  In short, my fear was causing me to sabotage my own efforts.  It would take me far too long to start a project and far too long to finish it.

So how does one conquer this fear?  I conquered it by simply thinking of all the things that I've accomplished in the last year.  I compare myself as a developer now to myself as a developer even three months ago and realize that I'm always learning a mind-boggling amount about my job.  Foremost, I realize that this growth in my job has enabled me to solve all kinds of different problems using all kinds of creative solutions.  When I realize how many times I've doggedly solved a problem to which I had almost no understanding when I first confronted the problem, it shows me that I've been in the trenches of these kinds of conflicts for quite a while.  In fact, I've realized that our job as developers is to creatively solve difficult problems.  This change in viewpoint produced a change in actions:  I now enjoy starting new projects because I know that I'll be presented with a problem to which I must apply my logical and creative thinking skills.  I enjoy finishing projects because I enjoy contributing to the success of my company and feeling that I've created something of value.

A very wise leader once told me that fear is an emotion just like love, and like love, we as humans cannot control it.  He said that what separates successful people from unsuccessful people wasn't a lack of fear, but a resolve to do one's job and perform one's duties in spite of that fear.  Those words were spoken in a much more dire context than programming, but I've found as I've gotten older that it applies to almost every facet of life.

Sunday, April 6, 2008

White Castle Programming: A Most Dangerous Game

Something that I deal with at work seemingly all the time is White Castle Programming. If you've never heard the term or don't know what it is, White Castle Programming is when one makes dubious assumptions as to the behavior of the client while writing one's code. This is code that will be interacted with in some way by a client. It could be a code library that will be accessed by client code, it could be a middle-tier layer joining two disparate layers, or it could be UI code that will be interacted with by a user.


Examples are in order. Let's say that you have a textbox on an ASPX Webform or a Winform and this textbox will be used to capture a dollar amount. If you assume that the user will never enter anything into this textbox other than a dollar amount, and you do not write any sort of validation code against that textbox, that is White Castle Programming. Or, let's say you're designing a code library and you give a class a public property that is some sort of collection, such as List, Dictionary, or whatever. If you assume that another developer writing client code against your code library will never use that collection in a way that you did not intend, that is White Castle Programming. In both cases, you are assuming that a user, be it an end user or another developer, will never do anything with your code that you did not intend. The logic in this thinking is something along the lines of, “No user would ever enter a non-dollar-amount string in a textbox that is clearly labeled for a dollar amount,” or, “It would take too much time for me to make this public collection property a private field and write access methods to it, and no developer would ever do anything stupid with the collection anyway.” The basis of these arguments is that it's inefficient to write code against outlier, statistically unlikely use cases and scenarios.


First, let me address the concept of YARGNI and how it relates to White Castle Programming. YARGNI, an acronym that stands for You Aren't Really Gonna Need It, is a concept that posits that a developer shouldn't write code that addresses a particular concern until there's a demonstrable need for the code. I am all for YARGNI and I try to practice it in my everyday programming; however, YARGNI can be taken too far and venture into the realm of irresponsibility. You wouldn't wait until after a user entered “DROP TABLE” into one of your textboxes before you began scrubbing your user input for SQL injection attacks, would you? If so, then I suggest you update your resume. YARGNI, however, would tell you to wait until your User table had been completely wiped out before writing such protective code, and in this way, YARGNI actually contributed to some White Castle Programming.


As you can see, White Castle Programming doesn't make a whole lot of sense. You're making very generous assumptions as to the behavior of any user of your code. However, you probably see examples of White Castle Programming in your projects every single day. Hell, it's something I see at work every single day. And I hate it. I despise White Castle Programming with every fiber of my being. It goes against everything I've been taught and believe about good, defensive programming practices. How on earth can a developer assume any particular behavior from the user?


So how do you fight White Castle Programming? Conceptually, you fight it with good, defensive programming practices. You write code that protects itself from the user. In the case of the dollar-amount textbox, you validate the user's input with a regular expression. For the code library with the public collection property, you take the time to do the job right, make that public collection a private field, and write access methods for it. Yes, both of those solutions require more time and add a little to your coding complexity. The payoff, however, is that you have greatly simplified the user's experience with your code. When an end user types “3.a6” in your shiny new textbox, now you can give the user a meaningful error message that let's him know that he mistyped the information. When a developer writes client code against your shiny new access methods to your private collection field, he'll know exactly what actions can be performed on that collection because you've provided access methods that are the client code's only interface with that private field.


When you program defensively, you greatly narrow the scope of the user's ability to interact with your code. You narrowly define exactly what actions the user may perform, and you create meaningful indications when the user does something that they shouldn't. Programming defensively makes your code structurally sound and ensures that the user can't do something that you did not intend. When you the developer defines what actions the user may perform on your code, you empower yourself to give the user the best experience possible, and isn't that what programming is all about?


Defensive programming is the conceptual method of fighting White Castle Programming. What is the practical method? What if, during a code review, your boss asks you why you added some extra validation code, and when you tell him that you were just defending against a certain use case, he fusses at you for wasting time programming against a statistical unlikelihood? The best thing to do is to actually show your boss the problem and demonstrate it for him. Most bosses, once they see that a problem is possible and that it could very well cause problems with the system, will be glad to let you leave the code in and will respect you for your foresight.


If you think about it, programming defensively is more efficient than waiting for the problem to occur. When you narrow the scope of the user's interaction with your code, by default, you also narrow the range of errors that can be produced as a result of users' interactions with your code. Problems become easier to track down and solve.


White Castle Programming, on the other hand, leaves the user open to perform any number of strange and unexpected interactions on your code. When you assume that the user will only interact with your code in an intelligent way, you widened the range of errors that the user can cause. The wider the range of errors, the harder they are to track down. You'll have to spend more time stepping through your code, trying to reproduce the user's problem. If you don't have overly descriptive error-logging in place, then it will be even harder as you try to figure out exactly what values the users' variables had, exactly what line of code they bombed out on, and so forth.


Of course, a good developer can't go willy-nilly with defensive programming. YARGNI teaches us that you don't want to attempt to defend against every possible use case. So how do you know which exceptions to your code you should program against beforehand, and which you should wait until they occur? Well, that intuition comes from experience. If in the past, you've seen that clients tend to perform one certain error that could possibly affect your code, then you should program against it. If it's something that happens often or could cause a serious problem to the system, you should program against it. Anything else, you should wait. I know that's a somewhat vague answer, but if you keep your eyes peeled, you'll eventually pick up that intuition.


I'd like to end this blog post with one of my faves: Telling about a real-world experience that totally demonstrates my point. Names and circumstances have been changed so that no one will know who I'm talking about and therefore get offended, though I never mean any offense with these real-world examples.


The boss comes up with some new functionality that will add value to one of our .NET Windows apps. After a few meetings and some brainstorming, fully fleshed out specs are given to me for implementation. There is no code in place, just database tables, so I get to design all of this from the ground up. I write all the stored procedures, design the business classes, and lay out the screens to spec. However, I program defensively. All of my Windows forms have extensive user-input validation. Hell, I even wrote some custom validators that validate against some third-party Windows controls that we use. I surround all my code that touches the database with try...catch blocks. I use various value types' TryParse() methods instead of Parse() methods. I wrap commonly used variables in form-level private properties that can perform their own logic and return certain values under certain cases. Lots of little things like that that add up to good defensive programming.


After I've written the code and designed the screens, I begin testing. On one particular screen, I accidentally mistype some figures and find that it's possible to enter data that would cause serious problems to the system. In particular, I find an error that could incorrectly bill one or more of our accounts. I see the problem, take ten minutes to add the logic to defend against it and BAM! problem solved.


Later in the afternoon, I go to a coworker's office and tell him of the serious error I'd found and fixed. His brow furrows and lips tighten. He then proceeds to tell me that he's not sure how valuable it was to program against that error because he doesn't think it's likely that the user would make that same mistake. I argued that it doesn't matter how statistically likely the error may be, I had already demonstrated that it could occur, and when it does, we would have not only invalid data, but invalid billing data. My coworker agreed that it was probably a good idea to check for this error but continued to say that he didn't think it was likely to happen. Never mind that I, who wrote the code myself and was intimately familiar with how it worked, had demonstrated that the error was possible, and had accidentally performed it myself. Let's see, that would be a statistical likelihood of, um, 100 fucking percent, right? However, my coworker did agree that the error should be defended against, so I went back to my office and continued on my merry little path of programming defensively (not that I would have done differently had my coworker disagree with me).


And you know what happened? I finished testing the new functionality and deployed it. A while later, after this code had been in use for two weeks, my boss, who never compliments anyone on anything ever, told me that I had done a “very good job” with that functionality. It was working right out of the box and was not generating errors or invalid data. We made one small set of changes based on user feedback and that was it. BAM, muthafucka! My code, bitch! And what was the reason of my success? I was a humble programmer and programmed defensively, never falling into that White Castle Programmer mentality of assuming that users of my code would magically know what and what not to do with it.