Thursday, December 4, 2008

Where did that come from?

Have you ever tested code and some inexplicable error keeps happening over and over even though you can swear that you removed or corrected the offending code. I can't count the times this has happened to me. I just worked my way through this very problem.

I was working on some javascript and I kept getting an error about a function/class not being a constructor. I kept changing code and adding alerts but I could not figure out why FF or IE couldn't identify my function. I went so far as to delete everything from the function and leave a lone alert. Still no luck. After hours of hair pulling, which is hard since I have very little hair, I finally discovered the problem. Two scripts on the page had the same name. Problem was that while I was importing my script the other script was magically being pulled in via an ajax/eval. So the import of the script went something like this HTML -> import script 1 -> script 1 has a dependancy on script 2 -> script 1 import script 2 -> script 2 has a dependancy on script 3 -> script 2 import script 3. Sounds simple enough right, well it would be if the HTML page either imported all of the necesssary scripts or even if you had a nifty dojo like require function so that scripts could explicitly import their dependancies. Oh no, what I had to deal with is some monkey writing a utility function that pulls in all of the scripts I could ever possibly need for every possible HTML page. That means that every script written for any portion of the site gets pulled in; lets see that's 76 scripts with 4 duplicates, 74 I don't even use or need and 3 of those are libraries like DWR and ProtoType, great libraries but I don't need them imported for every single page on the site.

Lesson: Fight the erge to bring the entire arsenal of weaponry to every fight. In other words stop trying to predict what will be needed for the future, let the very smart and talented developers who come after you decide what tool they need to solve their problems. Your code will be smaller, easier to read and best of all easier to modify. Poeple suck at predicting the future and the sooner developers understand this and write their code for what is and not for what might be the sooner you will stop writing impossibly complex and useless code.

Monday, December 1, 2008

Evolving: Coding Monkey to Software Craftsman

As an IT professional I hear a lot of things that make me cringe. Yesterday I heard an old school mantra. "Our code is pretty bad because we didn't have time to clean it up." I can't count the times I've heard this same statement uttered, either exactly or in spirit.

It blows my mind that in the age of agile development that people are still cowboy coding. The days of mindless hacking must end; IT needs to mature into a formal scientific discipline. Would you ever hear an architect say, well I was just experimenting, I meant to get the foundation complete but I wanted to make sure the roof worked first. While the physical examples of architecture can go a long way to describe a software developer's work the metaphor can become strained, but the point is valid. When building code you must always be cognizant of what, how and why of your problem domain: What are you building, how are you building it, why are you building it. If you keep all three of these questions in mind your development won't slip into cowboy coding. Better yet, practice TDD and you won't have to keep these principles in memory.

Test Driven Development guides you through th big three questions about any code you write. You write the test to meet the user's story and then the code almost writes itself. For example, if you have a user story that a user wants a way to figure out what day of the week they were born (I know its pretty contrived). You first write a test that guarantees that if someone were to be born today that whatever calculation you use in your code will return the correct day of the week. Then come up with a few random test cases, your own birthday, the current President's birthday, your spouses birthday or whatever. Finally, come up with some edge cases, what happens if someone were born on Feb 29, 2004, what about someone born before the Gregorian Calendar took affect. Then if you write code to pass these test you will of answered all three vitals; what are you writing: a solution for determining the day of the week for a given date, why are you writing it: to meet the user's requirement for a date tool, how are you going to build it: take in a date spit out the day of the week.

Another step in becoming more than a coding monkey is desire. As a developer do you sometimes find yourself falling back on what you know, on what is easy. That lethargy will never evolved your simian tendencies. A monkey has it easy they don't have to worry about lay-offs or that their knowledge going stale; but we developers have to constantly be worried about these real threats to our career survival. Developers are knowledge workers and our one and only commodity is our knowledge so why would you allow it to rot? Every line of code you write you should be pushing yourself to do it better (clearer, more concise) than you did on the last line of code. Refactoring is great for fixing smelly code, but what we need to have is a desire to prefactor: fixing smelly code before its written. The best developers I know never say, it isnt' as good as I could do but its good enough; instead I hear them say, I did the best I could but I know I can do better. The best developers have a desire to improve their craft. I just finished reading a great post How to be an expert, by Kathy Sierra on the blog Passionate that describes this idea much better than I ever could.

Most IT shops are broken, but there are solid ways to improve and even fix a lot of the problems. We, the developers, just need step up and realize that we are part of the problem but we can be part of the solution. Stop being a coding monkey and become a software craftsman.

Technical Interview Questions

Have you ever taken a technical interview that went terribly? I just did, and it was horrible. I was asked questions I had no clue how to answer, questions that I barely knew or had limited exposure to and finally questions I knew but answered incorrectly because I was so nervous about the previous bad answers I had given. The worst part is I incorrectly answered questions that I have asked interviewees in the past. So instead of crying over spilled milk I decided to learn from this experience.

First, asking a bunch of random technical questions may seem like a good way to quiz a prospective employee, it really just strokes the questioner's ego and doesn't necessarily give you a true picture of what the candidate is capable of. Do you really care that a candidate has memorized the entire Java API and can tell you the method name, signature and optimal use for any random class, abstract or interface; or do you care more that a candidate can access and understand the JavaDoc API? Is it more important that a candidate can give a detailed treatise on the definition of polymorphism or do you care more that a candidate understands the concept and can put it into practice. Let me elaborate, I had a youth minister once who could spout off any verse in the Bible, he had nearly memorized the whole thing, but when you asked him the meaning of a verse and not the verbatim dictation he was at a total loss.

Second, if you must ask raw technical questions, take the time to order them from simple to complex. Once the candidate starts missing question after question you can reasonably gauge their skill level by the last question(s) answered correctly. Plus you might be able to cut an interview short for a candidate that doesn't meet a minimum requirement, therefore saving your day and not pressing salt into the candidate's wound. Don't bombard the candidate with a slew of random questions from subject to subject. It only shows the interviewers lack of time spent preparing for the interview, and it also gives insight into how the company may work. A scattered interviewer means a scattered brain means a scattered organization.

Third, understand that the candidate may be very nervous; they are after all interviewing for their livelihood, and will sometimes make obvious mistakes. Lead them to correct answers, don't try and trick them. An interviewer who would expressly set out to trip up a candidate is a worthless human scavenger. I'm not saying answer the question for the candidate but sometimes they need a little help to get the ball rolling.

If you are an arrogant, self aggrandizing prig, then nothing will stop you from thinking that the best hires are those that have memorized some abstruse features of Java (http://softarc.blogspot.com/2006/10/my-favorite-java-developer-interview.html). All I can say is, 'congratulations in hiring MENSA.' I personally want to work with talented people who are there to solve business problems not quibble over the esoteric technical aspects of Java.

Success is Failure. Failure is Success.

My company just went through a major production release and the only good thing I can say about it is, "Thank God it's almost over - hopefully." It has been one emergency after another, each more critical than the last. The executive team sent out a corporate wide email congratulating everyone's hard work and dedication. They also claimed that it was a total success with only a couple of challenges left to resolve. Either they are incredibly naive, incredibly lied to or just crazy.

I am just a lowly developer but I consider a release that limits our customers ability to effectively work with our system a failure; a complete failure. As always I can't go into detail as to what went wrong but I can reflect and try to identify why.

First, a corporate culture that cultivates deception and evasion is BAD and will always end the same way; badly. How does a company encourage such fraud? Mistakes always have a cause, but it takes a healthy corporate culture to look for the root of the mistake instead of the mistake maker. People are more apt to divulge mistakes and issues if they feel that they will not be harassed incessantly. Lets face it, everyone makes mistakes, any honest person hates making mistakes, nobody wants to admit they made a mistake, but if you feel confident that your mistakes will not be used against you in a court of blame, you are willing, if begrudgingly, to admit them as soon as they happen. The company I work for is okay at not flashing the light of shame on mistakes but it still has a long way to go.

Second, a common, unwavering and attainable goal is vital to identifying success and failure. A common goal is necessary to map the course of a all but the most trivial corporate initiatives. Without a common goal you might as well be herding cats, that is unless herding cats is your goal. To get everyone in the company going in the same direction they must know what that direction is. A common goal is necessary so that everyone has an objective way of identifying how well they are doing, or how poorly.

An unwavering goal is necessary in the same way that a common goal is but for a different reason. A common goal gets everyone going in the same direction, but an unwavering goal keeps them going and gives them constant feedback of their progress. A goal that keeps changing, for whatever reason, be it a revaluation of progress or a change to meet market needs is flux, and goal flux in a major project is a killer. If everyday you come to work you spend time discovering where the capricious decisions of executives are, then you're never able to make a conscience assessment of your progress. Did all that work you did yesterday, or last week, get you closer to the goal; If you don't know what the goal is from day to day how can you ever know?

An attainable goal is one that all stake holders can agree on. If every goal, initiative and time line arrives to the masses from on high, why in the hell would you expect anything but peasant work? The people who are doing the work must have a say in what is and what is not attainable. I realize that every executive wants it yesterday, and every developer would work an eternity to improve a sort algorithm but that shouldn't mean that a reasonable agreement can't be made, and a reasonable goal can not be forged. While reasonable is in the eyes of the beholder, I don't believe that should negate an attainable goal. Attainable goals will probably never make both side happy, a project will always take too long in the eyes of management, and will always be impossibly short for the developers. A goal must, I repeat, must be negotiated between all interested parties otherwise it is a dictate that will end up being a very quick pile of crap or a very slow pile of crap, but in the end it will always be a pile of crap produced by a bunch of pissed off developers who have no skin in the game (Thanks Darren for that apropos line).

Third, waterfall is dead; long live waterfall. If you are fortunate enough to work for a company that is truly Agile, congratulations you lucky S.O.B. If you are like most of the IT slobs out there you are still stuck with the drowning waterfall methodology. If you can, and by God try as hard as you can, adopt as much agile as you possibly can within the constraints of the falls. I know, I know, the purists would have you believe that you are either Agile or you are not. I don't believe in such hard and fast rule. I'm stuck in the Niagra Falls of waterfall methodology but I still practive test driven developement, collective ownership and simple design. I've tried several times to get continuous integration incorporated, and thus far I haven't had anything that can be called success, but I'll be damned if that's going to stop me. With every project I am getting my group closer and closer to being Agile.

Finally, if any of this sounds familiar, well, I'm sorry, but you are not alone. There are plenty of people in exactly the same boat as you are. Don't give up, you got into IT because you love solving problems and boy howdy is this ever a problem that needs solving. Keep fighting the good fight and tell me how it went, good or bad. Good luck.

Tests? We Don't Need No Stinking Tests!

I've been banging out test after test and it is so awesome to see the results. I'm still not fully doing TDD because its so new to me that I'm still writing a little code then a little test. Slowly but surely I'm starting to flip it around to doing a little test doing a little code. In fact, its been going so well that I've started to go refactor happy. I see some poorly written code, I write a test, make sure it passes and refactor. I know, I know, there should have been a test in place and writing tests for exiting code is dangerous because you tend to write the test to the code not the code to the test; but I have to do the best I can with a code base starting with 0% code coverage. Its now up to 1.3% that's not too bad considering there are 323,658 lines of code.

I think my skill with writing tests is starting to improve as well. I've read that when you first start to do TDD that you should aim for 100% code coverage but as I mature in my understanding of the goal and purpose of the tests, I've come to believe that 80% or more is acceptable. I test the crap out of classes that have serious business logic and I tend to only hit the happy path for classes that support that business logic.

By Friday I should be ready for my first iterative release. Since I don't have management buy off for XP I'm just going to release it to the Test environment and see if I can convince anyone else to take a look at it. Then maybe I can begin to convince people that seeing results sooner and making decisions on reality rather than on assumptions is far superior to how we've developed code in the past.

Everywhere I Look, I See Scared People

I've been trying to implement some Agile practices at work but at every turn I'm getting shot down. I try to implement rigorous unit testing and I hear, "I don't know, we may not have time to implement unit testing." What this is really saying: 'I don't know… We may not have time to create quality code’. I try to set up a CI machine and I'm told that machine is going to be flashed and donated. What that says to me: 'CI isn't important to us because we can always fix defects later.' I try to do iterative development and am told, "We need to wait until all requirements are in and signed off before we can begin developing." What that says to me, 'we expect our BA's and customers to be clairvoyant and know exactly how the system, they've never seen, will work.' I could go on and on; suffice it to say that becoming Agile is going to be like parting the Red Sea - both requiring an act of God.

I've been so frustrated that only one or two people at work truly see the benefits of Agile development. They are a huge help but even they are getting shot down. We have started to practice XP in secret. While this works it really is difficult to try and implement Agile without the support of the stake holders.

The frustrations of trying to adopt XP has made me wonder why it the world is everyone afraid of trying Agile even though the current waterfall system produces nothing but abysmal failure after abysmal failure; and the only conclusion I have is that they are just scared. Scared of change and scared of the unknown. What is worse is their fear of blame; whether real or imagined people are truly scared of being blamed for trying to improve the entrenched development process. It baffles me completely. I guess it is the developer in me who is always trying to solve a problem that can't understand keeping up appearances for a process that is obviously and irrecoverably broken.

All I can hope is that my continuous vigilance and determination will someday pay off and shed everyone’s fear of success. I guess I expected to meet some resistance implementing XP but I didn’t realize my biggest resistance would be fear.