Monkeypatching for cleaner code

Recently, after reading Object on Rails, I started thinking and experimenting with various ideas of making Rails applications code cleaner. Here’s one of these ideas.

Let’s imagine we have two model classes, connected with a has-many/belongs-to relation, e.g.:

# file user.rb
class User < ActiveRecord::Base
  has_many :posts, dependent: :destroy
  # ...
  # rest of the user stuff
  # ...
end
# file post.rb
class Post < ActiveRecord::Base
  belongs_to :author, class: "User"
end

The above code is probably how most of Rails programmers would go about implementing a "user has many posts/post belongs to its author" scenario. It's the tutorials-approved way. But when you look at it from a architectonic point of view, you have just created a circular dependency.
Continue reading


My Favorite Interview Question

Recently I have been doing some job interviews (as an interviewer, not a candidate). Although I hate being schematic and try to come up with new & interesting questions for every candidate, I always ask My Favorite Interview Question, which is:

What are the benefits of using Dependency Injection pattern?

The answer for that immediately tells me, whether the candidate has broader horizons or is just a doing-what-I’ve-been-told-to-do drone.

So, what’s a bad answer? Anything along the lines of “DI allows you to configure your dependencies and inject them by a framework.” Seriously, that’s an answer that I would come up with if I had not even the faintest idea what DI is, and I get it from developers who claim several years of experience, working with Enterprise Java and all that stuff.

Even worse: candidate mentions XML in the first sentence. I mean, what are they thinking? Is “using XML” among the benefits of Dependency Injection? (I would say it’s a cost, not a benefit, but let’s leave that for another rant.) My point is, DI and XML are concepts from totally different and unconnected levels.

When you use DI, you might want to have your dependencies automatically injected, for that you might want to use the Spring framework (if it’s a Java project), and then you might want to configure it with XML files. See how many steps it takes to connect DI and XML? On each step you could decide to use something else, so there’s a good chance that you end up with no XML at all. And yet, XML has been imprinted so deep in Java developers’ brains that you might hear “DI lets you configure your classes with XML.”

OK, so what qualifies as a good answer (at least according to me)? Anything from “DI improves testability because you can easily mock dependencies” to “DI enables loose coupling” to “DI enables flexibility” to “I don’t see any benefits of DI, therefore I don’t use it” even.

In fact, any answer in form of “I don’t see benefits of X, therefore I don’t use X” is better than “I use X because they told me to/everyone uses it/that’s how it was always done.” It shows that you made a conscious decision about using or not using X. Of course, I would still like to know why you don’t want improved testability or loose coupling. But at least this is something that can be further discussed.

And the best answer would be that you don’t use DI, DI just happens when your code is testable and loosely coupled. So, if you happen to be interviewed by me, you will be asked this question, too. Now you probably know what answer would satisfy me. And if you get the job, that would probably be the first case of someone benefiting from reading this blog :)


Hash bars – simple ASCII-art charts in your console, database or Excel

When you have some data like this:

MONTH COUNT
2011-10
417
2011-09
903
2011-08
1051
2011-07
759
2011-06
835
2011-05
647
2011-04
393

it may be difficult to spot a trend in it. That’s why people use charts and other visualization tools and there’s a lot of them (you could use Excel, Google Charts, gnuplot, sparklines etc.).

However, sometimes it’s not possible or convenient to use any of this tools. In such cases, you can easily create a simple ASCII-art style chart. Doesn’t this look better?

MONTH COUNT  
2011-10
417
########
2011-09
903
##################
2011-08
1051
#####################
2011-07
759
###############
2011-06
835
################
2011-05
647
############
2011-04
393
#######

It’s actually so embarrassingly obvious I would not bother posting about but in the last couple of days several people told me that they think it’s a great idea that they wish they knew earlier. So here it is.
Continue reading


The endless cycle of code vs docs

Hereby I present to you a very first chart comic on this blog.

The endless cycle of code vs docs

Click picture for full-sized version

Nods and acknowledgements to The System Comic. I hope they don’t mind the stolen graphic. Any similarity to this particular comic is not quite unintentional.


WeekProgress — complete iPhone application source code available

While you weren’t watching I went and created a small iPhone app: WeekProgress. Don’t expect too much functionality (or sense!) there – it was born mainly for learning purposes. It features a main screen and 3 (three!) screens worth of settings.

Working week progress bar

Working week progress bar

On the main screen you’ll find a progress bar that tracks your way through the working week. It starts at 0% on Monday morning and goes to 100% on Friday afternoon. The settings allow you to select working days and change working hours, so you can adjust it to your schedule.

Changing working hours

Changing working hours

And it’s free! And it features insightful and funny comments! And it looks like a couple of folks already installed this! So what are you waiting for?

But there’s more: I’ve made the source code available! And it is a brilliant and beautiful source code (if there is such thing as beautiful Objective-C code). And it features unit tests! How cool is that?


Don’t force them, teach them

Working with a large Java legacy codebase lately, I spotted a couple of anti-patterns. Following are three of most annoying and ubiquitous ones.

Numberosus Constantitis

A lot of classes define these constants at the beginning:

private static final int NUMBER_3 = 3;
private static final int NUMBER_4 = 4;
private static final int NUMBER_5 = 5;
private static final int NUMBER_6 = 6;
private static final int NUMBER_7 = 7;
/* ... snip ... */
private static final int NUMBER_17 = 17;
private static final int NUMBER_18 = 18;

which are then used like this:

PreparedStatement ps = ....
ps.setString(NUMBER_4, dto.getUser());
ps.setString(NUMBER_5, dto.getRole());
ps.setString(NUMBER_6, dto.getReason1());
ps.setString(NUMBER_7, dto.getActivityType());
ps.setString(NUMBER_8, dto.getReason2());
ps.setString(NUMBER_9, dto.getActivityType());

or like this:

List<ReportXDetailDto>[] result = new ArrayList[NUMBER_OF_LOOPS];
result[0] = getRedRisk(criteria);
result[1] = getOrangeRisk(criteria);
result[2] = getYellowRisk(criteria);
result[NUMBER_3] = getBlueRisk(criteria);
result[NUMBER_4] = getWhiteRisk(criteria);

Why? Oh why?--you say... It's because the IT Management appointed checkstyle and checkstyle has been configured to complain about Magic Numbers.

Checkstyle skips 0, 1, and 2 by default as too frequent, that's why only numbers from 3 up are defined as constants here.

The developers did not bother to replace the Magic Numbers with some meaningful constants, they just got rid of the warning with a couple of what should rather be called "refucktorings".

As an added bonus to the last block of code, the NUMBER_OF_LOOPS constant is read from configuration file, so theoretically there could be other number of results, but the code here is hardcoded to provide 5 of them. I suspect that the NUMBER_OF_LOOPS was meant for something else, but since it happened to have the desired value, it has been "reused".

StringBuilderosus Misunderstanditis

Another case is ubiquitous overuse of StringBuilder/StringBuffer:

StringBuilder sql = new StringBuilder();
sql.append("insert into xyz_object_groups values (");
sql.append("xyz_object_groups_seq.nextval, ");
sql.append(":objGrp, ");
sql.append(":desc, ");
sql.append(":object, ");
sql.append(":mainObject, ");
sql.append(":closed, ");
sql.append(":closedWeek)");
Query query = getEntityManager().createNativeQuery(sql.toString());

The developers probably heard somewhere that "you should use StringBuilder for string concatenation" and followed that advice religiously, ignoring the fact that it's only applicable for string concatenation inside a loop.

What's even worse, if the code was written like this:

String sql = "insert into xyz_object_groups values (" +
             "xyz_object_groups_seq.nextval, " +
             ":objGrp, " +
             ":desc, " +
             ":object, " +
             ":mainObject, " +
             ":closed, " +
             ":closedWeek)";
Query query = getEntityManager().createNativeQuery(sql);

it would not only be more readable, but also more efficient (static strings are concatenated by the compiler). There's a lot of information on this topic on the Internet, but apparently some developers are google-impaired.

Obviousus Commentitis

The comment to code ratio in the codebase is quite high, but the comments are either large blocks of code that were commented out years ago or blindingly obvious comments like this:

synchronized (ranger) { /* Start of synchronized block */

// get form
XYZManageForm xyzManageForm = (XYZManageForm) form;

// get context
XYZViewRequestContext viewRequestContext = xyzViewActionContext.getRequestContext(request);

// set xyz for view in request context
viewRequestContext.setXyz(xyz);
// update xyz
xyz = xyzServices.updateXYZ(xyz, LogonUtil.getUserDto());

// set the xyz id to the context
context.setXyzId(xyzManageForm.getXyzId());

Note: XYZ is not an actual name.

So, the code is sprinkled generously with comments that might be useful only to someone without any knowledge of Java syntax whatsoever (but then how would they know what is a comment?) but if you check how much of the public API has javadoc, it's less than 5%.

Conclusion

You can't force the developers to write better code just by forcing the use of metrics, coding conventions, standards etc. You need to educate them. They need to understand the rationale behind each rule or advice and accept them. Otherwise they will game the metrics out of laziness or maliciousness and you'll get code like above.


The future is now

You know what future is now? The one you mentioned one month ago, when you said “let’s copy and paste for now and fix it in the future.” And the one from “we’ll add unit test for that in the future.” And when will this “later” from “we’re going to refactor this later” happen? Later, of course.

Your “now” is the “future” in which former developers hoped to find some time and fix all the problems. They never did, of course, and now you are pushing even more into the future, for yourself or your successors. It’s like taking a huge debt intended for next generations to pay up and then taking even more debt just to pay the interest. It’s like a Ponzi scheme in development :)

If you always decide to cut corners “now” and fix it in the “future”, that future never comes. Instead, you’re setting yourself up for the future of constantly putting out the fires and wondering why your application cannot be more stable.


Follow

Get every new post delivered to your Inbox.