views:

379

answers:

8

Hi all,

We have developed a system that uses a single code base, consisting of 4 visual studio projects. with an admin website, and customer facing website. (each system has its own MS SQL database)

This has been working great as all new websites (including admin) reference the same code base projects, from within SVN, therefore any changes made to the code base is then available to all websites.

Each website has different a master page, and different user controls (.ascx), and therefore partially different although the main coding behind the sites are the same.

The issue we are having now is if there is a bug, a feature change or a new feature we have to implement it in ALL the sites seperately (for both admin and customer site). Which is starting to drive us insane, and also means we have a HUGE margin of error for implementing the changes.

I have thought about using svn:externals but this will become messy.

Branching from a master website and master admin system could be the option, but merging to get the new code is a major issue with the sited not being exactly the same.

I think a nice over view would be say that the markup is totally different per site (except the admin site, which is just a theme change) but the code bases are the same.

What is the best way to manage this or are we stuck doing a lot of copy and paste?

EDIT

Which points would you like clarity on?

Issues that arise are such as in page javascript, being different, html layouts can be completely different bewtween websites. But the code for the pages is the same.

So I would need to 'synchronise' file and folder such as those found in app_code. but there are issues here as well.

Site 1 and Site 2 could be exactly the same, just a different theme. Site 3 has a different theme as well, but it also has some bespoke code that is only required by this site, some of the code in app_code also acts differently to Site 1 and Site 2

Now I could easily acheive this with branching, but when merging up to the new branches, if there are code difference then there are going to be major conflicts.

Merging would also become a large task and take too long, as we would need to merge only certain folders and files, although you cannot merge a single file through the branch. (this could be wrong)

For example

In the root there is a download.aspx which returns a stream as the response rather than a page, this is used to push all the download requests through the system. So this page in Site 1 and Site 2 is the same, but in Site 3 it does something extra which no other site requires or needs. We dont want this bespoke feature to be an overload as we dont want/need it for the other websites, we can now no longer merge this file, from the master website, it must be manually merged.

Hope this explains better what I am trying to achieve

EDIT 2

Basic site structure

|- App_code
|- App_Themes
|- Bin
|- Content
|     |- Flash
|     |- Images
|     |- Scripts
|     |- Uploaded
|
|- Controls
|     |- MasterPage
|     |     |-MasterPageControls
|     |
|     |- Navigation
|     |- Search
|     |- Templates
|     |     |- Control Templates 
|     |     |- Page Templates
|     |
|     |- WebServices
|     
|- Errors
|

Everything under Controls Navigation, Search, Templates is .ascx files

In the root there are several files including default.aspx, download.aspx and preview.aspx

These are the main pages for the website (ignoring Error pages) all pages are dynamically created from the DB

The Controls folder ise where most of the changes between websites happens in the MasterPage, and all other user controls

A: 

I am not sure I understand your situation correctly, but you can find clues on how to maintain the SVN repository in the Subversion book, under chapter 4.

It seems you either have to establish good routines for the SVN tree, or you have to change the code so that as much as possible is common to all the web sites, with the differences being configurable. For instance, you might be able to create a main project with site-agnostic code, and then code the changes as projects that build on top of it.

As for updating the sites themselves, this must either be done by synchronizing with the appropriate points in the subversion tree, or you have to perform a new release (or upgrade).

csl
A: 

You say you have one SVN repo with the code base for all the sites. So unless I'm misunderstanding, can't you simply move any shared components into that repository?

Things such as the in-page Javascript you mention should be made external where possible. If the HTML layouts are completely different, chances are the Javascript may be significantly different.

So this page in Site 1 and Site 2 is the same, but in Site 3 it does something extra which no other site requires or needs. We dont want this bespoke feature to be an overload as we dont want/need it for the other websites

Can't you extend the download code on site 3, so you have a common base across all sites, but extend it on site 3.

DisgruntledGoat
A: 

If I understand the issue correctly, you have the code for four broadly similar websites in one repository. A website instance has custom features. The punchline in the original posting, the question, expresses concern about being "stuck doing a lot of copy and paste." At various points you indicate frustration with "merging" and "manual merging."

I take it you are using svn to distribute new code to the four hosts.

Perhaps your codebase is approaching a point where the common material could be profitably considered to be a library. In this view, each of the four websites is considered to be an application built from the library. If so, then it may make sense to give each of the four apps its own repo in subversion. The developmental effort will be to separate the common features from the custom features, perhaps making the API on the "library" code a little more crisply defined. Each host then checks out the library code and its own app.

Is this close to what you're thinking?

Ewan Todd
This is what we have now, but it is contained with in a single repo.All the websites reference back to the CORE (the group of 4 projects) which includes, business, entities, data etc (I have used codesmith nettiers template)With a previous similar project I setup Cruisecontrol.net to build the CORE and distribute the compiled dll's, this is not currently the area of concern.As you point out I need to break down the website into common features and custom features, but how would I do this? Breaking the front end down like this is something I have never done
JamesStuddart
How would you break down the website into common features and custom features? This is a tough question to answer concisely in the abstract. It might be easier to discuss with concrete examples. Why don't you post a couple of representative snips? To be useful, the snips should show the corresponding feature on two of the sites, exhibiting a mix of common and custom code.
Ewan Todd
I guess by 'snips' you mean how the directory of the sites is laid out?
JamesStuddart
Sorry. I meant code snippets. However, if you think how the directory of the sites is laid out is important, that may be more pertinent.
Ewan Todd
Ah right, I dont think code snippets will profide anything to this really. Although directory structure might.I will mock it up and add it to the original post
JamesStuddart
It sounds like you check the build products into subversion rather than the build specification. That would be something like a C programmer putting the compiled binaries into subversion rather than the source code. I'm more familiar with a process where the build process draws its input from the version control system.Subversion is not ideally suited for package management.Here's an article about active generation and continuous integration. Items 4 and 8 seem salient here.http://timstall.dotnetdevelopersjournal.com/10_tips_to_integrate_codesmith_into_your_processes.htm
Ewan Todd
A: 

Like others, I'm a bit confused as to your problem, but I do think I have a general understanding of the issue. What you need to try to do in this case is abstract the customizations into separate libraries per client / project and leave the original codebase uncustomized. The base code should contain only the generic functionality applicable to all sites (although some functionality could be altered so that you could toggle its availability depending on the need).

If you do things right, you should be able to export / publish the original code base to any given site at any time and not screw things up. Any customizations should remain intact.

Chris
I think the system needs to be looked at again and maybe broken down even further, so as you say all javascript is in external files, which are all organised nicely with relevant components. But it there a way to break a website into two sections?So I would have the generic parts and the bespoke parts?
JamesStuddart
In theory, you could just mimic the directory structure and develop the scripts / templates in a separate project. You would then be able to merge the two tracks for deployment. In practice, this would make debugging more difficult than it should be. I wonder if anyone else has any ideas on that.
Chris
I've given this a bit more thought, and here's how I would do it, but it would take a CVS system with much better branching support than SVN has. I personally have transitioned to git where I work for this very reason. Basically, you would fork the original code and maintain it on a separate repo. An occasional merge from the core to the fork would keep the fork up to date on common changes while you could make any customizations in the fork and deploy from there. The key to success here is the awesome auto-merge tracking built into a system like git, which takes care of 95% of the work.
Chris
A: 

Establish a continuous integration server. Practice active code generation.

See 10 tips to integrate CodeSmith into your processes.

Ewan Todd
CI is something I will be setting up within the next few months, using cruisecontrol.netBut I currently dont have any servers or boxes to run it. This will be changing soon though :)
JamesStuddart
+3  A: 

I ran into this exact problem a few months ago when we started a significant rewrite of our web app. We had two separate versions of nearly identical sites. The back-end code was 99% identical, while the JavaScript, CSS, and other front-end stuff was very different. We had these two sites in separate trunks in the same SVN repository, and it soon became a nightmare of copying & pasting common code between them. Patching and merging was too painful to be useful, due to slight variations in the files.

Our solution was neither SVN-related nor builing of a common library. Instead, the concept of a separate site is defined in a single codebase via multiple config files and a heirarchy of CSS, image, and language resource files. Site-specific features are enabled by config values.

Each site gets a unique name (say, "foo" and "bar"), which is retrieved from the Web.config file at run-time. The name is used to determine which config file is loaded and which client-side files to use. The setting is blank in SVN. It is set by our deployment scripts when copied to the web servers. On our local development machines, an environment variable defines the site we want to work with.

The file structure of the site-specific files would look like this:

|- Config
|     |- AppSettings.foo.config      <- overrides Web.config AppSettings for "foo" site
|     |- AppSettings.bar.config      <- overrides Web.config AppSettings for "bar" site
|- Content
|     |- CSS
|          |- main.css               <- default CSS file for all sites
|          |- main.foo.css           <- CSS overrides for "foo" site
|     |- Images
|          |- logo.jpg               <- default logo
|          |- logo.foo.jpg           <- logo used if site name is "foo"
|          |- logo.bar.jpg           <- logo used if site name is "bar"

This has worked great for us, so far. Adding a new feature to a specific site is as easy as adding the feature to our code-base, and only enabling it for that site.

MikeWyatt
This is an ok idea, but due to the number of websites we have running from this system which is about 5 at the moment and soon to increase dramatically I think there would be some really dodgey looking switches through out the code.I think I need to strip everything from appcode that I can, move all webservices to their own project, including the webservices from the admin system, and get them into their own project.Then I think the main issue then will just be handling the themes and master pages.
JamesStuddart
A: 

Three thoughts, in ascending order of utility and effort:

1) Honing in on the "the markup is totally different per site (except the admin site, which is just a theme change) but the code bases are the same."

How much "code" can you move to a DLL project that gets shared? If it's almost all of it, then you can maintain separate projects for each of the sets of markup and those will use the DLLs as reference.

Obviously if you've got a lot of code that's not in AppCode, this isn't going to be feasible at all. If not, it may be a quick route to less insanity.

2) Would it be possible to maintain a repository for the shared code with separate repositories for each of the Sites? Then you'll need to create your own deployment script to handle pulling the source code from correct repositories and putting it in the right places.

Depending on how tightly coupled the code / markup is, this may not be feasible either.

3) Finally, what about moving the differing code into a database and having the app generate itself on deployment?

Obviously that's the most involved, but it gets you where you want to be.

Sammy Larbi
A: 

I'm going to start with thanking everyone for thier input.

I have no solved (more or less) the issue.

What I ahve done is move all images into the Themes folders and also created subfolders in the templates and controls folders where bespoke controls will live. I had already created some features in the database schema that gave me a helping hand along with this.

My preplanning of the system had a lot in it that I hadnt fully implemented and had forgotten about.

I have also seperated out some of the code as well for the likes of the webservices, well atleast for the webservices that can survive on their own anyway.

Collectively we got to the solution so Im not sure who to award the points to?

JamesStuddart