How To Maintain Basic and PRO Versions With Same Code Base

When you are selling “out of the box” software you quickly start getting customization inquiries. We get this all the time. Usually I have to handle these in case-to-case basis, means we’d just hack a custom version for the client and move on. Some requests are seen more often than once and I often figure out it would be a good idea to add their customization as a future feature for the next version of the upgrade. (In this case of course I let the client know what I think, and charge less than otherwise).

The problem is if you add every interesting feature, your core version will quickly become bloated. On top of that you may want to charge more for all this hard work and the evolution of your program. But what about the customers who were happy with the old version and would prefer that? The solution to this is called segmentation and marketers will tell you it helps you make more money. As marketing is not the point of this post, I’ll focus on the technical side: how do you actually handle two or more version without getting insane?

Lego Architecture 21005 - Fallingwater

The Solution: Keep Same Core Code Base

This isn’t really anything revolutional. Have a look at how WordPress manages extra functionality in plugins for example. You can follow the same logic – keep your core module extendable and then your PRO, Ultra and Mega versions can be built as “plugins” to it. But unless you are building a huge application that allows as diverse functionality like WordPress and its plugins, you don’t really need the complex API with hooks and all that. I’ll tell you the much simpler solution we used in our Watu PRO Intelligence module (yeah, it’s all for WordPress however you can apply the same ideas everywhere).

Step 1: Package Modules

The obvious first step is to keep your extra functionality encapsulated in classes. If you use the MVC concept (recommended), you should make a folder for your PRO version functionality and inside the folder place at least the following folders:

/models
/views
/controllers

I also like to include the module’s own images etc:

/css
/images
/js

So all the stuff of the module is placed there.

Then, if you plan to support more than one “module” or “version” of your app (let’s say Basic, PRO, and Corporate), ideally you should place all the modules in a folder. So, here is example folder structure of your application:

-/app folder
-/models
-/views
-/controllers
-…
-/modules
– -/pro
– – -/models
– – -/views
– – -…
– -/corportate
– – -/…

I hope you get the idea. Now, as everything is packaged, how do we include this extra functionality in a really simple way?

Step 2: Function to check if module exists

Here is how: you simply need to check if some of the module files exist. So let’s create a simple function in your core application.
I’ll keep this one procedural to make the code shot, you feel free to make it a static or non-static class method. All example code is in PHP:

function module_exists($module) { 
   switch($module) { 
      case 'pro': 
         if(file_exists(BASE_PATH."/modules/pro/models/basic.php")) return true; 
         else return false; 
      break; 
      case 'corporate': 
         if(file_exists(BASE_PATH."/modules/corporate/models/basic.php")) return true; 
         else return false; 
      break; 
   } 

   // if no match, return false 
   return false;
}

As you can see this is a really basic stuff. In the code above you have your absolute or relative path to the root folder in BASE_PATH constant and that your both “extra” versions have model file called basic.php. You can obviously have different structure and names. The idea remains the same – simply check if the file is there. This way you can package your Basic version with empty modules directory, your “PRO” version with modules/pro folder, but without modules/corporate. and your “Corporate” version with all the files and folders.

Then all you’ll need to do when you zip your packages for sale will be to remove the unnecessary folders.

Step 3: Run code conditionally

Then obviously you will need to place conditions here and there in your core app that will define whether a “module” code will be run. In “model” or “controller” level you will probably have something like this:

// some core method
function some_method() {
   // some core code here
   ///...
   if(module_exists('pro')) {
      PROModuleBasicModel::do_something();
   } 

   if(module_exists('corporate')) {
     CorporateModuleBasicModel::do_corporate_thing();
   } 
}

Of course this adds some extra code to your core app but it’s a great tradeoff compared to keeping 2 or 3 completely different codebases and trying to apply updates and changes to all of them.

At a view level you can probably just use an include like this:

<!-- example view code: some HTML below -->
   <h1>My Module Form</h1>
   <form method="post">
      <fieldset>
        <legend>Basic User Data</legend>
        <div><label>User email:</label> <input type="text" name="email"></div>
        .....
      </fieldset>
      <?php if(module_exists('pro')): 
         require(BASE_PATH."/modules/pro/views/user_details.html");
        endif;?>
      <?php if(module_exists('corporate')): 
        require(BASE_PATH."/modules/corporate/views/user_details.html");
        endif;?>
   </form>
<!-- end of the example -->

And these included views could probably include additional sections (fieldsets) that include extra options and fields offered by the more advanced modules.

That’s it in short. You can package your apps and start selling different versions. When you upgrade your core version, you’ll just copy the changed files to your other zips and you are all set. Feel free to use SVN or Git branches for this, the concept remains the same.

If you have better ideas, I’ll be happy to hear them!


					

One thought on “How To Maintain Basic and PRO Versions With Same Code Base

Leave a Reply

Your email address will not be published. Required fields are marked *