Showing posts with label opinion. Show all posts
Showing posts with label opinion. Show all posts

Why Bill Taylor is wrong about great hackers

I've just posted an article in response to Bill Taylor's post 'Great people are overrated' over at the C42 Engineering Blog. Do take a look.

Consistent interfaces, contrived examples and define_method for instances

Whenever I see code which does two (or more) things in sequence in order to achieve one objective, I feel obliged to try to figure out a better way. It has to do with the fact that I'm pretty compulsive - I like to have to use just one interface to achieve one logical objective. I also check the lock on my front door several times every night before admitting that it is, in fact, locked.

I came across one such example in the Pickaxe when I was reading up on threads in Ruby, specifically the one that talks about synchronising a method on a single instance using MonitorMixin(p 137). Needless to say my compulsions asserted themselves, threading went out of the window and I started looking for a cleaner way to implement the example. I'm duplicating it below to save you the trouble of looking it up:
require 'monitor'
class Counter
attr_reader :count
def initialize
@count = 0
end
def tick
@count += 1
end
end
c = Counter.new
c.extend(MonitorMixin)
t1 = Thread.new { 10000.times { c.synchronize { c.tick } } }
t2 = Thread.new { 10000.times { c.synchronize { c.tick } } }
t1.join; t2.join
The authors conclude the example with this observation:
Here, because class Counter doesn’t know it is a monitor at the time it’s defined, we have to perform the synchronization externally (in this case by wrapping the calls to c.tick). This is clearly a tad dangerous: if some other code calls tick but doesn’t realize that synchronization is required, we’re back in the same mess we started with.
We'd like to fix this problem and have our code read like
c = Counter.new
c.extend(ThreadSafeInstance).make_safe(:tick)
t1 = Thread.new { 10000.times { c.tick }}
.

Before we get started trying to sort this out, I should point out that situations where you need to extend individual instances and then decorate methods on them occur rarely. You're likely to find an easier solution if you re-examine your architecture and try to identify precisely why you need to mess with instances. The example above is clearly contrived and is almost certainly a code smell. What we're going to do to fix this contrived example is what a friend of mine (Srushti, the chap behind XStream.net) called a 'freaky cool' solution - it's cool, but if you need it in real life then you probably have some design issues in your architecture. We can consider it an exercise in metaprogramming, but not much more.

This problem calls for Rails' alias_method_chain style method decoration - a means by which we can decorate tick() so that we can have two new methods, tick_without_synchronization() and tick_with_synchronization(). In Java or C#, you could achieve a similar effect by using dynamic proxies. The catch is, in this case we only want to decorate a single method on a single instance whereas alias_method_chain and dynamic proxies work on classes and consequentially modify the perceived behaviour of all instances of a class - something we don't want. Instead, we need to implement alias_method_chain ourselves, but in a way which allows us to modify just a single instance.

This shouldn't be a big deal - we can use Ruby's alias_method, right? No such luck. alias_method works at a module level; since Class is a subclass of Module in Ruby, this method modifies all instances of a class that it acts on. The same holds good for define_method. This seems problematic - if we had define_method for instances, we can implement our own alias_method and in turn alias_method_chain.

The only way I could find which allowed me to programmatically add methods to an instance was by means of extending it with a module. That's what I ultimately did - I created an anonymous module, defined the method within it and then extended my instance with that module. Here's the RSpec specification for define_method followed by the code.
describe 'An instance of', Object do
before(:each) do
@o = Object.new
end

it 'should know how to define a new method' do
@o.should_not respond_to(:ooga)
@o.define_method(:ooga){}
@o.should respond_to(:ooga)
end

it 'should not affect other instances when defining a new method' do
@o.define_method(:ooga){}
Object.new.should_not respond_to(:ooga)
end

it 'should be able to define a new method which accepts parameters' do
@o.define_method(:echo){|*args| args}
@o.echo(1,2,3,4,5).should == [1,2,3,4,5]
end
end

class Object 
def define_method(method_name, &block)
self.extend(
Module.new{
define_method(method_name, block)
}
)
end
end


Now for alias_method - spec, followed by implementation
describe 'An instance of', Object do 
before(:each) do
@o = Object.new
end

it 'should be able to alias a method' do
@o.alias_method(:new_to_s, :to_s)
@o.should respond_to(:new_to_s)
end

it 'should have aliased methods respond like the originals' do
@o.alias_method(:new_to_s, :to_s)
@o.new_to_s.should == @o.to_s
end

it 'should ensure that aliased methods are copies of, not references to the originals' do
@o.to_s.should_not be_nil
@o.alias_method(:new_to_s, :to_s)

@o.define_method(:to_s){}
@o.to_s.should be_nil

@o.new_to_s.should_not be_nil
end
end

class Object
def alias_method(new_id, original_id)
original = self.method(original_id).to_proc
define_method(new_id){|*args| original.call(*args)}
end
end

Let's apply these two new methods to the original problem:
require 'monitor'

class Counter
attr_reader :count

def initialize
@count = 0
end
def tick
@count += 1
end
end

module ThreadSafeInstance
def self.extended(instance)
instance.extend(MonitorMixin)
end

def make_safe(method_symbol)
original_method = "_unsafe_#{method_symbol}_"
alias_method(original_method, method_symbol)
define_method(method_symbol){|*args|
self.synchronize{self.send(original_method)}
}
self
end
end

c = Counter.new
c.extend(ThreadSafeInstance).make_safe(:tick)
t1 = Thread.new { 10000.times { c.tick }}
t2 = Thread.new { 10000.times { c.tick }}
t1.join; t2.join

There! The interface is much cleaner now - client code which consumes instance c needn't be aware of the fact that tick() needs to be synchronised. They need only be concerned with the single objective of tick(), that it allows us to increment Counter.

Incidentally, we cannot define methods which accept blocks using these methods we just created, a limitation of the original define_method which our implementation uses.

The way programming should be - easy

As developers, we spend most of our lives writing code - eight hours a day (usually more) at work; perhaps a few more hours at home and on weekends. In this kind of situation, a single incremental improvement in how we write code makes huge differences over time to our productivity, over all well being, and chances at achieving moksha.

In an ideal world we'd move ideas into code on a computer using our minds. We'd like to treat our code like putty, to be shaped into whatever our minds can imagine - and then reshape it as requirements change, of course :-).
Unfortunately, this isn't an ideal world, so we're forced to use the keyboard and mouse but we should never stop aspiring to the ideal of code-as-putty.

There are two common routes to this ideal, given that we're stuck with keyboards and source files:
  1. the syntax and semantics of the language itself
  2. tool support
Clearly, both help make life easier and just as clearly the level of tool support needed decreases with improvements in the language. That said, I'm yet to come across a language which wouldn't benefit from some amount of tool support. Remember, we're talking about incremental improvements, not silver bullets - a better 'rename' which ensures syntactic consistency is definitely an improvement over regexp based find-replace. Obviously, everybody has a different idea about which languages and tools improve productivity and to what degree, just as everyone has a different opinion about what constitutes 'well being'. This shouldn't prevent us from constantly moving to languages and tools which make our lives easier, yet I never see tools being discussed except during the odd flame war. We have come a long way since we crossed refactoring's rubicon in Java seven years ago, yet how many posts do we see out there about how we can do more with tools today?

Sometime ago, I'd posted a rant calling VS2008 a piece of crap. In his typically polite way, Ramesh pointed out in his post that provocative titles and rants aren't always the best way to convey one's message. He's absolutely right. So to that end, I'm going to start posting productivity enhancing IDE tips and tricks I come across as I write code every day. Posts will be short, something I can compose when I'm taking a break and getting a cup of chai or some fruit juice in the pantry. Three lines of text, a couple of screen-shots, that's it.

To start with it'll be all in VS2008+ReSharper as I'm currently developing in C#, but I intend to continue this series as I move from one language to another - and I welcome any suggestions or improvement anyone may have, whether it's Lisp, Erlang, Java, Ruby or C#. Anything which makes the lives of those on those platforms that little bit easier :-).

A little tidbit to get started - smart code complete when filling in parameters.

If you're using a method which takes a bunch of parameters, here's a quick way to fill them in without having to look up the param list for that method. Just position the cursor inside the brackets and hit Ctrl+Shift+Space and you'll get the most plausible option from the variables available. ReSharper looks at the types and names of variables in scope at that point to do this and is almost always accurate. Instead of looking up docs, you simply hit Ctrl+Shift+Space a few times and your parameters will be populated. In the shot above, even though all the parameters being passed are strings, ReSharper correctly guesses their order based on variable names.

ReSharper also helpfully pops up the parameter list in cases where methods are overloaded to help you decide how many times you should press Ctrl+Shift+Space.

Evolutionary design of interfaces and the IClass pattern

My previous post on the IClass pattern where, for example, class Tree has an interface ITree and Tree is the only class implementing ITree, sparked a small debate in the comments section on whether creating an interface for every class
  • affects coupling (I don't think it makes a difference)
  • makes it easier to design in an evolutionary manner (I think it actually runs counter to principles of evolutionary design)
A significant number of my readers disagreed, so I started to respond in a comment - but it grew so big I figured I might as well make a post of it. I'm looking forward to feedback so I can refine my understanding and correct any misconceptions I may have had.

BTW, here are the exceptions I'd mentioned where creating an interface per class makes sense:
  • you are developing a framework where you may have just one class, but third parties may wish to implement functionality in the future in ways you can't predict
  • you are forced to do so by a framework you're using like an IoC framework or certain mocking frameworks
  • and a new one from refactoring.com: several clients use the same subset of a class' interface
Basically, I'm trying to say that we're talking about OO in isolation without limitations imposed from outside. So...

If there is a 1:1 mapping between a class and an interface, then using the interface instead in no way increases or decreases the level of OO coupling. Indeed, you try to decrease coupling for a reason, right? It's so you can polymorphically swap classes in and out at runtime without disturbing higher layers of abstraction. When there is no polymorphism (just one class), what benefit do we get?
Only if there are two or more classes implementing that interface, or multiple clients seeing the same subset of a classes' interface does creating and using the Interface instead of the implementors make a difference to the way you'd write and think about your code.

When you define an interface for a single class you're imposing a perception of the ways in which higher layers of abstraction will see that class in the future, without actually knowing what behaviour it will share with its sibling classes, because the siblings don't exist yet. The idea is to wait until a sibling exists, then extract an interface based on the way the two classes are being seen by higher layers. That is how I evolve interfaces at the moment.

If there is ever any need to introduce a second class which does the same things but in a different way, then I identify the common bits and run the 'extract interface' refactoring. This creates an interface signature based on how I'm actually using the interface as opposed tempting me to predict how it may be used in the future.

Otherwise, I cannot think of a single instance where I would use the class any differently from the interface in my code. Of course the interface makes stubbing easier, but that's a limitation of Java and is easily solved by using a good mocking framework. The test is to see if you need interfaces in other languages in the same sort of situation. Does the lack of interfaces in Ruby increase coupling? Not really. Then why should it make a difference in Java?

Can someone give me an example where creating an interface for a class (with a 1:1 mapping) makes a difference to the way you write your code, without any external influences (including external frameworks)?

Why isn't Java's Object class abstract?

This is the question which Ajiit Balan asked me a couple of days ago. As I told him, I have a answer, but I'm not sure if it's correct or complete - hence this blog post. If you have any points to add, please feel free to do so in the comments. But first, Ajit's question in full:

In Java the Object class is a concrete class. Now my question is why did the designers of the Java API make the Object class a concrete class.

According to the GOF design principles one must always program for interfaces and not implementation. The designers of the Java API could have used abstraction here which is one of the OO principles.

If everything in Java is an Object implicitly then why is the Object class a concrete class? It could have be an abstract class with common methods sitting in the Object class. It could have also been designed as a skeleton class where it implemented an Object interface and provided a skeletal implementation in an abstract class called AbstractObject similar to the way the Collection classes have been designed.
Here's my 2 paise:

Creating useful abstractions is good - however, this should not be confused with abstract classes. Similarly, programming to interfaces does not literally mean using the 'interface' keyword in Java. In fact, one can still do all this in languages like Ruby or Javascript where there are no 'abstract' or 'interface' keywords. In the case of Javascript, there isn't even a 'class' keyword, yet everything is still an object. The GoF patterns book provide solutions to specific problems, some of them created by the language itself. For example, you don't need the strategy pattern in Ruby or Javascript - you'd use a block. As Neal Ford explains, nomenclature is good, recipes - not so much.
To clarify, creating layers of abstraction helps you simplify the root problem you are trying to solve - the classic example being high level language vs. machine language. Programming to an interface is essentially defining a contract which your code will adhere to. A contrived example would be 'provided a motherboard supports PS/2, I can connect any mouse with a PS/2 interface to it.' The motherboard doesn't care whether the mouse uses a ball or a laser. Indeed, you're free to change it at any point, because the motherboard isn't aware of the implementation details. All it knows is the interface.

When deciding whether to make a base class abstract or not, I have a simple rule of thumb. I ask myself, 'Is there something I need to force child classes to do in a manner which I can't predict?'. Well, actually that's the second question. The first question is, 'What's changing and can I encapsulate it?' - some standard patterns which help answer this question are the strategy, visitor and command patterns. More often than not you shouldn't need an abstract base class. Favour composition over inheritance and all that...

But back to the second question. What is it that Object says every derivative class must do? In Java, these are described by methods like equals(), hashCode(), getClass(), toString() etc. Now which of these methods can the Object base class not provide a default implementation for? None of them - they can all be given default implementations very easily. Therefore there is no case for an abstract class.

Indeed, the 'is-a' (inheritance) relationship which Java objects have with the Object class is not the only way it's done. In Javascript, a similar result is achieved purely through 'has-a' relationships, in other words, by composition. Every object has a 'parent' object accessed through the prototype field. That object in turn has another parent object. Eventually the chain terminates with the base Object (remember, there is no distinction between objects and classes in javascript). Any attempt to access a field or method (again there is no distinction) will propagate up this prototype chain until either the field is found or the chain terminates at the base Object. Javascript has no inheritance at all, everything is done through composition.

The last part of your question is about using an Object interface and an AbstractObject. In the context of all that I have already said, the answer is 'We get nothing extra from creating an interface and an abstract implementation. So why bother?' or in short, YAGNI.

Non-rails unit tests don't hit the db but Rails unit tests do

Generally when unit testing in non-Rails apps, we never write unit tests which hit a database. If we're forced to, we keep them to a minimum, treat them as a symptom of bad design and do our best to refactor them away over time. This is because you should be able to create and use models independently of your database - otherwise your code is implicitly tied to your db schema, something you want to avoid.

Thing is, this isn't true for Rails because of the neat one-to-one mapping of a table to a domain object.

Just an observation.

JavaScript on Rails is here, and it promises to be as good as Ruby on Rails!

After years of an undeserved reputation of being that half-baked, inconsistent scripting language that was used to validate form fields on browsers, JavaScript, or more precisely ECMAScript appears to be progressing in leaps and bounds. Steve Yegge predicted a few months ago that in it's next avatar (ECMAScript 4), it would have what it takes to be the Next Big Language. ECMAScript 4 supports a whole bunch of totally sexy (I can't think of a better adjective) features. To quote from the Wikipedia article:
  • Classes
  • Packages and namespaces
  • Optional static typing
  • Generators and iterators
  • Destructuring assignment (likely)
  • JSON Encoding/Decoding

Not to mention performance improvements as a consequence of the optional static typing.

Steve also obviously believes in putting his code where his mouth is, because he's gone and ported the whole of Rails - yes, you got that right, ported it line by blessed line - to JavaScript. His implementation uses the Rhino engine which runs on the JVM. My guess is this port of Rails to JavaScript will be far more effective than other attempts using mainstream languages like Java. As a language JavaScript is as (if not more) open and expressive as Ruby. If you want an example of JavaScript's expressiveness as a language, go check out the superb jQuery library if you haven't already done so. It will knock you off your feet, I guarantee you.

This just makes the case stronger for bringing business logic to the browser and getting rid go all those annoying get or post parameter based web applications. I mean seriously, if an architect suggested building a desktop thick client where the controllers and models were only on the server and the UI communicated with the controller by passing strings to it to trigger state changes in the model, he'd be considered officially insane. But the vast majority of state interaction type web applications (those with complex domain models) use such an architecture and nobody considers it odd.

Bottom line - once ECMAScript 4 is out and browsers start supporting it, all the 'thick clients are dead, long live the browser' weenies finally have a case. But only because the browser would've stopped being thin.

You may also want to read: Bringing business logic to the browser, or why you should develop in JavaScript

Be the nail that sticks out - how to get hired by an interesting company

When I've posted about recruitment in the past and how ThoughtWorks strives to ensure that truly passionate and competent people are hired, at least one comment says "But do we really need that level of competence in plenty?" or something similar. It's an interesting question, but its obvious by observing hiring practices in India's vast outsourcing industry that most people don't think so. The question is, what does this mean for the developer who cares about his code?

Traditional career paths treat writing code as a menial task (that damn 'software is a commodity' philosophy). To get anywhere, you have to make team lead in 2 years, architect/project manager in 7 and then you start scaling the heights of upper-management. You need, essentially, to go from being a hacker to being a suit. This means that at most companies, it's people who have 0-4 years of experience who actually write code. And most of the time they have little say in the design or other decision making - a highly frustrating position to be in.

So the obvious step for someone who is an alpha geek in the wrong job is to find another, more suitable one. And the truth is, there aren't that many programming jobs out there which would suit. Worse, these jobs are distributed across several companies ranging from Google down to small start-ups in stealth mode. One ray of light is that the personnel departments (I dislike the phrase 'Human Resource', I mean, come on...) of these companies are as desperate to hire you as you are to work for them. In an industry flooded with 9-to-5 developers for whom writing code is 'just a job', separating the wheat from the chaff can be very difficult indeed.

Here is some advice to help get yourself noticed by such companies. Interestingly, they will work as a filter to weed out employers like the one you're trying to get away from. It's just two words - 'stand out'.
  1. Be opinionated. You can't write code, care about it, and not have opinions. In your current organisation you may get hammered for it, but hey, that's why you want to quit in the first place, right?
  2. State these opinions somewhere for the record. A blog, perhaps. It shows the evolution of your opinions over time and gives you a talking point during an interview. Please don't blindly copy someone else's. Of course, if I needed to tell you that, then I'm targeting the wrong audience with this post :-). I'm assuming you'd be too proud to do that anyways.
  3. You don't need to make your resume conform to the industry standard. For gods sakes, some of the things I see on resumes under the 'Objectives' section are plain silly. I'm pretty sure that the people who wrote them thought they were silly too, but were forced to put them in there because everyone knows it's expected in a resume. If a company won't hire you because your resume doesn't have an objective along the lines of 'To strive for the betterment of the organisation and for personal growth to achieve success', then you probably don't want to work there, right?
  4. Don't make assumptions about career paths. Most organisations where alpha geeks are respected also have flexible roles.
  5. Say which programming languages you like in your resume. Also say why. Like I said, if you think Java is an ugly language and someone won't hire you because of that (despite the fact that you've done n projects in java, know it well and thus have a sound basis for your judgement), then you probably don't want to work there, right?
  6. Try to publish some code on your blog or on Google code or something. Link to it in your blog and your resume. Put your code where your mouth is. If you are what you claim to be in you resume, then prove it in code. My initial impression of someone goes up substantially if they've linked to their code in their resumes.

If you have any additional suggestions which I can add to this list, please let me know and I'll drop them in.

Update 2007-07-01: As promised, here are more suggestions distilled from the comments on this post. Do keep them coming.
  1. Sunil: Some people I've come across have half-baked opinions, that they throw around to impress. I'm sure they'll be shot down during interviews. Know your stuff before you go around pronouncing opinions.
  2. Amy Isikoff Newell: Be a woman.
  3. Amy Isikoff Newell: Be honest. If you took time off for something important (like having kids), say so in your resume instead of trying to hide the 'gap', as they call it.
  4. Neil Bartlett: Look for opportunities to speak at conferences. Start small, for example with you local User Group, work up from there, and in a little while you could be presenting at JavaOne.
  5. Sidu: List your programming experience as far back as it goes. I have more years of BASIC than C++ and more of C++ than Java/C#/Ruby (and this is true for several of my classmates from school). People who have done programming in school usually tend to choose it as career because they've tried it for a while and decided they like it, not because it offers good job prospects (something which happens a lot in India).

You may also want to read: What developers look for when they consider a job offer

Enterprise software development: Keeping your edge

Something not often recognised in the IT services industry around here is the fact that software is a creative process. No matter what an organisation has in terms of processes or whatever, good software development is still overwhelmingly dependent on creativity. And creativity is heavily dependent on the environment.

I've seen a couple of blog posts on cool workplaces with a whole lot of photos, one of which is here and the other here and the bigger services firms have some pretty funky campuses with swimming pools and stuff, which is pretty cool. But a funky office isn't really the silver bullet for employee dissatisfaction - indeed, a funky office which interferes with the core principles of your work - ISO, CMM, Agile, common sense, whatever - is no good at all. So a cool workplace is nice, but one shaped to help you get your job done better is far more important. If you can have both, then nothing like it. Now our Bangalore space is nowhere as cool as the Pune space in that photo - but the underlying principles remain the same. In fact, the Pune office borrows all it's principles from Bangalore - since the Bangalore office is considerably older and evolved these principles to start with - and then adds a whole load of coolness. So you'll see the same dining tables in both offices and the same lack of cubicles in both spaces. Of course, Bangalore got both the XBox and the PS2, but then Pune got the cool look - so it's all fair I suppose.

The configuration of your office is just one part of the environment, of course. There are multiple factors which contribute to a positive environment and these tend to change over time. Regularly reviewing what these factors are and trying to enhance them is something which can hugely impact employee happiness. For example, something that some of my colleagues and I have been worrying about for some time now is that ThoughtWorks India seems to be losing its edge. Unlike me, they (and they're developers, not managers, before you ask) went ahead and did something about it.
They've just gone ahead and executed an office wide retrospective to identify things people like and things people don't so we can have more of the former and less of the latter. A retrospective is an enormously powerful tool to improve environments and there is no reason why it needs only be applied to individual projects. There are always macro issues which affect employees which don't usually show up in a project retrospective. The latter inherently tend to focus more on factors specific to that project, thus effectively hiding larger, office-wide concerns and trends. Implementing one across your entire office may not always be possible - ThoughtWorks India only has about 200 employees as opposed to any of the other services firms which usually have tens of thousand of employees - but one can certainly do so within a 'sub-environment' like a single floor, say. While retrospectives started as an 'Agile thing', there's no reason why they can't be applied everywhere. The secret is to have good retrospective facilitators who can keep an even pace and have people identify the good as well as the not-so-good. It is a natural human tendency to complain about stuff and while this is important, the nice stuff is probably even more important. It also falls upon the people involved to actually act on the knowledge distilled from a retrospective to bring in change - and of course, buy-in from management is essential for the whole thing to succeed.

The other important environmental factor in an IT firm is to encourage interest in technology. There all these really cool and really powerful languages and tools out there that could hugely benefit enterprise applications. Yet we still insist on doing things the same old way to minimise risk - or so we claim. How many .Net teams in Bangalore use Resharper? How many have even heard of it? Yet anyone who has developed with it installed for even a week would never care to do C# without it. Ditto for stuff like Rails, or Python or Hibernate or Ngnix or even, in some cases, Lisp. Again, none of these is a silver bullet, but identifying problems which they solve best and then using them appropriately can greatly mitigate risk and speed up delivery. Encouraging exploration of technology is essential to maintaining an edge, which in turn is essential to most IT firms (and not just startups, contrary to popular belief). Setting up stuff like hack days, conferences and tech seminars are pretty good ways of encouraging developers to do their stuff. Nothing keeps a developer happy like a healthy dose of admiration. Seriously.

Strategies for recruiting top notch developers in a flooded job market

Hiring experienced and competent developers in India is a very, very difficult job. Not because developers are hard to come by - but because there are just so many of them that filtering out the wheat from the chaff is a herculean task.

This post includes an explanation of why this problem exists, forces in the environment which exacerbate the situation and a description of how ThoughtWorks' recruitment practices attempt to solve at least some portions of the problem.

Understanding the root of the problem
Let's start at the beginning. Why is the Indian job market currently flooded with developers? The answer to this question is fairly simple - lack of opportunity.

For nearly fifty years after independence, the only opportunity for a kid from a middle-class family in India to make it big involved studying engineering or medicine and then moving to America. Interest or inclination had little to do with career choices - one had to be pragmatic in order to be able to support oneself. While this situation has improved over the last decade or so, engineering and medicine are still the only courses which guarantee some form of employment.

Sometime during the mid-nineties, a new field of engineering surfaced in mainstream Indian colleges - computers. Here was an engineering discipline which didn't need lakhs of rupees in investment to create lab infrastructure. Buy a dozen desktops and hire a few teachers and you're ready to roll. Soon, newer colleges which only offered courses in computers started appearing. These 'IT' colleges as they were called were a great success, with as many as a dozen new ones opening every year.

Then came the outsourced services boom and suddenly there was a huge market for these skills, with far less competition than was needed to go abroad. You no longer needed to crack the incredibly difficult IIT-JEE entrance exam (probably one of the most difficult in the world for a bachelor's degree) and make it into the IITs to achieve a good standard of living - an IT job guaranteed a salary far above what was normal at the time for fresh graduates and a standard of living to match. Of course, the cream still went abroad - the advantages of more than a hundred television channels, social security and spray paint in cans (something unheard of in India even today) were undeniable.

That trend has continued to grow to the point where today, roughly 10,000 students graduate every year with some degree in computers. A very small percentage of them actually enjoy writing code and learning new stuff in the field - both very necessary prerequisites for a successful programmer. This has resulted in a dramatic drop in the overall quality of talent available at the entry level. Some companies have simply stopped looking for knowledge of computers and now hire anyone with a BE in any field. The logic behind this decision is that the knowledge of computers one can expect from someone with a BE in, say, chemical engineering is much the same as someone with a BE in computers. The company doing the hiring looks for a base level of aptitude (indicated by the fact that the candidate has earned a BE) and proposes to train them themselves. The degree to which this affects the job market is clearly visible in the number of applications the bigger services firms receive. According to this article in the Economist, Infosys alone receives approximately 1.3 million applications every year, most of them unsuitable.

One must also keep in mind that this is equally hard on the all the people forced into software because (unlike in the first world) one does not get employment simply because one is educated in a certain area. I have several friends who graduated as engineers in various disciplines who have been forced into software jobs simply because there was no other alternative. If this is the case with engineers, it is easy to imagine what the situation is in fine arts, nursing or any other field where demand is driven from within the country rather than from without. But that rant is worthy of an entire post and I'll get around to it some other time.

One complicating factor is that demand from the software industry has also grown proportionately. The leading services firms like Wipro and Infosys routinely hire 20,000 people every year. A simple Google search for the keywords Infosys and hires brings a wealth of information to light. This makes for a very competitive market, where demand actually outstrips by a substantial margin.

Another is the way in which the career of a developer progresses in the majority of Indian firms. It is taken for granted that everyone eventually wants to become a manager, since that's where the money is. Whether he likes it or not, but his second or third year a developer is a team lead and by his seventh a project manager. Each step up the ladder means less hands-on coding - which most don't really miss anyway. The leveraged model followed in these firms result in developers being treated very poorly, with all the benefits accruing to managers. At the time of writing, the average developer with two years of experience could expect to earn approximately four lakh rupees a year before tax while his project manager took home that same amount simply in bonuses, with his entire package amounting to five times that. Finding a developer with ten years of experience is practically impossible. All you'll find are people with ten years experience who are managers and who used to be developers five years ago.

ThoughtWorks' recruitment process
There are two basic principles
  1. Leave assessing the capabilities of developers to other developers
  2. Don't hire developers without seeing their code
I'll get to these in a bit; we first need to do some filtering. Unfortunately, I have no earth shaking revelations here. The process is quite simple.
  1. Recruitment receives a CV
  2. They give it a once over to check that there is alignment in technologies (at the moment, this would include Java, C#, Ruby and Python)
  3. They look at the project work the candidate has been involved in. This is especially important for fresh graduates as little importance is attached to pure academic performance. The question is: Is the candidate interested in coding?
  4. They call the candidate in and administer a written test consisting of a dozen logic based questions - hardly rocket science.
Once the candidate clears this, we move onto the next level - writing code. Like Joel Spolsky says so succinctly in point 11 of 'The Joel Test', 'Would you hire a magician without asking them to show you some magic tricks? Of course not.' I personally feel it's pretty unrealistic to hire a developer without having him write code. Indeed, we feel so strongly about this that we get them to write code not once, but twice. The reason we actually have that logic test I mentioned is simply to ensure that ThoughtWorks' developers don't get flooded with too many code reviews and interviews. It isn't the best way to filter by any means, but it'll have to do until we come up with a better way.

So once a candidate clears the logic test, we send him a coding problem and ask him to solve it in (at the time of writing) either Java or C#. If the candidate prefers to do, say, C++, Ruby or Python, that too is acceptable. Once the candidate solves the problem, he emails it to us and it is assigned to a developer for review.

The objective of the review is to see if the style of writing code is up to the standard that we expect on our projects. This standard would of course vary from organization to organization depending on the kind of work they do - a company which specialises in kernel code in C may be completely indifferent to the candidate's Object Oriented Programming skills. In our case, the focus is very much on OO - for example, we occasionally receive code badged as C++ but which don't have a single class and is purely procedural. Such a submission would not be accepted because it doesn't make sense given the kind of work we do. The reviewer does base his expectations upon the number of years of work experience - you can't realistically expect a college grad to write unit tests, say. If they do, that's awesome, but if they don't - no big deal.

Once the candidate's code clears the code review, we enter the final stage of the process. The candidate is asked to come into one of our offices for a round of 'pairing' on his code. Here, he works with a ThoughtWorks developer to modify his code submission to handle the same problem but with more complex requirements. There are several takeaways. First, people who fudged on the code submission will never make it through this round. Second, the ThoughtWorker doing the pairing can fairly accurately assess the level of competence of the candidate, his openness to new ideas and his general exposure to programming concepts in general.

The pairing is followed by two rounds of interviews, with a couple of ThoughtWorks developers on the panel in each. I'm not going to go into the style of interviewing in detail - personally, besides technical competence, I look for two things:
  1. Does the candidate have opinions on technical subjects?
  2. Is writing code one of the top three things the candidate does in his or her spare time
Here I don't look for a 'right' opinion or a 'wrong' opinion; it's just a way of assessing the candidate's interest in technology in general (and I make it very clear to the candidate that contradicting the interviewer's opinion is not at all a bad thing :-)). Any opinion is a good thing and I make sure that the topics covered by the question are not something with very clear-cut positives or negatives. The ambiguity makes for good conversation.

These three rounds are followed by all the ThoughtWorks developers involved getting together for a chat and figuring out whether the candidate should be hired. If there is any area where there are still unanswered questions, the candidate may have to face a third panel. The final consensus of these developers is what decides if the candidate is hired or not.

Summary
The Indian job market is flooded with developers. Identifying good developers isn't easy and at a bare minimum, candidates must be asked to demonstrate their competence by writing code and must also clearly prove their inclination toward coding for fun.

When should you choose Google's GWT for your web app?

Up until about ten months ago, very few people would have considered javascript as a language in which one could build significant portions of the UI of an enterprise application. If, say, I needed to display a table of information with support for sorting and filtering, I would have been far more likely to do this processing on the server than to write it in javascript - simply because clean, maintainable and testable javascript code is not very easy to write - in contrast to something in say Java, C# or Ruby.

I guess it's pretty obvious where I'm coming from. I'm talking about the classic enterprise application where the focus is developing a robust code base with excellent test coverage which allows for easy maintenance and where the language of choice has good tool support so refactoring is joy for all concerned. These constraints pretty much eliminated javascript. Why is this so?
  • Javascript is a dynamic language. This requires that the developers be more disciplined.
  • Javascript (and other dynamic language) tool support has improved dramatically over the last couple of years, but still lags far behind Java and C# (with ReSharper installed, that is ;-))
  • Unit testing, while it exists, isn't very convenient.
  • This is a bit of a repetition but whatever; good Object Oriented Programming is very hard to do in javascript. And while you can do some pretty powerful stuff with blocks and closures, it takes a certain kind of developer to do a good job of it.
  • Cross browser compatibility. This is a complete nightmare. Of course I'll be the first to admit that on most enterprise projects there is just one target browser.

Bottom line - the life saving test-code-refactor cycle is far more difficult to implement when coding in javascript.

Once GWT comes into the picture, the scenario changes dramatically. GWT allows you to code in Java and compiles all that code into Javascript. What's more, the DOM element wrappers that GWT provides mimic Java Swing. As far you're concerned you are now in Swing territory with all it's tried and tested approaches and patterns. GWT also provides it's own implementation of JUnit which look and feels much the same as it's parent (no setUp(), but you can't have everything, what?) Most of the overheads of working with javascript for UI are removed (and yes, a few are added, what with Java not being dynamic :-))
You can now bring the awesome power of IntelliJ or Eclipse to bear on the problem. You can write all the unit tests you want. You're no longer worrying about that annoying javascript filterable table which five different developers have worked on and the customer really likes but which is now brittle and utterly unreadable.
You've now got a neatly separated domain model, presentation model, controller and view.
And it's all unit tested.
And you can refactor all you want.
And async calls/AJAX become utterly trivial.
And it's browser compatible.
No more muttering about having to manage with simple text renames instead of Alt+Enter/Ctrl+1. No more muddling around with explicit XMLHttp or JSON calls. The latter are now abstracted to simple RPC style method calls.

Of course, nothing is perfect. First, you need to choose between GWT layouts and CSS. Second, GWT apps are single page apps with all changes handled via DOM manipulations. If you're developing a site where users are likely to just drop by to view a single page for a short span of time (IMDB, Amazon - you get the picture...), then it doesn't make sense to dump 200KB of javascript on them - which is pretty average for a sample GWT application. The biggest danger is of course the temptation of trying to develop a full fledged thick client in the browser. Javascript executes pretty slowly compared to thick client UI written in managed languages - and this remains true even with the dramatic improvements in performance we see in Firefox 2.0 and IE7. Just try creating a simple application supporting the kind of complex drag-drop we see in many thick clients. Performance starts to degrade rapidly and soon the app practically freezes in the browser. The pitfalls are many and it is very important to keep in mind that GWT only offers the convenience of developing with a thick client paradigm and that your code is ultimately interpreted javascript which is going to be doing plenty of DOM manipulation. There are dozens of such nits one can pick - 'nuff said.

To summarize - thanks to GWT, we are now in a position to develop complex, rich, AJAX web-applications considerably faster and more reliably than we could using hand-coded javascript. The code base is more robust, easier to maintain and enjoys much better tool support. There will probably be some loss of performance, but one of the goals of the GWT team is to make the GWT compiler be to javascript what modern C/C++ compilers are to assembly. You just assume that most of the time the compiler can optimize far better than you can. GWT also costs you nothing and is completely OSS under an Apache licence and is being developed by a crack team of Google coders. It's just as important to remember what GWT isn't. GWT isn't a javascript library - it's a compiler. GWT also isn't a full stack solution - for that you'll have to whip up your own (I've had good experiences with Hibernate and XStream) or you can look at something like Spring.

Update: 2007-06-07
There were several thoughts which came out of this, one of them being that the whole model of web development is pretty messed up for certain kinds of applications. I've written a post explaining what I mean by this and why we should have our business models on the browser in javascript and use AJAX only to keep them synced with the server. You can find it here.

You may also want to read: The difference between a web application and a website
You may also want to read: Bringing business logic to the browser, or why you should develop in JavaScript
You may also want to read: JavaScript on Rails is here, and it promises to be as good as Ruby on Rails!