3

Our product is a web based course managemant system. We have 10+ clients and in future we may get more clients. (Asp.net,SQL Server)

Currently if one of our customers need extra functionality or customised business logic, we will change the db schema and code to meet the needs.

(we only have one branch code base and one database schema)

To make the change wont affect each others route, we use a client flag, which defined in a web config file, thus those extra fields and biz logic only applied to a particular customer's system.

if(ClientId = 'ABC')
{
   //DO ABC Stuff
}
else
{
   //Normal Route
}

One of our senior colleagues said, in this way, small company like us can save resources on supporting multiple resources.

But what I feel is, this strategy makes our code and database even harder to maintain.

Anyone there crossed similar situation? How do you handle that?

  • 4
    This is going to bite you in the ass so hard! Having code sprinkled about here and there for specific companies is not keeping things simple; it's increasing your technical debt - and mark my words - technical debt is always paid by the iron price. – sergserg Sep 4 '12 at 16:25
  • @Serg we are paying it now. It is a legacy system. I m thinking about the solution for this messy monster, though I m not a archetect. – ValidfroM Sep 4 '12 at 16:28
  • If you're doing a lot of db customization, try putting company-specific copies of the database in different libraries/schemas, then give them access to only that schema. The db's authority setup is going to be a lot better than any application-level stuff you're trying to pull. But @Serg is right, this is going to bite you bad. – Clockwork-Muse Sep 4 '12 at 17:00
3

Parameterize as much as you can first, of course.

Avoid writing:

if(customer == 'foo') {
  doBarCalculation();
}

, but rather write:

if(customer.usesBarCalculation) {
  doBarCalculation();
}

Use the Strategy pattern:

customer.getCalculation().doCalculation();

Customer {
  CalculationStrategy getCalculation();
}

CalculationStrategy {
  doCalculation();
}

; you can use Strategy at different scales; either offer many small, simple interfaces or a few large interfaces- it is worth thinking up the scale well; large interfaces tend to provoke code duplication between implementations (and code duplication is bad), while smaller interfaces are often harder to design in advance or increase complexity.

1

Create a company table in the database. Every user gets associated with a company. Here is some pseudo-SQL for company-customizations for displaying dates, time-zone, fiscal offset, and contact-person:

table user:
id
company_id
... other fields ...
foreign key (company_id)

table company:
id
date_format
time_zone
fiscal_offset
contact_person
... other customization fields ...

You probably need to query the user and company for most screens in order to test for customizations. Pulling a single record from the database for a screen should take no more than 5ms.

I understand that you don't want to introduce complexity, but having company-specific code for each client littered through your application is already complexity. Better to incorporate this officially into your database model, than to wake up one day with 100 one-off company customizations littered throughout the code. At least this puts them all in one place, and by looking at these settings on the company-edit screen, your testers can easily see what they need to think about when testing for different companies.

  • Custom table is not that helpful, as the customise logic is quite complicated. – ValidfroM Sep 4 '12 at 16:32
  • 2
    You need to decide whether you are a contracting company providing custom software to different companies based off a common set of routines, or whether you are a software company providing a single software product with a few customizations. If the former, then separate code bases may become necessary. If the latter, then you may have to say no to companies who ask for things that no-one else is going to want. – GlenPeterson Sep 4 '12 at 16:43
  • Agree. I think a seperate code strategy basing on IOC is a way. – ValidfroM Sep 4 '12 at 16:56
0

The technique described is a good stop-gab solution but does not scale well. It's okay if you only have a few cases.

I like both Alex's and GlenPeterson's solutions above

  1. Parameterization - make the different cases generalized and reusable. eq.: Allows international shipping (Y/N), or Break shipping tax out (Y/N).

  2. Database flag attributes - to record each customer's preference

In addition to those techniques other things to consider:

  1. Separate codebases. Isolate core functionality into a single code base. Have customer customizations in a different codebase which uses the core code base. This can be difficult to set up - but allows you to freely develop both codebases independently. Having good tests on the core code base will help avoid breaking the customized code bases.

  2. Separate databases (one for each client), or Namespace your database tables (one table for each client)

  3. Use Separate Configuration Files for each Customer. Yaml is great for config files. This can be much lighter weight than putting all flags in the database - and allows you to easily edit it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.