The configurable application, no need for recompilation and new deployment!
The following I will write about is something I have used in some projects to see if it gives me any value, I haven't seen any evolutionary results yet, but maybe it's because I often move along to other projects when the previous one is completed ;)
Let assume I have a User and the User has a property called Rebate. This method can have some business logic to calculate the rebate the use has when ordering products. Here is an dummy example of the method:
class User { public double Rebate { get { return superUser ? 10: 5; } } }
User user = new User(....);
double rebate = user.Rebate;
By using the Interfaces and also the Factory Pattern we could solve this. Here is an example where an Interface is added to the User and a Factory is used to create the User:
public interface IUser { double Rebate { get; } } class User : IUser { public double Rebate { get { return superUser ? 10: 5; } } }
IUser user = UserFactory.Create(...);
double rebate = user.Rebate;
The UserFactory will now create an User an return an IUser. Because the factory creates the user I don't use "new User". I can now use late binding and load the assembly which has the implementation of the User and return it. I can for example use a configuration file where I specify the type of the user I want use.
<object name="IUser" type="MyNamespace.User, MyAssembly, Version 1.0 ...">
The UserFactory can now load the type specified in the configuration file and create an instance of it. If I need an new version of the User because
some changes need to made based on business needs, I can create a new assembly and a new IUser. I can then modify my configuration file to make sure the UserFactory loads my new implementation. By using this solution I don't need to compile my application when changes to classes is needed. Instead I create a new version of the class, put it into a new version of the assembly and deploy it. Then I only change the configuration file so the Factory gets my new implementation instead of the old version.
class User : IUser { public double Rebate { get { return IsMegaUser() ? 11: 6; } } }
<object name="IUser" type="MyNamespace.User, MyAssembly, Version 2.0 ...">
Another solution to solve this could be to use Dependency Injection, where I inject a object with the implementation of the business logic. I can then for example use Spring.Net to inject the business object into my User. By using Spring.Net I can in a configuration file specify which business object that should be injected to the User class when it's instantiated. This will make it possible to only implement a new version of the business object rather then a new version of the User. I will not use this solution because it can be kind of ugly. But by using Spring.Net I can hide the injection of the dependency and never see it in my code. Let's think like an Object, would you like someone to easy change your behavior and you can't do any thing about it?
I sometimes uses Interfaces and in some cases Factories, but not so often (It depends on the project and if the Customer already have specified a design to use). I use interfaces and factories when I want my application to be plugable, for example make it easy to inject Repositories into my Services etc, and also to make it possible to use Mock object during test etc.
About using this solution for most of the classes in a application, wouldn't it in an Agile project sort of violate YAGNI!?
It can sort of help the people that need to maintain the application after it's deployed, as long as the interface of the classes can be intact. What do you think about it? Is this something you use today in your application and have it result into something good?