views:

93

answers:

3

The scope of the project I'm working on is being expanded. The application is fairly simple but currently targets a very specific niche. For the immediate future I've been asked to fork the project to target a new market and continue developing the two projects in tandem.

Both projects will be functionally similar so there is a very strong incentive to generalize a lot of the guts of the original project. Also I'm certain I'll be targeting more markets in the near future (the markets are geographic).

The problem is a previous maintainers of the project made a lot of assumptions that tie it to its original market. It's going to take quite a bit of refactoring to separate the generic from the market specific code.

To make things more complex several suggestions have been tossed around on how to organize the projects for the growing number of markets:

  1. Each market is a separate project, commonalities between projects are moved to a shared library, projects are deployed independently.
  2. Expand the existing project to target multiple markets, limiting functionality based on purchased license.
  3. Create a parent application and redesign projects as plugins, purchased separately

All three suggestions have merit and ideally I would like to structure the codeto be flexible enough that any of these is possible with minor adjustments. Suggestion 3 appears to be the most daunting as it would require building a plugin architecture. The first two suggestions are a bit more plausible.

Are there any good resources available on the pros and cons of these different architectures?

What are the pros and cons on sharing code between projects verses copying and forking?

A: 

1) NO! You don't want to manage different branches of the same code base... Because as common as the code may be, you will want to make sweeping changes, and one project will "at the moment" not be as important as the others, and then you will get one branch growing faster than the others.... insert snowball.

2) This is more or less the industry standard. Big config file, limit things based on license/configuration. It can make the app a bit cumbersome, but as long as the code complains about mutually exclusive stuff and all the developers are in constant communication about new features and how they ripple throughout the entire application, you should do fine. This also is the easiest to hack, if that is a concern.

3) This also 'can' work. If you are using C#, plugins are relatively simple, you only have to worry about dependency hell. If the plugins have any chance of becoming circularly interdependant (that is, a requires b requires c requires a), then this will quickly explode and you will revert (quite easily) back to #2.

The best resources you have are probably the past experiences of your coworkers on different projects, and the experience of people yammering about it on here or Slashdot or wherever. Certainly the cheapest.

Pros of sharing code: One change changes everything. Unified data model. There is only one truth. (Much easier for everyone to be on the same page)

Cons of sharing code: One change changes everything.. Be careful. If one bug is in it, it affects everything.

Pros of copying/forking: Usually quicker to implement a specific feature for a specific customer. Faster to hack when you realize that assumption A is only applicable for markets B and C, not D.

Cons of copying/forking: One or more of the copied projects will eventually fail, due to a lack of cohesion in your code. As above said: Sweeping changes take a lot longer.

Good luck.

Lomilar
Re (1): That's not what he said, he said that the shared code would be moved to a shared library.
David Moles
A: 

Forking is usually going to get you a quicker result initially, but almost always going to come around and bite you in maintenance -- bug fixes and feature enhancements from one fork get lost in the other forks, and eventually you find yourself throwing out whole forks and having to re-add their features to the "best" fork. Avoid it if you can.

Moving on: all three of your options can work, but they have trade-offs in terms of build complexity, cost of maintenance, deployment, communication overhead and the amount of refactoring you need to do.


1. Each market is a separate project

A good solution if you're going to be developing simultaneously for multiple markets.

Pros:

  • It allows developers for market A to break the A build without interfering with ongoing work on B
  • It makes it much less likely that a change made for market A will cause a bug for market B

Cons:

  • You have to take the time to separate out the shared code
  • You have to take the time to set up parallel builds
  • Modifications to the shared code now have more overhead since they affect both teams.

2. Expand the existing project to target multiple markets

Can be made to work okay for quite a while. If you're going to be working on releases for one market at a time, with a small team, it might be your best bet.

Pros:

  • The license work is probably valuable anyway, even if you move toward (1) or (3).
  • The single code base allows refactoring across all markets.

Cons:

  • Even if you're just working on something for market A, you have to build and ship the code for markets B, C and D as well -- okay if you have a small code base, but increasingly annoying as you get into thousands of classes
  • Changes to one market risk breaking the code for other markets
  • Changes to one market require other markets to be re-tested

3. Create a parent application and redesign projects as plugins

Feels technically sweet, and may allow you to share more code.

Pros:

  • All the pros of (1), potentially, plus:
    • clearer separation of shared and market-specific code
    • may allow you to move toward a public API, which would allow offloading some of your work onto your customers and/or selling lucrative service projects

Cons:

  • All the cons of (1), plus requires even more refactoring.


I would guess that (2) is sort of where you find yourself now, apart from the licensing. I think it's okay to stay there for a little while, but put some effort into moving toward (1) -- moving the shared code into a separate project even if it's all built together, for instance, trying to make sure the dependencies from market code to shared code are all one-way.

Whether you end up at (1) or (3) kind of depends. Mostly it comes down to who's "in charge" -- the shared code, or the market-specific code? The line between a plugin, and a controller class that configures some shared component, can be pretty blurry. My advice would be, let the code tell you what it needs.

David Moles
I settled on option 3. I took a step back and looked at what the markets had in common. I generalized this into the application shell and infrastructure classes. So the plugins focus on where the markets differ. When all was said and done the majority of the application had become a series of plugins: the market specific business rules, database layer, importing features. And yes, there was a lot of refactoring. :)
codeelegance
A: 

You said "copying and forking" which leads me to think that perhaps you haven't considered managing this "fork" as a branch in a revision control system like SVN. By doing it this way, when you refactor the branch to accomodate a different industry, you can merge those changes back into the main trunk with the aid of the revision control system.

If you are following a long term strategy of moving to a single app where all the variations are controlled by a config file (or an SQLITE config database) then this approach will help you. You don't have to merge anything until you are confident that you have generalised it for both industries, so you can still build two unique systems as long as you need to. But, you aren't backing yourself into a corner because it is all in one source code tree, the trunk for the legacy industry, and one branch for each new industry.

If your company really wants to atack multiple industries, then I don't think that the config database solution will meet all your needs. You will still need to have special code modules of some sort. A plug-in architecture is a good thing to put in because it will help, particularly if you embed a scripting engine like Python into your app. However, I don't think that plugins will be able to meet all your code variation requirements when you get into the "thousands of classes" scale.

You need to take a pragmatic approach that allows you to build a separate app today for the new industry, but makes it relatively easy to merge the improvements into the existing app as you go along. You may never reach the nirvana of a single trunk with thousands of classes and several industries, but you will at least have tamed the complexity, and will only have to deal with really important variations where there is real divergence in the industry need.

If I were in your shoes, I would also be looking at any and all features in the app which might be considered "reporting" and trying to factor them out, maybe even into an off the shelf reporting tool.

Michael Dillon