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.

Friday, February 8, 2008

Pride of Ownership: Euphoric, Powerful, yet Dangerous Programming Nunchucks

Have you ever sat at your desk and banged away at a chunk of code, and after hours of toil, gnashing of teeth, checking online, and asking other developers, you finally end up with an awesome piece of code? Remember that euphoria that you felt, looking at that most raddest code, thinking about how awesome it was? I bet you even made up excuses of why you should tell other people about it, just so they could look at it and then regard you with awe at the code you wrote.

If you've ever felt anything remotely like that, then you have experienced pride of ownership. You looked at your code almost like a pet or a child, and you guarded it jealously against heretic naysayers desiring nothing more than to refactor you code, saying by implication that your child isn't good enough!

I happily admit to this. I once wrote a piece of javascript that was so rad that once I fully realized just how easily, elegantly, and fully it solved a business problem, I literally wanted to ask myself out on a date. Even my hero, James Hetfield, would have been impressed.  I showed other developers my little javascript function, just "so they could be sure to use it if they needed it."  I marveled at my little codeling.

There's nothing inherently wrong with feeling pride of ownership in your code.  It's a good and healthy sign that you actually take pride in your work.  Feeling good when you write especially good code is a sign that you do in fact like your job and that you should probably keep doing it.

Personally, I think taking pride in the work you do is one of the most important aspects of any job, but especially so in software development.  Writing excellent code requires a fair amount of self-discipline.  This self-discipline involves not cutting corners just to make features work, not short-changing oneself in the design phase just so one can begin coding, and knowing when to stand firm about a decision.  Software development can be such an exact science that taking pride in doing it well constitutes a desire to write good code.

Having said that, there are two pitfalls to pride of ownership.  First, how many times have you written that one piece of angelic code and then tried to use it everywhere, even if it wasn't applicable?  That pride of ownership gets to you and you just want to use it willy-nilly.  Maybe it's a robust piece of javascript, maybe it's a really awesome DAL wrapper class, maybe it's just a single method that solves a problem thought to be unsolvable in any elegant way.  However, you have to realize it for what it is:  A piece of code that solves a specific business problem, not a be-all end-all solution to every problem you'll ever have.  Learn to use your new-found lovely code judiciously and only in places where it's truly applicable. 

The second pitfall of pride of ownership rears its ugly head when you've spent so long working on one piece of code that you become committed to it.  You've spent so long working on this piece of code that, by golly, on your mother's grave, you will finish it!  No matter that the algorithm wasn't well thought-out, no matter that the code is hard to follow, you will finish it, because goodness forbid the last three hours you've spent developing this code go to waste!  In the past, I've found that when I've slogged through those situations and finished the code, I was usually left with something of which I wasn't overly proud.  It is much better to scrap the code and start over writing something easily-read and maintained that you will be proud of.  Your boss might get irritated, but he will be more irritated if you submit crappy code.

Remember the two pitfalls, but always write code that you'd be proud to show someone else!

Wednesday, January 16, 2008

Refactoring Vs. Extending

Today I want to talk about refactoring versus extending and why you should almost always extend code instead of refactoring it. Like most of my posts, this post is a direct result of my personal experience as a Junior Developer.

Real World Example:  Recently, I was pulled into my boss' office and it was explained to me why a developer shouldn't refactor working code. The cause of my boss' ire was some poor testing on my part. I had been given the task of adding some functionality to an aspx page and while in there, I thought it would be a good idea to clean up the code and make it more consistent with logic in other places. In doing so, I remembered to test all the functionality of the page except for one stinkin' button. This button happened to be a button that is not pressed very often, so it was almost an entire month before someone finally clicked it and realized that my code was broken. It was then that my boss found my heavy refactoring and talked to me about it.

The basic gist of our talk was that a developer should always extend code instead of refactoring it. After mulling this idea over for some while, I realize the truthiness of the concept, but allow me to explain.

See, as a good Junior Developer, you cringe at bad code. All good developers worth their salt do. You may see a piece of code from a year or six months ago and actually be embarrassed that someone at your organization wrote such terrible code (imagine your surprise when you check the history of the code in source control and see that it was you that wrote it!). The urge to fix such terrible code is very strong and is pretty much in line with our desire as developers (and Junior Developers!) to push out only good, clean code.

But don't do it, young jedi! You must resist the temptation! For you see, for every line of code that you change and/or add, you increase the chances of introducing errors into existing code that already works. See those words in italics? They're important. So important, in fact, that they italicized themselves. Like, srsly. They came straight from the keyboard italicized. In fact, for the few seconds I was typing that phrase, the actual keys on my keyboard became italicized. Not the stickers on the keys, no, the actual physical keys bent their shape into an italicized form. It was very bizarre.

But seriously, it's true. Statistically speaking, for every line of existing, working code that you modify, you multiply the chances of introducing errors that will break that working code. Code that's already been tested and that another programmer has already been paid to write.  I'm not talking about compiler errors, either, oh no. I'm talking about anomalies that may not throw any compile- or run-time errors, but insidiously change the behavior of your application or website in subtle ways that may not be directly obvious. You could introduce anomalies into the code that may not even affect the area in which you're working or that may not be seen for several months, like in my earlier real-life example. I don't care how bad-ass you think you are, you are not perfect.

So how do you work around this maxim of not refactoring working code? By doing what any good Junior Developer worth his salt would do, by extending it! Remember extending from your computer science classes? Maybe they didn't call it that. Maybe they called it inheritance, or method overloading, or polymorphism, or any other name of very abstract ideas that you may or may not actually use in the real world. Well, now's your chance to put that expensive education to use! Sort of!

For instance, let's say that your boss comes to you and tells you to change the functionality of some user control used throughout the site. As a Junior Developer eager to please and hopefully show your value, you pull up the ascx page and it's code-beside and begin rewriting the offending methods. STOP RIGHT THERE! See what you're doing? You're changing working code, which as stated, is a big no-no! Instead of rewriting those methods and increasing the chances that you might introduce errors or anomalies, you should instead overload the offending methods and add whatever custom logic you need in order to gain the desired behavior. Many times, the original method isn't incorrect, other than that the business rules or user requirements have changed, so overloading really is the way to go. With overloading, you maintain the functionality of the original method while gaining whatever functionality that you write.

Real World Example:  This very idea paid off for me in spades yesterday at work.  I had to add a parameter to a search method in our data layer.  This parameter would be searched against in the database, so I not only needed to add a parameter to this method, I also needed to add logic to the method to search against that parameter.  Instead of simply adding the parameter and logic to the existing method, I just overloaded the method, copied the code from the original, and added the specific logic that I needed.  Several hours later, my boss changed the specifications for the search page on the website that eventually calls this search method in the data layer, and he changed it such that the new parameter was no longer needed.  Groaning and gnashing of teeth, right?  WRONG BITCH!  Because I was smart enough to overload the original method, I now only needed the extra logic I'd added in the overloaded method.  I had already thoroughly tested this extra logic, so to easily meet my boss' specifications, all I had to do was copy the logic from the overloaded method to the original and change the method call in the search page to call the original.  Utterly quick and painless, and since I was smart enough to overload, no on was the wiser!

Of course, overloading methods isn't the only way to extend current functionality without breaking anything. Let's say that a certain class exists that has all the functionality you need except for a few key ingredients. This could be a built-in class like Control or a custom class in one of your projects. To add this functionality, your first temptation again will be to add the properties and methods that you need to the class and move on. However, this would be just as incorrect as before. While adding properties and methods to a class isn't nearly as egregious an error as refactoring a method, it's still incorrect. Yes, adding properties and methods to a class will give you many similar benefits as overloading a method, but by adding properties and methods to a class that don't really belong to it, you're violating principles of OOP by giving it properties and behaviors that don't really belong to it. Instead, you should create a new class that inherits from the class that you want to extend. This of course gives you all the functionality of the original class and gives you the opportunity to not only add functionality, but also override any properties or methods in the base class that may be poorly implemented or implemented in a way that is inconsistent with the needs of your class.

While the obvious advantage here is that you are not breaking any working code, there are several non-obvious advantages as well. Firstly, you are adding code that is only called whenever your code calls it. So if you overload a method or extend a class, the code you add to call that class or method is the only code in the system at that moment that calls it. That means that you have now added code in a strictly controlled environment and in a strictly controlled manner. Secondly, that gives you huge peace of mind, knowing that even if you write a boneheaded logic error into your new code, it won't be adversely affecting existing functionality. Lastly, this gives you a huge advantage in testing, because you can also strictly control parameter values, break points, and any other way of testing the code. Of course, the burden will then be on you the Junior Developer to effectively test the new method or class.

Another non-obvious advantage of extending existing code is that even though current code may be ugly or less than optimal, the code you add will be as clean and optimal as you make it. Again, this lays the burden on your shoulders to write clean, easily-read code that doesn't do anything incredibly stupid, but if you're practicing the art of self-education mentioned in my previous posts, then you should be able to look at that old, ugly code and claim victory over it's stupidocity.

Having said all that, extending over refactoring isn't an absolute, of course.  However, there are really only two times that you should refactor working code. Firstly is when you're told to by your boss. If your boss comes into your office and tells you specifically to refactor something, then you probably should. Hopefully, your boss will have a very good reason for refactoring. Maybe he found a new language feature that more easily or efficiently accomplishes the code's business objectives, or maybe he just plain doesn't like what's there.  Regardless, make sure you cover with your boss exactly what he wants changed and exactly in what ways.  Make sure you talk it out with him as best you can so that you both know what you're getting into.

The second time you should refactor code is when it's actually broken. However, this post addresses why you shouldn't refactor working code, so that's not really relevant to this post.

I'll end this post by acknowledging that much of what I've said here is quire elementary.  Many developers might read this post and think, "Well no shit."  However, I've blogged about it because, for one thing, no one ever explained it to me.  I can't even fathom how much heartache I might have been saved had I read a blog post like this during my first six months as a professional developer.

Moreover, elementary though these practices may be, I still see developers, myself included, making these mistakes all the time.  In every job I've ever had, I've noticed that the people who succeed are not the ones with the fancy methods and tactics or the overly expensive equipment.  It's the people who master the basics and learn to integrate those basics into more complex processes that succeed.