Here's the situation:
A while ago, I created a back-end interface for adding/modifying/deleting items in a DB. It was created as an individual project, and we are still using that particular instance of the code. I will call this "version 1".
A little while after I completed this, I duplicated the code and integrated it into a much larger project. I copied all of the DB tables that were used in the original project's DB into the DB that this project was already using. I also had to duplicate the front-end here, but it's the back-end that I'm concerned with. The requirements for this interface (I will call this "version 2") were a bit more complex, so I had to keep working on it and also make some modifications to the DB tables.
It is essentially 2 branched versions of the same interface. However, version 1 has not received much attention since version 2's conception. Some of the changes I made in version 2 were not just new features, but improvements/bug fixes that are relevant to version 1. I should have made these changes on version 1 as well, but unfortunately I didn't. Going forward I will need to make improvements to both versions, and some of these improvements will apply to both of them.
I would really like to merge the 2 interfaces somehow, as I'm quite sure that it will reduce my workload in the long run. Frankly, I would like to abandon version 1 and adapt the version 2 UI to version 1's DB.
My first instinct is to transport everything to a user control that has a "version" attribute. The version would then be used to hide/show the controls that are or aren't relevant to that version, and it would also be used to determine what DB queries/stored procedures to use. The issue with this is that this whole interface spans across 5 pages. A few of these pages are opened up as dialogs from another one of the 5 pages. I suppose that I could simply have one div per interface, and then when !IsPostBack, I can set the Visible property of each div according to a querystring variable. However, this seems like it would be awfully messy and it would be a LOT of code and markup on one page. I guess alternatively I could have 5 user controls, but this just seems like an odd design.
Are there any other viable solutions?
i've been maintaining 4 products with nearly identical interfaces:
they started from one project
got cloned and branched
i've been slowly re-merging them
The best suggestion i have is try to some up with a UI that works for both, and switch both to using that.
After that i have a project-local settings file, which defines which features should not exist in one or the other.
Related
We have a website application that stores data and pictures for a specific customer. We are about to release the same application for use by another customer. The second application will eventually be customized for the second customer. Eventually we hope to have several customers using their own versions of the application.
We are using ASP.NET in Visual Studio 2012. Should we:
clone the existing application and maintain separate code bases?
add a project to the existing solution for the new customer?
We have searched for an answer to but this seems to be a rare situation.
Thanks.
I dont think its rare at all. SAP and Maximo use this a a businiess model. Same core but each package customized to the clients specifications. I have done this (on a much much smaller scale) with some of the programs that we have.
We always start a new project rather than just copy the old. No telling what is in the old one that references the old client. Sort of embarasing when an About window that you forgot about is for someone elses company.
All the code, forms, reports that are customizeable should be in the project for that customer. All of the code, forms, reports that are standard should be in a library.
It really depends on the scope of the application. I've had to do this internally with the company I'm working for; I wrote one solution for one company, then the sister company found out and wanted the same and had to implement it there.
I had a fairly small project to work on, so it was easy to make it universal (while also keeping things rooting from the same code base). All i did was:
break out the unique setting [page title?] using appSettings or similar.
add a new configuration to your solution. Then take advantage of the *.config migrations to:
set connectionStrings
specify appSettings values
When it comes to unique business logic, I had the luxury of using the *.config migrations (most of the data I gathered came from WCF endpoints of services local to the company)--so I lucked out. However, you could make generic interfaces within the app then break out implementation for each company in to separate libraries.
I have developed 9 multiple websites/stores in one magento installation. On DEV server it is ready and working good. Now my client wants to launch first 3 websites in next month, then after we will make some modifications in other websites based on feedback from first 3 websites. Then launch other websites one by one.
One thing which I am worried about is how we make modification and further development. Because magento files and db is one installation, if we launch first three which means we are launching whole system, and if we make DEV work in live site that is not good because if anything breaks etc. LIVE sites will go down.
What is the best and logical procedure in magento to launch multiple stores one by one. What approach we can follow for such situations.
Please help, thanks!
To my eyes, the fact that you have 9 different websites/stores running off the install is of minor importance. You will encounter the same issues that any dev / live Magento set-up will encounter. At the point the site launches you will need to create a second copy of your database / code for use as a development environment. With regards to the code, I would hope that you are using some kind of VCS such as Git or SVN, if you aren't you should seriously consider it.
The database is the slightly trickier side of things. It is also going to be the issue exacerbated by the fact you have 9 different websites, since you will have a lot of different configurations. There will likely be 3 different types of configuration changes to be made.
1.) A setting that needs changing for the live websites.
2.) A setting that needs changing for a future website to be launched.
3.) A setting that needs changing in order to make your development site work.
The 3rd type is the easiest to deal with. You can simply change them in the database and forget about them. These will include things like setting the base_url values in core_config_data.
The 2nd type should ideally be made with migrations rather than through the UI. If you are using Source Control these migrations would be kept in a branch that will get merged into your master branch at the point you wish to launch the website they effect (at the point the code is merged, you may have to do some tinkering with the version numbers based on how you deal with type 1.
The 1st type can be handled in one of two ways, a migration is a favourable option as it means all installs of you code dev / staging / live can be kept in sync. If needs be, simply ensuring you update your dev database at the same time as the live one, would suffice.
Some of the things you need to change won't necessarily be the easiest things to achieve through migrations, but doing so should prevent any errors from arising whereby you forget to update a single value on one of your servers.
I am looking for some advice on how to allow easy customisation and extension of a core product on a per client basis. I know it is probably too big a question. However we really need to get some ideas as if we get the setup of this wrong it could cause us problems for years. I don't have a lot of experience in customising and extending existing products.
We have a core product that we usually bespoke on a per client basis. We have recently rewritten the the product in C# 4 with an MVC3 frontend. We have refactored and now have 3 projects that compose the solution:
Core domain project (namespace - projectname.domain.*) - consisting of domain models (for use by EF), domain service interfaces etc (repository interfaces)
Domain infrastructure project (namespace -projectname.infrastructure.*) - that implements the domain service-EF Context, Repository implementation, File upload/download interface implementations etc.
MVC3 (namespace - projectname.web.*)-project that consists of controllers, viewmodels, CSS, content,scripts etc. It also has IOC (Ninject) handling DI for the project.
This solution works fine as a standalone product. Our problem is extending and customising the product on a per client basis. Our clients usually want the core product version given to them very quickly (usually within a couple of days of signing a contract) with branded CSS and styling. However 70% of the clients then want customisations to change the way it functions. Some customisations are small such as additional properties on domain model, viewmodel and view etc. Others are more significant and require entirely new domain models and controllers etc.
Some customisations appear to be useful to all clients, so periodically we would like to change them from being customisations and add them to the core.
We are presently storing the source code in TFS. To start a project we usually manually copy the source into a new Team Project. Change the namespace to reflect the clients name and start customising the basic parts and then deploy to Azure. This obviously results in an entirely duplicated code base and I’m sure isn’t the right way to go about it. I think we probably should be having something that provides the core features and extends/overrides where required. However I am really not sure how to go about this.
So I am looking for any advice on the best project configuration that would allow:
Rapid deployment of the code – so easy to start off a new client to
allow for branding/minor changes
Prevent the need for copying and pasting of code
Use of as much DI as possible to keep it loosely coupled
Allow for bespoking of the code on a
per client basis
The ability to extend the core product in a single
place and have all clients gain that functionality if we get the
latest version of the core and re-deploy
Any help/advice is greatly appreciated. Happy to add more information that anyone thinks will help.
I may not answer to this completly, but here some advices:
Don't copy your code, ever, whatever the reason is.
Don't rename the namespace to identify a given client version. Use the branches and continuous integration for that.
Choose a branching model like the following: a root branch called "Main", then create one branch from Main per major version of your product, then one branch per client. When you develop something, target from the start in which branch you'll develop depending on what you're doing (a client specific feature will go in the client branch, a global version in the version branch or client branch if you want to prototype it at first, etc.)
Try the best to rely on Work Item to track features you develop to know in which branch it's implemented to ease merge across branches.
Targeting the right branch for you dev is the most crucial thing, you don't have to necessary define some hard rules of "what to do in which occasion", but try to be consistant.
I've worked on a big 10 years project with more than 75 versions and what we usually did was:
Next major version: create a new branch from Main, dev Inside
Next minor version: dev in the current major branch, use Labels to mark each minor versions Inside your branch.
Some complex functionnal features was developped in the branch of the client that asked for it, then reversed integrated in the version branch when we succeeded in "unbranded" it.
Bug fixes in client branch, then reported in other branches when needed. (you have to use the Work Item for that or you'll get easily lost).
It's my take on that, other may have different point of view, I relied a lot on the Work Item for traceability of the code, which helped a lot for the delivery and reporting of code.
EDIT
Ok, I add some thought/feedback about branches:
In Software Configuration Management (SCM) you have two features to help you for versionning: branches and labels. Each one is not better nor worst than the other, it depends on what you need:
A Label is used to mark a point in time, using a label, for you to later be able to go back to that point if needed.
A Branch is used to "duplicate" your code to be able to work on two versions at the same time.
So using branches only depends on what you want to be able to do. If you have to work one many different versions (say one per client) at the same time: there's no other way to deal with it than using branches.
To limit the number of branches you have to decide what will be a new branch or what will be marked by a label for: Client Specific Versions, Major Version, Minor Version, Service Pack, etc.
Using branches for Client versions looks to be a no brainer.
Using one branch for each Major version may be the toughest choice for you to make. If you choose to use only one branch for all major versions, then you won't have the flexibility to work on different major versions at the same time, but your number of branches will be the lowest possible.
Finally, Jemery Thompson has a good point when he says that not all your code should be client dependent, there are some libraries (typically the lowest level ones) that shouldn't be customized per client. What we do usually is using a separated branch tree (which is not per client) for Framework, cross-cutting, low level services libraries. Then reference these projects in the per client version projects.
My advice for you is using Nuget for these libraries and create nuget package for them, as it's the best way to define versionned dependencies. Defining a Nuget package is really easy, as well as setting up a local Nuget server.
I just worried that with 30 or 40 versions (most of which aren't that different) branching was adding complexity.
+1 Great question, its more of a business decision you'll have to make:
Do I want a neat code-base where maintenance is easy and features and fixes get rolled out quickly to all our customers
or do I want a plethora of instances of one codebase split up, each with tiny tweaks that is hard (EDIT: unless your a ALM MVP who can "unbrand" things) to merged into a trunk.
I agree with almost everthing #Nockawa mentioned except IMHO dont substitute extending your code architecture with branches.
Definitely use a branch/trunk strategy but as you mentioned too many branches makes it harder to quickly roll-out site wide features and hinder project-wide continuous integration. If you wish to prevent copy/pasting limit the number of branches.
In terms of a coding solution here is what I believe you are looking for:
Modules/Plug-ins, Interfaces and DI is right on target!
Deriving custom classes off base ones (extending the DSL per customer, Assembly.Load())
Custom reporting solution (instead of new pages a lot of custom requests could be reports)
Pages with spreadsheets (hehe I know - but funnily enough it works!)
Great examples of the module/plugin point are CMS's such as DotNetNuke or Kentico. Other idea's could be gained by looking at Facebook's add-in architecture, plugin's for audio and video editing, 3D modeling apps (like 3DMax) and games that let you build your own levels.
The ideal solution would be a admin app that you can choose your
modules (DLL's), tailor the CSS (skin), script the dB, and auto-deploy
the solution upto Azure. To acheive this goal plugin's would make so
much more sense, the codebase wont be split up. Also when an
enhancement is done to a module - you can roll it out to all your
clients.
You could easily do small customisations such as additional properties on domain model, viewmodel and view etc with user controls, derived classes and function overrides.
Do it really generically, say a customer says I want to a label that tally's everyone's age in the system, make a function called int SumOfField(string dBFieldName, string whereClause) and then for that customers site have a label that binds to the function. Then say another customer wants a function to count the number of product purchases by customer, you can re-use it: SumOfField("product.itemCount","CustomerID=1").
More significant changes that require entirely new domain models and controllers etc would fit the plug-in architecture. An example might be a customer needs a second address field, you would tweak your current Address user-control to be a plug-in to any page, it would have settings to know which dB table and fields it can implement its interface to CRUD operations.
If the functionality is customised per client in 30-40 branches
maintainability will become so hard as I get the feeling you wont be
able to merge them together (easily). If there is a chance this will
get really big you dont want to manage 275 branches. However, if its
that specialised you have to go down to the User-Control level for
each client and "users cant design their own pages" then having
Nockawa 's branching strategy for the front-end is perfectly
reasonable.
This question mixes a bit of project management as well as development. I understand the [major].[minor].[patch] scheming for version numbering of a project. With my clients' projects I use these numbering primarily for internal purposes so instead of refering to a project by the features involved, the team can say "what is the progress of v1.3.2?".
However, sometimes our clients have multiple minor releases at once. Each minor release contains a set of independent features (working with different departments of the client company), but both could launch different times. So if we label them as v1.3.3 and v1.3.4, the v1.3.4 version could release earlier than v1.3.3 and then the whole naming scheme is invalid.
How do you refer internally to these various builds if you don't know which will release first (due to waiting for client approval, or other external scheduling conflicts)?
Thanks!
Pretty simple -- we don't assign version numbers until we release. Problem solved!
That may sound flippant, but it's the truth. Sure, we would have internal projects dubbed e.g. "v5.5", but those were separate and independent from current work on the next iteration of v5.4.x, which would receive the next value of 'x' only upon completion and release. When v5.5 is ready, work on 5.4 ceases, we merge any changes made to 5.4 into 5.5, and then we release 5.5.0.
If you have separate builds for different clients (departments in your case), you can employ a modified versioning scheme. What we did is use [major].[minor].[client].[patch], e.g. 5.4.client1.4. The [patch] would be independent and only meaningful to that particular client, whereas [major].[minor] would correspond to the [major].[minor] version of the main codebase from which we forked off. For example, we might have simultaneous work on 5.5, 5.4.x, and 5.4.client1.x. When 5.5 is ready, 5.4.x merges into that, and then both projects fold into 5.5.x, but the client project might not be ready to merge all those changes and thus it would remain 5.4.client1.x until it was brought up-to-date with 5.5, then becoming 5.5.client1.x.
This may sound confusing, but it actually worked very well for us. We previously employed a variation of this scheme, where the client name was appended to the complete version number, i.e. [major].[minor].[patch]_[client]; again, however, [major].[minor] corresponds to the "core" [major].[minor] from whence it was forked/last merged, and the [patch] is wholly independent from the other versions and only meaningful to that client (this is why we later swapped the relative positions of [client] and [patch], to make it clear that e.g. 5.4.7 might actually have more fixes/be more "current" than 5.4.12.client1, and to better communicate that independence.
When a client-specific project merges back, of course, you drop it and increment to the next [patch], or perhaps make the jump up to the next [minor] or even [major] version, depending on the nature of the work. This does occasionally lead to some temporary confusion when a client project merges into the 5.4.x project and then we release from that version 6.0, then remember to rename the internal 5.5 project to 6.1, but it worked nonetheless.
As an alternative for your environment, internally refer to your current projects simply by client (department) name, e.g. the Accounting project, the HR project, etc. Don't use version numbers internally for this kind of thing, because as you see it just leads to confusion like version 5.4.6 coming out after 5.4.7 but before 5.4.9; meanwhile 5.4.8 never gets released because it was canceled. That's just a mess, so stay away from that. Simply call your projects by client name, and assign the next number
There is a similar question at Best practice for managing project variants in Git? but the context is different and I suspect the answer might be too.
I have a Cocoa product "First" managed with Xcode and versioned using git. "First" is still evolving, and is currently at its third version.
Then a customer comes and ask for a variant of First, called Second. The changes from First to Second affect many, but not all, files. The changes affect source code but also resources (graphics elements, nib files, property lists...).
Now the two products are alive and share a number of common files. However, some changes such as bug fixes might apply to both products. Possibly, a new feature might be added to both products.
What would be the best way to manage such a scenario:
with Xcode
with git
I have two ideas, which are mutually exclusive:
Idea 1: git branch "First" into "Second", and apply any applicable change from one project back to the other one. This leads to two totally separate Xcode directories and projects.
Idea 2: Add a target named "Second" to the Xcode project. Now the same Xcode project has two targets and is used to develop and build both products. But this makes it difficult to manage releases for First and Second in git (releases have no reason to be synchronized).
Idea 2 makes the parallel development process very easy. Code is always in sync. Divergences can be handled through compile-time variables and a single source file OR through different source files. It makes version management more obscure though.
Idea 1 is perhaps cleaner, but then, what's the best practice to manage whatever stays common between the two projects? Can you do a "partial merge" between two git branches? On what basis? Or must that be handled manually?
It might be possible to encapsulate and extract some common part into a module or library, but not always. For example I don't think that's possible for the common document icons. Also refactoring "First" so that all common items are extracted away in a build-able manner is a major undertaking that I'd rather do a bit at a time.
I realize there may not be a perfect solution. I am looking for ideas and suggestion.
As a relatively recent git adopter I also realize that this may be an RTFM question. Then simply point me to the FM to R.
My preference is idea2. I currently do this as a way of writing a plug-in for the Main App, and then client apps that go on all the nodes of a cluster. The Plug-in and clients share 90% of the same code, so this makes it super-easy to maintain and debug the where/how of what's going on.