Thursday, September 6, 2007

The Refactoring Quandary

We all know by now that refactoring is important. The problem is- when do you refactor?
In my opinion, the time to refactor is when the thought first crosses your mind.

Let's say you're implementing a new feature or fixing a bug. You think 'hmm, I seem to be duplicating code' or 'looks like we could reorganize a bit of this'. Instead of pushing the thought 'this could be refactored later' to the back of your head where it will stay there for a very long time and come back to haunt you once your code is so messy that even you don't know how it got that way, the answer is to refactor immediately. Do what you can to improve your code. If you don't, then you and everybody else just pass the buck on and say "X will do that someday", and soon you are in programming hell. Moreover, if you refactor regularly, you most often need to just refactor small areas at a time. It's much better then saying we'll refactor this entire application- more often than not, throwing it out and restarting would be more appealing.

Of course there are reasons why people are frightened of refactoring. Acknowledging the need to refactor does not mean saying to the world "I have bad code". You do not have to have glaring bugs to think of refactoring. Think of it as general housekeeping. Just because the hotel housekeeping staff cleans your room every morning does not mean you left it looking like a pig sty the night before.
Another important reason is the fear of breaking code. Which is why to refactor confidently, you need to be backed by a solid suite of test cases. If you don't, then this is a very real risk you run.

Refactoring is easier said than done. You rarely find that you've been told to spend the next week refactoring. There are always more pressing tangible deliverables. However, it is extremely important to realize that the intangible ones will actually affect your tangible deliverables in the near future. Just as we need to consciously budget time to write automated tests, refactoring does not happen magically either. A small bit of effort regularly will go a long way to contributing to better manageable, extensible and flexible code.

-Luanne

Friday, August 24, 2007

At the local Udipi...

So I'm sitting in this udipi fast food restaurant waiting for my lunch (rawa idli - highly recommended), and I find myself observing the waiters going about their jobs. This is what typically happens:

1. Customer enters, sits, decides what he wants and tells the waiter.

2. Customer asks the waiter how long it will takes and the waiter gives an approximate waiting time.

3. Waiter heads over to the kitchen and bellows the order to the cooks.

4. If a customer gets impatient, the waiter goes to the kitchen to check and assures the customer 'it's almost done!'.

5. Once the order is ready, the waiter takes it to the customer's table and serves it to him.

6. If the customer didn't like the meal, the waiter gets a earful. He smiles and goes back and abuses the cook.

7. Waiter handles many customers at the same time.

8. Finally the waiter hands over the bill.


With a start I realise - it's no different from my current job. I'm sort of a Project Lead. This is what I do:

1. The client sends me the requirements.

2. Client asks me how long it would take to deliver it. I estimate and return a figure.

3. I hand the requirements over to my team, who then start working on it.

4. Client gets impatient and eager to see 'anything', so I tell them 'it's 90% done!'

5. When it's actually done then it's released to the client

6. If it's a poor quality release, then I get a earful from the client and I pass it on to my team.

7. Many such requirements are being handled simultaneously.

8. End of the month, I total up the time sheets for the billing.


!!!



I ate quickly, tipped the waiter handsomely and left.


Someday, I want to go back into the kitchen and be the cook...



Cheers,
Aldrin

Monday, June 11, 2007

How much can we test?

A couple of years back, I was introduced to unit testing. At the time, I found it rather tedious. Though it did expose bugs in our code early in the cycle, maintenance of test cases were becoming a nightmare. So the question is, what should you test, and how much should you test it? I've formed some opinions along the way- tell me what your experience has been...

First, every automated test is NOT a unit test. A unit test is simply a test that validates the smallest "unit" in your application. It could be a class, and you would be validating each operation of that class by testing its methods, for example. A test which tries to validate a business operation that spans more than one class would probably be a functional test.
A simple example would be a Shopping Cart class. A unit test could verify that deleting items from an empty cart is not possible. A functional test would be one that validates the shopping process- add items to cart, checkout, verify bill amount.

Which kinds of tests should you write? Only unit? Functional? Both?

Well, unit tests are no doubt good. You should ideally write them before you write your actual code. Ideally. In the real world of the services industry at least, there are very many projects whose scope and functionality change so fast that programmers are always playing catch up with unit tests. It is simply not possible to maintain a vast number of test cases. So writing unit tests become an afterthought. And they are the very first thing axed from the budget :-)
If we were to write comprehensive unit tests that really add value, teams would require time to do so. They would also require time to maintain them. That time is rarely granted.

So, what is the next option? What about writing functional tests? Agreed, they will not provide 100% coverage, but let us assume that we could test major business flows/processes. The amount of test cases decrease, but the ROI is visible earlier on because major flaws can be uncovered before moving into system testing. There will always be bugs. Subtle bugs that even unit tests will fail to pick up. So is it worth spending time trying to think of many, many ways to break the code when the code will certainly break somewhere in a place you did not expect it to?
I personally would write functional tests, and enhance the suite over time. For example, when a bug is reported, a test could be written for it. It could very well be a unit test. But with bugs and change requests, the suite will grow in sensible proportions.

What do you think?

Tuesday, May 22, 2007

Preventing multiple user sessions with the same user account

Often you want to prevent the same user account being used simultaneously in different sessions (business license restrictions being one reason, complex technical synchronisation problems being another)। There are two typical strategies to prevent थिस :-
#1. Prevent any new sessions while a session with the same user account exists.
#2. Allow a new session, but disconnect any previous sessions if they exists.

Imho, I think #1 can be very problematic for the user. If the user faces a system crash during his session, his subsequent attempts to login after recovery will be thwarted. Until his previous session times out, he will be left twiddling his thumbs. Using cookies to maintain the session information would be a good idea here. If you are supporting auto-login, then you are already doing something like this. A session id stored in the cookie, would be enough clue to server to reconnect to the same session. You need to ensure however, that the user does a proper 'logout' - even going to the extent of hooking your 'logout' into the body unload event if the user chooses to shut the browser window, without clicking on your 'logout' link.
Now what happens when a user logs into your site, shuts his browser, deletes his cookies and tries to login again, before his session times out ?? Let him suffer, i say ! :)

#2 is much easier to implement. All you need to do is maintain a Map of user accounts with their sessions in application scope. Add a listener for session timeouts, to remove these entries from the map when the session times out. When a new session if being created, simply look up the map for previous sessions by the user and invalidate them if present and also remove them from the map.

I'd like to hear your comments on how you achieved similar requirements।

Cheers
Aldrin

Monday, April 16, 2007

You minus IDE=helpless?

Nowadays, the IDE is your workbench. You can generate your UML, debug, run embedded servers, inspect your code, read the Dilbert strip...all from within a single application.

With each release boasting nifty features, there is very little reason to leave the comfort of your IDE.

Or is there?

In the good old days, we had no such pleasures. I remember writing code in Notepad, and was thrilled when I discovered EditPlus. Debugging meant compiling on the command line, fixing error by error till you had a successful compile, starting tomcat and testing your web app. Today, you can do all this and more at the click of a button.
This is certainly great news for the developer...and a very bad habit as well.
No doubt IDE's save you a lot of trouble and time. IntelliJ IDEA has increased my productivity tremendously and helps me with a whole lot of things- including reading the Dilbert strip ;-)
But, if I had no IntelliJ for a day, then I would still be able to code in EditPlus and look up the JavaDoc from wherever if need be, deploy my application and debug it. And that is the difference.

Too often I see IDE whizzes who can do almost anything with CTRL, SHIFT or ALT and one or two keys. But take the IDE away...and they are helpless. This is Bad Thing in my opinion. The fallout of not knowing the basics is terrible. And this doesn't just apply to software.

I have seen cases where for some reason, the embedded web server plugin fails for whatever reason. Everyone is examining their code and can find nothing wrong...and they're re-examining it for hours and hours. I say shut it down and deploy manually...but few know how to :-)
In fact, very few know how to run javac !!! Turns out that the code base is fine...it was the embedded web server....hours and hours of valuable time wasted because we refused to abandon our beloved IDE.

Consider this scenario- you've developed this fantastic application, deployed it using your IDE, debugged it and it runs like a dream. Then you go to install it at the clients site. And horror of horrors, they don't have your IDE. And won't let you install it. Now what???
You should be able to say so what? You'd roll up your sleeves, check your code out of CVS or wherever, set your build properties, run ANT, deploy, start your webserver and go home in a couple of hours to have a nice drink.
But if you know no such thing...then you'll be pleading with IT to install your IDE and when they refuse you'll have to call someone in your team and have them guide you step by step. And you'll be drowning your sorrows in many drinks after many, many tense hours. Which is a better option??

I am not condemning IDE's. On the contrary. I have used a couple (and IntelliJ by far is THE best...though beware, after using it, like me, you will hate the likes of Eclipse). They are huge help. But use them after you know how to get up and running without their help. If you are developing a simple webapp, can you code a servlet for example, without the IDE? Can you compile it? Can you deploy it? Do you know how to run Tomcat? Where to find the log files?
If yes, then go ahead...open up your IDE and be happy :-)

-Luanne