How to refactor this? - c#

I'm struggling with a small issue with regard to how I go about refactoring this to a decent pattern.
public class DocumentLibrary
{
private IFileSystem fileSystem;
private IDocumentLibraryUser user;
public DocumentLibrary(IDocumentLibraryUser user) : this(user, FileSystemFrom(user)) { }
public DocumentLibrary(IDocumentLibraryUser user, IFileSystem fileSystem)
{
this.user = user;
this.fileSystem = fileSystem;
}
public void Create(IWorkerDocument document)
{
document.SaveTo(fileSystem);
}
public IWorkerDocument AttemptContractRetrieval()
{
return new Contract(fileSystem, user);
}
public IWorkerDocument AttemptAssignmentRetrieval()
{
return new Assignment(fileSystem, user);
}
private static IFileSystem FileSystemFrom(IDocumentLibraryUser user)
{
var userLibraryDirectory = new DirectoryInfo("/DocLib/" + EnvironmentName() + "/" + user.Id);
return new FileSystem(userLibraryDirectory);
}
private static string EnvironmentName()
{
using (var edmxContext = new Entities())
{
return (from setting in edmxContext.EnvironmentSettings
where setting.Name == "EnvironmentName"
select setting.Value).First();
}
}
}
I have two types of worker documents, but I can't seem to easily refactor the two methods above (AttemptContractRetrieval and AttemptAssignmentRetrieval) to a decent form.
Any help would be much appreciated.
Regards,
Jim.

Personnally, I would consider either a factory pattern using factory methods or a builder pattern.
Good use of the factory pattern can be seen in the Enterprise Library solution e.g:
Database.CreateDatabase();
I would say this would be the most straight forward to integrate.
If you chose the Builder pattern, with a requirement to create more complex objects, then you can separate out the creation of complex objects into a series of build commands e.g:
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
Then within these methods, given your chosen implementation, you can add your complexity but make the method calls and construction quite straight forward.
If you haven't come across it, http://www.dofactory.com is a good place to go.

I can see two aspects to this:
What do I need to do to add a new IWorkerDocument class? Adding new methods seems heavyweight.
What code does the caller need in order to create an IWorkerDocument? Right now the responsibility for calling the correct method lies with the caller, hence it's quite likely that the caller also needs to change each time there is a new IWorkerDocument implementor.
The extent of possible refactoring very much depends upon the answer to 2. Sometimes the caller just has to know what they're making, and in which case the code you have is pretty much all you can do. In other cases you have some "WorkerDefinition" stuff, perhaps in the form of a set of Properties, or a name that can be looked up in a registry. In which case the caller wants an api of the form
makeMeAWorker(WorkerDefinition def)
on a Factory. Now the caller has no idea what he's asking for, delegates the whole thing to the factory. So the client's world need not change as you add new Worker types.
The Factory can be made extensible by some form of registration scheme or dynamic configuration scheme. We can inject new types into the factory by many different mechanisms.

I think it depends on what other responsibilities the class has that contains those methods. Design patterns are structural constructs. Here we infer that there is a class
class Retriever
{
...
public IWorkerDocument AttemptContractRetrieval()
{
}
public IWorkerDocument AttemptAssignmentRetrieval()
{
}
}
The client code is already deciding whether to call AttemptContractRetrieval(), or AttemptAssignmentRetrieval, so maybe polymorphism is in order.
class ContractRetriever
{
public IWorkerDocument AttemptRetrieval()
{
}
}
class AssignmentRetriever
{
public IWorkerDocument AttemptRetrieval()
{
}
}
You can make an abstract Retriever class and have these as descendents of that. This will force the derived classes to have an AttemptRetrieval() method.
If you execute similar actions on the retrieved documents, you may consider having Contract and Assignment classes instead of ContractRetriever and AssignmentRetriever. Then you can put common actions in their parent.
In short, a lot of the answer here lies in the unstated context of the problem.

For interested people, I have gone for a factory method.
public IWorkerDocument AttemptRetrieval<T>() where T : IWorkerDocument
{
return WorkerDocument.Create<T>(fileSystem, user);
}
calls
public static IWorkerDocument Create<T>(IFileSystem fileSystem, IDocumentLibraryUser user) where T : IWorkerDocument
{
var documentType = typeof(T);
if (documentType == typeof(Contract))
return new Contract(fileSystem, user);
if (documentType == typeof(Assignment))
return new Assignment(fileSystem, user);
throw new Exception("Invalid Document Type");
}
It's a little messy, so does anyone have any suggestions to clean the actual factory method up?

what about this:
public IWorkerDocument AttemptRetrieval<T>() where T:new, IWorkerDocument
{
return new T {FileSystem=fileSystem,User=user}
}
Out of the top of my head, so may contain a blatant error ;-)

Are you looking for the Abstract Factory pattern? The declared intent in 'Design Patterns' is "Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
http://en.wikipedia.org/wiki/Abstract_factory

Related

How can I avoid God Class anti-pattern on this design

I think I designed my app focusing all the logic in one single class (A). I have been reading that is not a good practise to do this. Class A have a lot of nested logic, each method of Solve() uses as input the result of the previous ones. I dont know if I should create separate classes for DoTask1, DoTask2, DoTask3 and DoTask4, and instantiate them from Solve(). Would that be better? I know I can also create separate classes with static methods but I have read that too many static methods are bad.
Main()
{
A a = new A()
a.Solve()
}
A()
{
Solve()
{
partialresult1 = DoTask1()
partialresult2 = DoTask2(partialresult1)
partialresult3 = DoTask3(partialresult2)
finalresult = DoTask4(partialresult3)
}
DoTask1(){}
DoTask2(){}
DoTask3()
{
B b = new B()
b.doWathever()
}
DoTask4(){}
}
B()
{
doWhatever(){}
}
It is difficult to know without the full extent of the problem but I'll take a guess and make a suggestion.
You have different payloads and based on them, you want to apply different tasks.
I would, at first create the ITask interface:
public interface ITask {
Result DoWork(PartialResult res);
}
Now you can create task classes that can do some part of the work. The client could create the list and execute accordingly.
public Task1: ITask {
public Result DoWork(PartialResult res) {
// some work here
}
}
Now as an extra, you could use the AbstractFactory design pattern. Each abstract factory implementation, will create the list of tasks needed for a specific job. The client can the use them to execute the payload.
Those two solutions will probably make your super class obsolete
For more information on the AbstractFactory design pattern, check: https://refactoring.guru/design-patterns/abstract-factory

How to get/set a property of an interface that is not always implemented

What is a good (object oriented) way of setting a property of a class which implements an interface, when that property doesn't always exist in all classes that implement that same interface?
e.g.
Let's say I have an interface
public interface IDataRepository {
public DataStructure GetData(); // DataStructure is an arbitrary class, doesn't matter for this example
}
Now I also have two classes that inherit from this
public class DatabaseRepository : IDataRepository {
public DataStructure GetData()
{
// get data from database
}
}
and
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; }
public DataStructure GetData() {
// get data from files
}
}
Now my client method doesn't necessarily know what the repository is but here's what I want to do...
private DataStructure ReadData(IDataRepository repository)
{
repository.WorkingFolder = #"C:\Data"; // What is the best way of doing this?
return repository.GetData();
}
obviously the above code won't work and I could do...
if (repository is FileRepository) {
((FileRepository)repository).WorkingFolder = #"C:\Data";
}
or add WorkingFolder as a property of the interface (and therefore all the classes that implement it) even though in most cases it's irrelevant.
but both of these (esp. the first one) seem very inelegant and not very object oriented. What is the oop way of doing this kind of thing?
Edit
The obvious question is if the method doesn't know what repository is, how can it know the correct value for WorkingFolder... But the above is an over-simplification of what I'm trying to do, so let's just say it can find out...
Apparently your ReadData method can't actually accept any type of repository. It is only able to handle a FileRepository. That's what it expects, and that's what it needs to do its job. Given that, that's what it should actually accept as its parameter, rather than an interface that doesn't actually provide a contract that is sufficient for it to do its job.
The entire point of having an interface is so that anyone using that interface can use it without caring what the implementation is. So if you do want to use the interface you need to include enough information in the interface's definition such that it provides every operation that anyone using the interface needs, otherwise you're better off just not using it at all (at least for that specific operation).
As for the specific example given, you should probably just be providing an already configured repository, that has whatever values it needs in order to allow this method to do its work, as a parameter. It doesn't make sense for a method that's reading a value from an arbitrary repository to be configuring that repository at all. That is, if it really is reading something from an arbitrary repository.
As others have said in the comments, you should initialise these properties in the constructor. This is where you know what type you're creating, so you also know what arguments its constructor requires / can set those there.
Once you've initialised the object, you can just pass it around / have anything using that class operate against its interface.
Example:
public void Main(string[] args)
{
var myRepo = new FileRepository(args[0]); //Here's where we set the working directory
var myThing = new Thing();
var data = myThing.ReadData(myRepo);// of course, the current implementation means you could just call `myRepo.GetData()` directly, since ReadData just passes out the same response; but presumably that method adds some additional value..
Console.WriteLine(data.ToString());
}
Supporting Code
public class DatabaseRepository : IDataRepository {
DbConnection connection; //you may want a connection string or something else; going with this type just to illustrate that this constructor uses a different type to the FileRepo's
public DatabaseRepository(DbConnection connection)
{
this.connection = connection;
}
public DataStructure GetData()
{
// get data from database
}
}
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; } //Do you need set? Generally best to keep it constant after initialisation unless there's good reason to change it
public FileRepository (string workingFolder)
{
this.WorkingFolder = workingFolder;
}
public DataStructure GetData() {
// get data from files
}
}
How do I call the code that creates the class
i.e. maybe you've implemented a really basic factory pattern like so, and want to know how to provide arguments:
public class DataRepositoryFactory
{
Type baseType = typeof(IDataRepository);
IDictionary<string, Type> typeMap = new Dictionary<string, Type>() {
{"File", typeof(FileRepository) }
,{"Db", typeof(DatabaseRepository) }
}
public void RegisterType(string typeName, Type type)
{
if (!baseType.IsAssignableFrom(type)) throw new ArgumentException(nameof(type));
typeMap.Add(typeName, type);
}
public IDataRepository GetDataRepository(string typeName)
{
return (IDataRepository)Activator.CreateInstance(typeMap[typeName]);
}
}
(For a more complex example of a factory, see https://web.archive.org/web/20140414013728/http://tranxcoder.wordpress.com/2008/07/11/a-generic-factory-in-c).
I.e. in this scenario, when you call the factory you know what type you want, but you're only giving it a string to name/identify that class. You could add a params object[] args to your GetDataRepository method, allowing you to call it like so:
var myRepo = myDataRepositoryFactory.GetDataRepository("File", "c:\somewhere\something.dat");
That's a good approach / is actually what's used on the linked example above. However, it means that your call to this code differs for different types; since if we use variables instead of hardcoded values as in the above example we can't simply do the below, since myRepoType could be set to "Db", whilst "myFilePath" would be a string:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myFilePath);
That's fixable by calling:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myArgs);
i.e. where myArgs is an object[], giving all of the values required in the desired order to initialise the type. The piece to populate object[] with the required values could then take place at the same point at which you decided you wanted the type to be a file repo vs database repo. However, this approach isn't that clean / casting to and from objects stops you from getting help from the compiler.
So how do I improve things?
There are a few options. One is to replace the need to use object[] by instead creating a type to hold your arguments. e.g.
public interface IDataRepositoryConfiguration
{
//nothing required; this is just so we've got a common base class
}
public class FileRepositoryConfiguration: IDataRepositoryConfiguration
{
public string WorkingFolder {get;set;}
}
public class FileRepository : IDataRepository {
public FileRepository (IDataRepositoryConfiguration configuration)
{
var config = configuration as FileRepositoryConfiguration;
if (config == null) throw new ArgumentException(nameof(configuration)); //improve by having different errors for null config vs config of unsupported type
this.WorkingFolder = config.WorkingFolder;
}
//...
}
This still has some issues; i.e. we may pass a DatabaseRepositoryConfiguration as our IRepositoryConfiguration when creating a FileRepository, in which case we'd get the AgumentNullException at runtime; but this does avoid issues should parameters change order, and makes it less of a headache to code / debug.
Could it be further improved?
Dependency Injection offers one solution. This could be used along the lines of the code below (i.e. you create instances of each of your classes, providing the required arguments, and give each instance a name, so that you can later fetch that instantiation. Exactly what that code looks like would depend on the dependency injection library you used:
//setting up your repositories
var container = new Container();
container.Configure(config =>
{
// Register stuff in container, using the StructureMap APIs...
config.For<IDataRepository>().Add(new FileRepository("\\server\share\customers")).Named("customers");
config.For<IDataRepository>().Add(new FileRepository("\\server\share\invoices")).Named("invoices");
config.For<IDataRepository>().Add(new DatabaseRepository(new DbConnection(configurationString))).Named("persist");
config.For<IDataRepository>().Use("persist"); // Optionally set a default
config.Populate(services);
});
//then later when you need to use it...
public DataStructure ImportCustomers(IContainer container)
{
var customerRepo = container.GetInstance<IDataRepository>("customers");
return customerRepo.GetData();
}
I'm sure there are many other approaches, and exactly what approach to use depends on how your program will operate. Hopefully the above is enough to get you past your current problem; but if you find you're still struggling please post a new question with more detail / saying where you're still having issues having considered these points.
If possible, I'd just put the value for that property in the constructor or create a subinterface, like others suggested.
If it's not possible, C# 7.X (don't remember the exact minor version) has a nice code structure for conditional casting:
IDataRepository repo = new FileRepository();
if (repo is FileRepository fileRepo)
{
fileRepo.WorkingFolder = "some dir";
}
However in your case, you should probably rethink your architecture and always pass (or even better always create) a repository object which is ready to be used.
a) Put it into the Inferface definitions. Deal with any "NotImplemented" Exceptions. You always have to expect those with Interfaces anyway.
For example, IEnumerable has a Reset() function. But in most cases it is not implemented. It is not even supposed to be implemented in most cases. Afaik it is only there for Backwards Compatabilty with some old COM stuff.
b) make a sub-interface just for the property
c) Verify the Interface is properly implemented via is checks (throw exceptions thows if nessesary, like Array.Sort will throw a InvalidOperation one), generic constraints, proper argument types and the like.

Can I use more generic interfaces to simplify my classes to use a command pattern?

I'm trying to make an app I'm designing more generic and implement the command pattern into it to use manager classes to invoke methods exposed by interfaces.
I have several classes with the GetItem() and GetList() methods in them, some are overloaded. They accept different parameters as I was trying to use dependency injection, and they return different types. Here are a couple of examples:
class DatastoreHelper
{
public Datastore GetItem(string DatastoreName)
{
// return new Datastore(); from somewhere
}
public Datastore GetItem(int DatastoreID)
{
// return new Datastore(); from somewhere
}
public List<Datastore> GetList()
{
// return List<Datastore>(); from somewhere
}
public List<Datastore> GetList(HostSystem myHostSystem)
{
// return List<Datastore>(); from somewhere
}
}
class HostSystemHelper
{
public HostSystem GetItem(int HostSystemID)
{
// return new HostSystem(); from somewhere
}
public List<HostSystem> GetList(string ClusterName)
{
//return new List<HostSystem>(); from somewhere
}
}
I'm trying to figure out if I could use a generic interface for these two methods, and a manager class which would effectively be the controller. Doing this would increase the reuse ability of my manager class.
interface IGetObjects
{
public object GetItem();
public object GetList();
}
class GetObjectsManager
{
private IGetObjects mGetObject;
public GetObjectsManager(IGetObjects GetObject)
{
this.mGetObject = GetObject;
}
public object GetItem()
{
return this.mGetObject.GetItem();
}
public object GetList()
{
return this.GetList();
}
}
I know I'd have to ditch passing in the parameters to the methods themselves and use class properties instead, but I'd lose the dependency injection. I know I'd have to cast the return objects at the calling code into what they're supposed to be. So my helper classes would then look like this:
class DatastoreHelper
{
public string DatastoreName { get; set; }
public string DatastoreID { get; set; }
public object GetItem()
{
// return new Datastore(); from somewhere
}
public List<object> GetList()
{
// return List<Datastore>(); from somewhere
}
}
class HostSystemHelper
{
public int HostSystemID { get; set; }
public string ClusterName {get; set;}
public object GetItem()
{
// return new HostSystem(); from somewhere
}
public List<object> GetList()
{
//return new List<HostSystem>(); from somewhere
}
}
But is the above a good idea or am I trying to fit a pattern in somewhere it doesn't belong?
EDIT: I've added some more overloaded methods to illustrate that my classes are complex and contain many methods, some overloaded many times according to different input params.
If I understand the concept correctly, a design like this is a really bad idea:
class DatastoreHelper
{
public string DatastoreName { get; set; }
public string DatastoreID { get; set; }
public object GetItem()
{
// return new Datastore(); from somewhere
}
public List<object> GetList()
{
// return List<Datastore>(); from somewhere
}
}
The reason is that getting results would now be a two-step process: first setting properties, then calling a method. This presents a whole array of problems:
Unintuitive (everyone is used to providing parameters as part of the method call)
Moves the parameter binding away from the call site (granted, this would probably mean "moves them to the previous LOC", but still)
It's no longer obvious which method uses which property values
Take an instance of this object and just add a few threads for instant fun
Suggestions:
Make both IGetObjects and GetObjectsManager generic so that you don't lose type safety. This loses you the ability to treat different managers polymorphically, but what is the point in that? Each manager will be in the end specialized for a specific type of object, and unless you know what that type is then you cannot really use the return value of the getter methods. So what do you stand to gain by being able to treat managers as "manager of unknown"?
Look into rewriting your GetX methods to accept an Expression<Func<T, bool>> instead of bare values. This way you can use lambda predicates which will make your code massively more flexible without really losing anything. For example:
helper.GetItem(i => i.DataStoreID == 42);
helper.GetList(i => i.DataStoreName.Contains("Foo"));
The first code samples look quite similar to the Repository Pattern. I think this is what are you trying to apply. The last sample is not good and Jon told you why. However, instead of reinventing the wheel, read a bit about the Repository (lots of questions about it on SO) because, if I understood correctly, this is what you really want.
About reuse, not many things and especially persistence interface are reusable. There is the Generic Repository Pattern (I consider it an anti-pattern) which tries to accomplish that but really, do all the application needs the same persistence interface?
As a general guideline, when you design an object, design it to fullfil the specific application needs, if it happens to be reused that's a bonus, but that's not a primary purpose of an object.
It is not a good idea. Based on these examples you would be better off with a generic interface for the varying return type and parameters of GetItem/GetList. Though honestly the prevalence of Managers, the use of something cas vague as GetItem in multiple places and trying to fit your solution into design patterns (rather than defining the solution in terms of the patterns) are huge code smells to me for the wider solution.

Question about Factory Design Architecture

Consider this example
The Interface
interface IBusinessRules
{
string Perform();
}
The Inheritors
class Client1BusinessRules: IBusinessRules
{
public string Perform()
{
return "Business rule for Client 1 Performed";
}
}
class Client2BusinessRules: IBusinessRules
{
public string Perform()
{
return "Business rule for Client 2 Performed";
}
}
class Client3BusinessRules: IBusinessRules
{
public string Perform()
{
return "Business rule for Client 3 Performed";
}
}
The factory class
class BusinessRulesFactory
{
public IBusinessRules GetObject(int clientIdentityCode)
{
IBusinessRules objbase = null;
switch (clientIdentityCode)
{
case 1:
objbase = new Client1BusinessRules();
break;
case 2:
objbase = new Client2BusinessRules();
break;
case 3:
objbase = new Client3BusinessRules();
break;
default:
throw new Exception("Unknown Object");
}
return objbase;
}
}
sample usage:
class Program
{
static void Main(string[] args)
{
BusinessRulesFactory objfactory = new BusinessRulesFactory ();
IBusinessRulesFactory objBase = objfactory.GetObject(2);
Console.WriteLine(objBase.Perform());
objBase = objfactory.GetObject(3);
Console.WriteLine(objBase.Perform());
Console.Read();
}
}
My question is, how about I add another method on the ALgorithm1 Class
but not in the interface because im going to just use it on special scenario?
class Client1BusinessRules: IBusinessRules
{
public string Perform()
{
return "Client1 Business rules is Performed";
}
public string Calculate()
{
return "Additional functionality for CLient1";
}
}
how Am I suppose to call that on the UI something like this
objBase = objfactory.GetObject(1);
Console.WriteLine(objBase.Calculate());
Is there any other solution? thanks in advance
EDIT: I rewrite it to resemble my current project design
I presume you are using the factory class in order to:
have a standard facade accepting parameters that lead to business rule selection and provisioning
encapsulate business rule provisioning
decouple the users from actual implementations of IBusinessRules
Hence I would solve your problem by introducing new interface
interface IComputableRules : IBusinessRules
{
string Calculate();
}
As long as you follow the interface-based design, there's nothing wrong about casting the actual instance to an interface different from IBusinessRules.
IBusinessRules businessRule = objFactory.GetObject(...some input...)
...
// check if the computable service is supported and print the result
IComputableRules computable = businessRule as IComputableRules;
if (computable)
{
Console.WriteLine(computable.Calculate());
}
Here you can think of you business rule classes as service providers, that guarantee some basic service, plus optional additional services depending on the nature of the business rule.
Note: By turning the BusinessRulesFactory into a generic class you might make the indication of a specific service a part of the factory contract, and make sure the returned business rule implementation will support a particular (otherwise optional) service.
class BusinessRulesFactory<TService> where TService : IBusinessRules
{
public TService GetObject(int clientIdentityCode)
{
// ... choose business rule in respect to both clientIdentityCode and TService
}
}
In case where you wouldn't require a specific additional service to be available, you'd just use IBusinessRules as the actual type parameter.
The whole point of the factory pattern is to return the proper implementation of a contract so that the consumer shouldn't worry about how to instantiate it but simply invoke its methods. You could always test the actual type, cast to it and invoke the method but that's a very bad design and I wouldn't recommend it. The consumer shouldn't know anything about the actual type. You will need to rethink your design.
If you want to stick to the current architecture you can introduce a new interface declaration
interface ICalculationRules
{
string Calculate();
}
Now let modify Client1BusinessRules by adding the interface declaration:
class Client1BusinessRules: IBusinessRules, ICalculationRules
{
// everything remains the same
}
Modify your calling code like this:
var objBase = objfactory.GetObject(1);
Console.WriteLine(objBase.Calculate());
var calcBase = obj as ICalculationRules;
if (calcBase != null) calculable.Calculate();
Maintenance implication: Every time you introduce a new interface, you have to touch all your calling code. Since you posted that this code is placed in the UI code, this can get quite a mess.
Each interface you are introducing just means added behaviour to a class. If you have a large range of different behaviours, then the solution above my not feel right, because there is always the need to use the as operation and conditional execution a method. If you want to stick to some classic design pattern this variability of behaviour can be countered with the Decorator Pattern or the Strategy Pattern. They can be smoothly combined with the Factory Pattern.
There are many approaches that can be employed in this case, and it depends on the cost you're willing to put in order to get the value.
For example, you can go with simple casting. You'll get the algorithm object from the factory, cast it to the proper (specific) algorithm object, and then call the "Calculate" function.
Another option - a much more generic one, that would also require much more code - would be to supply a querying mechanism within the base class, that will supply information about the available functionality within the object. This is somewhat comparable to querying for interfaces in COM.
The important questions you need to ask yourself is:
1. How many times will you need to implement specific functionality?
2. Is there a way you can solve the problem with added polymorphism stemming from the base class?
3. Will users of the derived objects know that they are using the specific object, or do you want them to be ignorant of the actual type?
In general what I personally do in such cases is start with the simplest solution (in this case, specific casting and calling the function), and go back and refactor as I go, when I have some more data about the domain. If you're sensitive to "smelly code", you'll get to a point where you see there's too much clutter and you'll refactor it into a better solution.
I would modify it like this
interface IBusinessRules
{
string Perform();
bool CanCalculate { get; }
string Calculate();
}
and add an abstract base class (optional but recommended for further extensibility)
public abstract class BusinessRules : IBusinessRules {
protected BusinessRules() {
}
protected virtual bool CanCalculateCore() {
return false; // Cannot calculate by default
}
protected virtual string CalculateCore() {
throw new NotImplementedException("Cannot calculate");
}
protected abstract string PerformCore();
#region IBusinessRules Members
public string Perform()
{
return PerformCore();
}
public bool CanCalculate
{
get { return CanCalculateCore(); }
}
public string Calculate()
{
return CalculateCore();
}
#endregion
}
So the call site now looks neat:
objBase = objfactory.GetObject(1);
if (objBase.CanCalculate) {
Console.WriteLine(objBase.Calculate());
}
One big problem of extending the interface is, it gives the caller no hint at all that you might support that interface as well.
This is a domain modelling issue and relates to what you mean by BusinessRule and IBase in your problem domain.
What is IBase? Sounds like it should be called IBusinessRule. In which case, what does Calculate mean in the context of a "business rule". If it has a generic meaning in your domain then IBusinessRule should implement it, as should the other classes, even if only as an empty method.
If it doesn't have generic meaning in your domain then your class should implement another interface ICalculable (IAlgorithm?) that has Calculate, which you call as:
ICalculable calculable = obj as ICalculable;
if ( calculable != null ) calculable.Calculate();

What is the design pattern in this code?

Say I have a singleton-ish, factory-ish, reflection-ish class that receives some input, and spits back a new instance of a concrete implementation of some interface. What kind of design is this? Is there a better way to do what I want?
Here's some code to illustrate the point:
using System;
using System.Collections.Generic;
// static factory class
public static class ArticleFactory
{
// given an SKU, store the Type object for an IArticle object
private static Dictionary<string, Type> articleRegistry = new Dictionary<string, Type>();
// allow public registration of SKU-to-Type object relationships
public static bool Register(string sku, Type typeInfo)
{
if(!articleRegistry.ContainsKey(sku))
{
articleRegistry.Add(sku, typeInfo);
return true;
}
return false;
}
// given a SKU, give me an instance of the related IArticle object
public static IArticle NewArticle(string sku)
{
if(articleRegistry.ContainsKey(sku))
{
// use reflection to invoke the default constructor
return articleRegistry[sku].GetConstructor(Types.EmptyTypes).Invoke(null) as IArticle;
}
return null;
}
}
// example concrete-implementation of an IArticle
public class Jeans : IArticle
{
public decimal GetPrice() { return SomeDecimal(); }
}
// WHERE DO I CALL THIS LINE?
ArticleFactory.Register("0929-291", typeof(Jeans));
// Later on, if another group needs to write the class for Snowboards,
// how can they self-register their class, without changing any "Main()"
// or "Page_Init()" function?
Looks like you've already identified the pattern. It's the Factory Method Pattern. Or rather, a somewhat half-baked implementation of one. A slightly better approach would be to first make it an interface:
public interface IArticleFactory
{
IArticle CreateArticle(string sku);
}
Then implement the factory without any Reflection at all:
public class MyArticleFactory
{
private Dictionary<string, Func<IArticle>> instantiators =
new Dictionary<string, Func<Iarticle>>();
public MyArticleFactory()
{
Register("Jeans", () => new Jeans());
Register("Shirt", () => new Shirt());
// etc.
}
public IArticle CreateArticle(string sku)
{
Func<IArticle> instantiator;
if (creators.TryGetValue(sku, out instantiator))
return instantiator();
throw new UnknownSkuException(sku);
}
protected void Register(string sku, Func<IArticle> instantiator)
{
creators.Add(sku, instantiator);
}
}
A few important differences:
Registration isn't public, nor should it be. Registration usually either resides in a configuration file somewhere or is private.
Does not require the IArticle concrete types to have a default parameterless constructor. This can easily register articles with parameterized constructors (as long as it knows what parameters to use).
Throws an exception on duplicate registrations. I don't like the idea of simply returning false; if you try to register the same factory method twice, that ought to be considered a bug.
It's not static. You can replace this factory with a different factory. You can unit-test it.
Of course, an even better approach would just be to use any of the myriad of existing .NET Dependency Injection/Inversion of Control Frameworks, such as Ninject or AutoFac.
I don't know if it has a "name" as such, but it looks like some kind of manual service resolver. The problem I can see (from experience, sadly) is that it is inflexible in real terms, in that:
the registration only has a single configuration
it is hard to unit test
Personally I'd look at an IoC container if I was doing this in a new system; the IoC can handle this relationship, and provide a lot more capabilities for free (lifetimes, enrichment, extra setup, etc), and solve many associated problems.
BTW, it may be easier to:
return Activator.CreateInstance(articleRegistry[sku]);
I think what you're doing here is basically Dependency Injection (or Inversion of Control is what the cool kids call it). Have a look at these links:
Explanation from Wikipedia: http://en.wikipedia.org/wiki/Dependency_Injection
Two DI .Net frameworks:
StructureMap: http://structuremap.sourceforge.net/QuickStart.htm
Castle Windsor: http://www.castleproject.org/container/index.html
It's just a factory pattern that happens to use reflection in its implementation. Rather than using reflection, though, it would probably be more efficient to simply put instances of factory classes directly in the dictionary, though this might require some boilerplate code.

Categories