kruegerste
kruegerste

Reputation: 83

How to version middle tier .NET application classes/methods

We have a typical N-Layer .NET application which sits in between our database and Web API service layer. This application consists of Business Layer, Data Repository/Access along with the related DTOs and Business Objects.

We have solutions in place to version our stored procedures and our Web API endpoints. The issue is the solution to version this middle layer, the actual class methods and schema objects. All Google searches come up with results for versioning source code in a source control solution or how to version using the Assembly info, neither of these are what we are referring to so results are limited.

So for example, we have two endpoints:

...api/v1/tax/charges

...api/v2/tax/charges

v1 must hit one version of the method CalculateTaxPctgs and v2 hits another version with updated business logic. Along with both needing to use different versions of the POCO Tax and TaxItems as we changed the name of one field in v2.

The easy to develop but hard to manage and very rigid/static solution would be to create two different methods, CalculateTaxPctgs_V1 and CalculateTaxPctgs_V2. This doesn't seem like a good idea.

Hard to find best practices or even alternative solutions for this dilemma. This is an enterprise application which takes millions of requests every day so performance is extremely important but so is code management and reliability.

Upvotes: 6

Views: 2077

Answers (3)

Keith Nicholas
Keith Nicholas

Reputation: 44316

To solve this problem we have implemented dynamically loading assemblies which handles over 80 different versions. It works well. We don't change the deployed software (unless there is a serious flaw) since it's part of a production system that we can't afford to break once it works.

We also have some critical changes over time, like using several different versions of .NET. To handle this we route requests to different application deployments.

Upvotes: 0

Andy Nichols
Andy Nichols

Reputation: 3002

Instead of different methods I'd use object inheritance. This way if a method stays the same between different versions you don't need to change the implementation in any way. You could then use a factory of some sort to create the instance required. For example:

public virtual class TaxCalculatorBase {
    public virtual ICollection<TaxPercentage> CalculateTaxPercentages() {
        DefaultImplementation();
    }
}

public sealed class TaxCalculatorV1 : TaxCalculatorBase {
    //Same implementation so no need to override
}

public sealed class TaxCalculatorV2 : TaxCalculatorBase {
    //Same implementation but with a bit extra
    public override ICollection<TaxPercentage> CalculateTaxPercentages() {
        base.CalculateTaxPercentages();
        ExtraStuff();
    }
}

public sealed class TaxCalculatorV3 : TaxCalculatorBase {
    //Different implementation
    public override ICollection<TaxPercentage> CalculateTaxPercentages() {
        NewImplementation();
    }
}

public static class TaxCalculatorFactory {
    public static TaxCalculatorBase Create(int version) {
        switch (version) {
            case 1: return new TaxCalculatorV1;
            case 2: return new TaxCalculatorV2;
            case 3: return new TaxCalculatorV3;
            default: throw new InvalidOperationException();
        }
    }
}

public class CallingClass {
    public void CallingMethod(int versionFromURL) {
        var calculator = TaxCalculatorFactory.Create(versionFromURL);
        var percentages = calculator.CalculateTaxPercentages();
        percentages.DoStuffWithThem();
    }
}

If the api implements an entire new version each time the factory can be more generic and something like:

public static class MyFactory {
    public static TaxCalculatorBase CreateTaxCalculator(int version) {
            switch (version) {
                case 1: return new TaxCalculatorV1;
                case 2: return new TaxCalculatorV2;
                case 3: return new TaxCalculatorV3;
                default: throw new InvalidOperationException();
            }
        }
    }
    //various other methods to create classes which depend on version
}

Upvotes: 1

mp3ferret
mp3ferret

Reputation: 1193

Obviously this depends on exactly how your solution is put together but would redirecting assembly versions be something you could leverage :

https://msdn.microsoft.com/en-us/library/7wd6ex19%28v=vs.110%29.aspx

You can redirect your app to use a different version of an assembly in a number of ways: through publisher policy, through an app configuration file; or through the machine configuration file.

Upvotes: 0

Related Questions