Friday, April 4, 2008

The Anatomy of a Command Line

Command Line

Command line needs no introduction among the computer folks. We all know what it is. Yet, many of the developers are really scared to work on the terminal; they rather prefer GUIs. Command line somehow makes them uncomfortable. They think it is tough. In fact, when they design their own application's command line interface, they forget some of the simple and basic things they should have taken care. It will be one of my agendas in this post.

You may read this post even if you are not a developer, this isn't a developer specific post.

Misconceptions/Preconceptions

There are two kinds of people who don't prefer command line:
  1. The ones who've used and quit because it looked tough at the beginning
  2. The ones who've never tried (I call it the startup-syndrome)
I went through both the phases until the bulb glowed over my head. It shouldn't be tough, computers are easy to use. After all, command line is not programming. It is aimed at the end user. The Operating System designers must have came up with some pattern before implementing these commands. Yes, the keyword is pattern.

The Basic Syntax

A command consists of three main parts:
  1. What to do?
  2. How to do?
  3. Other Inputs
Can You Show Me an Example?

Yes My Lord! Sure. Let's take an example. We will see the command line interface of the tail Unix utility. Here are the first few lines from the man page and I quote (please read it thoroughly once):
NAME
tail -- display the last part of a file

SYNOPSIS
tail [-F | -f | -r] [-q] [-b number | -c number | -n number] [file ...]

DESCRIPTION
The tail utility displays the contents of file or, by default, its stan-
dard input, to the standard output.
The part that is found difficult and that I would like to explain here is the SYNOPSIS. Remember the three main parts? The what? The how? And the other inputs? Let us see these three parts for this tail command.

The How part can be a little tricky for the newbies. You may even wander what is -f? -n? number? the "|" sign? Actually, that is what makes the command line interface friendly. This little table should help you understand about the syntax.
Anything inside []          = Optional
... = Can occur more than once
-something (or --something) = The How
option1 | option2 = Either option1 or option2 can appear

The "how" part can consist of two kinds of options. 1) Self descriptive options 2) Options that need more input.
tail -v -n 25 logs.txt
The "How" in the above command tells the tail command to print the last 25 lines of the file logs.txt and print the output in verbose mode. The below figure explains better.

The Design Difference

In a well designed graphical user interface, everything is presented to you. You need not remember or search for anything (like the -n option). GUIs follow the "push" model. Everything is pushed to you and you get to choose. You learn and discover things quickly. Whereas, in a command line interface, you need to tell what you want to do. You need to search and "pull" the options from the manual and tell the command "how" you want to execute it.

How *NOT* to Design a Command Line Interface

Have you ever used a command line that was like:
doSomething 49595 39504 "/usr/local/file" "/home/srikanths/dir/file"
You got the point. The "how" and the "other inputs" parts are totally messed up. You don't know the meaning of the numbers you are passing and even if you have a manual about this command, you need to refer it every time you use and you have to double check to make sure you pass the arguments correctly. A command line nightmare! Now, see the same command's better version:
doSomething\
-port 49595\
-fallbackPort 39504\
-configFile "/usr/local/file"\
-fallbackConfigFile "/home/srikanths/dir/file"
So, when you design a command line interface, make it more user friendly and follow the common pattern that is already there for decades now. There are many modules available either out of the box or as frameworks that can parse the command line arguments for you. Just search which ones are the most popular CLI frameworks for your language and choose one from that. Hope this post helped you!

Bottom Line

"The next time you tell someone RTFM, tell them how to RTFM."

References
Other posts

Friday, February 29, 2008

The Deadly Question!

One of my favorite questions that I ask during an interview is "What is a deadlock and how do you avoid them?"

Typical answers:

Definition: Deadlock happens when Object 1 is waiting for Object 2 which is waiting for Object 1 again.

Avoiding deadlocks: (Answer 1): Using wait & notify. (Answer 2): Using synchronization.

Not only is the terminology wrong, it also clearly shows that the candidate is not sure with the fundamentals of multi-threading. To be frank, I was asked the same question when I was interviewed and I wasn't able to give a proper answer even though I did good amount of multi-threading before to answer this innocent looking question.

Lets suppose there are two threads T1, and T2 running in your application. T1 is executing a method called method1() and T2 is executing method2(). method1() has acquired lock1 and now it is trying to acquire lock2. But at the same time, method2() has acquired lock2 and it is now trying to acquire lock1. method1() cannot relinquish lock1 until it gets lock2 and finishes the job; method2() cannot relinquish lock2 until it gets lock1 and finishes the job. Both the threads, T1 and T2, are now waiting for one another to proceed their execution which will never happen. This situation is called a deadlock or a deadly embrace.

See the following code that is almost sure to encounter a deadlock during it's execution.
public class DeadLockDemo {
private Object lock1 = new Object();
private Object lock2 = new Object();

public void method1() {
while (true) {
// Acquire lock1 first
synchronized (lock1) {
// Acquire lock2 next
synchronized (lock2) {
System.out.println("Method 1");
}
}
}
}

public void method2() {
while (true) {
// Acquire lock2 first
synchronized (lock2) {
// Acquire lock1 next
synchronized (lock1) {
System.out.println("Method 2");
}
}
}
}

public static void main(String[] args) {
final DeadLockDemo deadLockDemo = new DeadLockDemo();
Thread thread1 = new Thread() {
public void run() {
deadLockDemo.method1();
}
};

Thread thread2 = new Thread() {
public void run() {
deadLockDemo.method2();
}
};

thread1.start();
thread2.start();
}
}

How do we avoid this deadlock here? The typical answers like "synchronizing" the code doesn't solve the problem. Actually, deadlock happens because of improper synchronization. The answer is very simple though. Always acquire the locks in the same order. That is, acquire lock1 and then lock2 or lock2 and then lock1. Yes, it's as simple as that. You can try running the code and check it for yourself.

Till then, happy multi-threading!
Srikanth

Tuesday, February 26, 2008

Cool Firefox Tips

Firefox is my favorite browser despite it's appetite for memory. I use a few command line options and extension that is worth sharing here.



Firefox Profiles: Do you use more than one profile in Firefox? It's a very useful feature. I use it when I would like to log into multiple Gmail accounts at the same time (or you can also use it if you don't use your Gmail account for other Google services such as Reader and Orkut). My main use of the "profiles" feature is during development and testing. You can have one Firefox loaded with all the extensions in the world like Firebug, XPath viewer, various themes, etc. and you can have another light-weight Firefox with a very few extensions which you always need.



So how do you create and use another profile?

$ firefox -profilemanager -no-remote
This opens up the following self explanatory profile launcher window:





As you can see, I have one 'default' and one 'dev' profile. To open a particular profile:

$ firefox -p profile_name -no-remote
The "-no-remote" option is used from Firefox2+ when there's already a profile running.



Firefox Extensions: This is what makes Firefox truly a personal browser. You can create your own extensions or you can download and install the existing ones that are available on the internet. Typically, you browse for an extension and you install it using the "Install" button that is found on the website. But when you do it in this way, the installation only happens for that current profile you are using. To install an extension for all the profiles follow the steps below:



1. Instead of directly clicking on the "Install" button, use right-click button and select "Save Link As..." and save it to your local hard drive. Typically this file is a .xpi or a .jar file.



2. Type the following command on your terminal (or Start -> Run on Windows):

$ firefox -install-global-extension "path_to_saved_extension_file"
# for example:
$ firefox -install-global-extension "c:\downloads\firefox\firebug.xpi"
My favorite Firefox extensions are:

Other recommendations:

Happy browsing!

Srikanth



PS: One more feature you may want to turn on. Firefox on Ubuntu selects the complete URL when you double click on any part of the URL. Try double clicking on any single word on this this URL: http://codeblog.srikanths.net, if you could select the complete URL then you are doing good. Otherwise, follow the steps:

  1. Go to Location bar on Firefox (Alt + D)

  2. Type about:config and press ENTER

  3. In the Filter text box, type this: layout.word_select.stop_at_punctuation

  4. Double click to change the value to FALSE to enable URL selection while double clicking.

I learned this trick from this blog post, so all the credit goes to him/her for this tip.

Tuesday, February 19, 2008

Microformat

As I was browsing through the speculated features of Firefox3, I happened to hit something called Microformats. If you haven't heard about it before, then I must tell you it looks very interesting to me.

Microformats in plain English: The content we read on the Internet using our browser is HTML. Some of those contents belong to a particular category (logically). Examples: Contact details, Events, etc. Take this scenario, lets say that you received an e-mail from your friend and your friend has sent his new address in the content of the e-mail. How nice would it be if you can add that contact details of your friend to your favorite contacts manager applications with just a click of a button without you leaving the browser?

Take another scenario. You are going through Sun's Tech Days website and you see that there is a program next Sunday at your city at 12:00 PM. How nice would it be to add this event to your favorite Calendar application with just a click of a button so that it is added to your schedule and you will be reminded automatically? It would be very nice to do so.

For now, the contact detail or the event detail is lying in the HTML page just like any other text or image and there is no way a software can differentiate them from the normal content. This is where Microformats are going to play a big role. The web site developer while constructing the HTML page will add some meta-data to these content which will tell the browser that the microformatted content belongs to a particular category (say, a contact detail or an event). Then the browser will visually indicate you about the content in someway and provide you an interface to do the action you would like to do (say, add that event to your Calendar). Isn't it cool?

Well, this is what I understood from what I read. It could be completely different.

References:
I like the Microformat's logo, looks green and cute:


PS: I noticed several times Gmail detecting the events in my e-mails' content and presenting an option to add it to Google Calendar. Bravo Gmail! You are ahead of time!

Monday, February 11, 2008

Filter Your 'Tasks View' in Eclipse Using Patterns in TODO

The Feature: Eclipse's Tasks is one of my favorite features in the IDE. You can set reminders right there in your source code and you can see all of them in the Tasks View of the IDE which you can dock it anywhere you want. A sample screenshot of the Tasks View can be seen below.





The Problem: As you can see from the sample screenshot that many people added their own TODOs and FIXMEs. Imagine this for a big project, this will be in hundreds. The point of adding TODOs and FIXMEs right in the source code is that it can be seen more often such that we will be constantly reminded about the unfinished. But when everybody adds, it becomes a problem to keep track of your own Tasks and we may start ignoring them like spam mail. Having control is the key to using this feature, just like e-mail.



The Solution: Fortunately there's a very simple solution to this problem with a little effort. You can create and configure filters, just like you can create filters for your e-mails in Gmail. On the Tasks View you will see the button using which you can create filters. See below:



The rest of the filter configuration work is simple. The Filters dialog pops up and it's very intuitive as what all you can do with it. I typically create filter that contains the string "(srikanths): " in its description. And when I write my TODOs and FIXMEs, I make sure I prefix them with that description. You can come up with your own standard within your team and follow that.



The tasks that I write in the code typically look like this:



// TODO(srikanths): Srikanth should come back to complete this.
// FIXME(srikanths): Srikanth should fix this ASAP or he is dead.






Happy coding!

Srikanth

Thursday, February 7, 2008

Favor 'Read' Time over 'Write' Time

There are thousands of books and millions of web pages that will define modularity and explain you how to achieve them in your program. I am not going to talk about that here. I will answer you why modularity is important.

Any program can be written in just one single method (or function). At least theoretically? The people who are new to programming do this till they are told about "Abstraction", "Encapsulation", etc. Still I see many programmers not following this. They don't modularize their program well. Sure, they understand what is going on but it's not about them. Code should be written keeping in mind that it will be read many times by many people.

557774423456789.

Can you repeat the number? Don't peak! :-)

(Most of us would have not even read it completely just looking at those many digits)

Now, read this: 55-777-44-23456789.

So, which one was easier to read? And which one was easier to write? The first form (without the hyphen separator) was easier to write if you have this number memorized but it is hard to read and recollect for someone who is not familiar with this number. At the same time, the second form took some more time to carefully break at the right places and make it easy for the reader. We invested some more time in writing to save a lot of time for others to memorize this.

This is the whole point. When you write code, you surely understand and it may seem trivial and waste of time to do "separation of concerns." But it's not about you or me, its about that someone who is going to maintain your code in future long after you have moved to another project. Make sure that she won't curse you :-)

Sunday, February 3, 2008

Programming Language of 2007

And the award goes to... Python!?!

Source: http://www.tiobe.com/tpci.htm


I must tell this very frankly, I am pleasantly surprised for one reason: The programming language I learned in 2007 is Python. And now it is declared as the programming language of the year. I am feeling lucky :)

When I started learning it, I hated it for one reason ---Dynamic Typing. Coming from a heavy Java background this was a hard unlearning curve for me. I debated a lot on this topic with my friends and coworkers. I debated on Python forums about this. A very strong debate that I had can be found here (you will have fun reading this, I had fun reading my own post after a very long time!): How to program safely in Python?

Not only this, Guido van Rossum once replied in my post in one of the mailing lists when I asked about Why isn't there a try-catch-finally block in Python? It's available only from Python 2.5+. After pondering, I came to the conclusion that every programming language has its own pros and cons and Python is one such beautiful and stylish language. Yes, you don't have a compiler, yes you will have a python-bite at runtime, but guess what? A compiler only tells that your program is syntactically right. The best way to ensure that your program works is by testing, testing and more testing. Like Bruce Eckel once said, "If it isn't tested, it's broken."