Which design patterns to use to implement this business logic? - c#

I am trying to determine the best design pattern to use for a business key validation web service. The basic logic flow is coded below. The program will take a parameter and use a field to help determine the path to take in searching multiple systems where this business key can be found. System1 is searched first, if not found, search System2 and System3. The System1 search logic depends on a field in the parameter passed into the original validation method.
I am not exactly sure which design pattern to use. It looks like Command, Chain of Responsibility, Template Method all could be used here.
With my implementations below, I see the following problems:
Each SearchSystemX method needs to know to return null if the business key is not found so that the "control" method will continue to search other systems.
Each SearchSystemX must know how to populate the business object, currently just implemented by a simple primitive string, but that is for example only.
Please let me know your thoughts.
public string Validate (string parms) {
string returnValue = null;
returnValue = SearchSystem1(parms);
if (returnValue == null) {
returnValue = SearchSystem2(parms);
if (returnValue != null) {
returnValue = SearchSystem3(parms);
}
else if (returnValue == null) {
if (parms == "Criteria1") {
returnValue = SearchSystem4(parms);
if (returnValue == null) {
throw new ApplicationException("ID Invalid");
}
}
else if (parms == "Criteria2") {
throw new ApplicationException("ID Invalid");
}
}
}
return returnValue;
private string SearchSystem1 (string parms) {
string returnValue = null;
if (parms == "Criteria1") {
returnValue = SearchSystem1UsingColumn1(parms);
}
else if (parms == "Criteria2") {
returnValue = SearchSystem1UsingColumn2(parms);
if (returnValue == null) {
returnValue = SearchSystem1UsingColumn4(parms);
}
}
if (returnValue != null) {
returnValue = FetchXYCoordinate(parms);
}
return returnValue;
}
Thanks!

Chain of responsability
Each processing object contains a set of logic that describes the types of command objects that it can handle, and how to pass off those that it cannot to the next processing object in the chain
So you define and abstract SearchSystem ( or SystemSearch ) and add subclasses like this:
class SearchSystem
{
//link to the next in the chain
SearchSystem next;
// Basic search, If cannot handle forward to the next.
public Result search( Criteria c )
{
Result r = doSearch( c );
if( r != null )
{
return r;
}
return next.search( c );
}
// subclass specific system search
abstract Result doSearch( Criteria c );
}
class SearchSystemOne: SearchSystem
{
Result doSearch( Criteria c )
{
// do some system 1 speficif stuff
// and return either and instance or null
}
}
class SearchSystemTwo: SearchSystem
{
Result doSearch( Criteria c )
{
// do some system 2 speficif stuff
// and return either and instance or null
}
}
.... etc etc.
// End of the chain
class SearchSystemOver: SearchSystem
{
public Result search( Criteria c )
{
throw new ApplicationException("Criteria not foud", c );
}
Result doSearch( Criteria c )
{
// didn't we throw exception already?
}
}
Instantiate
SearchSystem one = new SearchSystemOne();
SearchSystem two = new SearchSystemTwo();
SearchSystem three = new SearchSystemThree();
SearchSystem four = new SearchSystemFour();
SearchSystem over = new SearchSystemOver();
And build the chain
one.next = two;
two.next = three;
three.next = four;
four.next = over;
And finally search it.
SearchSystem searcher = one;
searcher.search( Criteria.addName("Oscar").addLastName("Reyes"));

Possibly the Strategy Pattern.
It allows you to abstract away the algorithms you're using to perform the logic, encapsulate them in their own objects, and then use them interchangeably throughout your application (allow the caller to define which algorithm to use).

I'd probably use the strategy pattern here by defining an interface for the search system(s):
public interface ISearchStrategy
{
string Search(string criteria);
}
and then passing them to the validate method (although the validation class could get them from somewhere else).
public string Validate(string parms, IEnumerable<ISearchStrategy> searchStrategies)
{
string returnValue = null;
foreach(var strategy in searchStrategies)
{
if(returnValue == null)
{
returnValue = strategy.Search(parms);
}
}
if(returnValue == null) throw new ApplicationException("ID invalid");
return returnValue;
}

Without knowing more about your domain, I can only suggest minor tweaks. First would be to use guard clauses.
Also you mention how the SearchSystems need to know how to build a business object. I would make sure the SearchSystems can be treated polymorphically (that way you have a path to refactoring out a strategy or some kind of dependency injection). Also I would favor a SystemSearcher over a family of SearchSystem methods. Then I would inject into the SearchSystems a business object factory. I would also design the behavior with TryXXX semantics.
public interface ISearchSystem
{
bool TryGet(string parms, out string businessObject);
}
public class System1Searcher : ISearchSystem
{
public System1Searcher(BusinessObjectFactory factory) { _factory = factory; }
private field BusinessObjectFactory _factory;
public bool TryGet(string parms, out string businessObject)
{
// do internal logic
return _factory.Create(string stuff);
}
}
public class Service
{
// is "Validate" the correct metaphor for this logic?
public string Validate(string parms)
{
string returnValue = null;
if (new System1Searcher().TryGet(parms, out returnValue)
return returnValue;
if (new System2Searcher().TryGet(parms, out returnValue)
return returnValue;
if (new System3Searcher().TryGet(parms, out returnValue)
return returnValue;
if (new System4Searcher().TryGet(parms, out returnValue)
return returnValue;
// this message should be written in terms of the logic of this method
// such as "Parameters invalid"
throw new ApplicationException("ID Invalid");
}
}

Related

Should I throw an exception or return false?

I'm developing a simple service locator in C# using TDD.
At the moment, I've created a TryAddService method that looks like this:
public bool TryAddService(Type type, object service)
{
if (service == null)
{
return false;
}
if (this.services.ContainsKey(type))
{
return false;
}
if (!type.IsAssignableFrom(service.GetType()))
{
return false;
}
this.services.Add(type, service);
return true;
}
My question is, should I be returning false in all these cases? Or should I throw an exception?
My customers in this scenario would be other developers.
As informally agreed, whenever you use TryXXXX pattern, your method must be always successful, but return actual success result as boolean. If you'd like to throw and Exception, then just remove the "try" word from your method name.
On the top, if you follow the TryXXXX pattern, I recommend you to add a try-catch block, to ensure your method really always succeeds:
public bool TryAddService(Type type, object service)
{
if (service == null)
{
return false;
}
if (this.services.ContainsKey(type))
{
return false;
}
if (!type.IsAssignableFrom(service.GetType()))
{
return false;
}
try
{
this.services.Add(type, service);
}
catch
{
return false;
}
return true;
}
I use this scenario :
I have a class that all services return this class named (MyReturn for example)
public sealed class MyReturn<TEntity> : IDisposable
{
public string Message { get; set; }
public TEntity Entity { get; set; }
public string SysException { get; set; }
// and etc...
public void Dispose() {}
}
Now your service:
public MyReturn <bool> TryAddService(Type type, object service)
{
if (service == null)
return new MyReturn <bool> {Message = "Your messgage"};
//and etc...
return new MyReturn <bool>();
}
In your form u check Message , if null or empty, you have no error ....
You can customize it...
My customers in this scenario would be other developers.
Are you expecting consumers of your class will register types conditionally?
if (TryAddService(typeof(IService), new Service1()))
{
// Added successfully - what to do next
}
else
{
// What here? Try another service?
}
Or developers will just register implementation they need and rely on the fact that TryAddService will throw an exception during application startup.
TryAddService(typeof(IService), new Service1());
As developer I want to receive quickest feedback as possible if I did something wrong. Throwing exception during application startup (where usually service registration is done) will be quickest possible feedback. Unless you will use generics with constraints, which will provide feedback early during compile time.
If developers don't have logic for failed registration, then return nothing, but throw custom exception with descriptive message
public void TryAddService(Type type, object service)
{
if (service == null)
{
throw new RegisterServiceException($"Can not register null for type '{type.FullName}'");
}
if (this.services.ContainsKey(type))
{
throw new RegisterServiceException($"Service for type '{type.FullName}' already registerd.");
}
if (!type.IsAssignableFrom(service.GetType()))
{
throw new RegisterServiceException($"Type '{type.FullName}' should be assignable from service of type '{service.GetType().FullName}'");
}
this.services.Add(type, service);
}

What is best practice for returning value or error message from method in c#?

I am trying to find the cleanest solution for returning value or error message from function / method in c#.
For now I have tried:
public float ValidateValue (float value)
{
if (value == VALID_VALUE)
{
return value;
}
else
{
throw new ArgumentException("Invalid value", "value");
}
}
This solution seems to be good enough but in Clean Code Cheap Sheet I have found:
Using Exceptions for Control Flow – Don't do this
Using exceptions for control flow:
has bad performance, is hard to understand and results in very hard
handling of real exceptional cases.
What will you do in the case of invalid input?
If you are writing code at the UI level that is taking the input from the user then it makes most sense to do something like:
private bool IsValid(float value)
{
return value == VALID_VALUE; // replace with real check.
}
Then in the calling code you would have:
public void ReactToInput()
{
float value = HoweverYouGetTheFloatFromTheUser();
if(!IsValid)
{
//Code to display error message.
}
else
{
//Code to do something useful.
//
//Code to display result.
}
}
Because your job at this level is "take what the user gave me, return what they want as best I can" and at this level its best to have the possibility of the user doing something incorrect front and centre.
If you are writing code for other code to make use of, then it makes most sense to do something like:
private void CheckValid(float valid)
{
if(value != VALID_VALUE) // replace with real check.
throw new ArgumentException();
}
Then in the calling code you would have:
public float DoWork(float value)
{
CheckValid(value)
//Code to do something useful.
//
//Code to return result.
}
Here your job is to do what the method's task is cleanly and return a meaninful result (or void if there isn't one). If you can't do that job, because the input you were given is nonsense (or for any other reason) then you need to stop as soon as you can and deal with that problem. You could do this by returning an error/success code every time and having calling code checking it every time, but while this approach does indeed have some advantages, exceptions let us:
Write with a focus on the correct behaviour.
Pass up exceptions.
For an example of 1, compare:
private bool WithExceptions()
{
return A() > B() && C() > D();
}
private bool WithExplicitChecks(out bool result)
{
result = false;
int a;
int b;
if(!A(out a))
return false;
if(!B(out b))
return false;
if(a <= b)
return true;
int c;
int d;
if(!C(out c))
return false;
if(!D(out d))
return false;
result = c > d;
return true;
}
For an example of 2, consider:
private void A()
{
if(_someField == null)
throw new InvalidOperationException("field not ready");
_someField.DoSomething();
}
private void B()
{
A();
}
private void C()
{
B();
}
private string D()
{
try
{
C();
}
catch(InvalidOperationException)
{
Console.Error.WriteLine("Was not ready");
}
}
Obviously a real case would have B() and C() do more, but we can see here that only A() has to worry about raising exceptions and only D() about dealing with them, B() and C() can both just concentrate on the main concern.*
The two approaches can be mixed. Consider:
private static string CheckValid(string path)
{
if(path.Length == 0)
return "You cannot enter an empty file path";
switch(path[path.Length - 1])
{
case '\\':
case '/':
return "You cannot enter a directory path";
}
return null;
}
public static void Main(string[] args)
{
Console.WriteLine("Enter a file path");
var path = Console.ReadLine().Trim();
var validationError = CheckValid(path);
if(validationError != null)
Console.Error.WriteLine(validationError);
else
{
try
{
using(var reader = new StreamReader(path))
Console.WriteLine(reader.ReadToEnd());
}
catch(FileNotFoundException)
{
Console.Error.WriteLine("File not found");
}
catch(UnauthorizedAccessException)
{
Console.Error.WriteLine("Access denied");
}
catch(IOException ioe)
{
Console.Error.WriteLine(string.Format("I/O Exception: {0}", ioe.Message));
}
}
Console.Read();
}
This simple program takes a file path from the user, and opens the relevant file and outputs the contents as text. It takes both approaches to error-handling.
Because we can easily check for invalid input that is empty, or which ends with / or \, that is done with simple control-flow and we present an error message instead of doing something.
Other issues we can only know about by trying to open the file and failing, so in those cases we handle the exceptions. I combine both explicit checks for two types of problem along with one for a general class of problems, and act accordingly.
There is a third type of exception handling here; if an exception happens that I don't expect at all, the program fails with a exception message being dumped for debugging purposes. This is the case anywhere you don't catch all exceptions, but a very useful one; because I don't have a blanket catch or catch(Exception) I don't confuse exceptions I'm expecting to deal with (go me for handling them!) with exceptions that are there because I made a mistake in not realising they could happen (boo me! now I have to fix it).
This is a simple program that takes a file path from the user, and outputs the contents of the file. Note that it combines both approaches:
*Do though always consider that something started in a method may not be finished if an exception busts through it.
If you want to validate some input value, I would expect a bool to be returned indicating 'valid' or 'invalid', or no return value and an exception thrown when the value is invalid.
So I would suggest to use this:
public bool ValidateValue(float value)
{
return value == VALID_VALUE;
}
Or this:
public void ValidateValue(float value)
{
if (value != VALID_VALUE)
{
throw new ArgumentException("Invalid value", "value");
}
}
So throwing an exception is not a problem, especially when there are multiple reasons to reject, and you want to distinguish the various reasons. Otherwise, just use a bool, like int.TryParse does for example.
A tuple may be useful to solve that issue:
public Tuple<float,string> ValidateValue (float value)
if (value == VALID_VALUE)
{
return new Tuple<bool, string>(value,string.Empty);
}
else
{
return new Tuple<bool, string>(false,"Invalid value");
}
When calling a function, check if the error string is empty first:
var validation = ValidateValue(myFloatValue);
if (validation.Item2 != string.Empty)
{
// report error
}
else
{
// No error core here validation.Item1 is your result
}
One idea could be to have some generic model. You may have some model roughly like:
public class MyReturnModel
{
public bool Success { get; set; }
public string ErrorOrSuccessMessage { get; set; }
public dynamic AnyModelToReturn { get; set; }
}
Now let's apply this on your provided case:
public MyReturnModel ValidateValue(float value)
{
//function logic here
bool result = value == VALID_VALUE;
string msg = result ? "valud is valid" : "value is invalid";
return new MyReturnModel { Success = result, ErrorOrSuccessMessage = msg }
}

Strange control flow

I'm working on a framework in C# that will depend on pluggable components implemented as classes inheriting a base class. In order to make the components as simple as possible, I am working on some weird control flow.
The base class includes a static method RunStep(parameter). This method is called a number of times by the inheriting class, and each time it is called a condition is checked. If this condition happens to be false, I want the calling method to stop and return. A simplified working version of the code would be:
Base class:
class MyBase
{
private static object RunStep(string parameter)
{
if(SomeFunction(parameter))
return SomeOtherFunction(parameter);
else
return null;
}
}
Inheriting class:
class MyInheritor
{
public void Run()
{
object result = RunStep("mystring1");
if(null != result)
{
//perform some logic on result
result = RunStep("mystring2");
if(null != result){
//perform some different logic on result
RunStep("mystring3");
}
}
}
}
What I am wondering is whether it is possible to do something in the base class so that I can simplify the inheriting class to this:
class MyInheritor2
{
public void Run()
{
object result = RunStep("mystring1");
//perform some logic on result
result = RunStep("mystring2");
//perform some different logic on result
result = RunStep("mystring3");
}
}
}
I would put the parameters in a list and loop over them, but there is logic that needs to happen after each call to the RunStep method, and the logic is different each time. This takes a loop off the table. Also note that the logic between the RunStep calls accesses properties on result, so it crashes without the null checks.
It may seem like a trivial thing, but there may be thousands of these Inheriting classes and simplifying them is a big deal.
Let the base class to control the execution flow:
class Base
{
private readonly List<Tuple<string, Action>> steps = new List<Tuple<string, Action>>();
protected void RegisterStep(string parameter, Action someLogic)
{
steps.Add(Tuple.Create(parameter, someLogic));
}
protected void Run()
{
foreach (var step in steps)
{
var result = RunStep(step.Item1);
if (result == null)
{
break;
}
// perform some logic
step.Item2();
}
}
private object RunStep(string parameter)
{
// some implementation
return null;
}
}
class Derived : Base
{
public Derived()
{
RegisterStep("1", () => { });
RegisterStep("2", () => { });
RegisterStep("3", () => { });
// etc
}
}
There's no way to make a function call exit the calling function except for throwing an Exception, which you shouldn't do.
What you can do to make your code cleaner is to invert the cases.
object result = RunStep("mystring1");
if (result == null) return;
result = RunStep("mystring2");
if (result == null) return;
result = RunStep("mystring3");
if (result == null) return;

How to evaluate why a method returns what it returns

What strategy do you use to give to the user the reason why a certain method "failed"
Exemple:
public List<Balance> GetBalanceFinale(Periode periode)
{
if (periode == null || periode.DateStart >= DateTime.Now || isBalanceFinished(periode.PeriodeID))
return null;
//My other code...
}
I want to tell the user which of the steps went wrong. I don't want to use a messagebox in such class. I can't return the description of the failure because I already return something.
What do you usally do? Any advice? Thanks!
You can throw an exception with a descriptive message.
Consider throwing exceptions instead of returning null.
In this case you will be able to provide descriptive information with each exception, which later can be properly handled and presented to the caller.
I am assuming you don't want to throw an exception otherwise you would've already done that. Something like an alert / warning without stopping execution of the program. In that case, you can still use an exception, just don't throw it, instead pass it as an out parameter or put it somewhere where the user can access it if desired. If that seems over the top then just use a message instead.
Also framing it as a 'Try' method might be a good idea. It makes it very clear that the method is prone to failure under certain conditions.
These are all different options:
public bool TryGetBalanceFinale(Periode periode, out List<Balance> list, out string msg)
{
// return false if anything is wrong, and have an out parameter for the result & msg
}
public bool TryGetBalanceFinale(Periode periode, out List<Balance> list, out Exception ex)
{
// return false if anything is wrong, and have an out parameter for the exception
}
These first two above are my two preferred approaches. The following are possibilities as well, however they are somewhat non-standard:
public Tuple<string, bool> TryGetBalanceFinale(Periode periode, out List<Balance> list)
{
// return false if anything is wrong, and include message in the returned Tuple
}
// an anonymous type approach
public object TryGetBalanceFinale(Periode periode, out List<Balance> list)
{
return new {
Successful = false,
Message = // reason why here
};
}
// a functional approach
public List<Balance> list GetBalanceFinale(Periode periode, Action<String> messageAct)
{
// when something is wrong, do:
messageAct("Something went wrong...");
}
I think the 'Try' strategy makes the most sense when you consider how it will be used:
string message;
List<Balance> result;
if (!TryGetBalanceFinale(periode, out result, out message))
{
// examine the msg because you know the method failed
Console.WriteLine(message);
}
else
{
// you know the method succeeded, so use the result
Console.WriteLine("The result is: " + result.ToString());
}
I like to wrap my results in a ResultState<T> object (usually for Json or Xml serialization). Might be helpful if you are building a framework for someone else to consume as each result can be handled the same way by the consumer.
public class ResultState<T>
{
public T ResultValue { get; set; }
public Exception ExceptionThrown { get; set; }
public bool IsValid { get; set; }
public string FriendlySummary { get; set; }
// whatever else properties you think are needed
}
public interface IResultState<T>
{
public T ResultValue { get; }
public Exception ExceptionThrown { get; }
public bool IsValid { get; }
public string FriendlySummary { get; }
// whatever else properties you think are needed
}
public IResultState<List<Balance>> GetBalanceFinale(Periode periode)
{
ResultState<List<Balance>> result = new ResultState<List<Balance>>();
try
{
if (periode == null
|| periode.DateStart >= DateTime.Now
|| isBalanceFinished(periode.PeriodeID))
{
result.IsValid = false;
result.FriendlySummary = "Periode is in an invalid state.";
}
//My other code...
result.ResultValue = new List<Balance>();
result.ResultValue.Add(...);
}
catch(Exception ex)
{
result.IsValid = false;
result.Exception = ex;
// Ambigious is bad.. so for bad example..
result.FriendlySummary = "An unknown exception happened.";
}
}
An alternative that has worked for me in the past is the Notification pattern.
This is a way of getting information out of your domain layer and up into the presentation. For example, create something like this:
public class Notification
{
public List<Message> Messages;
public bool HasMessages;
// etc
}
and use an instance of it as a property on your domain.
You can then do something like this:
myDomain.GetBalanceFinale(periode);
if(myDomain.Notification.HasMessages)
// get the messages and do something with them
You need to re-factor your code first. before calling GetBalanceFinale you can validate it and show proper message if validation failed. if validation pass you can call GetBalanceFinale method.
Sometimes you may not able to do all the validation before calling the method. in that case you can throw exception with proper message or use out parameters.
If I need to return a value and a message, I just use an out parameter.
public List<Balance> GetBalanceFinale(Periode periode, out string errorMessage)
{
if (periode == null)
{
errorMessage = "Periode is null";
return null;
}
// Other checks
}
Then just call it like
string errorMessage;
var value = GetBalanceFinale(periode, out errorMessage);
if(value == null)
// Do whatever with errorMessage
You can decompose your logic into 3 separate tests, and then define an 'out' argument to return the "reason"
public List<Balance> GetBalanceFinale(Periode periode, out string reasonFailed)
{
reasonFailed = false;
if (periode == null)
{
reasonFailed = "preiod is null";
return null;
}
// etc.....
//periode.DateStart >= DateTime.Now || isBalanceFinished(periode.PeriodeID))
//My other code...
}

C# Refactoring: How would you refactor 2 methods that do the same except that they use a different Interface

Having 2 different interfaces is a must.
How would you refactor this?
Should I refactor this code at all?
private void CreateInstanceForProviderA()
{
a = FactorySingleton.Instance.CreateInstanceA("A");
if (a == null)
{
ShowProviderNotInstanciatedMessage();
return;
}
a.Owner = Handle.ToInt32();
lbl_Text.Text = a.Version();
}
private void CreateInstanceForProviderB()
{
b = FactorySingleton.Instance.CreateInstanceB("B");
if (b == null)
{
ShowProviderNotInstanciatedMessage();
return;
}
b.Owner = Handle.ToInt32();
lbl_Text.Text = b.Version();
}
If there would be a common interface, I could write:
private void CreateInstanceForProvider(string provider)
{
p = FactorySingleton.Instance.CreateInstanceB(provider);
// p is shared over the whole class
if (p == null)
{
ShowProviderNotInstanciatedMessage();
return;
}
var tmpProvider = p as ICommonProvider;
tmpProvider .Owner = Handle.ToInt32();
lbl_Text.Text = tmpProvider .Version();
}
Well, the first thing to do is to yell at the author of FactorySingleton to fix has damn code so that ClassA and ClassB have a common interface for their common fields.
In the meantime, you pretty much stuck using reflection, which would be ugly and not worth it for just that little bit.
What version of C# are you using?
In C# 4 (Visual Studio 2010) the new dynamic keyword could help share code in this case. I wouldn't use if it this is a performance-critical section of code though, but if this just runs a handful of times then go ahead.
InstanceA and InstanceB ought to implement a common interface.
public interface IA : ICommon {...}
public interface IB : ICommon {...}
public interface ICommon
{
int Owner {get;}
string Version();
}
This way, you still have two different interfaces, but the common aspects of those interfaces are defined in a way that you can do some of the same things with both of them.
Perhaps have a third method that is private, and replace your code with calls to this third method, as so:
private void CreateInstanceForProviderA()
{
return DoSomething();
}
private void CreateInstanceForProviderB()
{
return DoSomething();
}
public interface ICommon
{
int Owner { get; }
string Version();
}
public interface IA : ICommon
public interface IB : ICommon
private void CreateInstanceForProvider(ICommon c)
{
if (c == null)
{
ShowProviderNotInstanciatedMessage();
return;
}
c.Owner = Handle.ToInt32();
lbl_Text.Text = c.Version();
}
It's always painful to fight the type system. Without using dynamic, here goes my attempt.
Given that you have these two distinct interfaces for a and b:
interface IA {
int Owner { set; }
string Version();
}
interface IB {
int Owner { set; }
string Version();
}
You can create a wrapper type like this:
class WrapperAB : IA, IB {
IA a; IB b;
public WrapperAB(object o) {
if (o is IA) a = (IA)o;
else if (o is IB) b = (IB)o;
else throw new Exception();
}
public int Owner {
set {
if (a != null) a.Owner = value;
else b.Owner = value;
}
}
public string Version() {
if (a != null) return a.Version();
else return b.Version();
}
}
And change your methods to this:
private void CreateInstanceForProviderA() {
CreateInstanceForProvider<IA>("A", FactorySingleton.Instance.CreateInstanceA, out a);
}
private void CreateInstanceForProviderB() {
CreateInstanceForProvider<IB>("B", FactorySingleton.Instance.CreateInstanceB, out b);
}
private void CreateInstanceForProvider<TI>(string name, Func<string, TI> factory, out TI instance) {
instance = factory(name);
if (instance == null) {
ShowProviderNotInstanciatedMessage();
return;
}
var w = new WrapperAB(instance);
w.Owner = Handle.ToInt32();
lbl_Text.Text = w.Version();
}
I would leave it as it is, no refactoring necessary...
YET!
If/when ProviderC shows up, then I would refactor. 8 )
It all depends on those method calls (.CreateInstanceA and .CreateInstanceB).
If they're doing the same things in the same way, and the only difference is that string parameter, then yes: refactor the method to CreateInstanceForProvider(string providerCode) and let the user / calling code pass in the proper parameter.
If they do slightly different things, then you may still be able to refactor, and it becomes more of a headache. At that point, you have to determine whether the increased abstraction (and additional ease of adding new Providers) is worth refactoring and having to re-run (and possibly rewrite) whatever tests are necessary.
Remove the duplicate code. In this case, you should be able to remove the middle message block that does the null check and message for a failed instantiation.
private void CreateInstanceForProviderA()
{
a = FactorySingleton.Instance.CreateInstanceA("A");
if (IsNullObject(a))
{
return;
}
a.Owner = Handle.ToInt32();
lbl_Text.Text = a.Version();
}
private void CreateInstanceForProviderB()
{
b = FactorySingleton.Instance.CreateInstanceB("B");
if (IsNullObject(b))
{
return;
}
b.Owner = Handle.ToInt32();
lbl_Text.Text = b.Version();
}
private bool IsNullObject(object obj)
{
if (obj == null)
{
ShowProviderNotInstanciatedMessage();
return true;
}
return false;
}
If you do find a way to provide a common interface or shared virtual methods on these providers, we can refactor more aggressively.
I'd pass an enum in to specify the create instance code to call. After that create a wrapper class containing methods to get/set using reflection as suggested in other answers use reflection. Not sure it's worth it, as you code is probably harder to read than before.
public enum Provider
{
A,
B
}
private void CreateInstanceForProvider(Provider provider)
{
ProviderWrapper provider = null;
switch (provider)
{
case Provider.A:
provider = new ProviderWrapper(FactorySingleton.Instance.CreateInstanceA("A"));
break;
case Provider.B:
provider = new ProviderWrapper(FactorySingleton.Instance.CreateInstanceB("B"));
break;
}
if (provider == null)
{
ShowProviderNotInstanciatedMessage();
return;
}
provider.SetOwner(Handle.ToInt32());
lbl_Text.Text = provider.GetVersion();
}
public class ProviderWrapper
{
private readonly object _original;
public ProviderWrapper(object original)
{
_original = original;
}
public void SetOwner(int value)
{
_original.GetType().GetProperty("Owner").SetValue(_original, value, null);
}
public string GetVersion()
{
return (String)_original.GetType().GetProperty("Owner").GetValue(_original, null);
}
}
EDIT: This does no work because a and b are different types (not sure if that was before or after I gave my answer...)
I'm assuming a and b are fields, not properties.
Abstractly, put the common functionality in a single method called by both of the original methods:
private void CreateInstanceForProviderA()
{
a = CreateInstanceForProvider("A");
}
private void CreateInstanceForProviderB()
{
b = CreateInstanceForProvider("B");
}
private FactorySingleton CreateInstanceForProvider(string which)
{
var instance = FactorySingleton.Instance.CreateInstanceB(which);
if (instance == null)
{
ShowProviderNotInstanciatedMessage();
return;
}
instance.Owner = Handle.ToInt32();
lbl_Text.Text = instance.Version();
return instance;
}

Categories

Resources