The Inquisitive Coder - Davy Brion’s Blog

Trying to walk that thin line between intelligence and ignorance

How Do You Deal With Common Infrastructure Code For Multiple Projects?

Posted by Davy Brion on December 2nd, 2008

Here’s the situation: a couple of months ago we started developing according to a new architecture. Obviously, you need infrastructure code for this. For the first project, we just put the infrastructure code into the project’s solution and everything was easy. We could make changes as we needed them, and it enabled us to ‘grow’ the infrastructure into what we really needed. Then came the second project. I was reluctant to extract the infrastructure code in a separate reusable assembly because i felt it would lead to less flexibility to make changes. So i copied the infrastructure classes into the new project. Obviously, some changes were made in the classes of the second project, which weren’t ported to the classes of the first project. Add another project or two, and you can see the problem :)

So now we’re trying to figure out how best to move forward. I’ve got 3 options in mind:

  1. Infrastructure code as a separate project, binary ‘framework’ dependency per ‘client’ project
  2. Infrastructure code as a separate project, ‘framework’ dependency (in source form) per project (as in: copying the code of a specific version of the ‘framework’ into the project’s own repository)
  3. Each project just contains the infrastructure code in their own project and there is no specific ‘framework’

The way i see it, each approach has its pro’s and con’s:

  1. Infrastructure code as a separate project, binary ‘framework’ dependency per ‘client’ project
    • Pro’s
      • The code only has to be maintained in one place
      • Everybody can benefit from changes
    • Con’s
      • Can make debugging harder because you can’t step into the framework code
      • Requires a lot of discipline for versioning and distributing updates to ‘client’ projects
      • The infrastructure code has to have a lot of extensibility points so each application can add extra functionality


  2. Infrastructure code as a separate project, ‘framework’ dependency (in source form) per project (as in: copying the code of a specific version of the ‘framework’ into the project’s own repository)
    • Pro’s
      • Does not have the debugging issue
      • Code only has to be maintained in one place (in theory)
      • Everybody can benefit from changes
    • Con’s
      • The infrastructure code has to have a lot of extensibility points so each application can add extra functionality
      • If people change the infrastructure code in their project, all changes should be sent upstream to the ‘real’ infrastructure repository, or extension points need to be provided in the original infrastructure code so upgrades of the infrastructure library still offer the same possibilities for the specific project
      • Still requires versioning discipline, although it probably wouldn’t need to be as strict as with Option 1


  3. Each project just contains the infrastructure code in their own project and there is no specific ‘framework’
    • Pro’s
      • Highly flexible… each project can freely make changes to make the infrastructure behave exactly as it needs to for the project
    • Con’s
      • Leads to multiple ‘versions’ of many of the classes… when a new project starts, which versions of each class should be used?
      • Starting a new project contains boring set-up work which is basically just copy/pasting existing classes from previous projects

The reason i’m posting this, is because i’d love to get your feedback on this… what other pros/cons can you think of for each approach? Which approach would you recommend? Is there another approach we haven’t thought of?

Share/Save/Bookmark

17 Responses to “How Do You Deal With Common Infrastructure Code For Multiple Projects?”

  1. den Ben Says:

    Important side note: in contradiction to most ‘enterprise software factories’ we need to provide many extensibility points since things like authentication, authorization, logging, and the lots… differ for each customer.

    Maybe consider some sort of hybrid approach between the options?

    Backbone Code -> option 1
    Default Dependencies/”Providers” -> option 2
    Very specific customer dependent code -> option 3

    And should in time things that were considered very customer dependent become more common for other customers too, move them to option 2.

  2. Koen Says:

    I’d go for option 2, basically the same approach as we did for the DotNetFramework and the DaVinci framework.

    Everyone would checkout the code of the framework in a separate folder, although not everyone may be able to commit changes (maybe use subversion patches which should be validated by the framework “owner”). This project(s) will be added as existing projects to the solution for each specific “project”. I think being able to debug the framework code is a very valuable pro, because you cannot know exactly how the whole framework works.

    We can also create branches of the framework for each “version”. I remember at one point we had to do a backward incompatible update in DaVinci and we had to update all our projects. For projects that were “inactive” we had to do that later (and remember how to apply the update exactly). With branched versions that might also be no problem (but then of course you would have to checkout that version and change your solution – or switch to option 1 for that project).

    I also think the framework should contain a library of (regular used) extension methods…

  3. Adam Toth Says:

    I prefer solution 2, it is still pretty flexible yet aims to integrate improvements into the main infrastructure repository.
    It also tries to standardize the infrastructure which improves the learning curve for new projects.
    With some workaround it’s probably also possible to have some customizations in this scenario, however I really think that this should be avoided in all cases where possible and solved with extensibility points.

    The descriptions above also imply that approaches 1 and 2 require extra development and management effort for the infrastructure which may not always be clearly related to a project, so a separate responsible person and some developers in at least part time are required. Our project changed from 2 to 3 for the data access framework. The way I see it the reason was that our customizations needed better extensibility and nobody had time to add it to the framework and thoroughly test it too.

    Another con for 1 and 2 is that we need to be extremely careful with changes to the infrastructure and it needs to be well tested. This may also be a good thing because in case of 3 the customizations are probably not as well tested.

  4. Frederik Gheysels Says:

    The first disadvantage of the first option can be removed from the ‘cons’ list, if you set up a symbol server for your infrastructure-project.

  5. Davy Brion Says:

    @Frederik

    aha, interesting! :)

  6. Jeroen Budts Says:

    I would try to use a slightly different approach, which is a mix of 2 and 3, thanks to partial classes/methods and some Subversion tricks:

    * Create a general Framework, in a seperate repo, say ‘Freckles’:
    svn://svn0001/freckles/trunk
    * development should be done in a way that we try not to break things.
    * Everytime when a new ’stable’ version of the framework is ready, the repository should be tagged: STABLE1, STABLE2, STABLE3 or branched (which is allmost the same).
    * In the framework code, try to use partial classes and partial methods, to make it as easy and flexible as possible to ‘inject’ project-specific code into the framework (obviously other techniques that should also be used are inheritance, abstract methods etc). But by using partial classes and partial methods, specific essential parts can be re-implemented without having to touch the original code and without being limited by any inherited implementation from an abstract class.

    To use the framework:
    * Create a seperate project in the solution with one folder (’FrameworkCode’) where the framework should go. That folder should be defined as an ‘external’ in subversion, and point to either the Trunk of the framework-repo, or (and this is better), to a specific Tag or Branch.
    * In that same project, another folder should be added ‘FrameworkExtensions’, where project specific code (like the other sides of partial classes) go.
    * Because all the parts of the partial classes are in the same assembly, this will compile, although the code is split up in two seperate repos.

    Modifications to the framework can now also be made rather easily:
    * Non-breaking changes go on the Trunk and a new tag is created.
    * Projects that want to use these new features redefine the Subversion Externals to point to the new tag
    * projects that don’t want the new changes do nothing.
    * Security and bugfixes should be made on the Trunk, and then also be merged in all Branches (=versions) that are still in use. So if we still have an old project that still uses STABLE3 (while we already have STABLE6), we merge just the bugfix into STABLE3, and once we update the old project, we will have the bugfix in a version of the framework that is still completely compatible.

    I think that might work…

  7. Koen Says:

    About the symbol server: that enables you to step through the framework code and debug it, but if you need an update you have to go to the code master to do that. Even if it’s a very small update or fix…

  8. Davy Brion Says:

    @Koen

    if the infrastructure code ends up in a central repository, then you’d always have to go through the maintainer(s) to get a change in that code… there has to be some kind of process involved with making changes in that code because it’s definitely not as easy as just making a change here and there, even if you are careful.

    btw, with option 2 i didn’t mean that each project would reference a _checked out_ folder of a known version of the shared code… i actually ment _copying_ the code of a known version into the repository of the project.

    Referencing a project in another repository is kinda problematic for a buildserver, and it also imposes a certain kind of folder structure _above_ the root project folder, which isn’t ideal either. We could use svn externals, but then again, i’ve heard way too many people complaining about problems they had when using svn externals so i’d rather not go that route either.

  9. Neal Blomfield Says:

    If it is truly a framework then you should be able to treat it as a binary dependency without any issues (think about how you use .NET / NHibernate / Monorail / ASP.NET MVC).

    No matter which of the choices you make, you must first recognise and accept that unless your framework is TRULY a framework (a fixed set of guides for building something within a reasonably constrained set of parameters), you will always struggle with issues like those you raise in your post. If it really is a framework, then you must treat it like a piece of production code where every change goes through some rigour to ensure it benefits the framework (and not just one project) and doesn’t break the framework (without significant investigation / justification as to why).

    Projects should be build against a specific version of your framework (i.e. a tagged version, generally not the trunk), unless you want to invest a lot of time and energy fixing any breaking changes in projects that rely on the trunk (it is not pleasant - I’ve been there done that with Monorail a couple of times after Ayende / Hammett when through one of their whirlwind fix phases). This becomes even more critical when the project moves from active development to support.

    IMHO homegrown frameworks are nasty things that always seem to cause more problems than they solve (unless you are very careful).

  10. Software Factories and Frameworks. How to maintain infrastructure code? « Extending forth my insignificant self Says:

    [...] Software Development — benpittoors @ 8:53 pm In a reaction to Davy Brion’s post about how to deal with common infrastructure code for multiple projects I’d like to share my take on said topic.  I already placed a brief comment on Davy’s [...]

  11. Reflective Perspective - Chris Alcock » The Morning Brew #236 Says:

    [...] How Do You Deal With Common Infrastructure Code For Multiple Projects? - Davy Brion talks about project structures and where the infrastructure stuff best sits, canvassing the community for opinions leads to some good comments on this post. [...]

  12. Mark Brackett Says:

    I have common code in a seperate repository, and use svn:externals to reference COMMON/TRUNK while developing. I include the .csproj into the application solution, and make changes as necessary to accommodate my application. TortoiseSVN takes care of checking in changes both to APP/TRUNK as well as COMMON/TRUNK (if I’ve made changes).

    When it’s time to release the app, I tag COMMON/TRUNK to COMMON/VERSION and branch APP/TRUNK to APP/RELEASE to make release modifications. One of the release modifications is to point svn:externals back to COMMON/VERSION. APP/VERSION gets tagged from APP/RELEASE.

    Future app development can occur either on APP/TRUNK, which is linked to COMMON/TRUNK, or APP/RELEASE (for bugfixes) which is linked to COMMON/VERSION.

    This means for APP/TRUNK development, I’m always developing against the latest and greatest COMMON/TRUNK code. It does impose a slightly higher testing burden, but APP/TRUNK is already subjected to unit and release tests anyway. “Smart” changes to COMMON/TRUNK keep breaking changes from getting out of hand.

    The APP/RELEASE dance keeps the released version of COMMON in a tag - so there’s never any question about what version of COMMON has been tested and deployed with APP/VERSION.

    The first few apps tend to generate a lot of churn in COMMON/TRUNK - but after that, changes slow down and you’re (usually) effectively developing against the same version. But, you still have the flexibility to fix bugs and add features to COMMON pretty easily.

  13. Jason Says:

    I agree with Neal on this. I have been using option #1 with 3 frameworks and it has worked well for us for the last 3 years. When we tried option #2, developers were too tempted to make changes to the infrastructure code because they had the source right there in the solution and it seemed like the path of least resistance. Then we end up with slight variances of the infrastructure code from solution to solution and makes debugging a nightmare.

    We have specific developers who are responsible for maintaining & testing the framework code and each change goes through a change control process. After a change is completed, a binary (.dll file) is placed in a well-known, public place in our source control repository where other developers can set a binary reference to it from their projects. Each release warrants a new assembly version number.

    This way, when there is a problem, the app developer can tell the infrastructure developer (might be the same person), which version of the framework has a problem, and then it is normal debugging of that version of the source (maintaining tags of the source is important here).

    As far as debugging the framework code from the application, we have no problems. Our release builds of the framework code has a .pdb file that points to the source code. All of our developers set up their workspace using the same location on their hard drive. Even if it is different, Visual Studio will prompt you with the “open file” dialog and ask you where the .cs file is to continue stepping through the code.

    Good luck to you in which ever you choose.

  14. Dew Drop - December 3, 2008 | Alvin Ashcraft's Morning Dew Says:

    [...] How Do You Deal with Common Infrastructure Code for Multiple Projects? (Davy Brion) [...]

  15. MarcT Says:

    Interesting post. We have similar questions where I work. Good summary of the technical issues, but nobody has brought up the political issues yet. With Options 1 & 2 the person/team maintaining the framework will be different than the teams for the clients (if not now, then soon). This can lead to significant roadblocks to getting things done, when a client team requests a critical change to the framework, but the framework team a) is busy, b) disagrees on the scope or priority of the change, or c) turns bitter and unresponsive.

    Of course, that was my last company. I’m sure it will never happen where I (or you) work now.

    Any other pros/cons on the “soft” side that people have run into?

  16. Davy Brion Says:

    @MarcT

    interesting response :)

    there was one big downside to option 1 that i experienced at a previous client. the framework was a pretty prestigious thing to work on in that place, so that kinda attracts people who’re mostly interested in the status that comes with it. One of the people who was assigned to work on the framework was (IMO) not up to the task, technically speaking. But the only reason he was assigned to it was for political reasons. If someone like that has to work on something so important, there are obviously a lot of issues that come with it. The most important one being that people who deserved that spot more than this person were frustrated about not getting that opportunity. Another downside was that after a while, i really didn’t like working on it anymore either.

    I think it’s very important to try to keep everyone involved, even if they are not working directly on it. Encourage them to submit patches, always listen to their feedback and try to incorporate that feedback into the framework/library/whatever. If you don’t, pretty soon you won’t get that feedback anymore and then it all turns to shit pretty fast.

  17. Latish Sehgal Says:

    At my current project (8 devs and close to million lines of code), we use Option 1 and its working out very well for us. However, our team is not divided into Framework and non-Framework devs, like Davy mentioned. Since most of the UI controls/ business logic is incorporated into the framework, you can’t really work on the project without being well versed with the framework. The only difference is that code review is performed more diligently over framework code since it is shared by several teams.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>