Jan 19

Git = a tree. Most (all?) labels refer (directly or indirectly) to a node in the tree. A node is identified uniquely by an SHA1 hash, which is generated from both the file system contents and the meta data. A node can have both N parents (google octopus merge) and/or N children, though the norm is 1 or 2 parents and N children, with N usually = 1. The files you see are just the physical representation of the node. You can move around in the tree by referring to labels or hashes directly. You can manipulate which node a particular label refers to by various commands such as commit, merge, rebase and reset. Labels exist as, at least, local branches, remote branches, tags. There is no magic. You’re probably over complicating it in your mind.

Jan 1

I just moved all of my godaddy domains, which I’ve always resented having, to namecheap due to their promotions and support of organisations against SOPA. SOPA will cripple the internet if it goes ahead. Of course, godaddy’s corner of the internet is so slow and unintuitive that it’s already crippled. Poor service, poor site, poor ethical values, poor pricing, just generally shit, or as they say here, mierda! Adios you worthless bastards.

Jul 8

Oxford dictionaries define this to mean:

Blind love of Apple iOS based products, especially for the latest iPhone variant, whatever that may be.

or at least, they should…

I first noticed this some time ago when I was dismayed to find out that my “pencil and paper” girlfriend had decided that she wanted “an iPhone”. Needless to say, she now has an HTC Desire - which she dropped and broke (it still works, though).

What had happened was that her colleague had been quietly singing the praises of her fancy new iPhone 4 for some time, and then “clearly” demonstrated that it was the ultimate phone by downloading an MP3 for a customer in a time-critical situation. Through this subtle indirect marketing approach (AKA social networking) Apple had made my task (to bring intelligence, rational and reasoning back into the decision) very difficult indeed.

It took me more than two weeks to start to turn her, and more than a month and a half of to and fro emails before the conversation was effectively over.

To summarise what Apple have done to the cellular phone market, you can simply say this:

People don’t go shopping for a smart phone and choose an iPhone. They go shopping for an iPhone and choose the colour.

To be a little more blunt about it, people blindly ignore the fact that there are other comparable, different and in many cases arguably superior products available. IE, they suffer from Apple induced ignorance, which is sad.

Recently an old friend of mine posted this on facebook:

To iPhone or not to iPhone, that is the question? Discuss/voice opinions.

Which, of course, brought out all of Steve’s fans, and a handful of others to remind him, in the onslaught of (in the sound of a zombie or robot) “Buy an iPhone”, that there were perfectly good, more flexible, more open, more powerful, better looking, better performing, lighter, better battery life, etc etc Android based phones available and that he should check them out before committing to Apple’s Nazi-like application distribution policies.

As I rather un-smoothly put it:

The only valid advantage of having an iphone, right now, is if you are stupid or lazy or careless.

And by that, rather poorly written sentence, I meant that Apple check all applications distributed through iTunes to ensure they meet various standards, and that can help keep you safe if you’re prone to clicking install when viruses download themselves from websites, etc.

With an Android the world is your oyster, including all of the bastards trying to screw you. User beware.

There are two lessons here, number one:

As a consumer, think for yourself, do your homework, and don’t be led along by others like a glorified money-bearing sheep!

And number two:

All big worldwide projects require a smooth, charismatic, intelligent, friendly, fun, articulate leader, if they want to be a true success.

To see the difference between such a project and one without, compare Apple with Microsoft.

Jul 1

I’m in LOVE with Firefox 5, THANK YOU ALL VERY MUCH!!! I’ve not been this excited about a “boring” piece of day to day software tooling since, well, Mac System 7! I’m not sure if it’s that much better than 3.6 or if it was using POS Safari for 2 months that did it… but I am REALLY appreciating Firefox right now. I’ve not had a crash for AGES either, lets hope FF5 doesn’t ruin that good streak! :-)

That is all. Carry on.

Jul 1

This is just a little note for those that don’t know about Markdown! I didn’t. Now I do. I’m happier. To summarise Markdown it’s human readable and editable in a simple text editor, and easily converted into HTML and other formats. Github use it for README.md parsing, and it brings a professional touch to any directory in a git source tree on github with a README.md file. Here is one such example on my project:

FreeEMS Decoders Directory Markdown README

The top level directory also has one, of course.

The reference for Markdown is this site:

Markdown Reference

I like the way he writes!

Enjoy!

Nov 11

I regret having to write this post, but apparently my suggestions shall be ignored along with those from anyone that isn’t the author. The author, Sitaram Chamarty, only takes patches to documentation and not the actual application. I find this attitude pretty sad indeed. No man is an island, especially not in the world of FOSS code.

There are two problems, that are related, that I had with gitolite. I was trying to get my dearly beloved girlfriend access to some repos on my server in California when I ran into the trouble that lead me to track down the cause. I had successfully set her up with an ssh key/config and git installation (she is a complete technophobe) all over the phone, gmail chat, and skype. We tried to clone our first repo, and it asked for a password, strange! I figured that I had done something wrong on her setup, somehow, remotely and setup a second account for myself on a friends home boxy that I have access to with dyndns (Thanks Dave!). However, after I replicated her config setup, when I tried to clone a repo, it failed in the same way. That’s odd, I thought, and hacked around with ssh until I proved that it was using the key as it should have been. Weird!

The only thing left to do was go digging on the server, so that is what I did. I quickly found that the authorizedkeys file had not been updated with Isabel’s key, nor my new test account. Hmmm. I then remembered that when setting up my symlink style repos, the subsequent gitolite admin repo pushes had resulted in errors, but upon fixing each error another appeared… I had given up fixing them because I found out that they seemed to do nothing and didn’t care. However, now it occurred to me that the fact they were failing early, and not continuing to try to update further repos possibly meant that it was failing completely and not ever adding the ssh keys to the auth file. I was right! Upon creating all the missing symlinks to the empty “gitolite-hooked” hook and pushing an empty line config file change in the gitolite admin repo, suddenly I could clone with the test account.

So, what’s wrong with this? Quite a few things, actually.

Firstly, when you have 100 symlink errors and it only reports the first one it finds in the file and then exits, you have to fix that first one, make a change to the config, commit, push, get the next message, fix that, and repeat, ONE HUNDRED TIMES. Not cool. It should treat each independent repo seperately and independently such that all errors are delivered at once, and can be dealt with at once.

Secondly, failing at the symlink stage and not trying to perform other independent operations such as add the authorisation keys is also flawed IMO. These tasks are unrelated and should not impact each other.

Thirdly, creating those symlinks silenced gitolite error messages, however, not correctly. My gitolite is now in an incosistent state without various hooks that it “needs” to do it’s thing. Pull/Push/Clone work, repo granularity permissions work fine, not sure what is not working, but it sure as hell does not matter to me, at all.

It turns out that gitolite checks for existance of this empty hook in order to determine whether or not it needs to create other real hooks/symlinks. OK, I guess that could work, BUT, not the way he does it. Currently he checks, if it’s not there, creates it, then tries to create the other links. If it fails to create the other links, but succeeds in creating the gitolite-hooked link, then the state is left inconsistent - he doesn’t clean up afterwards! That can happen if there are permissions for the git user to write to the directory, which allow it to create the empty and uniquely named symlink, however, there aren’t such permissions to allow it to overwrite the other hooks that are already present.

What is needed is one of the following three options:

  • Create gitolite-hooked only after success in writing out the other hook links.
  • Create gitolite-hooked first, but remove it if installation of other links fails.
  • Forget the entire sentinel idea and just test for the stuff you actually want to be there rather than some indicator that can lie for a large variety of reasons…

At the VERY least, he should include something in the error message that makes it clear that the push did NOT complete the normal things that it needs to do to function. As it stands, it appears to the user that only one minor thing has gone wrong, not the entire system has fallen over because of a single symlink…

I was motivated to write this blog post because I tried to articulate myself to the author and had every idea and fix rejected out of hand simply on the basis of “I don’t want to”. The fact that the logic with which the hook test works is flawed doesn’t matter to him at all. It’s moments like this that I wonder about the quality of the rest of his work :-/

I commented to him that he seemed like a good guy:

> You seem like a good guy, so obviously you’re getting pounded with dumb
> requests resulting in your “i accept doc fixes, not code fixes” statement.

And this is the response that I received:

I only *seem* like a good guy, actually. You found out my
secret much, much, faster than most people; in fact many
people haven’t even found out yet. No idea why though :-)

I was stunned to say the least. Mostly because after reading the rest of his email in response to a carefully worded email of mine that I had spent half an hour or so on, I simply had to agree. I’ll save the expletives for the next driver that cuts me off, he’s not worth the breath.

Fred.

Oct 29

Quite some time ago I setup Gitosis on my VPS and enjoyed having things like apache configuration and simple html sites backed up to my local machine with full revision history, and checks for changes and hacking on the box itself, too. There are so many benefits to putting your sensitive but not often worked on files under version control. That isn’t the subject of this simple post, though. This simple post is just to publicise Gitolite a bit more, as I hadn’t heard of it until recently when I happened to search for an alternative after locking myself out of Gitosis (a common problem).

Gitosis has had no commits for quite a long time, which could imply that it is perfect, or could imply that it’s no longer being maintained/improved. Gitolite is being maintained and provides extra functionality over Gitosis in terms of fine grained permissions, particularly.

I could pick on a few things about Gitolite, but nothing serious. I’m using it in earnest now, and am happy to be using it. If you want a private Git hosting service and have a box with SSH and Git installed, Gitolite could be for you!

I have written quite a few tech article drafts over the last year or so. I hope to put a few more of them up on this blog before too long. Thanks for your patience.

May 21

A few weeks ago I came across a piece of code inside a DAO class with logic to instantiate new model objects and return them with null contents (new object) instead of just null itself. This is wrong. It is particularly wrong because the entire rest of the DAO classes in this application use the normal method of just returning whatever hibernate does, IE, null if not found. layer separation is important. Please keep such logic out of the DAOs and put it where it belongs above. Doing this precluded using the same DAO for other purposes without changes in several classes - yuck, spaghetti.

Another gem I found with the same author was a class with about 7 methods, one public, the rest private. The public one had an if else structure which delegated to the other methods. The return type was boolean. Upon inspecting these methods to see what they did and why true or false might be returned, I came across the following :

boolean ret = false;
// Lots of code, some of which throw exceptions...
ret = true;
return ret;

Which can of course quickly be refactored to :

// Lots of code, some of which throw exceptions...
return true;

Which in turn can quicly be refactored into :

// Lots of code, some of which throw exceptions...

But, of course, with a return type of void, NOT boolean.

As it turns out, there was some reasoning to this exceedingly dodgy code. The boolean, urr, i mean, the true value (or exceptions) were being processed and converted into serialised JSON for a front end display tool. I still would not have done this, rather I would have used a return type and embedded the exception, message, and true/false value in that directly (such a return object already existed). If you were going to do this, comments were essential… there were none. Poor form.

Lastly, again, from the same author, we have the following method signature :

Employee getEmployee(String email, Integer offset) {

Which, at first, seems reasonable enough. On closer inspection it was apparent that it actually had a few side effects. What it really did was this :

Employee employee = employeeDAO.findByEmail(email);
if (employee.getEmailAddress() == null) {
    employee.setEmailAddress(email);
    employee.setLanguage(languageBO.getLanguage());
} else {
    languageBO.setLanguage(employee.getLanguage());
}
labelTextBO.setLanguage(employee.getLanguage());
session.setRequestedFor(employee);
session.setSubmittedBy(employee);
session.setTimeZoneOffset((offset != null) ? offset : 0);
session.setLastLogin(employee.getLastLogin());
getEmployeeDetailsFromLDAP(employee);
return employee;

So, of course, I changed the method name to this such that any potential user could instantly tell what it was going to do for them…

Employee getEmployeeAndPopulateSessionAsSideEffect(String email, Integer offset) {

Again, this is the sort of code that leads to mistakes by unsuspecting developers that come along later and wonder why it behaves so stangely, afterall, all they did was get an employee, right?

The astute among you will, by now, have noticed that the DAO which returned the fresh object instead of null was the EmployeeDAOImpl class as used in the EmployeeBOImpl. This project was, unfortunately, riddled with such messy dangerous code. We’ll leave the class and method naming for another day as that was appalling in places too.

It would appear that the colour scheme for Java doesn’t go at all well with my theme’s style. I’ll try to remedy this shortly if possible.

Apr 7

This really belongs on The Daily WTF, but it will just have to live here for now I guess. All real names (except mine) have been replaced!

Preface :

A few months back I setup a project using Maven2 from scratch (You’ll hear more about this in an upcoming article). This project wasn’t large, but had strong potential to require a mildly complex build setup for multiple clients.

For those unfamiliar with this indispensable build tool, one of its major positive aspects is that dependencies on other artifacts are explicitly declared by the developer based on his understanding of the projects environment. Another is consistency - that you can ALWAYS sit down and “just build it” on a maven project with absolutely no knowledge of the specifics. There are many more.

I was stolen from this project a month or so back and moved to a new one. This project is not popular with the resourcing department of the company it is being produced by so staff theft (to other clients/projects) was commonplace. As of yesterday the project has one front end flex developer who knows that aspect very well, and one new java back end developer who doesn’t know much about it at all.

Body :

Over the last few days since the new guy started on my old project I’ve been contacted fairly regularly with various questions about how to find this, what the password is for that, etc. Today the back end developer contacted me asking for help with doing a release of the system. His Maven knowledge was a bit thin so it should have been a 5 minute case of “type this and hit enter” type stuff. Not so fast, Fred.

Something is wrong with this pom.xml snippet :

<groupId>com.company.application</groupId>
<artifactId>services</artifactId>
<version>${this.version}</version>

These instructions might start to explain why :

7) Run ‘mvn company:version’
8) Run ‘mvn scm:checkin –Dinclude=pom.xml –Dmessage=”company:version”
9) Check pom.xml and ensure the version element contains ‘${this.version}’ and the this.version element (child of the properties tag) contains the newly incremented snapshot release version number, e.g. 0.0.4-SNAPSHOT 10) Check the subversion history, it should appear something like this:

3346       31/03/2009 10:34              1              user       company:version
3345       31/03/2009 10:00              1              user       [maven-release-plugin] prepare for next development iteration
3343       31/03/2009 10:00              1              user       [maven-release-plugin] prepare release xxx

The somewhat edited conversation in which I found out about these changes (expletives removed) :

Fred: did you release those artifacts?
Bob: Partially, Harry did but forgot to do the mvn company:version command so Henry did that
Fred: wtf is that?
Bob: It updates the version numbers in the pom
Fred: it does what?
Fred: who put that in?

A small snippet of conversation after pasting the above to a colleague :

David: omg lol, they actually bothered to write their own plugin to circumvent maven versioning
Fred: Yes…

It turns out that another developer had put a significant amount of time and effort into creating a plugin and configuration to automatically update dependency and artifact versions. This allows them to work on multiple packages in parallel to produce a working product at the end.

Summary :

So, what is the big deal? Well, for starters, dependency versions should be explicitly set. Why? Because you and ONLY you know what is required. Who says that the latest data access library is the one you really want to use? Automation of this task is plain just a bad idea. Secondly, the project is no longer a normal standard Maven2 project. As such it is difficult to support it remotely without having a good look over the “plugin” and other associated changes. In short, several of best Maven’s features have effectively been disabled and made worthless by these senseless changes. But, the developer must have had a reason for doing this, right? Yes, laziness and lack of up front component and interface design. These features allow an application to be thrown together haphazardly with little thought in a fine grained incremental development style described as Programming by Coincidence. Such practices are best avoided especially by inexperienced developers, using a properly modularised project layout goes a long way to fostering a good working style.

On another, more positive, note :

Lastly, the formatting on this page was done with the following WP-Syntax plugin. The style sheet for the code blocks still needs some work, but I’ll get there sooner or later.

Update! (14/4/09)

This evening I had the pleasure of being asked (ever so nicely) to come back into the office after hours to help get a build of the project out. After getting a normal mouse connected and a usb keyboard (ps2 seemed to die) I started fishing to see what was wrong. Of course it was just a matter of adjusting some versions to match (I had [] hard versions setup to guarantee consistency). No problem there. The usual array of error messages were being pumped out. No problem there. The problem (and it was only a small one) turned out to be that the carefully used variables for versions of dependencies had been replaced (presumably by the script/”plugin”) with hard coded versions. Thus editing the variable at the top made no difference at all as it wasn’t being used. I guess it’s possible that the developer was to blame, but I strongly suspect it was the “plugin” working its magic and screwing things up. Certainly the developer was surprised to see the hard coded versions in place. Lesson learned? We will see what happens as time progresses…

Mar 31

What better way to start this blog than to thank those people that helped it come together! First of all, thanks to the crew at WordPress for creating this fine piece of software and sharing it with GPL!

Thanks to Heidi for some theme hunting advice!

Thanks to Barry for his simple search box setup!

Thanks to Aaron for some late night Apache2 advice!

Thanks to NASTY for the simple default avatar setup!

Thanks to Jarek for help with the finer points of CSS!

Thanks to Paul for hosting and other random bits of *nix advice!

Last but not least, thanks to the guy that wrote the article on how to server N WordPress blogs from one copy of the application. The article works with the latest WordPress version with just a few small tweaks. If you also want to save maintenance and host more than one blog from one server, here is the article that I used.

That’s about all for now I guess. I’m glad the whole tweaking the blog theme thing is over. Stay tuned for actual articles on software and other interesting tech :-)