From the category archives:

work

A change of direction?

by Andrew on September 23, 2008

A few months ago we announced Citrus, a suite of tools we’d been developing for estate agents. Despite our bullish attitude to building and selling the application we’ve taken a step back over recent weeks and taken a long hard look at what it is we’re doing. The result of the look is a change of direction, back to some ideas we’ve had in the past about personal search, bookmarking and some location based services. It’s a bit too early to get into too much detail about what we’re planing but I wanted to take the time to give a bit of an explanation of why we’ve changed our minds. 

The market has changed, there is no doubt, but we know that. On reflection though we decided our assumptions were probably wrong. We knew there were not going to be a lot of new players entering the market but existing businesses probably aren’t going to want to change, software tools and they’re not going to want to part with money especially if they had already paid to have a site developed and especially if they’re being forced to lose people.

Then came the next blow to the project,  we were asked to shut down the only current user of our software. They’d decided to put their business on hold because of changes to the Spanish regulations and the current state of the market.  So now we were facing selling a product, in an unfriendly market without our evangelist. 

I’d also be lying if I said that we had generated the interest we’d hoped to generate, we didn’t. It goes without saying that had we generated that interest, or close to that interest we wouldn’t have had the moment of introspection and we wouldn’t have needed to take this difficult decision.

{ Comments }

Integration testing in maven - With Maven, Cargo, httpunit and Selenium

by Andrew on September 22, 2008

I’ve been trying to figure this out for months, and thought it should have been simple. All I wanted to do was write a set of unit tests to test my java code, have them run whenever I hit test. Next I wanted to have a set of HTTP Unit, Selenium or similar tests run to test that the actual application is working when it’s built and deployed to a container using the cargo plugin.

I didn’t really want to have a separate project to do this because it seemed like a massive pain in the ass to maintain the whole thing. I didn’t see any reason why it shouldn’t be easy with Maven either - it does have a phase for integration-tests already.

My first try looked good to me:

 

...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>**/integration/**</exclude>
                </excludes>
            </configuration>
            <executions>
                <execution>
                    <id>integrationtest</id>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                    <configuration>
                        <excludes>
                            <exclude>none</exclude>
                        </excludes>
                        <includes>
                            <include>**/integration/**/*Test*.java</include>
                            <include>**/integration/**/*Test.java</include>
                            <include>**/integration/**/*TestCase.java</include>
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        ...
    </plugins>
    ...
</build>
...

 

I tried to run the tests, but unfortunately when it gets to the second round of tests - which should run my integration tests - it runs the same sets of as it ran the first time. I tried adding the combine.children="append" attribute to the includes, and excludes but that didn’t work either. Finally I came across a source file XppDom, part of plexus which maven uses. XppDom allowed the combine.children attribute as well as another I haven’t seen mentioned anywhere else childMergeOverride. I added that instead and it worked!

 

...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>**/integration/**</exclude>
                </excludes>
            </configuration>
            <executions>
                <execution>
                    <id>integrationtest</id>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                    <configuration>
                        <excludes childMergeOverride="true">
                            <exclude>none</exclude>
                        </excludes>
                        <includes childMergeOverride="true">
                            <include>**/integration/**/*Test*.java</include>
                            <include>**/integration/**/*Test.java</include>
                            <include>**/integration/**/*TestCase.java</include>
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        ...
    </plugins>
    ...
</build>
...

 

 

Setting it up for Cargo

I’ve done this on a few projects, the first was a project that built a series of taglibs which are used across a number of applications. The release for the project is a jar so I have a separate test web-app structure in ${baseDir}/src/test/web-app. The code for generating this war looks like this:

 

...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <executions>
                <execution>
                    <id>generate-test-war</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>war</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <warSourceDirectory>${basedir}/src/test/webapp</warSourceDirectory>
                <warName>${project.artifactId}-test</warName>
                <webappDirectory>${basedir}/target/${project.artifactId}-test</webappDirectory>
                <primaryArtifact>false</primaryArtifact>
            </configuration>
        </plugin>
        ...
    </plugins>
    ...
</build>
...

 

During the pre-integration-test phase the above simple generates a test war. If you’re project is a web-app and it already generates a war you can skip the above as one will be generated for you already.

The next step for was then to get Cargo to deploy the application:

 

...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <configuration>
                <wait>false</wait>
                <container>
                    <containerId>tomcat5x</containerId>
                    <zipUrlInstaller>
                        <url>${integrationtests.tomcatURL}</url>
                        <installDir>${installDir}</installDir>
                    </zipUrlInstaller>
                    <output>
                        ${project.build.directory}/tomcat5x.log
                    </output>
                    <log>${project.build.directory}/cargo.log</log>
                </container>
                <configuration>
                    <home>
                        ${project.build.directory}/tomcat5x/container
                    </home>
                    <properties>
                        <cargo.logging>high</cargo.logging>
                        <cargo.servlet.port>8080</cargo.servlet.port>
                    </properties>
                </configuration>
            </configuration>
            <executions>
                <execution>
                    <id>start-container</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>start</goal>
                        <goal>deploy</goal>
                    </goals>
                    <configuration>
                        <wait>false</wait>
                        <deployer>
                            <deployables>
                                <deployable>
                                    <location>${basedir}/target/${project.artifactId}-test.war</location>
                                    <type>war</type>
                                    <pingURL>http://localhost:8080/${project.artifactId}-test/index.html</pingURL>
                                    <pingTimeout>300000</pingTimeout>
                                    <properties>
                                        <context>${project.artifactId}-test</context>
                                    </properties>
                                </deployable>
                            </deployables>
                        </deployer>
                    </configuration>
                </execution>
                <execution>
                    <id>stop-container</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        ...
    </plugins>
    ...
</build>
...


Most of this is pretty self explanatory, I try to use parameters to configure as much as I can and try to maintain it in higher level POMs wherever appropriate. This is especially true for the tomcat URL which changes on a regular basis. The seem to post new releases and remove the older ones, and it can be a chore to keep up in multiple projects. You may want to look at the cargo plugin documentation, you can ignore some of what I’m doing above if you’re project’s default artifact (the one package creates) is a web-app. 

So there you have it, eventually I got there after a lot of digging. I’ve been pretty brief in my explanations and have assumed a fairly good understanding of maven. if you have any questions by all means leave a comment and I’ll do my best to make it clearer.

Reblog this post [with Zemanta]

{ Comments }

How to demoralise staff

by Andrew on September 17, 2008

Coders, desginers even your support staff actually want to take pride in their work, the want to do a good job. As a manager you’re meant to make that easier, but what if you don’t want to - how would you go about breaking someone’s will and what would a completely demoralised staff member look like, want to find out?

Start by micromanaging them

Assume from the start that they’re incompetent, they won’t get it right and make absolutely sure they’re told every task they need to do. Make sure you tell your staff in minute detail how you want it to look, how big you want it, what colour and how they should discuss it with customers - because let’s face it, the fuckers aren’t capable of figuring it out themselves.

Free will is alright in religion, but not in this workplace!

Make sure you’re ever vigilant and make sure you’re giving each member of staff a list of things they need to do. Of course there are things that will crop up and they’ll need to address those as well, but don’t allow it to impact your lists - you are the boss and your will, will be done.

The key to true micromanagement lies in the process, or more to the point in creating a process. When something slips through, there is a failure or anything breaks down it’s because of a procedural failure, the only solution is to fix the procedure, with a new one. Creating a new process allows you to have complete control without requiring you to interact on a case by case basis; though that is highly recommended, because as we made clear earlier - the fuckers just aren’t capable on their own.

For the advanced, micromanaging further can be a worthwhile challenge; take a task you’ve assigned and make sure you’re staff are aware of each step that you need them to complete. Basically micromanage your micromanaging! Tell them what to do and how you want them to do it, tell them in detail and make sure they know you’re doing this because it wasn’t done right last time and we just can’t afford any more mistakes.

Documentation is key

We all know that documentation is important, but only a gifted few are able to take it to the next level. If you’re in charge of anyone for the love of god, cover your ass. As in the wild if you’re the alpha male (or female) you need to defend that position, show any weakness and someone will certainly try to unseat you - make them document their worth, then use it against them!

As you micromanage processes and create new ones you’re handed a golden opportunity for documentation, new spreadsheets, new flow charts and new forms to fill in!

Make it pointless

It’s not meant to be about something that is easy for the staff - this is about you. Make sure the documentation is unweildly at the very lest - shooting for downright maddeningly pointless is of course the ultimate goal if you want to truly demoralise people.

Timesheets are a great starting place. But they should never list time on task - they lying bastards always just add them up to make a full week work, even when you know they’re bunking off. Make they list the time they started, then the time they finished a task and make them do it in a separate document for each task. Another great place is a call logs and error reports - make them document it all!

Make it feel like they’re justifying themselves

Make sure that when someone is filling out documentation, especially things like timesheets, they’re aware the true intention of the activity is to justify themselves. Make sure you say, and repeat, things “They’re kept on file for management review, internal accounting and cost/benefit analysis”. That’ll keep ‘em on their toes.

Make them justify themselves

Use the documentation in meetings - they knew you were going to even if you said you wouldn’t. Haul them out during a performance interview and you’ll have everything you need to keep costs down.

Advanced documentation

  • Make sure it’s on paper, as we can’t trust these computers
  • Even better, mandate they fill in a spreadsheet, print it and then file it
  • Even better, mandate a more detailed format, update a communal spreadsheet (stored on a shared drive and only accessible by a single user at a time), print it, then file it.

That was fun, where to from here?

Now that you’ve moved away from the traditionally held position that lower level tasks should be delegated down the chain of command so you can focus on the higher level tasks, start complaining that your staff are useless. Tell them that they can’t seem to accomplish anything without you hand holding them. Put pressure on them, make them sure that THEY are holding up business development.

Hire them a new boss

You need help, your staff are useless so create a new tier of management. Hire someone from outside to help you better manage your staff. Even better, bring someone from a different division into the team and put them above the team members.

The above is satire, I wouldn’t actually suggest you do any of that if you want to have a happy productive workplace. To a greater or lesser degree I or people I know have been guilty of some of them but it isn’t based on any real concrete experience.

{ Comments }

More time passes

by Andrew on August 15, 2008

Again, I’m here apologising for letting things slip a little. I’ve been busy and posting has unfortunately suffered for it. I’ve been working hard trying to get things moving for goroam, and it’s been time consuming. I basically spend the last half of last year bogged down with a project and had no time at all to spend on it, so for the last half of this year the focus is really to turn it around, launch a few things and start bringing some revenue in.

Our biggest project at the moment is running an online marketing campaign for Mediqol a medical device consultancy. Our lofty goal is to show up in the first position for the search keywords medical device, short term we’re just interested in optimising the adwords campaigns, and increasing organic traffic for the keywords we know work.

Then there is Citrus - Work is progressing, but we might be looking at an end of the year launch for it. My gut feeling is that we won’t be anything approaching a launch before the end of November.

In the meantime we’re looking into a couple of smaller launches. I have a couple of ideas for tools and products that tie into the Citrus roadmap that we can launch.

I’m going to spend some time this afternoon and weekend writing some posts to get on top of it again.

{ Comments }

Don’t listen to your customers

by Andrew on July 30, 2008

Too many times I’ve seen businesses slam the wheel hard to the left and change course chasing money. You know the drill, if only our product could do something else we’d sell so much more. Or worse a customer or potential customer suggests a feature that would clinch the deal.

Let’s face it just because one person wants it doesn’t mean you’re on to a winner, success just isn’t that easy - someone won’t just walk in the door and give you all the answers. The hard reality is that talk is cheap and it’s easy for someone to say they would certainly buy something if only it did something else as well, it’s quite another for them to actually drop their current system to replace it with yours when the feature happens.

Focus

Focus on what is important, delivering a product that long term meets your vision and accomplishes the goals of your users.

You know your market, focus and stick to that

You should be, as 37 signals put it, hiring the right customers, figure out your core target market and target them. A common fault I see with businesses that end up in a position where they’re chasing cash is generally that they’ve refused to figure out a core market, and refused to focus on it.

They argue that by adopting too narrow a focus they’re cutting themselves out of a potentially lucrative market. It may sound like a compelling argument, unfortunately most of the time, it leads to spreading yourself too thin, or not being agile or focused enough to truly serve any of your “target” markets.

Find a core market, where you can make a difference and focus exclusively on that market.

Branch your product from a strong trunk of core users, just like a tree if you branch too early the trunk won’t be able to support the weight.

You have a vision for your product, focus and stick to that

It’s very tempting to listen to every feature request from every passionate user and fall in love with it. That’s why a vision is important, knowing what it is your product is meant to accomplish helps immensely as a filter for “good ideas”.

An example of a product vision is goroam’s citrus. Our vision is simple “estate agent tools that don’t suck” and the filter for new features is a simple set of questions

  • will it help sell more properties?
  • does it give users valuable information?
  • does it save users time?

If a feature doesn’t have a compelling answer to any of these questions, it’s a non starter. Most importantly though the answer has to affect most of our customers. We’re not in the business of worring about edge cases or selling features.

Adopt a pragmatic approach to feature requests

And by pragmatic, I mean ruthless. Make absolutely sure it focuses on your market, your vision and affects most of your customers. Don’t keep feature lists, the good ideas will come back again and again the bad will just languish there anyway. Have a roadmap, but execute it quickly and only look as far as the next release. Don’t be rude, be positive about good ideas but make no promises.

{ Comments }

Don’t sell features

by Andrew on July 29, 2008

Your product has a vision, a roadmap and you’re in control of it. You’ve worked hard to build a niche and now you’re faced with the dilema that faces too many small companies: Company X wants your product to do something else - but unlike the other tire kickers, they’re willing to pay for it.

Here there be dragons!

Bootstrapping is hard work, and sometimes you’ll have to do other work to pay the bills but resist the urge to allow customers to pay for features in your product. It makes a very subtle change in the relationship, suddenly the feature is now your customers and they’re paying for it, so they’re dictating how it should work; not just today, but tomorrow as well.

the devil is in the details

Even if you’re in the rare situation that the next big feature on your list to implement is the feature you’re being paid to build, beware. While you might agree on the feature in principle, you might not see eye to eye on the implementation details. They will more than likely want things to match their internal processes. Which isn’t likely to match that of your other customers, or your vision.

When a user sits down to plan out a feature they’re paying for they have specific goals in mind, those goals aren’t going to be keeping things simple and they’re not going to be looking at how to achieve most of the needs of all your customers. They’ll be looking to achieve all of their own and wont care a jot about anyone else’s. They may pay lip service to caring but in the end why should they? They’re paying to have the feature developed and if someone else wants it to do something else - let them pay.

no control

So in the end you’ve developed the feature, been paid for it but probably compromised your vision for the product in the process. You’ve also painted yourself into a corner, because now that someone has paid for this feature updates, changes and even taking it away at a later date isn’t really going to be at your discretion.

Compound this when the strategy works the first time and you try it out again. Now you’re totally loosing control of your product and your vision is a thing of the past. Your nice simple product is growing tentacles and doesn’t quite work the way an average user would want it to work. Your edge cases are taking over and your vision is becoming bloated with £10,000 buttons one person clicks once a week that confuse everyone else.

rules must have exceptions

I have seen selling features actually work in practice a few times. There have been some notable examples of open source software developers doing this.

The difference here is the features have already been requested by the community and a bounty is paid or the customer is paying to fork the code. Forking code is an option, even for a company developing closed source software or a service offering, but it’s not really an attractive one. You want to keep things as simple as possible and trying to maintain more than one product is orders of magnitude harder than just maintaining one.

it’s not worth it, just don’t do it

My very strong recommendation is to keep it simple, one code base, one product, one vision - keep it simple and don’t sell features.

{ Comments }

Setting subversion up to work with contractors

by Andrew on July 28, 2008

In my last post I promised I’d write another about subversion and how to set things up to work with contractors. I was supposed to post this the next day, but I got caught up with other things.

Anyway, let’s just jump right in…

We run all our projects out of one big subversion repository, some people create a repository per project or group projects into a number repositories. In all honesty it really doesn’t matter how you group things, I think that one repository works better for us, I can move things around and I can allow people access to all or parts of the repository. You may feel differently, but for the time being I’m going to assume you’re working with a single repository like us.

getting started: installing apache, subversion and mod_dav_svn

I recently upgraded to Subversion 1.5, there wasn’t a package available for the version of Fedora we’re running on our server so I had to build it. It was a relatively painless process of simply making sure dependencies existed and following the instructions in the INSTALL file.

http://subversion.tigris.org/getting.html

Go do that now, get subversion and mod_dav_svn installed. There are more than enough resources out there on how to install subversion that I’m not going to go into too much detail about building from source or installing on any specific platform.

In fact since the steps and concepts I’m going over in this post don’t require a specific version I’ll just throw up some common defaults.

If you’re on a Red Hat based linux system try:

# yum install subversion
# yum install mod_dav_svn

If you’re on a Debian based system try:

# apt-get install subversion
# apt-get install libapache2-svn

In your apache configuration file, near the module declarations make sure you have the following lines.

LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so
LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so

setting up a repository

Again moving quite quickly here, there are tons of other better resources for getting started with Subversion on the web, better than I could hope to write. The basic command you need to run simply creates the directory structure that subversion needs.

$ svnadmin create /path/to/repo

It’s usually best to create this somewhere near, but not in the document tree for the webserver.

Open you’re apache config file, or the config file that stores the details for the virtual host you’re using and add the following lines:


DAV svn
SVNPath /path/to/your/repository
AuthType Basic
AuthName “Subversion repository”
AuthUserFile /path/to/your/passwdfile

Now create the htpasswd file and add a user or two using the following commands

# htpasswd -cm # htpasswd -cm /etc/svn-passwd andrew
New password:
Re-type new password:
Adding password for user andrew

# htpasswd /etc/svn-passwd -m simon
New password:
Re-type new password:
Adding password for user simon

Restart apache and that’s it all done. You should now have a running subversion repository with two users, andrew and simon, they should be able to view and commit anywhere. We’ll assume these are staff members who can view and commit on any project.

Setting up for an external contractor

Now you want to bring a contractor in on a project, so let’s create them a user:


# htpasswd /etc/svn-passwd -m john
New password:
Re-type new password:
Adding password for user john

The next thing you need to do is to setup svnauthz to control access to the repository. Back in your apache config file, add the following line into your svn config:

AuthzSVNAccessFile /home/goroam/dev.goroam.net/user/repos/svn-authz

So that it looks something like this:


DAV svn
SVNPath /path/to/your/repository
AuthType Basic
AuthName “Subversion repository”
AuthUserFile /path/to/your/passwdfile
AuthzSVNAccessFile /path/to/your/repository/svn-authz

I tend to keep my svn-authz file within my repository path, you may wish to place it elsewhere - whatever works best for you.

The next step is to create the svn-authz file. That’s as simple as this:

[groups]
staff = andrew, simon
contractors = john

[/]
@staff = rw
* = r

[/external-project]
@contractors = rw

The file is pretty simple and self explanatory but the first block starting with [groups] defines the groups. In this case we’ve got two one for staff with andrew and simon and one for contractors with john as the single member. The usernames to use here are the same as you set in your htpasswd file. Authentication is controlled by the standard basic authentication, subversion is only controlling access.

The next two blocks are paths within the repository. The first:


[/]
@staff = rw
* = r

Tells subversion to give all members of the staff group read and write access to everything under the / path - basically the whole repository. The next line * = r tells subversion to give everyone else, read access to everything.

Again this may not work for you, but we tend to allow read access to everything to everyone with a password. If we trust them enough to give them a password, we trust them. Also it allows contractors to build dependant libraries from the head, which is required at times and saves us the trouble of working out dependencies in our svn-authz file.


[/external-project]
@contractors = rw

In the next block, above, we’re giving everyone in the contractors group read and write access to everything in the /external-project path of our repository. This of course is the project they’re currently working, so your path will be different.

That’s it. Contractors hired, up and running in your subversion in minutes.

Slightly more complicated, but easy now that you know how

Let’s just complicate things a little bit by adding two external contractors from the first company and a third from second working on two different projects.

Let’s say that CompanyA Limited are working on project-x. They’ve asked us to create accounts for Dick and Jane. Then we hire Dave from CompanyB to add a feature called zing-bang to project-y. You could, of course just create two accounts, one for each company - but we tend to avoid that. We like to know WHO committed what code. Not just where they were from, we work closely with our contractors and it helps us when we’re communicating with them.

We know how to create the users, but just to recap here we go again:


# htpasswd /etc/svn-passwd -m dick
New password:
Re-type new password:
Adding password for user dick

# htpasswd /etc/svn-passwd -m jane
New password:
Re-type new password:
Adding password for user jane

# htpasswd /etc/svn-passwd -m dave
New password:
Re-type new password:
Adding password for user dave

Assuming, as above we have andrew and simon as staff users we should make our svn-authz file look something like this:


[groups]
staff = andrew, simon
companya = dick, jane
companyb = dave

[/]
@staff = rw
* = r

[/project-x]
@companya = rw

[/project-y/branches/zing-bang-feature]
@companyb = rw

We’re only building slighty on the previous file with the groups entries, and that should be clear. The entry here for project-x should also look familiar - Both dick and jane, members of the companya group have read and write access to the path.

For the next entry we’ve created a branch and we have company b working on the branch. I’m really just throwing that out there, mostly because I can, but also to show that you can go to any depth in the repository tree granting access as you see fit.

In this case it’s been determined that the work CompanyB in engaged to complete only needs to take place in this branch, so while they can read the whole repository they cannot write anywhere except here. This would allow you to continue internal development, or indeed external with some more entries on project-y making point releases while zing-bang feature is developed and CompanyB could merge the trunk in at will, since they have read access to it.

a lot of words

It was a lot of words, but the concepts are pretty simple. It doesn’t take long to set subversion up and even with basic auth and htpasswd files it’s not complicated to administer. So go on, get your contractors under control. I promise the dividends paid through increased accountability, visibility and communication will more than offset the time spent administrating the system.

Reblog this post [with Zemanta]

{ Comments }

Saying no some more

by Andrew on July 16, 2008

Re-reading my post about saying no got me thinking about the other reasons we’ve turned down work. It’s hard getting work in the first place and doubly hard turning it down, but sometimes you just have to say no.

One big one that comes to mind is we quoted to do some work for a company we’ve had a long term working relationship with. A small company, they were unfortunately facing the loss of a key member of staff in the final few months of development of a key project already well overdue. A update to a project we’d worked with before, so we were familiar with the architecture, team and almost every aspect of the project.

We made quoted a day rate at the low end of the scale and offered to agree fixed times for each bit of development, insulating them from any estimate errors by delivering that iteration for the quoted price before undertaking the next. We agreed to put the work we were quoting on first, push our own development schedule back, not take on other work and offer any time the needed to get their project released.

I got the very distinct impression they wanted the work done cheap from a discussion with the technical lead for the project. I tried to mitigate any problems by sending an email detailing our costs and how they break down from developers salaries, equipment costs and the meagre profit margins. I also made it clear that we were uniquely qualified for the work, due to our extensive working history directly with the project.

The response was disappointing, they were willing to pay about half the rate we quoted. I had a brief discussion with the technical lead, who was as disappointed as us with the reaction, but it was clear there was going to be no middle ground. The offer was never even going to come up enough.

We gave up in the end - a shame really, like any small business we could have used the money. It was an issue of value. Despite all the positives, the experience, the fact that there was nobody else who could have hit the ground running like us and our prior working relationships they weren’t willing to pay what we consider a very reasonable price. They effectively wanted work done for less cost to them than it would have cost to hire a member of staff, with none of the security or benefits. A short term contract under terms worse that a job I’d been offered months prior.

In the end they had to give the member of staff who had planned to leave a significant pay rise to entice them to stay, hired another, less experienced developer who needed more managing and training and still haven’t delivered the project, months later.

For us, and for anyone else considering taking work at less than a market rate, it’s a tough choice. Though we could afford to survive without the work, it would have been nice to have the money in the bank. There is also always the potential that work can lead to more work, however do you want cut rate work leading to more of the same? It’s all too easy for it to set the tone of a working relationship and an expectation that you will continue to work for the low rate. Also the whole time you’re servicing the contract you’re not getting new clients or doing other more lucrative work. As a consultant if you’re not saving for a raining day you’re taking a huge risk, especially if things get a bit lean for a few weeks or months.

{ Comments }

Peanuts and monkeys.

by Andrew on July 14, 2008

It’s well known, but amazing how often people are willing to succumb
to the temptation to save a buck - even at the expense of quality or a long term relationship.

Hiring or paying for experience is always going to cost you more than the lowest quote you can manage. When your looking for the cheapest possible quote though you’re rarely making a proper value judgement including quality as a component. Cheap work all top often is just that: cheap. Good value doesn’t just mean the cheapest.

Not all employees or contractors are created equal. This applies to everyone sales, techies, designers and support staff. Cheap out on them and you will suffer. Speaking from experience and repeating industry wisdom one good coder or designer is worth orders of magnitude more than a weak one. It bears repeating, a good coder or desginer is not just 5%, 10% or even 25% better than a weak one - they are 200%, 300% or more better. The same variation appears in almost all organisations in almost all roles that require any sort of special skill. Your best and your worst sales staff will show the same sort of variation - the good will be very, very good.

On top of just being better, an experienced designer or coder working in a team long term will get it right first time without a lot of questions or explination. They’ve been working with the team for long enough they know most of the details without needing to be told. You’ve invested in their knowledge - you’ve effectively paid to develop the brain that if you’re making a value judgement based on cost alone will be walking out the door with value worth thousands.

Trying to cut costs by hiring cheaper staff or contractors can quickly backfire on you in a very severe manner. Your staff are your biggest cost, you’ve invested more in them than any other area of your business. Throwing that investment away for a cheaper alternative might seem like it can make sense from a purely numeric point of view but it’s missing the true value they’re bringing.

{ Comments }

Minimum Stable Feature-set

by Andrew on July 3, 2008

From time to time this blog will reflect a decision we take as a company, this is one of those times. We’re currently working on a product called Citrus, a better way for agents to sell property online because frankly existing stuff sucks, scheduled for launch in the autumn.

One of the key decisions we’ve taken is not to implement everything on our feature list. We’d rather build half an app than a half assed one. As flippant as that sounds, it’s true- we could spend years analysing all the competition, ensure that we’ve not only bested them at the key features we know we need to implement, but at everything else as well and some day in the distant future launch a product. Or we can look at our feature list, choose the killer features we know our application needs to have to achieve everything 80% of our potential customers need from our app and forget the rest.

We’ve chosen the latter. It’s going to help us get to market faster, it’s going to help us get customers quicker and it will allow our customers actual use of the product drive our vision for it- not some paper list. Also if we’re totally wrong in assumption that a good product can gain traction in a poor market, we know and can move on sooner.

UPDATED: I renamed the title for consistency - we refer to the stage of development as either both the Minimum Launch Feature-set or the Minimum Stable Feature-set internally - the latter being the best really since it’s useful both for an initial launch and for discussing post launch updates.

{ Comments }