What language would you use for the job? Sure, you spend all day coding in Java, but you also work on enterprise software that runs on app servers, parses XML, connects to relational databases, and does other typical enterprisey stuff. You design complicated class hierarchies and testing frameworks. Your dependencies are all injected, control all inverted. Your frameworks and APIs are legendary.
But here you are...it's 10 am and you have a whiteboard, some markers, and some simple string manipulation to do (when was the last time you had to manipulate strings anyway?). You're nervous, the clock's ticking, and now that you've got the O(N) solution in your head, you need to express it in working, readable code... and fast!
So you break out your best Java, and suddenly the language presents you with a number of distracting questions. Do you return an array of Strings or a String of words? Do you use a List or an array (and possibly arraycopy)? Since it won't technically run without one, do you bother defining a class? Is the method public, private, protected, or default? You know static is evil, but should you just make it static for the sake of the interview?
Here's how I envision a typical* interview for an entry-level position...
Java Jimmy
JJ: "OK, I think I have a working solution in my head, I'll just write it up as a method...I'll have it take a String and return a String, and I'll call it reverseWords."
public String reverseWords(String words) {
JJ: "Oh, wait, is it ok that this isn't in a class? I know it won't run outside of a class, so maybe I should play it safe."
class StringUtil {
public String reverseWords(String words) {
Me: "Hey, don't worry about that, a simple method is fine."
JJ: "And I can skip main?"
Me: "Yes, that's fine, this is just a utility method somewhere."
JJ: "OK, I should probably make it static, even though static is evil."
public static String reverseWords(String words) {
JJ: "Do you care about being super efficient? I could use String concatenation or StringBuilder."
Me: "Whatever you prefer."
JJ: "Ok, since using StringBuilder.reverse is probably cheating, I'll use Strings and an index."
public static String reverseWords(String words) {
String reverse = "";
for (int i = words.length()-1; i>=0; i--) {
reverse += words.charAt(i);
}
// now reverse words...
JJ: "Should I use StringTokenizer or regular expressions?"
Me: "Whatever you prefer."
JJ: "Hm, OK, StringTokenizer is pretty easy, so I'll use that. Do you want me to write the import statement?"
Me: "No, that's fine."
JJ: "Great."
String result = "";
StringTokenizer st = new StringTokenizer(reverse);
while (st.hasMoreTokens()) {
String word = st.nextToken();
for (int i = word.length()-1; i>=0; i--) {
result += word.charAt(i);
}
if (st.hasMoreTokens()) {
result += " ";
}
}
return result;
}
Me: "Great, now how does it perform?"
JJ: "Oh, well jeez, Strings are immutable, and I'm using string concatenation, so I should probably use StringBuilder...I'd never actually write it this way in production."
Me: "Sure, go for it."
public static String reverseWords(String words) {
String reverse = new StringBuilder(words).reverse()
.toString();
// now reverse words...
StringBuilder result = new StringBuilder();
StringTokenizer st = new StringTokenizer(
reverse.toString());
while (st.hasMoreTokens()) {
String word = st.nextToken();
for (int i = word.length()-1; i>=0; i--) {
result.append(word.charAt(i));
}
if (st.hasMoreTokens()) {
result.append(" ");
}
}
return result.toString();
}
JJ: "How's that?"
Me: "OK, great, now that you're warmed up, let's get to the main question."
JJ (inner monologue): "Holy crap, I only have 25 minutes left!"
Peter Python
PP: "OK, I'll define a simple method and use Python lists freely."
def reverse_words(words):
result = []
words = words[::-1]
for word in words.split():
result.append(word[::-1])
return ' '.join(result)
Me: "Great, can you make it even shorter?"
PP: "Oh! Of course!"
Me: "And how does it perform?"
def reverse_words(words):
return ' '.join(words.split()[::-1])
PP: "O(N), assuming that reverse, split, and join are all O(N), and why wouldn't they be?"
Me: "Nice work."
Rebecca Ruby
RR: "Oh fun! This'll be easy to code up in Ruby, is that ok?"
Me: "Sure, whatever you prefer."
RR: "OK, let's see, I want to reverse the words, split them, reverse each item, and then join them again."
def reverse_words(words)
words.reverse.split.map{|w| w.reverse}.join(' ')
end
RR: "I think I'm done. I hope I did it right. I just used some pretty basic ruby."
Me: "Wow, that was fast. What's the runtime?"
RR: "Assuming that reverse, split, and map are O(N) (and why shouldn't they be), this is O(N)."
Here are a few other things you'll have an easier time doing on your interview with Python or Ruby:
- Easily work with typical interview datatypes like strings, numbers, and lists.
- Slice and dice collections and strings
- Read to and from files
- Dynamically grow or shrink lists (it's amazing how often you actually need this in an interview)
- Create and manipulate hashtables (also comes up a lot in interviews)
- Generate test data
- Iterate over your solution and profile how long it takes for various datasets
- Just run your program. You don't need to compile it, you don't need "public static void main", you don't need classes, and you don't need to explain how you're using static even though you know it's a Bad Idea. And you don't need to choose between complicated command-line classpaths and big IDEs.
18 comments:
Java *is* more verbose, but it's not *that* bad. (Generics erased because blogger.com barfed on the angle brackets.)
public static String reverse(String words) {
List list = new ArrayList(Arrays.asList(words.split(" ")));
Collections.reverse(list);
String reversed = "";
for(String string : list) {
reversed += " " + string;
}
return reversed.trim();
}
But, yeah. Definitely more fun in the other languages. Oh for Collection.join() ...
As evanchooly showed, your java-fu is sorely lacking. Also, if StringBuilder.reverse() is cheating, then just about everything employed by either evanchooly or your python and ruby examples are most definitely cheating, so what's the point of this exercise?
To prove that you suck at java? As it stands, the only effect this blog post is going to have, is make people who are already on board with ruby or python feel very good about themselves.
I ask not to aggrevate, by the way. I merely want to highlight how this isn't going to convince anybody that's in love with java to follow your advice. They'll see your bad java code, and, perceptions somewhat coloured (pesky humans and their cognitive dissonance!), will assume that -proper- java code would be just as easy to write as your python and ruby samples.
Yes, if you had used evan's sample your argument wouldn't be quite as convincing on the surface, but at least it would be honest. And in my opinion, still plenty convincing to follow your fine advice.
A tip for those who read this, and see some point in it, but don't trust their python and ruby skills enough to pull this stunt at an interview: You may want to use groovy, which is similar to java in syntax, but has most of the benefits. And if you forget one of those nice shortcuts, just write it in java form. Generally that works in groovy.
The examples are not supposed to demonstrate perfect solutions. And certainly the Java one is a poor example of great code, but it is typical of many candidates I see who are recent graduates and who are not using an IDE.
Few candidates seem to remember Arrays.asList without looking it up. It's also a rare candidate who remembers Collections.reverse off the cuff. But for some reason everyone remembers StringTokenizer. (It's also pretty rare for a candidate to remember StringBuffer.reverse.)
In contrast, every candidate I've known who used python remembered split, join, and [::-1] (reverse). And the Ruby methods are even more easily recalled.
The point of this post is not to compare ideal solutions in the three languages, or to take shots at Java. It's to suggest that python and ruby are worth considering for job interviews. The languages, syntax, and library APIs are easy to remember and often lead to short solutions, which is exactly what you want when the clock is ticking.
Your python and ruby examples are pretty much perfect, and your java one isn't. If you're going to explain this away as representative of the median interviewee who chooses to use that language, then your argument is -entirely- different:
Your average java user is a wannabe who can't remember his libraries, whereas your average python user is much more up to date with his language idioms.
This is undoubtedly true, mostly because colleges and unis tend to focus heavily on java, and java is the language to learn when you just want to become a well paid programmer drone (or at least, so goeth the theory employed by those who care only about a fat paycheck). However, it has nothing at all to do with the language itself, nor about the quality of code written by experts.
I'm certain that if python were the default go-to language for unis and colleges, you'd get tons of clueless 'python' folks who don't know about the 3rd parameter to a slice to reverse things, and come up with a page-full to do the job.
I'd certainly rate a slice's third parameter as being equally obscure (and -less- readable) than Collections.reverse. And, if you can't immediately recall that Arrays.asList is the easiest way to turn a bunch of literals into a List, then you aren't a java programmer that should even pass an interview.
I essentially agree with your point but I reiterate my doubts that this post will convince anybody who wasn't already planning to do it.
(Off topic) Shortly version for ruby:
str.split.reverse.join(" ")
(On topic) Great post.
Personally, the last time I interviewed a developer I was looking for a good C# programmer (for programming a windows desktop application). The job interview was for a .NET developer and I must admit that if someone had come responded to my questions with some slick Python or Ruby I would have thought "not a curly brace programmer" and I would have been less impressed.
Generally I am not fussy about the syntax used for responding to interview questions, but asking an interview question that in answered by a making a single, standard API method call seems to be a waste of time and does not really show-off the talents of the candidate or help the interviewer in his quest.
Interview questions are suppose to test how candidate think, not their encyclopedic knowledge of framework APIs (unless you are looking for a language guru). In any case, newly hired programmers are rarely given the chance to influence the choice of programming language for a project.
While you're at it, in Smalltalk:
a:='abc'
a reverse
Looking at your java code again, it really, really sucks. Here's the shortest version I can come up with.
public static String reverse(String words) {
String[] s = words.split(" ");
Collections.reverse(Arrays.asList(s));
return Arrays.toString(s).replaceAll("[\\[\\],]","");
}
It's longer than the shortest possibles for python or ruby, but, they're all in the 'so trivial I could just dictate them' range. Any of these should impress your interviewer sufficiently to move on.
Scala:
def reverse(words: String): String = {
words.split(' ').reverse.mkString(" ")
}
I think that Scala fits better in a "Java developer at a job interview" context. Someone mentioned about your influence on what language is going to be used in a company. Since you implied big company it's quite unlikely that you will have some influence there. And if you applied to an interview with Java experience in your resume, then its probably what are they hiring you for. In that sense Scala is native to Java so it makes sense to use it in those tasks you mentioned.
Nothing against Python or Ruby, quite opposite, just putting things in a context. I would make a list something like this:
1. Scala or Groovy (personal preference)
2. Python or Ruby (personal preference)
P.S. Your Python examples are incorrect since you lost indentation :)
You should have used x64 Itanium assembly.
You're right that the typical Java programmer will write crap code.
And that's because 60% of all programmers probably consider themselves as Java programmers, and Ruby and Python programmers are about 1% together. And the ones who jump to non-mainstream languages probably are the ones who really like programming, and are the ones who really like to write good code.
But that doesn't mean that the other 60% are just bad programmers, just that it's much harder to find the good ones (I don't know, about 10%?) from the lot.
Thanks for all the great comments (and improved code samples). I think readers will be happy to see the shorter versions.
It's interesting to compare the 3 shortest solutions:
-- Java --
String[] s = words.split(" ");
Collections.reverse(Arrays.asList(s));
return Arrays.toString(s).replaceAll("[\\[\\],]","");
-- Python --
return ' '.join(words.split()[::-1])
-- Ruby --
str.split.reverse.join(" ")
It would surprise me to see the Java 3-liner in a interview scenario (or even in real code). The Python and Ruby examples, on the other hand, are typical.
Arguments about languages are silly. Here's what I suggest you try to answer the question for yourself. If you know Java and Ruby/Python, stop after you read this post, grab a notebook and a pencil, and solve the problem on your own.
If you don't know Ruby or Python, spend a day working through some online tutorials and playing with python or irb. At the end of the day grab a notebook and solve the problem in Java and Python/Ruby.
You might surprise yourself!
settle down reinier
becoming defensive over the fact that someone supposedly made your beloved java look 'inferior' to python or ruby is completely and utterly ... retarded
someone replied with an even shorter version of ruby code... you don't see him slamming the author by saying that his ruby sucked do you?
sheesh grow up
Dear Sir,
I love you un-conditionally.
You opened my eyes by showing how java suckss badly.
I would also like to point out that python is better than ruby but that is my personal experience.
Also, now some group in google is working for improving python speed by 5 times. so i bet java will be erased in future with all its bad features.
I request every one to try Django once in their life time to appreciate python and its capability in web applications.
Love,
Smart Programmer
(Do what u want in small time and attempt more tasks)
The jave version can be shorter if using Google Collection (cheating):
Return Joiner.on(" ").join(
Iterables.reverse(Arrays.asList(
words.split(" "))));
Post a Comment