Happy Holidays everyone! I hope you all are having a great time!
And to those who are into the FSM — I gotta make me one of these next year.
RAmen.
Happy Holidays everyone! I hope you all are having a great time!
And to those who are into the FSM — I gotta make me one of these next year.
RAmen.
Dec 2
Posted by The Rontologist in Java, Programming | 1 Comment
Returning multiple values from a single function is not supported in most programming languages. To get around this limitation some developers have wrapped their return values in an array. This is a bad practice that should not be followed as it leads to fragile and unreadable code.
For example, lets make a function that needs to return a user object and her favourite movie. This can be done by wrapping both pieces of data in an object array like this:
public Object[] getUserInfo(String username) {
/* code to look up a user */
return new Object[] {user, favouriteMovie};
}
This is nice, compact, and easy to implement. Unfortunately it is a bit unwieldy trying to use it:
Object[] info = getUserInfo("bob");
String name = (String) info[0];
Movie favouriteMovie = (Movie) info[1];
There is a fair amount of casting going on, and it does add several extra variables. But it does work, and because of time considerations we decide to leave it be until we have time to go back to it (and since this is software that will never happen).
A week down the road the code gets selected for a random code review. The reviewers are feeling the time pressure as well and decide that the only thing that needs changing are the index literals. It would be much better if they were constants. This is a change that can be done quickly with little risk of making a mistake.
public static final int USER_INFO_USER_IDX = 0;
public static final int USER_INFO_FAV_MOVIE_IDX = 1;
public Object[] getUserInfo(String username) {
/* code to look up a user */
return new Object[] {user, favouriteMovie};
}
// usage
Object[] info = getUserInfo("bob");
String name = (String) info[USER_INFO_USER_IDX];
Movie favouriteMovie = (Movie) info[USER_INFO_FAV_MOVIE_IDX];
The constants are in place and everyone agrees that it is an improvement.
Another week down the road a new requirement comes down the pipe requesting that the software also tracks the users favourite snack. It is decided that the getUserInfo function should be expanded to return this information as well.
public static final int USER_INFO_USER_IDX = 0;
public static final int USER_INFO_FAV_MOVIE_IDX = 1;
public static final int USER_INFO_FAV_SNACK_IDX = 2;
public Object[] getUserInfo(String username) {
/* code to look up a user */
return new Object[] {user, favouriteMovie, favouriteSnack};
}
// usage
Object[] info = getUserInfo("bob");
String name = (String) info[USER_INFO_USER_IDX];
Movie favouriteMovie = (Movie) info[USER_INFO_FAV_MOVIE_IDX];
Snack favouriteSnack = (Snack) info[USER_INFO_FAV_SNACK_IDX];
As you can see it is getting uglier with each iteration. The focus of our business changes and we no longer care about movies, but they are so ingrained in the system that we will need to take an iterative approach in removing them. The first set is to remove it from the getUserInfo function. Doing it for the function is easy.
public static final int USER_INFO_USER_IDX = 0;public static final int USER_INFO_FAV_MOVIE_IDX = 1;public static final int USER_INFO_FAV_SNACK_IDX = 1; public Object[] getUserInfo(String username) { /* code to look up a user */ return new Object[] {user,favouriteMovie,favouriteSnack}; } // usage Object[] info = getUserInfo("bob"); String name = (String) info[USER_INFO_USER_IDX];Movie favouriteMovie = (Movie) info[USER_INFO_FAV_MOVIE_IDX];Snack favouriteSnack = (Snack) info[USER_INFO_FAV_SNACK_IDX];
When we try to compile this we will get a warning from every class that used the USER_INFO_FAV_MOVIE_IDX symbol. Once those are fixed up it should be fine, but unfortunately it is not.
When the array is returned there is no way to enforce that the constants are used while accessing it. Any usage of it where developers used literal numbers to access the elements will still compile, and cause runtime errors since info[1] is now returning a Snack instead of a Movie. This can be the source of more bugs than you can shake a stick at, and is precisely the reason why you should never return an array like this.
A better approach would be to create a small object as a container and return that. It is a little more overhead up front but it does pay off during the maintenance cycle. Assume we had implemented getUserInfo loike this prior to the request to remove the favourite movie.
public static class UserInfo {
private String user;
private Movie favouriteMovie;
private Snack favouriteSnack;
/* getters and setters */
}
public UserInfo getUserInfo(String username) {
/* code to look up a user */
return new UserInfo(user, favouriteMovie, favouriteSnack);
}
Not only will the usage of this be nicer (since the casting and temporary variables are no longer needed) but it’ll be easier to maintain to. If we remove the movie property from our object the compiler will let us know every usage of it – not just the ones that people accessed with optional constants.
Arrays as a multiple return mechanism is a bad idea and a horrible code smell.
Nov 4
Posted by The Rontologist in General Software, Programming | No Comments
Code coverage reports are neat. At a glimpse you can determine what pieces of code have been executed in a batch of unit tests, and get a good guesstimate on how well your unit testing efforts are going. Unfortunately there is a tendency to jump to the conclusion that covered code is tested code. If only it was that simple!
Assume we have a simple method:
function calculateTotal(amount, includeTaxes) {
if (amount < 0) {
raiseError();
}
var total = amount;
if (includeTaxes) {
total *= 1.05;
}
return total;
}
This can be tested fully with a few simple asserts
assertEquals(100, calculateTotal(100, false)); assertEquals(105, calculateTotal(100, true)); assertEquals(0, calculateTotal(0, false)); assertEquals(0, calculateTotal(0, true)); assertError(calculateTotal(-5. true)); assertError(calculateTotal(-5. false));
Running these tests will provide a coverage report that indicates we have 100% code coverage. That is good, since any fully tested function will have 100% code coverage, and our tool would be broken if it didn't say that. However, what happens if we need to add a small bit of functionality to this function? Maybe we want to include the option to include a default tip. Our function could be changed like this:
function calculateTotal(amount, includeTaxes, includeTip) {
if (amount < 0) {
raiseError();
}
var total = amount;
if (includeTip) {
total *= 1.15;
}
if (includeTaxes) {
total *= 1.05;
}
return total;
}
Since we have added to the function we need to modify our tests or the compiler will ball at us. There also needs to be additional testing included to cover the new functionality. Ideally we would have done this TDD, but that's a topic for another day.
//existing tests modified for third param assertEquals(100, calculateTotal(100, false, false)); assertEquals(105, calculateTotal(100, true, false)); assertEquals(0, calculateTotal(0, false, false)); assertEquals(0, calculateTotal(0, true, false)); assertError(calculateTotal(-5. true, false)); assertError(calculateTotal(-5. false, false)); //new test assertError(115, calculateTotal(100, false, true));
If we run our tests again we will find that we have 100% code coverage again. It is tempting to assume that it is 100% tested, but jumping to the conclusion is wrong since we did not test how the function behaves if we are calculating both the tip and the taxes. Never assume that you have 100% test coverage if you have 100% code coverage.
Does this mean that the code coverage report is useless? I don't think so. While you cannot determine if a covered line is tested, you can determine that an uncovered line is not. This may give you a clue on the best place to start your unit testing effort.
Oct 21
Posted by The Rontologist in Bad Code, Java, Programming | 4 Comments
Sometimes you just have to ask why. Why would you ever produce this monstrosity?
void processMovies(ListmovieList, User user) { if (user.hasFavouriteMovies()) { Movie movie; while (movieList.hasNext()) { movie = movieList.next(); switch (movie.getRating()) { case LOVED_IT: if (movie.hasExplosions()) { doLovedItWithExplosions(movie); } else { doLovedItWithoutExplosions(movie); } break; case HATED_IT: if (movie.hasExplosions()) { doHatedItWithExplosions(movie); } else { doHatedItWithoutExplosions(movie); } break; default; if (movie.hasExplosions()) { doIndifferentItWithExplosions(movie); } else { doIndifferentItWithoutExplosions(movie); } } } } }
There is no good reason to have an if inside a switch. If you have to do a further conditional in the switch than either break it out into a function or get rid of the switch. It makes it unreadable, especially if it is nested inside two other layers of nesting as in the example above. That is too much to handle.
We can refactor this in multiple ways. I prefer the cases of my switch statement to be small so I will break out the logic into separate functions and thus reducing the cyclic complexity of that code. You could also translate the switch statement into an if/else if/else structure as well, but I do not find that to be as elegant.
void doLovedIt(Movie movie) {
if (movie.hasExplosions()) {
doLovedItWithExplosions(movie);
} else {
doLovedItWithoutExplosions(movie);
}
}
/* doHatedIt, doInfferent */
void processMovies(List movieList, User user) {
if (user.hasFavouriteMovies()) {
Movie movie;
while (movieList.hasNext()) {
movie = movieList.next();
switch (movie.getRating()) {
case LOVED_IT:
doLovedIt(movie);
break;
case HATED_IT:
doHatedIt(movie);
break;
break;
default;
doIndifferentIt(movie);
break;
}
}
}
}
I find that to be much more readable, and it is easier to test. The new functions can be unit tested easily since they are isolated, and the processMovies function can be tested easier as well because it no longer have all the extra ifs to execute.
A friend on mine pointed me in the direction of Stack Overflow the other day. It is a great resource for developers, and just a little bit addictive. Go check it out if your a developer and haven’t already.
Conditionals when used correctly can make verbose code concise and readable. However, there are enough examples of them being used incorrectly that can scare most people away from them completely.
That is one of the most unreadable conditionals I have ever seen. It returns true of false depending on whether or not $year is a leap year. However this is a bit of an extreme example. Just because something can be used badly doesn’t mean we cannot use it well. If that was the case then most Hollywood actors would be out of work.
The following code sample does a very simple thing. It calls a sort method with a sort direction depending on a flag.
if (flag) {
sort(SORT_ASC);
} else {
sort(SORT_DESC);
}
This is quite verbose, but it does not use conditionals. It can be modified to be even more readable with the use of a simple conditional:
The benefit of doing it this way is that the logic of the sort direction is contained in the function call. There is no need to look at its surrounding lines to figure out what is going in. This means less work, and a win from my point of view.
Sep 5
Posted by The Rontologist in Java, Javascript, Programming | No Comments
Sometimes when you are trying to create a custom tag for JSPs you come across the strangest problems.
For example, I was creating a JSP custom tag for generating JavaScript. The generated code is responsible for filling a JavaScript associative array with values so that they can be used later on in the JSP. Here is the kicker — the JSP can optionally create a variable with the same name before using the tag and fill it with its own values. In that case the custom tag has to append its own values to it instead of creating a new array. This means the the generated code cannot simply declare a new object, since this would erase any of the values that the JSP inserted into it. You have to love requirements sometimes.
After a bit of experimenting I discovered that all the variables (and functions for that matter) for the page was stored in the window object.
if (typeof(window['varName']) == "undefined") {
window['varName'] = new Object();
}
Voila. The above checks to see whether or not the variable has been defined, and creates it if it’s not.
I love it when I find a new source of humour on the web. I came across The Stonemaker Argument today and had a good laugh.
Aug 25
Posted by The Rontologist in General Software, Programming | No Comments
In an earlier post I tried to outline the various reasons that I have heard for using a Single Exit Philosophy. I prefer not limiting myself to it.
One of the reasons that I mentioned before as an advantage for single exit functions was that it makes debugging easier. I thought I knew the reason for this but I cannot recall it. With good use of stack dumps and break points I cannot think of any reason why debugging would be easier.
The main reason why I like multiple exits is that it reduces the amount of nesting required. This makes any given function more readable since you do not have to immerse yourself extra if layers. Additionally it simplifies the logic since you do not have to carry a value to the end of your function if you can determine it earlier on.
For example, lets look at a piece of code that calculates the tax rate of an amount given the region. We are given the stipulation that it must return 0 as fast as it can for amounts of 0 or unknown regions since look ups (especially of unknown regions) are expensive. It should also return a negative number when it encounters an error.
function calculateTaxes(amount, region) {
var taxes;
if (region != null and amount > 0) {
var lookupFailure = false;
var nationalTax;
var provincialTax;
nationalTax = lookupNationalTax(region);
if (nationalTax < 0) {
lookupFailure = true;
}
if (!lookupFailure) {
provincialTax = lookupProvincialTax(region);
if (provincialTax < 0) {
lookupFailure = true;
}
}
if (!lookupFailure) {
taxes = amount * (nationalTax + provincialTax);
} else {
taxes = -1;
}
} else {
taxes = 0;
}
return taxes;
}
Refactoring this to use multiple returns gains us several advantages:
Would become:
function calculateTaxes(amount, region) {
if (region == null or amount == 0) {
// fast fail. looking up taxes is expensive
return 0;
}
var nationalTax = lookupNationalTax(region);
if (nationalTax < 0) {
return -1;
}
var provincialTax = lookupProvincialTax(region);
if (provincialTax < 0) {
return -1;
}
return amount * (nationalTax + provincialTax);
}
I’m not sure about you, but I would be much happier maintaining the second piece of code. It is easier to follow and shorter to boot.
Aug 22
Posted by The Rontologist in Javascript, Programming | No Comments
I was adding a new feature to an existing page in a web application a few weeks ago. This required the addition of a cache to the page to reduce the amount of Ajax calls that were being made.
I was greeted with the following JavaScript:
function loadUserPreferences(userId) {
YAHOO.util.Connect.asyncRequest (
'GET', 'someUrl?id=' + userId, {
success: function(v) {
// yada yada yada
}}
);
}
// several more loadXPreferences functions existed with very similar code
function userClickHandler() {
var userId = document.getElementById('userField').value;
loadUserPreferences(userId);
}
The first thing that I noticed was that there was a lot of repeated code in loadXPreferences functions that could easily be removed with a single loadPreferences function. The other functions were only different because of a different URL and the actions that occurred on a successful load. I proceeded to refactor it to handle the different URL with a preferenceType argument, and the special code with a function reference.
function loadPreferences(preferenceType, preferenceId, callbackFunc) {
var url;
if (preferenceType == 'user') {
url = someUrl;
} else if ( ... ) {
// code
}
YAHOO.util.Connect.asyncRequest (
'GET', url, {
success: function(v) {
callbackFunc(YAHOO.lang.JSON.parse(o.responseText));
}}
);
}
function userClickHandler() {
var userId = document.getElementById('userField').value;
loadPreferences('user', userId, function(prefs) {/* user handler code */} );
}
The reason I used an inline function reference is because the loadPreference function was called only once per preference type. It seemed better to inline them rather than create a separate callable function since it was only half a dozen lines of code.
This managed to reduce the code significantly, and coincidentally made adding a cache object simpler. The problem with adding a cache to code with Ajax is that you can get the information immediately some of the time, and the other times you are stuck waiting for the server. Fortunately this is an easy problem to solve. We can create the function reference before we check the cache, and either call it right away if we have the data on hand, or pass it along to our load function.
var userPrefCache = new PreferenceCache();
function userClickHandler() {
var userId = document.getElementById('userField').value;
var codeBlock = function(prefs) {
userPrefCache.addPrefs(prefs);
/* user prefs code */
}
if (userPrefCache.contains(userId) {
codeBlock(userPrefCache.getPrefs(userId);
} else {
loadUserPreferences('user', userId, codeBlock);
}
}
A nice simple solution that is readable with no duplicated code. I would call that a success.
You are currently browsing the archives for the year 2008
Arclite theme by digitalnature | powered by WordPress