Next time I will be a lazy programmer. I promise.
Now can this nightmare please end?
Next time I will be a lazy programmer. I promise.
Now can this nightmare please end?
Wouter Coekaerts has published some really nice Java puzzles in his site. This is my solution to the first one. My solution is not as simple and elegant as his, but hey – it works:
package you;
import clowns.Clown;
import clowns.Volkswagen;
public class You {
static final Volkswagen vw = new Volkswagen();
public static void main(String args[]) throws InterruptedException {
for (int i = 0; i < 20; i++) {
new Thread() {
@Override
public void run() {
vw.add(new MyClown());
}
}.start();
}
// I'm an ugly hack
Thread.sleep(5000);
synchronized (vw) {
vw.notifyAll();
}
// Me too!
Thread.sleep(5000);
vw.done();
}
private static class MyClown extends Clown {
@Override
public int hashCode() {
try {
vw.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return super.hashCode();
}
}
}
My solution took advantage of the fact that using a synchronized method instead of synchronizing on a private lock object gives an attacker to ability to manipulate the Volkswagen’s locking mechanism from the outside. Had the programmer used a private object for synchronization, my solution wouldn’t have worked (which is another reason why Wouter’s solution is superior).
Me: We are using this open source project, and I thought about a way to improve it for us and everyone else that use it. Maybe we should spend some time on it and contribute the code back to the community?
Boss: Don’t you want to make money out of it?
Me: This is open source! It’s like socialism – everyone give what they can and take what they need.
Boss (from the former soviet union): I’ve had my share of socialism, thank you very much!
And so the open source project remained unimproved.
Well, I took upon myself the task of learning a new web application framework for a small personal project I’m working on. Honestly, this is somewhat new to me. Aside from a short one-night-stand with an organizational J2EE framework[1] as part of my training a couple of years ago, I never had anything to do with GUI or business application development. I was quite excited about the possibility to learn a new language, new tools, new ways of thinking and gain experience with a new type of missions, and I happily set out to see what’s out there.
After a short exploration, I decided to play with Grails (aka. Groovy on Rails) for several reasons:
Well, having my exams to study for and my daily job, I didn’t have too much time to play with my new toy, but I already have several things to say[3].
While Grails has several IDE integrations, I chose to use Springsource’s STS, which is an Eclipse-based IDE as a development environment. I didn’t take me long to realize it might have been a mistake. Aside from the fact that IDE itself is heavy and slow on my machine, running Grails related commands, and have no mistake – you need to run many during the course of development, requires loading the Grails runtime, which is a slow-slow process. Having to wait several minutes for the simplest of actions to complete really ruins the working flow, and you know how much I like that.
In Grails defense I will say that my computer is almost 5 years old, and that eclipse wasn’t the best IDE choice to begin with.
So far it seems like Groovy is the down-side of this bargain for me. Of course, I’m not well versed in the language yet and I assume things will seem more natural to me as I learn more, but after reading a good deal of the getting started guide (and especially the style guide for Java programmers), I am a bit disgusted. Yes – I admit it, I am highly fond of rigid formalism and I have a slight mistrust in dynamically typed languages as a result, but this is not the issue. Right now the Groovy seems to me like a collection of random features and syntactic constructs that were plundered from other languages and forced to live together without harmony.
I don’t like the fact that there are several ways to write the same code. I don’t like the fact that return statements, parentheses and semicolons can be sometimes omitted[4]. I don’t like the ways methods were added to the JDK, which breaks any form of reasonable design.
Well, you catch my drift.
If you don’t look too hard at the Groovy code, the Grails framework was surprisingly easy and fun to get started and work with. The project is very well structured, everything has its place, most – if not all – the things that you need to do beside pure business logic have already been thought of, and everything is designed to promote good programming practices.
Of course, a good framework is really put to the test when you try to use it in ways that stretch the limits its original designers had imagined for it but I didn’t hit that spot yet so I really can’t tell.
I did have one problem with the framework, from a newcomer’s point of view. Its design relies heavily on the convention over configuration principle, which helps keep the project very clean and the development fast-paced when you know what you are doing, but it really makes it hard for me to learn how things work. When I face a new technology, one of my preferred methods of learning is by “pulling out threads” of software – I find something that I don’t understand, like a piece of code or configuration, and I follow its lead by searching strings in the project sources, configuration or compiled code, decompiling classes where necessary, until I reach some code that I do know.
I like this method because it really helps understand the “guts” of the technology or project you are working with, but with CoC, you have to know the convention to be able to follow the thread, which means that in order to learn I have to… know in advance what I’m looking for?
These are my thoughts on the subject for now. I’m sure they will change over time as I’m still green around the edges[5].
—
[1] Which, admittedly, was quite advanced for its time
[2] Which will probably be the next language I will try to put to practical use
[3] This statement shouldn’t surprise those who know me, and the fact that the real challenge with me is to make me SHUT THE F#@& UP!
[4] And sometimes not?! They make things formal, dammit!
[5] Pun intended
I think that all the programmers I know want to get better at what they do. In fact, I think that every professional who takes pride in her work, not just a programmer, wants to get better at what she does. Sadly, I figured long ago that just by doing my work and following my daily routine, I will never be able to advance in a way that satisfies me.
This is why I’ve resolved to taking active steps towards my professional development.
Surrounding myself with bright people
I think that being surrounded by smart people with whom we communicate and work well is crucial for our development. I’ve learned so much from the people I work with, and I’m not talking only about technical knowledge and methods – by comparing myself to the people around me and finding our similarities and differences, I’ve been able to find out what my strengths and weaknesses are, and highlight my strengths while working on the things that need improving.
Working on my BSc in Math and Computer Science
It is a known fact that in the Israeli IT market, if you have the right kind of military experience, you don’t need a BSc in CS in order to get a job and advance to many positions. However, I feel that the broad formal education you get in the university often proves useful in unexpected situations.
Further than that, I hope that later my education will enable me join a research position in the field.
Reading
I make a point of always reading a book or a magazine that may broaden my horizons: it can be a technical book, a book about project management, general management (I’m currently working my way through Harvard Business Review‘s essays bundles, they are quite fascinating), or any other type of book that seem like it can open my mind to new ideas, or spark my creativity.
Working on pet projects
This is something that I learned from the guy that is sitting next to me. I always say that programming is a job that leaves you with a lot of free time. This is why I always keep an IDE open in the background with some pet projects, which I use to explore concepts that I find interesting, or features that may contribute to our product but I am not “formally allowed” to code.
Following technical blogs
I try to find interesting people whose opinion I value, and follow them online. I consider this an extension of the “surround yourself with bright people” principle to smart people who live oversea and have no clue that I exist.
Writing a blog!
Having to communicate your ideas often makes them clearer in your head. Writing a blog is a way to deal with subjects you may not normally talk about with your peers. In addition, when I worked on some of the (unpublished) technical articles for this blog, I faced the fact that I had some gaps in my knowledge, which I had to fill in order to complete my writing.
As an added bonus, I am also forced to slowly but surely improve my English skills.
Teaching
Similar to writing, teaching forces you to communicate with your students. Teaching also pushes you to always learn a bit more than what you already know, because no matter how knowledgeable you are, your students will always find a way to surprise you with questions about this extra bit of information you’ve neglected.
I haven’t taught for a long time, and I really miss this experience.
What about you? How do you get fit and keep in professional shape?
I think this is a pretty common programming pattern:
boolean updated = false;
for (MyUpdater updater : MyUpdatersList) {
updated = updated || updater.update(someData);
}
if (updated) {
performPostUpdateTask(someData);
}
Obviously, this code is supposed to loop over my list of updaters (forgive my unimaginative names), give each one of them the opportunity to update the data, and do something only if at least one of them has actually modified it.
Alas! Most programming languages (Java included), will short-circuit this line, effectively preventing all the updaters after the first one from being called.
This is especially dangerous if you are writing code for future extension, and you plan for other people to add updaters later. You will probably test this loop with one updater: the one you currently need, and conclude it is working fine. The coders that will maintain this code in the future will have a blast trying to figure out what went wrong after they relied on your design!
Good thing I stepped through the code and wondered how come I cannot step into these methods!
Consider the following real-life problem: you are assigned a task to write a program that keeps a collection of objects, sorted according to some criteria, and at any given time you should be able to provide a list of the top N objects in that collection. Your program will receive events that modify the objects (and therefor trigger re-ordering of the list), and the processing of these events is time-critical. How would you implement it? What algorithms and data structures would you use?
…
My instinct, and I think that most programmers share this tendency with me, is to start thinking in Computer Science terms when we hear this question. We iterate over all the data structures we know, mentally compare their performance, try to think about sorting algorithms, weigh the options and…
Wait! Is this the right approach for this problem?
I’d argue that it certainly isn’t. In this case, all of the facts we know about our data structures and algorithms, are true in certain conditions. Take sorting performance, for instance. Everyone knows that insertion sort has horrible performance (O(n^2)), so we shouldn’t use it, right? But if our array size is small enough, and the data is already sorted, it is superior to other algorithms, so maybe for this problem it is better than any other option? What about data structures? Different implementation of the same data structure differ significantly in performance. And how does your preferred solution behaves on the production machine?
This is why I think that the best way to go about this problem is to write a small benchmark application, that compares several approaches with typical data and sample sizes, using different data structures implementations and algorithms, and run it on the machine that would eventually host the final product, if possible.
Programmers (and especially those of us who work in the field of performance measurement) tend to think that they know where the performance issue in the application will be, and that they can prepare for them in advance.
Well, they are wrong.
I’ve had the pleasure of doing performance testing and improvement several times in my career, and quite ironically, I’ve achieved the biggest improvements by undoing the damage that other programmers did when they thought they were writing some really clever, lightning fast, code[1].
Now, don’t get me wrong – I don’t say that knowing your stuff isn’t important. It is. But real-life application behavior is just too complicated to be evaluated on a whiteboard, and your performance issues will always be where you least expect them to be.
Stay humble, and measure measure measure.
—
[1] Seriously, people? Writing your own (incorrect) versions of data structures? Re-implementing String.equals, which is one of the most optimized pieces of code in the JVM? What were you thinking?!