Archive for July, 2011

CV Likes And Dislikes

2 commentsWritten on July 31st, 2011 by
Categories: work/career

Last week, i posted the following tweet:

Bart De Keersmaeker replied with an interesting question:

I don't read a lot of CV's in my current job (in this case, i was just filling in for someone else who was on vacation), but in my last job i did a lot of technical screenings and have seen more than my fair share of CV's. I don't really have a 'number 1 item' that is guaranteed to get your CV in the 'must-interview' pile. But there are things that i love to see on a CV, and there are things that i absolutely hate to see on a CV. While reading this, please keep in mind that i am a developer and that my opinions of what makes a good CV are most likely entirely different than those of recruiters (since most of them just scan for buzzwords and specific technology mentions). If you let this influence your CV, don't complain if it actually makes it harder to get through the recruiters. But i do think that once (if?) your CV makes it into the mailbox of a developer, it should improve your odds.

Dislikes

  • Mentioning every single technology/framework/library you've ever worked with. Keep in mind that less is more. Just list the important ones. There's no point in providing a lengthy list of stuff that nobody is using anymore. Also, group them into categories (languages, ORMs, IOC containers, testing frameworks, etc). Believe it or not, that is a very easy way for you to show that you can at least categorize them, which is something that many people who list every single thing they've ever used aren't often capable of doing. Grouping them in categories also indicates that you're aware of the concepts behind them, which gets my hopes up that you're the kind of developer who can easily apply his knowledge of those concepts to similar frameworks/libraries/tools/whatever which you may not have used yet. Also, don't list anything that you don't feel comfortable answering questions about. Always assume that you will be questioned about anything that you mention.
  • Mentioning every single project you've ever worked on. Again, less is more. Mention the important ones and describe them briefly (a couple of sentences at most). If they weren't very interesting (and that's not necessarily a reflection on your abilities so don't be afraid to be honest about this), just list them as 'various forms-over-data applications' or something like that. I'll know what it means, without having to read the same thing over and over again and i will appreciate the honesty.
  • Repetitiveness in job descriptions. There's nothing wrong with mentioning your role on the projects you've worked on (actually, please do so!) but keep it short and don't make it look like a copy/paste job (unless you're only listing the role). There's really no need in repeating the same responsibilities and tasks over and over again, and it sort of indicates an inability to communicate efficiently.
  • Dogmatic statements. I love opinionated developers. It's an indication that you're serious about your job and usually (though not always) shows a level of passion. However, if i get the impression that you're incapable of compromising, don't expect an invite. If you're going to be working with other developers, i need to know that you are capable of putting your own preferences to the side in favor of any team-preferred solution. I want you to be open about those preferences, but if there's a "my way or the highway"-vibe, i'd be reluctant to have you come over for an interview.
  • Bad grammar and spelling. If i get the impression that you couldn't even take the time to proofread your CV, i'm going to assume you're unlikely to do so with your code before you commit it, or mails before you send them.
  • Unexplained overlapping dates. Be sure to explain any overlapping dates between projects and assignments. Every time i see overlapping dates without an explanation, i can't help wonder whether it's a mistake or not. A CV should not contain mistakes, because that's another sign of sloppiness.

Likes

  • Mentioning Open Source contributions. It shows that you're passionate about what you do which unfortunately, is rather rare. It also gives me a chance to check out your code which is always very telling. Also, if you have a GitHub account it definitely makes sense to list it. It not only gives me access to the code you published, it also allows me to see how you interact with other developers if you get contributions to your code or submit contributions to other projects.
  • Mentioning community involvement. Giving talks, going to (or helping with the organization of) conferences or any other developer focused events, blogging, etc... mention it, even if it's just 'small' stuff. In the case of blogging, be sure to include a link to your blog as well. All of this stuff shows that you care about improving as a developer.
  • Listing your favorite technical books and/or what you're currently reading. Another good indication that you're willing to invest some of your personal time to improving as a developer. It also provides a good look into your technical interests, which can lead to interesting conversations during an interview.
  • Keeping things short and to the point. Nuff said :)

To be clear: i don't consider open source contributions or community involvement as requirements, but it certainly increases your odds to get an interview. It is however unrealistic to assume that everyone has the time for that or even wants to do that. There are plenty of good developers out there who don't contribute to open source projects or blog and i'd be more than willing to invite them for an interview if their CV avoids the Dislikes.

Geek Browser Usage

17 commentsWritten on July 25th, 2011 by
Categories: Off Topic

About a year and a half ago, i had a short post about the increasing userbase of Chrome. It included the following graph:

image

I was interested to see how browser usage amongst us (geeks) has evolved since then. In the original post, i mentioned that i still used Firefox at home (where it's a surprisingly critical tool for most of us geeks) but had started using Chrome at work. These days i don't have the patience to wait for Firefox to start, so i'm using Chrome both at home and at work. Not only because of speed and just an overall nicer user experience (IMO), but also because it wastes a lot less memory than Firefox (a pet peeve of mine).

So i quickly gathered the numbers of your visits to this blog between February 2010 and June 2011 to see how it was evolving. Obviously, it's a relatively small sample since i'm only averaging a little over 1000 views a day in that period, but it's not exactly insignificant either.

The colors for each browser remained the same, so it's easy to compare with the previous image. While i no longer use Firefox myself, i was surprised to see its market share (at least among my readers) drop from 70% to slightly over 30% in less than 3 years. That is quite a drop, though i do expect the majority of tech-related sites/blogs to have similar drops in their Firefox stats because i can't really think of a reason why my readers would differ significantly statistically in browser usage from most other tech-related blogs/sites. Meanwhile, we notice that IE is doing a remarkable impersonation of Microsoft's stock value.

Did you change browsers in the past year/months? If so, what switch did you make, and why? In my case: faster startup time, better experience and less memory usage made me switch from Firefox to Chrome. How about you? Also, with Microsoft's renewed focus on the browser, how likely are you to switch to IE9 or IE10? I don't use IE9 because i didn't like the UI, but have to admit that i haven't really given it a fair chance. The fact that i hardly use Windows at home obviously doesn't help either :) . And what are your thoughts on Firefox turning things around? I don't really like their odds, though i hope things remain largely competitive over the next few years.

Clean Code Versus Great Code

24 commentsWritten on July 21st, 2011 by
Categories: Code Quality, Opinions

I've had some interesting discussions with other developers about writing code recently. I often have the impression that some developers put too much emphasis on clean code. Don't get me wrong, i strive for clean code as well, and have written about its importance quite a lot in the past couple of years. But when i'm coding, clean code is my secondary goal and it could never take the place of my primary goal: making it work. And preferably, i want to make it work great.

A lot of people love to talk the talk when it comes to writing clean code. They'll stress their dedication to it, in some cases even wearing Uncle Bob's green band while coding so they'll never lose sight of what's incredibly important to them: writing clean code. Unfortunately, i've noticed on numerous occasions that many of these people don't always put as much emphasis on what the code is doing compared to how it looks. Sometimes they don't really bother to learn what their ORM is doing behind the scenes. Or they'll prefer to use something like Automapper to map entities to DTO's even though it is woefully inefficient compared to simply retrieving projected data. They don't always think about the cost of multiple remote calls or sending way too much data over the wire. And when they're not perfecting the art of writing bowling games over and over again, they just might hit the database in loop.

Clean code is not necessarily great code, nor is great code necessarily clean code. To me, great code is code that works great, performs great, is easy to understand and easy to change. In that order. I know all too well how important it is to easily understand code when you first read it, and to be able to easily and safely make changes to it. But no matter how easy it is to read or change, if it's not doing what it should be doing (including covering all the corner cases) or if it's taking more than its fair share of time to do it, it's not good code. Sure, it might be clean, but it's not great, is it?

That doesn't mean that you should indulge in premature optimization. Unless you have Neo-like skills in this coding Matrix, you're unlikely to be right in even a quarter of all scenarios that you want to optimize prematurely. There are however a few guidelines which will help you avoid most common performance problems. Most other situations are better left ignored until proven by a profiler to be a bottleneck. But you should at least think about what the code is actually doing and whether or not any downsides to that are worth the cleanliness. Don't hesitate to go with the slightly less clean looking code if that code makes more sense from a correctness and performance point of view.

By all means, strive to write clean code. But think twice before you sacrifice its ability to be great.

First Steps With MongoDB, Mongoose and Jasmine-Node On Node.JS

2 commentsWritten on July 20th, 2011 by
Categories: JavaScript, mongodb, mongoose, node.js

(NOTE: i'm still learning since all of this stuff is very new to me, so everything i say here should be taken with a grain of salt. Better solutions/approaches than what i'm doing are likely available and i'd definitely appreciate good tips from anyone who reads this.)

I started working on my breakable toy, and the first thing i wanted to get working was storing my documents in MongoDB and getting them back out again. I first read Karl Seguin's The Little MongoDB Book because it's a great introduction to MongoDB and to working with document databases in general (btw: it's free, only 33 pages and very well written => highly recommended!).

I originally intended to use MongoDB directly in my code, but once i realized that i wouldn't be able to simply create entity types with their own behavior and just store them in the database, i looked for alternatives. The 'problem' is that MongoDB just expects documents, which are JavaScript objects. But if you pass it a JavaScript object with functions, it'll just store those functions as strings. Not exactly what you want. You can move the functions to the prototype of the object, and if you have more than a few instances that's almost always better than storing the functions in the object itself, but MongoDB doesn't care about the prototype and doesn't return objects with their original prototype when you execute queries. There is a rather ugly trick that you can use to change the prototype of the object (settings its proto property) but it's not official JavaScript and even though Node itself relies on that ability, it felt like too much of a hack to use it. I also didn't feel like writing a layer of infrastructure code on top of the MongoDB driver because then i'd just spend too much time working on infrastructure stuff which i was hoping to avoid on this project.

So i looked around and found Mongoose. It presents itself as an ORM-like layer on top of MongoDB which it kinda is, though i prefer to think of it as an Object Document Mapper instead of an Object Relational Mapper since they definitely differ in significant ways. Anyways, let's get to some code. As mentioned in the first post about my toy project, the goal is to generate invoices and timesheets for the work i do for my customers. So i started off with 2 entities (obviously, i'll need more, but this is enough to get started):

    var mongoose = require('mongoose'),
        Schema = mongoose.Schema,
        ObjectId = Schema.ObjectId;
        
    var customerSchema = new Schema({
        name: { type: String, required: true },
        address: {
            street: { type: String, required: true },
            postalCode: { type: String, required: true },
            city: { type: String, required: true },
            country: String
        },
        phoneNumber: String,
        vatNumber: { type: String, required: true },
        contact: {
            name: String,
            email: String
        },
        includeContactOnInvoice: { type: Boolean, required: true, default: false }
    }); 

    mongoose.model('Customer', customerSchema);
    var Customer = mongoose.model('Customer');

    var performedWorkSchema = new Schema({
        date: { type: Date, required: true },
        hours: { type: Number, min: 1, max: 8, required: true }
    });
    
    mongoose.model('PerformedWork', performedWorkSchema);
    var PerformedWork = mongoose.model('PerformedWork');
    
    var activitySchema = new Schema({
        customer: { type: ObjectId, required: true },
        description: { type: String, required: true },
        hourlyRate: { type: Number, required: true },
        performedWork: [performedWorkSchema],
        billed: { type: Boolean, required: true, default: false }
    });

    activitySchema.methods.addPerformedWork = function(date, hours) {
        this.performedWork.push(new PerformedWork({ date: date, hours: hours }));
    };
    
    mongoose.model('Activity', activitySchema);
    var Activity = mongoose.model('Activity');

There's quite a bit going on in this piece of code already. This defines the schema of our entities. Some of you might be thinking "wait a sec, i thought document databases were schema-less?". They are indeed, but Mongoose uses these 'Schema' instances to generate constructor functions for your entity objects and to give them some interesting behavior out of the box. Those schema-definitions in the code are still meaningless as far as MongoDB is concerned. But for Mongoose and our code, they certainly are important.

As you can see, we define a Customer type which has some properties, as well as embedded Address and Contact objects. When properties are made required or given default values, it only has an influence on Mongoose. I could still connect to MongoDB through its shell (which is awesome btw, check Karl Seguin's book for some interesting examples) and insert whatever i want in the collections (similar to tables in a relational database, though there is no schema that is upheld for the elements in the collection). We also have a PerformedWork type, though there won't be a collection in the database for those instances. You can see in the schema of Activity that its performedWork property holds an array of PerformedWork instances. We just mapped a one-to-many without requiring a separate MongoDB Collection (or table, if you prefer to think of it that way). If you're using MongoDB directly, you could just put whatever you want in an array-property of a document. For Mongoose, it's important to know the structure of the data, so you have to define a schema for embedded documents in arrays. Notice also that i can easily define min and max values for the hours property of PerformedWork. You can go a lot further with validation in your entity objects, but i haven't looked further into that yet. Also interesting to note is that Activity has a customer property, in which we'll store an ObjectId. It means that the customer property will refer to a customer through the id value that it holds, but it is not an actual Customer reference. I'll show you how the actual documents are stored in the database later on in this post.

Another thing that you'll probably find weird is this:

    mongoose.model('Customer', customerSchema);
    var Customer = mongoose.model('Customer');

The first line basically tells Mongoose that there is a 'Customer' type and the passed in schema instance is the one that Customer instances should be based on. The second call to mongoose.model actually returns a constructor function which we can use to create our types or to execute queries through methods on the constructor function. Sounds weird, but in JavaScript a function is a first class object, which means that a function can have properties as well, and those properties can in turn contain other functions. Think of it as static methods... it's not entirely the same, but it's sort of similar, sometimes. I'll try to make the rest of this post less confusing than this paragraph was :)

To make sure that my entity objects can be stored in MongoDB and retrieved again, i wanted to write some automated tests. While there are a few good testing frameworks for JavaScript, i'm going to (try to) use Jasmine exclusively, through Jasmine-node (which just runs the tests on Node). Jasmine is a BDD framework, so a lot of people probably wouldn't use it for more technical tests or exploratory tests, but i'm testing technical behavior here so i think it still fits.

Suppose i want to test some of the behavior related to saving a customer, i'd start with something like this:

describe('when a customer is saved', function() {

});

Within the function that is passed to the describe method, i can start adding some tests. For instance, here's one that tests whether or not Mongoose applies the validation rules i specified on my CustomerSchema:

    describe('with none of its required fields filled in', function() {
        it('should fail with validation errors for each required field', function() {
            var customer = new Customer();
            customer.save(function(err) {
                expect(err).not.toBeNull();
                expect(err).toHaveRequiredValidationErrorFor('name');
                expect(err).toHaveRequiredValidationErrorFor('vatNumber');
                expect(err).toHaveRequiredValidationErrorFor('address.street');
                expect(err).toHaveRequiredValidationErrorFor('address.postalCode');
                expect(err).toHaveRequiredValidationErrorFor('address.city');
                asyncSpecDone();
            });
            asyncSpecWait();
        });
    });

This test tries to save an empty customer object to the database, but our CustomerSchema specifies that a couple of its properties are required. Our customer object has a save method (created by Mongoose), and we need to pass it a callback which will be executed after the customer has been inserted. On Node, all I/O calls are asynchronous so you have to tell Jasmine-node to wait for the callback to executed, which is what the call to asyncSpecWait() does. When we get in our callback, we assert that the passed in error object (typically named 'err') is not null, and then we use the toHaveRequiredValidationErrorFor method to assert whether the expected validation error messages are present. The toHaveRequiredValidationErrorFor method doesn't come with Jasmine, it's a custom matcher which we make available before each test:

beforeEach(function() {
    this.addMatchers((function() {
        var toHaveValidationErrorFor = function(err, validatorName, propertyName) {
            if (!err) { return false; }
            if (err.name !== 'ValidationError') { return false; }
            var value = err.errors[propertyName];
            if (!value) { return false; }
            return (value === 'Validator "' + validatorName + '" failed for path ' + propertyName);
        };
                
        return {
            toHaveRequiredValidationErrorFor : function(propertyName) {
                return toHaveValidationErrorFor(this.actual, 'required', propertyName);
            },
            toHaveMaxValidationErrorFor: function(propertyName) {
                return toHaveValidationErrorFor(this.actual, 'max', propertyName);
            }
        };
    }()));
});

We pass an object containing 2 functions to the addMatchers function, which will in turn make those 2 methods available to our expectations.

Let's take a look at a more interesting example, saving an Activity object with an array of PerformedWork instances:

    describe('with valid performed work added to it', function() {
        it('should be inserted as well', function() {
            var activity = new ActivityBuilder().build();
            var today = new Date();
            var yesterday = new Date();
            yesterday.setDate(yesterday.getDate() -1);
            activity.addPerformedWork(yesterday, 8);
            activity.addPerformedWork(today, 6);
            activity.save(function(err) {
                expect(err).toBeNull();
                Activity.findById(activity.id, function(err, result) {
                    expect(result.performedWork.length).toBe(2);
                    expect(result.performedWork[0].date).toEqual(yesterday);
                    expect(result.performedWork[0].hours).toEqual(8);
                    expect(result.performedWork[1].date).toEqual(today);
                    expect(result.performedWork[1].hours).toEqual(6);
                    asyncSpecDone();
                });
            });
            asyncSpecWait();
        });
    });

The ActivityBuilder constructor constructs a typical builder object. I won't go into the details of this pattern, and i won't list the code since this post is already getting a bit too long but you can look at the code here if you're interested. Anyways, back to the test. We're creating an activity object and using the addPerformedWork function (which we added to ActivitySchema.methods in the first code snippet) to add some performed hours to the activity. We expect the save function to not cause errors, and then we launch a simple query: finding an activity by its id value. Note how we use the findById function through the Activity variable. That Activity variable points to the constructor function which creates activity instances when invoked directly, but as i mentioned earlier it can have properties, which can hold functions, of its own. Notice the syntactic similarity with calling a static method in a static language. Behind the scenes it's entirely different, but from a conceptual point of view, it's sorta the same. As you can see, in this test the save operation works, so what does the activity object, or better yet, document look like in the database? Here it is:

{ 
    "performedWork" : [
        {
            "_id" : ObjectId("4e25f7d2041ec8c006000006"),
            "date" : ISODate("2011-07-18T21:32:02.652Z"),
            "hours" : 8
        },
        {
            "_id" : ObjectId("4e25f7d2041ec8c006000008"),
            "date" : ISODate("2011-07-19T21:32:02.652Z"),
            "hours" : 6
        }
    ], 
    "billed" : false, 
    "_id" : ObjectId("4e25f7d2041ec8c006000005"), 
    "hourlyRate" : 75, 
    "description" : "some cool project", 
    "customer" : ObjectId("4e25937456436de850000006") 
}

It doesn't actually store it with all that whitespace, i just formatted it to increase readability. Anyways, what's interesting here is that we have our array of PerformedWork instances embedded right here in our document. So whenever we retrieve this activity instance, we automatically get its PerformedWork instances as well. Also notice the _id properties. We never defined id properties in our schemas, so MongoDB automatically adds an _id property. The id value is filled in by the MongoDB driver before the document is sent to the database. And as you can see, our customer property simply holds an ObjectId, not an actual customer document. Customers are stored in the customers collection, and an instance of a customer in MongoDB looks like this:

{ 
    "address" : { 
        "country" : "some country", 
        "postalCode" : "1234", 
        "city" : "some city", 
        "street" : "some street" 
    }, 
    "contact" : { 
        "email" : "some.email@gmail.com", 
        "name" : "some name" 
    }, 
    "includeContactOnInvoice" : true, 
    "_id" : ObjectId("4e25f7d2041ec8c006000016"), 
    "vatNumber" : "0456.876.234", 
    "name" : "some customer", 
    "phoneNumber" : "123456789" 
}

Pretty self-explanatory i think.

That's enough for this post. We've seen how we defined our objects in Mongoose, got a glimpse of Jasmine and covered some very basic interactions with MongoDB. I'm going to post more on this stuff as i continue working on my toy project, though i won't make any promises on how long it'll take before new posts will show up :)

This code will likely evolve significantly in the next couple of weeks/months, and if you're interested you can always follow its evolution on github.

Arguing About Developer Communities Doesn’t Make Sense

9 commentsWritten on July 17th, 2011 by
Categories: Opinions

There's been a lot of arguing about the differences between the .NET developer community and the Ruby community lately. It started because of a developer who moved to Ruby and then wrote about how great that community is compared to the .NET community. I'm not going to link to the original post or any of the reactions to it. I'm also not going to name names because some ego's don't need to be inflated more than they already are, and the people involved will probably feel stupid enough already a year from now about some of the things that were said. And to be clear: that goes for people on both sides.

The original post was a rather silly rant where the author vented his frustration with the community he had previously been a part of. And yes, some of you are currently thinking "umm Davy, didn't you do the exact same thing last year?". I sure did, and i know now how stupid it was (personal growth for the win, amirite?). I too was very frustrated with the state of the .NET community, found something that i thought was better and took a few shots at the .NET community, like some other people who've moved to a different community.

The thing is though: why even bother? Sure, sometimes the urge to tell someone (or a group of people) off is hard to resist. But doing so rarely benefits you, and when it does, it's most likely when it's targeted to one person who might need to be confronted with something. If you tell off a group of people, what good can you possibly expect to come out of it? You can't expect them to suddenly agree with your point of view, even if some of them might do so. The majority of them will just think you're a dick and will be even less inclined to listen to what you have to say in the future. So what exactly did you accomplish? Apart from getting a bunch of people to think less of you, there is absolutely nothing to get out of it. Also, if you plan on becoming a vocal member of your new community, you might want to keep in mind that some of the people in that new community will take notice of your childish rant and some of them will expect you to do the same thing to them once you're ready to move to yet another community a few years down the line. You won't just look like a dick, you're also setting yourself up for negative future expectations that some people will have of you. Really, why even bother writing such posts? If you need to vent, at least try to do it in a constructive manner and in a respectful tone instead of acting like a spurned lover or a kid that didn't get his way.

As for the people who reacted defensively to it, again i ask: why even bother? Why get all worked up about something that was written by someone who doesn't even want to be a part of your community anymore? Why even get angry or frustrated about someone making a blanket statement that wasn't even directed at you personally? Why would you extend the attention that it's going to get by going on and on about it on Twitter? That too, is off-putting and a waste of time and energy. Not just yours, but everyone else's who has to filter through the noise. And what exactly are you arguing about? You're arguing about something that is inherently subjective. Do you get into heated arguments about music or movies as well? You're getting all worked up about other people's preferences, which doesn't really improve your life or situation in any way at all. On the contrary, your whining about it might just result in people not wanting to listen to you anymore either. I unfollowed a couple of people on Twitter because i didn't see the point in reading the same bitching in my timeline for a couple of days in a row. If you really need to get it off your chest, write a coherent post about it, publish it and make your statement once and then move on to something more interesting, like, having fun building working software.

Different strokes for different folks, people. Focus on the things you find interesting and have fun with it. Enjoy building things and try to improve by learning whatever you think will make you a better developer. Consider sharing what you learn with others if you have time for it. But please, let's quit bitching about other development communities because there really is nothing good that can come out of it.