How to Start a Software Company 2.0

by Richard Rodger

       
 
Be the Best Available

There are only two (profitable) markets. The cheapest available and the best available. Play the middle ground and you play to lose. Seth hits the mark again. Imagine how much it would have been to hire this guy before blogs? Now you can get his head for free.

OK, I know this is not exactly rocket science. High volume versus high margin. Clean and simple. Lots of people have written about it. But it's nice to get a reminder. It gives you motivation and inspiration.

When I started Ricebridge I had this in mind, if not in words. Give something a name and you give it power. Give an idea a name and you manifest it. "Be the best available". What a brilliant way to give yourself focus.

In my own market (software components) I have really tried to live this idea. Yes, there are loads of Open Source alternatives. That's the high–volume competition. And I go for the high–end business. When you really need to get the best there is, I'm there. People need this option.

Of course, it's a lot more work to build full-service components. All that other stuff outside the code. All the additional support that comes with the product. That's really where my market is, not the code itself. I've been thinking about this truth for quite a while now. Fully embracing it means providing high-level support for my components, as standard.

Pretty soon I'm going to announce an entirely new licensing model. Prices will change, but what you get will be far more than just a piece of code. Instead of providing support as separate (expensive) products, I'm going to make support a part of the core offering. When you buy a Ricebridge component, you will get high-level support as standard. Your questions will be answered directly and quickly. No more searching through documentation or FAQs. What you buy is another team member who just happens to be a complete specialist in one part of your project.

I really think that the lack of support is what puts people off buying software components. Commercial components are usually so badly supported that people are driven to Open Source. We've all had our nightmares. At least Open Source has some sort of support structure. It may be random, but at least you have some hope. If you look at the component vendors that are well-respected, you find that they are the exception that proves the rule. Everybody raves about them.

The thing is, supported components are what is needed, not software components. There is no such thing as plug–and–play when it comes to building software. You always need a helping hand.

It's time to start playing to my strengths.

tag-gen:Technorati Tags: Del.icio.us Tags:

@ 02:57 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Further Versioning Contortions

Yesterday I had a plan to use reflection to solve the compatibility versioning problem with my software components.

Basically I need to change an interface that existing customers have implemented. And I want to maintain compatibility so that no-one has to recompile anything.

I did try to anticipate this problem by providing for changes in an abstract support class. Users were advised to extend this class rather than implement the interface directly so that future changes could be hidden from them.

Well it looks like I might be able to get away with it after all. And without any reflection. Here is a concrete example of the problem, and a proposed solution.

The solution satisfies the requirement that existing code must not be changed. Existing binaries must still work, and existing code must still compile without errors. But the interface will change. Here goes...

First, here's the current situation, demonstrated in code. I've used a simple example to show the essence of the problem.

We have ColorManager class, to which Colors can be added. Colors have names and numbers. To implement a new Color you extend the ColorSupport abstract support class which in turn implements the Color interface. Instead of implementing the interface methods directly, you implement protected *Impl methods instead. These are called by ColorSupport. This insulates you from changes to Color.

The change is that the Color.getName method is to be renamed Color.getCode, and the ColorSupport.getNumberImpl method is to be made protected (it was accidentally released as public).

Anyway, here's the initial code:

public class ColorManager {

  public void addColor( Color pColor ) {
    System.out.println( "color:"+pColor.getName()
                        +","+pColor.getNumber() );
  }

  public static final void main( String[] args ) {
    ColorManager cm = new ColorManager();

    Red red = new Red();
    cm.addColor(red);
  }
}


public interface Color {
  public int getNumber();

  // this will be changed to getCode
  public String getName();
}


// this is the abstract support class
public abstract class ColorSupport implements Color {
 
  public int getNumber() {
    return getNumberImpl();
  }
  
  public String getName() {
    return getNameImpl();
  }
  
  // this needs to be made protected
  public abstract int getNumberImpl();
  
  protected abstract String getNameImpl();
}


public class Red extends ColorSupport {

  public int getNumberImpl() {
    return 0;
  }

  protected String getNameImpl() {
    return "red";
  }
}

These classes mirror the current design of the LineListener and LineProvider callback interfaces in CSV Manager.

So the class Red represents a user created class. It cannot change. And neither can any existing Red.class bytecode.

The solution has to take into account the following: The old ColorSupport will be deprecated, but still supported. The next major version will use a changed ColorSupport and remove all compatibility code. This is allowed as compatibility can be changed on a major release. ColorSupport is a name we want to keep (for consistency across product lines). So if we use a new support class in the meantime, we have to insulate new users who implement the new, correct, Color methods. We must make sure that their code required no changes when we move to the next major version!

So here's the basic idea: apply the changes to Color, which breaks the old ColorSupport and Red Classes. Detach ColorSupport from Color and make it a standalone class. Add a method to ColorManager that can accept ColorSupport. This ensures that old Color implementations that extend ColorSupport still work with ColorManager.

Next, create a ColorSupportImpl class. This is the new ColorSupport. It will replace the old ColorSupport with the next major version. ColorSupportImpl extends the new Color interface directly. It works just the same as the old design. But we know that the name ColorSupportImpl is temporary and will be dropped. So we need to place an insulation class in between the concrete color classes and ColorSupportImpl. To do this we change the recommended way to implement colors. For every color, there is a specific color support class. For example, Green will extend GreenSupport which then extends ColorSupportImpl.

That still leaves one little problem. What about colors that we have not defined? What about user-defined colors? We need to specify that custom colors extend an insulation class rather than ColorSupport, as is currently the case. We'll use CustomColor. So this suggests a change to the standard policy across product lines. Custom concrete user classes extend an abstract custom class which extends an abstract support class that implements the interface in question.

Wow, that seems like a really complicated way to do something simple. In a normal environment you would never do this. You would refactor and modify client code. And for released software components you can't do this. Releasing commercial software creates an entirely different set of issues. In this case it is far far more important to support existing customers than it is to refactor to a clean design. The vendor has to accept the responsibility for maintaining compatibility for reasonable periods and between clear boundaries. You only need to take a look at the situation with plugins to Eclipse or Firefox to see how difficult this problem is. And they get it mostly right!

Here's the code for the new version. Watch out, we've got lots more classes!

public class ColorManager {

  public void addColor( Color pColor ) {
    System.out.println( "color:"+pColor.getCode()
    +","+pColor.getNumber() );
  }

  // this keeps the old colors working
  public void addColor( ColorSupport pColorSupport ) {
    addColor( new ColorSupportFixer(pColorSupport) );
  }

  
  public static final void main( String[] args ) {
    ColorManager cm = new ColorManager();

    // this is an old color
    // old custom colors will work this way as well
    Red red = new Red();
    cm.addColor(red);

    // this is a new standard color
    Green green = new Green();
    cm.addColor(green);

    // this is a new custom color
    Blue blue = new Blue();
    cm.addColor(blue);
  }
}


public interface Color {

  public int getNumber();

  // this is the new version
  public String getCode();
}


// this is the same as before, but no longer
// implements Color
public abstract class ColorSupport {
 
  public int getNumber() {
    return getNumberImpl();
  }
  
  public String getName() {
    return getNameImpl();
  }
  
  public abstract int getNumberImpl();
  
  protected abstract String getNameImpl();
}


// this is unchanged - just what we want!
public class Red extends ColorSupport {

  public int getNumberImpl() {
    return 0;
  }

  protected String getNameImpl() {
    return "red";
  }
}


// this is the new verion of ColorSupport
public abstract class ColorSupportImpl 
  implements Color {

  public int getNumber() {
    return getNumberImpl();
  }

  public String getCode() {
    return getCodeImpl();
  }

  protected abstract int getNumberImpl();
  
  protected abstract String getCodeImpl();

}


// an insulation class, currently does nothing
public abstract class GreenSupport 
  extends ColorSupportImpl {}


// a new standard color
public class Green extends GreenSupport {

  protected int getNumberImpl() {
    return 1;
  }

  protected String getCodeImpl() {
    return "green";
  }

}


// an insulation class for custom colors
public abstract class CustomColor 
  extends ColorSupportImpl {}


// a custom color
public class Blue extends CustomColor {

  protected int getNumberImpl() {
    return 2;
  }

  protected String getCodeImpl() {
    return "blue";
  }
}


// this hooks up the old and new interfaces
public class ColorSupportFixer 
  extends ColorSupportImpl {

  private ColorSupport iColorSupport;
  
  public ColorSupportFixer( ColorSupport pColorSupport ) {
    iColorSupport = pColorSupport;
  }
  
  protected int getNumberImpl() {
    return iColorSupport.getNumber();
  }

  // convert getCode to getName
  protected String getCodeImpl() {
    return iColorSupport.getName();
  }

}

Like I said, it's not pretty. But it does allow the API to move forward with full backwards compatibility.

The insulation classes (GreenSupport and CustomColor) are empty in the example above and will probably also be empty in the next CSV Manager release (1.2). Their purpose is to allow ColorSupportImpl to change its name in release 2.0.

And they serve another very important purpose. If in the future further changes arise that require more compatibility workarounds, they allow for the use of a reflection-based solution in ColorSupport and/or the insulation classes. Thus one layer of changes can be applied on the interface side, and one on the implementation side. This "feels" like the right solution.

Of course, some types of changes (for example, changing method access from public to protected) may not be amenable to a reflection-based solution. They may require a third layer of insulation. We'll cross that bridge when we come to it, if we cross it at all. I rely on the belief that as the API converges on an acceptable design, these types of changes will become less of a problem. Once the API has been in use for a longer period, changes become so exponentially expensive that it is better to put up with design mistakes. This is what happened with the standard Java API.

I reckon I am still able to pull this off at this stage in the life-cycle of CSV Manager. The cost will be more complex documentation until 2.0, when the compatibility code can be ditched. And the cost will be increased code complexity inside CSV Manager, which means more work for me to bug fix it all. Of course, I have a large set of unit tests so this should not be a big problem.

Well, it looks like we're set. Any final thoughts before I dive into the code?

@ 04:35 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
More On Versioning

Brian Smith made some good points on my last post about software component versioning. They're too detailed to reply to in a comment so I'm posting a reply as a full entry.

You'll probably need to read that last post for this one to make sense. Also, I kind of have a strategy now. More on than at the end of this post.

I would just change the version number to 2.0, and then tell your customers that they can have a free upgrade even though this isn't the normal policy.

There's not enough new stuff to go to 2.0. It's not really fair to customers either. I think it has to be 1.2. I'd like 2.0 to be a bigger bang.

Unless you are taking away functionality I have a hard time understanding why you cannot maintain backward-compatibility. Compatability is something that everybody expects, and doubly so if they are paying for the product. It seems like the problem could be solved by adding a new interface instead of replacing an existing one.

When adding methods, this is the case. In fact I will be adding methods and maintaining the old ones. But if you want to change method access permissions it's basically impossible. I want to move a public method to protected.

Also, adding a new interface is not an option as I need to keep the name of the interface consistent across product lines. Bit of a catch-22 really. It's a bit of a pain when you have to manage more than one product. I'm starting to have some sympathy for Sun and the mess that is java.*.

The nice thing about backward-compatibility is that there is helps encourage people to upgrade to the latest version. If people refuse to upgrade then you end up supporting old versions longer. If a customer finds a bug in version 1.1 then they will ask you for a 1.1.1 to fix it, instead of upgrading to 2.x where it was already fixed.

Ah. Yes. But I do this in any case. All major versions will be supported for as long as possible. This is important. Part of the reason developers hate external components is because they can't be trusted and a lot of vendors just don't care if there are bugs. Well I care, and I won't let bugs stand if I can help it.

I don't really like the idea that the first component of the version number only changes when there is an incompatible change. If you maintain compatibility for five years then the version number would be something like 1.9. But, 1.9 probably would have much, much more functionality than 1.0. Yet, the numbers 1.9 and 1.0 don't seem that much different from each other (it is easy to misread it as 1 & 23/100). The result is that this scheme is counterproductive to marketing the product: the main version number increases when something bad happens.

The worst case would be when you publish an interface in, say, version 1.6.1 that for some reason has to change immediately (e.g. the way the interface was structured facilitates some kind of security problem). To fix this problem you want to release a fixed version of the API. But, now you have to call this version 2.x even though it might be a very, very small change. Maybe the jump from 1.0.1 to 1.6.1 was a huge improvement in functionality. Yet, the increase from 1.6.1 to 2.0.0 was a single bugfix, perhaps just a few characters changed in the source code. It is counter-intuitive.

This is a very strict interpretation. I would say that one can bump to 2.0 at anytime, for marketing reasons say. It would only be forced by a compatibility issue.

In any case, I think I am going to drop the minor version restriction and say that minor numbers can accept compatibility changes. This means that you can only be 100% sure of compatibility on the same major.minor revision. But that's pretty much OK.

It works okay for open source products because marketing for them is totally different (often ignored).

Very true. And there is something to learn from Open Source. Version numbers are an important way to give a quick overview of the state of the project. I like that and it's very useful, even necessary, for software components. It's much less important for applications, where the version number is just a marketing gimmick. But for my stuff the version number is, in a way, part of the customer service. It's very important that it has a crystal clear meaning.

So this all seems like a very difficult problem to solve. However I was forgetting one thing about Java: Just-In-Time compilation!

How does that help? Well, it means that reflection is not as bad as you think it is. The "common knowledge" is that reflection is slow. Well sure, the lookup is slow, but once you have the method reference the JIT compiler will optimize the calls for you. In the case of data processing where you perform the same operation many times, this effect comes into play very quickly.

So reflection is OK! I can use it! I'm going to look at trying to rewrite the support classes to handle this situation. They will introspect themselves to see if the old methods are declared. They can thus recognize the old interface and work with it. Old code should just keep working.

Yes this will make my support classes messy and more complex. Tough for me. That's the price to be paid. If you want to maintain compatibility for paying customers, as Brian noted above, you must do this. Anything else is just lazy.

Of course, this may not work completely. We'll see. But even if I can reduce the changes required, that's a good thing.

Thank You Blogosphere, and Thank You Brian!

@ 02:34 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Versioning Cistern

My versioning system is broken. It's painful and I'm not entirely sure what to do about it. Time for a blog entry so!

Previously I wrote about my vision for the Ricebridge Versioning System. All Ricebridge components have three version numbers. For example, 1.2.3 means that you have major version 1, minor version 2, and build number 3.

Major versions allow for incompatible changes. Minor versions add new functionality but keep compatibility. Build numbers track bug fixes and minor changes. I think it works very nicely. It's pretty clear and easy to follow. And you know where you stand and what you can upgrade to. You know that a major version change will probably break your code and you'll have some extra work to do. But you also know that you can upgrade to a bug fix release or take advantage of a new method in a minor release by just dropping the jar in and continuing on your way.

I'm very attached to the three number versioning system. And so are my customers who've got very used to it. Changing versioning system is in itself a major version change really (given that you are breaking semantic compatibility), and I don't really feel like it at the moment!

So what's broken? Well I have new version of CSV Manager coming out soon. This will add a few new things, including Java Beans support. Nothing that will affect the existing code, so no problems there.

However, based on the experience gained building XML Manager, and my future plans for the product set, it looks like some of the interfaces in CSV Manager will have to change.

I want to create a coherent set of components that all work the same way. That's very important. There has to be interop, both at the code level and at the user level. That means that the APIs should be the same, Once you learn the API of one Ricebridge component, you can then apply it to all Ricebridge components (pretty much).

But the original CSV Manager API is not right for this. It needs to be modified. That breaks compatibility. So fine. We go to CSV Manager 2.0.

Except, not so fine. Not at all. You see, Ricebridge customers get an upgrade path. When you buy from us, you get the right to upgrade, for free, to a release that has the same major version. Right now CSV Manager is at major version 1. If I bump it up to major version 2, then all those customers will loose out. Ouch. Not very nice at all. Definitely not the right way to go. I want existing customers to get the full benefit of the new API as well.

It looks like we can’t bump the major version. So let's drop the compatibility restriction on minor versions. That could work. Except now, when you look at a version number, you can't tell right away whether it will work with your current setup. Not so good either.

How about using four version numbers? We can add an extra one for compatibility: major.release.minor.build. So we bump the release number every time there's an incompatibility change. Except this is not very user-friendly. Four version numbers is really pushing it. Three is just about as much as anyone can take. In any case, it's a change I don’t want, as noted above.

Another option is to stick with the old API until the real version 2.0. We can add the new stuff, but keep the old stuff in and deprecate it. This is the standard way of doing things and it is the approach that I use normally. It works especially well for adding and removing methods from API classes. But it doesn't work for interfaces that the user implements.

If you want to change an interface that a user has implemented, then you have to force the user to change their implementation class. There's no easy way round that (sadly we're in Javaland, so dynamic solutions are awkward). This happens because the interaction model between the interface and client code changes. The implementation class must provide the new services required by the client code. In some cases it might be possible to work around this, but mostly it's very messy and there is no way you can ask people to do this.

In the end, we are forced to choose between a new implementation interface and an old one. So if we want to wait until 2.0 for the big change, then we must stick with the old API for now. This works, but it increases the amount of people using the old API and makes the changeover much more painful for many more people. Microsoft has been badly stung by this many times: The long and sad story of the Shell Folders key. It seems better on the whole to take the hit now and impact the smallest number of people.

So where does this leave us? The next release of CSV Manager will include the new API. It will break old code. I'm really sorry to have to do this to my customers. It's very nasty. But the benefit will be the many ways in which you will be able to use Ricebridge components together to solve all sorts of tricky problems. It seems like a good tradeoff in the longterm.

Actually it's not even as bad as all that. The main CSV Manager methods will not be changing much and 90% of existing code should still work fine. The change will be occurring in a part of the code that is not even used by most customers (LineProviders). So maybe all this agonising isn't even necessary!

That still leaves the problem that version 1.1 and version 1.2 will be incompatible. We still need a way to communicate this and to allow users to control versioning in their own projects. It looks like an additional stream of version information is needed. We need to track API changes separately.

One idea is to have API revisions. This means publishing a detailed description of the API and assigned it a revision number. All CSV Manager releases with the same API revision number are going to be API compatible. That means you can copy in the new jar and things will still just work.

When incompatible changes have to be made to the API, then the revision number changes. A new API description is published, showing the changes, so that users can track what happened. So each version of CSV Manager has an API revision. You can show this in a table and it should then be easy for people to follow.

API revisions would not change very frequently. In fact, as we move further along with building Ricebridge components, things should start to settle down very solidly. I don't think that there will be many API revisions.

In this system, the minor version number then means: new functionality and possibly a new API revision. This creates extra work in that API revision changes have to be made clear to users, and handled carefully.

What really gets me about all this is that I had actually put in place a system to deal with it. After reading David Bau's posts about a theory of compatibility, I created a design for the user-implemented interfaces that could accommodate certain types of changes.

When you implement a Ricebridge interface, you are actually advised to extend a designated abstract support class. This class has the job of insulating you from future API changes by translating changes into the older version of what you expect. Except that this only works in some cases. To solve my existing problem it looks like I would have to write a lot of reflection code and that would probably have a bad effect on the performance of the system. It also means that new customers would find the support class to be a confusing mess. I have in fact used this technique already on one minor change to CSV Manager.

One problem that it does not solve however is that I made a mistake with the method signatures when I first released CSV Manager. Some *Impl methods which should be protected are actually public. Bugger!

So the way forward is still not clear. I am inclined to take the hit now and offer free support to all customers who need it to make the change.

What do you guys and gals think I should do?

In proving foresight may be vain;
The best-laid schemes o' mice an 'men
Gang aft agley,
An'lea'e us nought but grief an' pain,
For promis'd joy!

Robert Burns

tag-gen:Technorati Tags: Del.icio.us Tags:

@ 10:41 AM GMT+00:00 [ comments [2] ]   email this   links to this
 
 
Make $97 With One Blog Post

If Jonathan can give away free servers, then I can give away free licenses! I've been inspired by Sun's T2000 promotion to try something like it myself.

Here's the deal. You blog about one of our products, after trying the trial version out, and you get a free single-developer license.

You can write whatever you like. Tear us to shreds or sing our praises. It's all good. We just want links :)

Well, you should make sure that your audience is OK with doing something like this. Full disclosure is a good idea. So don't do anything you're not comfortable with.

Before you start writing, here's the full details of the blog promotion.

Our products are data-munging widgets for Java: CSV Manager (for CSV files, surprisingly), and XML Manager (for XML files, again, a surprise there). The single dev licenses are worth $47 and $97 dollars respectively.

Oh, and the $15 gift cert you get for every bug found, that's still valid. So you might even end up with something nice from Think Geek.

No idea when I'll end this promotion, so don't hang around if you want one, get writing!

And no, I won't apologise for the blatantly linkbaiting title! :)

tag-gen:Technorati Tags: Del.icio.us Tags:

@ 02:33 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Rant: Maven Muppetry

Hani was right. Maven really is a pain in the arse.

I have just managed to install the cobertura plugin. Not by following the instructions mind. On no.

The install instructions are to run the following command:

maven plugin:download
  -Dmaven.repo.remote=http://maven-plugins.sourceforge.net/repository
  -DgroupId=maven-plugins
  -DartifactId=maven-cobertura-plugin
  -Dversion=1.2

Well shucks ain't that nice and easy. And it used to work, because I used that very same command a few months ago and it just worked. Tip for the documentation writer: put this command all on one line and then it's much easier to cut-and-paste into a command window.

But now it doesn't work anymore. Wanna know why? Because it references a load of dependencies inside http://maven-plugins.sourceforge.net/repository/ that do not exist. Did someone delete them? Huh?

In order to install you have to drop the cobertura plugin jar into your repository manually, and then run maven. Then it picks up the dependencies from berlios.

Am I missing something here?

If you're going to release open source stuff, make sure your install just works. No arsing around. People lose interest pretty quickly when you do that sort of thing.

@ 02:33 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
CSV Manager 1.1.10 Released

This is a bug fix release for bug report 0012: the TableModelLineListener object was dropping the first row of data when the headers setting was true. If you are using Swing TableModels please check if this bug affects you. As usual, all Ricebridge customers get a free upgrade with this fix.

Thanks to Jøgen for catching this one!

tag-gen:Technorati Tags: Del.icio.us Tags:

@ 09:09 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
10 Reasons Not To Use Commission Junction

Ooh, a blog list! So commission junction (no capitals for you, ya messers!) are off my site. Here's why:

10. When they deactivate your account, they don't send you any email to let you know about it. The first time you find out is when you try to login. Bummer for you!

9. There is no way to contact them by email. No addresses on their site. Nix, Nada, Zippity-Doo-Da. Customer support is provided by international telephone numbers. Oh yeah! Do it to me baby!

8. The only way to get in touch using this new-fangled interwebnet thing is by using a teeny-tiny itsy-bitsy help form for lost passwords. No, I'm not linking to it, but it's not hard to find from the login page. Ah go on, go find it, it's hilarious. Just remember to write really small. Oh, and I wouldn't try to have a longish domain name - cos it won't fit! Muppets! /shakes head

7. If you're not making the numbers after six months, they cut you off. Hello? Ever heard of the long tail fellas? Hey I know it's just a little old personal blog, but do you have to be so mean? Not everyone can be Cory or the Doc, you know. Some us of just have our own wee little corner of cyberspace we call home. Sob …. bwwahhhaahha…

6. If your account is deactivated it can't be reactivated. Ah Holy God! databases … yesss … beeg ma-jeek! veree scaree … yesss …

5. After kicking you in the metaphorical nuts, they say, and I quote:

Thank you for allowing us to be of service to you. Client Services Commission Junction, A Valueclick Company

ROFL dudes.

4. All their mails are Roach-Motel mails. As in, you can receive 'em, but you can never reply… stimulus, no-response, stimulus, no-reponse, ...

3. Their online reporting sucks. This one is from memory since I can't, um, login anymore.

2. They deactivate your account, without confirming your final balance. Nasty. Any word on how I'm supposed to get my few pence out guys (if indeed there is any)?

And the number one reason not to use commission junction (still no caps for you!) ...

1. Their site is … puke-green. Oh my poor dear eyes.

Well CJ, it's been great, but it's time to move on. It's not you, it's me. I'm sure you'll find someone who loves you.

Wait. Actually…

Go gcreime maorlathaí­ m­í­thrócaireach do chuid infheistí­ochtaí­!
The curse of Cromwell on you!
Go scriosa cúnna ifrinn do chuid fo-éadaigh!
May you be afflicted with the itch and have no nails to scratch with!
etc.

Me? Bitter? Nah…

tag-gen:Technorati Tags: Del.icio.us Tags:

@ 08:30 PM GMT+00:00 [ comments [2] ]   email this   links to this
 
 
Friday Fun: Fancy an Island?

Feeling a little despotic? Need to impose your vision on the world?

Look no further than … a private island!

Sure Charlie did it. So can you!

@ 09:42 AM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Jostraca 0.4.1 Released!

I have just released the latest version of my open–source code–generator: Jostraca. I first released Jostraca in late 2000 and I have been unable to get rid of it since, despite repeated kicking!

So what does Jostraca do? It takes a template and generates a lot of repetitive code. Anytime you have loads of repeated code, you can use it. Now maybe with EJB3 that's not such a big deal anymore,
but if you still want just one definition of your data objects, templates can keep them DRY.

The other thing about Jostraca is that is uses JSP-style syntax, so you don't have to learn any new-fangled semi-language. You just use the language you know. And you can also use regex macros to completely define your own template syntax if you really want to. Jostraca is also language agnostic. Currently you write templates in Java, JavaScript, Python, Jython, Ruby, C, Rebol and Perl (of course!). And you can even define your own code generator formats so you're not stuck with the standard one (which just wants to dump out a load of files).

That said, Jostraca is warty. It's a work in progress and the project iterations are about 1 year(!) in length. In this business it can be quite rare to work with a piece of code for such a long time. Most projects come and go. You move on, others take over (and curse you), and the merry-go-round continues.

The nice thing about running an open-source project is that you get to step out of the coding rat-race once in while. Jostraca has been through many refactorings, and is a lot better for it. Of course, there's still a lot to do and there's a bit pile of user stories in the unassigned bucket. But no harm. I've got years to get it right. You don't often have that luxury as a coder.

One last thing. I'd like to welcome Morten Christensen on board. He's done some great work on the Eclipse Plugin for Jostraca, which was sorely lacking. He's doing some good stuff for code-generation in Eclipse.

By the way, you may have noticed that I love competitions. So here's another one. If you can figure out how I came up with the name "Jostraca", you can get a free XML Manager license. BUT DON'T POST THE ANSWER HERE! To qualify you have to send me the answer in a private mail. That means everyone has a fair chance. (The standard competition rules apply, blah-de-blah etc.)

Oh yeah. The Sphinx is kind of a clue…

tag gen:Technorati Tags: Del.icio.us Tags:

@ 12:59 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
CodeGenClipse Released!

Jostraca now has an Eclipse plugin: CodeGenClipse! (Jostraca is a code-generator, in case you're interested.)

Open source is great. The plugin is all thanks to Morten Christensen. And he found a load of bugs in Jostraca while he was writing it, so they're all fixed now.

And that's not all folks. CodeGenClipse is not just Jostraca specific. It's a general plugin framework for code-generation. So look out for some more cool stuff from Morten in the future.

This post probably sounds a little over-excited. Sorry about that. It's just cool when open-source works out. It really is a great way to get things done. Of course, I still think there's a place for commercial stuff, but especially when it comes to developer tools, you can't beat a shared solution.

And for all you Jostraca fans out there, the long wait is nearly over — 0.4.1 is oh–so nearly, nearly ready… (and will be announced right here on this blog of course)

@ 03:51 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Munster Wins!

Woohoo! Munster wins the Heineken Cup Final!

I'd only have a casual interest in Rugby, but I'd have to say I really enjoyed the final. Nail-biting stuff at the end.

@ 04:44 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Most People Are Below Average

The almighty Seth Godin says: "In every category, in every profession, half the people are below average.".

Bzzt! Wrong! Na-ah. Half the people in any industry are below the median. As in, half the people are below the half-way point (which is what the median is).

But I still think his main point is right. Let's fix the math.

In any industry you're going to have star performers. Programmers ten times better than the rest, etc. We all know the cliche. That drags the average up and beyond the main group of code-monkeys or office-slaves or whatever-you-call-your-grunts. And it drags the average higher than the median. Ability is a skewed distribution:

So Seth's argument about marketing to the below average applies even more he realises. More than half of the people in any industry are below average.

But there is a counter-point: the average is a lot higher than you think. Most jobs look easier on the outside than on the inside. Assuming you are more clever than most people is a dangerous game.

As for me, hey, I'm with the huddled masses. Who wants to be a Distinguished-Engineer anyway!

tag-gen: Technorati Tags: Del.icio.us Tags:

@ 10:08 AM GMT+00:00 [ comments [7] ]   email this   links to this
 
 
Pay Per Character

I've been doing this online typing course, and it's been going pretty well. It's not the flashiest of sites, but it gets the job done. I would prefer more coaching, tips and advice.

So today I got to the end of the "basic" course. And what was waiting for me? The Advanced course, only $29! Hmmm. OK. Well fair enough it is a good course. So I am pretty sure I will sign up for the next stage.

I like this little business model. Particularly as all the computation takes place client side (the course uses JavaScript). But I do think they could have been more up-front about the need to pay for the full course.

In fact, I have some marketing advice for goodtyping.com, if they'll allow me. Guys, there are a bunch of online typing courses out there. They're probably all following the same basic business model. So use the fact that your course is actually commercial and not free to your advantage. I just picked your course at random. If you had sold it to me as a basic course for free, and an advanced course for a fee, with an emphasis on course quality, you would have had a great differentiator. I want to learn to touch-type and I don't want to waste time on crappy courses that teach me bad habits. A commercial course gives me much more confidence that I've made the right decision. Oh, and you can raise your prices. At least $50 and the advanced course is still worth it. I'll easily reward myself that much for having made it to the end of the basic course.

Why not go for it? You have a little gem here.

tag-gen: Technorati Tags:

@ 10:42 AM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
Credit Card Fraud

Every business has "shrinkage". Stock levels mysteriously reduce. Inventories decline overnight. Products grow legs.

You'd think that the software business is different. "There's nothing physical to lift!" you say. Not true. If you're thinking of selling software via the web, take note: you're going to get dodgy orders. It's just a fact of life.

So how exactly does it work? Well you get an order in, same as usual. Now what I do for each order is check the IP address against the credit card address. You can use a site such as maxmind to do this. Unfortunately this is can only happen after the order is processed. And then you get one. An order where the IP address is from a very different country than the credit card address. A stolen card. In these cases, the email is also usually from a free email service, and is usually one of those numbered emails, as the account has been created just for the purposes of fraud. You do get the occasional sad individual who will use a traceable email address. It will show up on gaming and script-kiddie websites.

When you get one of these orders you're stuck. The perpetrator already has your product downloaded. And you have to put through a refund asap, otherwise you'll get hit with callback charges. And you should put through the refund as soon as you can so that you don't offend the poor eejit whose credit card number was stolen.

As a software company, it's not too bad — at least you don't loose money shipping out physical goods. On the other hand it makes you more vulnerable to this sort of thing, as the fraudster doesn't need a physical address for pick-up, just an email address.

Now there are a few things you can do to prevent or reduce this type of fraud. You can block certain countries from purchasing. This works, but it's not something I want to do. First, some of the dodgy orders may come from people who genuinely can't afford the products (hey – just ask me for a free copy guys! I'm reasonable). I grew up in a developing nation (South Africa), so I can understand that. Second, other folks from those countries want to do legitimate business, and they should have the chance to do so. I just don't like the idea of blanket bans.

Another thing you can do is have more stringent automated checks, based on IP and email address. Given the relatively low level of this problem, I'm not sure it's worth it. It's not like the bad guys would suddenly decide to play by the rules as a result. They'd probably just try to hack the trial download instead (Hint to bad guys: please hack the download instead of using fraudulent credit cards). So I'll put the time into coding features for my products instead.

Finally you might want to sign up with a fraud detection service. Never used one so don't know how well they work. Maybe I'll do this if the problem ever becomes really bad.

If you sell stuff on the web, you will get credit card fraud. It's a cost of doing business with the entire planet. And hey, doing business with the entire planet is a much bigger win than losing a few sales. So I guess my final advice would have to come from Tony: "Suck it up!"

One other thing to note, if you are developing a software product for download via the web: really strong copy protection is useless and a waste of time. It seems to be really easy for certain groups of people to get hold of stolen credit cards, so they'll just buy a copy. A nice, easy way to get around your oh-so-clever copy protection. And then you loose anyway. You could opt for "phone home" protection, but that has it's own issues, like customer privacy. (And don't even think about using a dongle! How sad.)

This interwebnet thing is no bed of roses. The rules are different and you'd better leave your outrage at home.

tag-gen: Technorati Tags: Del.icio.us Tags:

@ 09:58 PM GMT+00:00 [ comments [0] ]   email this   links to this
 
 
 
YahooBloglines
NewsgatorMSN
Google Readerdel.icio.us FurlSubscribe with myFeedster
« July 2006 »
SunMonTueWedThuFriSat
      
1
2
5
6
7
8
9
11
12
13
14
15
16
18
19
20
21
22
23
24
25
26
27
28
29
30
31
     
Today

All | General | Java | Business | Fun | Perl | Rant | Ireland | Web
[This is a Roller site]
[Valid Atom 1.0] [Valid RSS]
Technology Blog Top Sites
Blogarama - The Blogs Directory

Blog Directory & Search engine

Blog Flux Directory
Irish Blogs
 View My Public Stats on MyBlogLog.com

Performancing
Enter your Email


Powered by FeedBlitz
Theme adapted from Sotto.
 
Ricebridge XML Manager
  • Convert XML to a table of data
  • Convert XML to CSV, and CSV to XML
  • High-speed, single-pass XPath
  • Memory-stable and fault-tolerant
  • Loads of documentation
  • Cut-and-paste code examples
  • Find a bug, get a gift cert
Ricebridge Java XML Manager Component


Ricebridge CSV Manager
  • Convert CSV to a table of data
  • Handle any type of delimited file
  • Memory-stable and fault-tolerant
  • Loads of documentation
  • Cut-and-paste code examples
  • Find a bug, get a gift cert
Ricebridge Java CSV Manager Component


Popular Posts

 Sign up for MyBlogLog.com
Alertra Website Monitoring Service
Get Chitika eMiniMalls
Solo Tees
BlogJet