views:

265

answers:

6

Often, customers will request specific functionality that doesn't really fit into the existing system and probably will only get used by the specific customer.

For example, there is a web application that functions as a portal for many different organizations. Say there are 15 organizations that all use the same underlying code, but have different accounts that display a customized logo and css template for each organization. A 16th organization wants a new portal, but they have a few requests for their home page that don't fit with the existing system. Say it's an extra legal disclaimer or a picture of their founder on the left side of the page. Something specific to that organization that probably won't be reused by any other organizations.

How do you handle those kinds of situations without creating a huge mess of conditionals or specific code for one customer?

A: 

My experience is that it's very rare for something to be purely one-off or at least unable to be made to work for multiple customers. When you architect the feature, make it so it's reusable and add it to the code for all customers, but make it configurable with the default to off, so it can be turned on for the one customer. You can then let all the existing customers that you have a new feature that they can take advantage of. This way it A) makes the new customer happy, B) gives existing customers a good feling that you're doing continual improvement, even if they don't need it and C) it will be there when a future customer wants it.

ctacke
A: 

Just say no. =)

But seriously, you have some choices,

1) Create a system/platform that allows you to easily make such changes by separating the presentation layer. Obviously, if the backend logic has to change, you need to make a decision if that makes sense

2) Say no. Scope creep is in pretty much every project I have ever seen. Some requests which may look like simple requests and ending being huge timesinks. Do everything you can to avoid those.

HTH.

Jauder Ho
A: 

Charge them a suitable amount of money for an extra customized version, and make it a general change so I can offer it as an extra feature to other clients that will sweeten the pot when they try to get us to lower our price, as we can show that we have more features than the competitor they were comparing our price to.

As far as coding goes - give each client a separate CSS template override (a small bit of css code in the DB that is dished out on a per client basis that overrides the general CSS code you use across the board) and put the show/no show functionality in there for presentation layer objects.

Adam Davis
+1  A: 

I find modules and filters (think DotNetNuke) driven by database settings work well for this. We have a site that serves the entire insurance food chain, with various customized sites for individuals. In the end, we just track the options selected for a given customer in a table of products and options and we give ourselves a UI to turn these features on.

Rarely have the features not filtered out into the general use if the request was for something of value, so from time to time we merge the most popular customizations into the core codebase and remove the option from the database. The only case we don't is if the customer was charged for time and materials at the full rate, rather than at the cut rate that we charge for sharable customizations. It turns out that people prefer the savings to the exclusivity.

Godeke
A: 

My usual approach is to create something with hooks or plugins. I have a list of functions/objects/function pointers to call at a key point in the program. This list is normally empty. For this one customer, I write a hook or plugin that registers itself at program startup and provides the feature that the customer wants.

Glomek
+1  A: 

[Capitalizes on previous answers....]

  1. If it truly doesn't make sense to add the feature, say no, or gently point the customer in a different direction that works better for both of you.
  2. If you proceed, bill for the feature. Include expected maintenance costs.
  3. Genericize the feature so you'll be able to reuse it. Worst case, keep the feature disabled in your base system unless it's explicitly enabled.
  4. Charge for the feature in the future, if it truly adds value.

The easiest way to deal with the problem, unfortunately, is in the past tense: anticipate it and plan for it from the beginning. But even if it's too late for that, consider likely requests as you move forward and build "hooks" in legacy and future code to accommodate them when they arise.

Adam Liss