Methods specific for customers:
I try to refactore a code, where are a lot of logic for specifi customer:
public void SendDocumentsToCustomer(List<Case> cases)
{
foreach(var case in cases)
{
if(case.CustomerId==123)
{
if(case.Type==1 || case.Type==2)
{
SendDocumentsToCustomer123(case)
}
else if(case.CustomerId==456)
{
if(case.Type==1 || case.Type==3)
{
SendDocumentsToCustomer456(case);
}
}
else if(case.CustomerId==768)
{
if(case.Type==2)
{
SendDocumentsToCustomer456(case);
}
else
{
SendDocumentsToCustomer(case);
}
}
}
The list of specific customer will grow, and the conditions will be modified as well. I will have a generic solution, but maybe code like this with method DoItForClient123 is not a bad solution and I should leave it like that and goint this way introduce methods like CanDocumentsBeSendToClient123 and so on?
I will be very gratefull for some input
To separate logic for each specific customer I would use such code:
abstract class DocumentSender //Base class for all document sending components
{
public abstract bool CanSend(Case #case); // Check if sender can send the document
public abstract void SendDocument(Case #case); // Send the document
}
class DefaultDocumentSender : DocumentSender
{
public override bool CanSend(Case #case)
{
return true; //Can process all requests
}
public override void SendDocument(Case #case)
{
// Do something
}
}
class Customer123DocumentSender : DocumentSender
{
public override bool CanSend(Case #case)
{
return #case.CustomerId == 123; //Specific case
}
public override void SendDocument(Case #case)
{
if(#case.Type==1 || #case.Type==2)
{
// Do something different
}
}
}
//Separate class for getting the correct sender
class CaseSenderFactory
{
readonly List<DocumentSender> _senders = new List<DocumentSender>();
public DocumentSenderFactory()
{
//Initialize the list of senders from the most specific.
_senders.Add(new Customer123DocumentSender());
// Add more specific cases here
_senders.Add(new DefaultDocumentSender()); //Last item should be the default sender
}
public DocumentSender GetDocumentSender(Case #case)
{
//At least one sender needs to satisfy the condition
return _senders.First(x => x.CanSend(#case));
}
}
You then can use the senders like this:
var factory = new DocumentSenderFactory();
foreach(var #case in cases)
{
var sender = factory.GetDocumentSender(#case);
sender.SendDocument(#case);
}
I think it would be a good ideea to make something like this:
The ideea is if the code is really specific to some of the Customers then you could make a class for them. If the code for specific customers somehow related but combined in a diferent way then you should take a loot at DecoratorPattern(mabye it helps)
class Customer
{
public abstract SendDocumentsTo(Customer c);
}
class SpecificCustomerA
{
public overwrite SendDocumentsTo(Customer c)
{
if (c is SpecificCustomerB)
{
//Logic here
}
}
}
class SpecificCustomerB { ... }
Related
I have the following use case for a factory safety system. Currently designing the system as console application.
- A Machine's speed can be increased or decreased using human input - i or d
- when the speed is increased above 50, there is an alarm raised
- There is a safety lock in the machine which can be locked or unlocked again by human input - l or u
- If the speed of the machine is increased by 10 and safety lock is not locked, then there is an alarm raised
I have implemented the system, however, the system is not scallable. Tomorrow if another safety system introduced, then looks like I need to go back to the existing class and modify.
Implementing open close principle looks to be difficult as functionality like speed increase/decrease (ISpeedController) and machine lock/unlock (ISafetyLock) does not share a common interface.
public interface ISpeedController
{
void Increase();
void Decrease();
}
public interface ISafetyLock
{
void Lock();
void UnLock();
}
Moreover, there is an event speed change, which fires whenever speed is changed to raise an alarm. That makes things even more complicated.
Can you help me how the system can be designed so that we can seamlessly add new safety measures in future without impacting the current code?
Thanks.
Well, you just need to go with convention over configuration approach.
For example, you can define a common interface with registration:
using System;
using System.Linq;
public class Program
{
public static void Main()
{
var handlerType = typeof(IHandleKey);
var classes = typeof(Program).Assembly // you can get them however you want
.GetTypes()
.Where(p => handlerType.IsAssignableFrom(p) && p.IsClass)
.Select(t => (IHandleKey)Activator.CreateInstance(t)) // or use IoC to resolve them...
.ToArray();
while(true) {
var key = Console.ReadLine(); // or however you get your input
var handler = classes.FirstOrDefault(x => x.Key == key);
if (handler == null) {
Console.WriteLine("Couldn't find a handler for " + key);
} else {
handler.Handle();
}
}
}
}
public interface IHandleKey
{
String Key { get; }
void Handle();
}
public class Banana : IHandleKey
{
public String Key { get { return "u"; } }
public void Handle()
{
Console.WriteLine("I did banana work");
}
}
This way if you need to develop a new feature, all you need to add is one class that contains information about valid key and the implementation logic.
Likewise, if you don't want to have the instances ready to handle the command, you can split this and have an attribute describing the key on the type, like so:
using System;
using System.Linq;
public class Program
{
public static void Main()
{
var handlerType = typeof(IHandleKey);
var classes = typeof(Program).Assembly
.GetTypes()
.Where(p => handlerType.IsAssignableFrom(p) && p.IsClass && p.GetCustomAttributes(typeof(KeyHandlerAttribute), false).Count() > 0) // note we're checking for attribute here. This can be optimised.
.ToArray();
while(true) {
var key = Console.ReadLine(); // or however you get your input
var concreteType = classes.FirstOrDefault(x => ((KeyHandlerAttribute)(x.GetCustomAttributes(typeof(KeyHandlerAttribute), false).First())).Key == key);
if (concreteType == null) {
Console.WriteLine("Couldn't find a handler for " + key);
} else {
var handler = (IHandleKey)Activator.CreateInstance(concreteType); // or use IoC to resolve them...
handler.Handle();
}
}
}
}
public interface IHandleKey
{
void Handle();
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class KeyHandlerAttribute: Attribute
{
public String Key { get; set; }
}
[KeyHandler(Key = "u")]
public class Banana : IHandleKey
{
public void Handle()
{
Console.WriteLine("I did banana work");
}
}
Update Here's the updated program listing using the second variant and implementing shared state and event-based communication.
To be honest, I find this rather trivial, so feel free to ask any questions as i'm not sure what might appear more confusing and what not...
using System;
using System.Linq;
using System.Collections.Generic;
namespace Whatever
{
public class Program
{
public static void Main()
{
// This part belongs to IoC as a Singleton
var state = new State();
// This part belongs to IoC as scoped services
var handlerType = typeof(IHandleKey);
var dict = new Dictionary<String, Object>();
foreach (var type in typeof(Program).Assembly
.GetTypes()
.Where(p => handlerType.IsAssignableFrom(p) && p.IsClass))
{
var attributes = type.GetCustomAttributes(typeof(KeyHandlerAttribute), false);
if (attributes.Any())
{
var attribute = (KeyHandlerAttribute)attributes.First();
var handlr = (IHandleKey)Activator.CreateInstance(type);
handlr.RegisterEvent(state);
dict.Add(attribute.Key, handlr);
}
}
// Main routine here
while (true)
{
var key = Console.ReadLine(); // or however you get your input
var handler = dict.ContainsKey(key) ? (IHandleKey)dict[key] : null;
if (handler == null)
{
Console.WriteLine("Couldn't find a handler for " + key);
}
else
{
handler.Handle();
}
}
}
}
// This class allows us to share state.
public class State : ISharedState
{
// As required by the question, this is an event.
public event EventHandler StateChanged;
public void RaiseStateChange(object sender)
{
this.StateChanged.Invoke(sender, new EventArgs());
}
}
// This makes our Handlers unit testable.
public interface ISharedState
{
event EventHandler StateChanged;
void RaiseStateChange(object sender);
}
// Familiar interface -> note how we have a 'register event' method now.
// We could instead just use a constructor on the HandlerBase. This is really dealer's choice now.
public interface IHandleKey
{
void Handle();
void RegisterEvent(ISharedState state);
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class KeyHandlerAttribute : Attribute
{
public String Key { get; set; }
}
// To avoid boilerplate in our handlers for registering/unregistering events we have a base handler class now.
public abstract class HandlerBase: IHandleKey
{
protected ISharedState _state;
public abstract void Handle();
public void RegisterEvent(ISharedState state)
{
this._state = state;
this._state.StateChanged += OnStateChanged;
}
public abstract void OnStateChanged(object sender, EventArgs e);
~HandlerBase()
{
this._state.StateChanged -= OnStateChanged;
}
}
// Actual handlers...
[KeyHandler(Key = "u")]
public class Banana : HandlerBase
{
public override void Handle()
{
Console.WriteLine("I did banana work");
this._state.RaiseStateChange(this);
}
public override void OnStateChanged(object sender, EventArgs e)
{
if (sender != this) // optional, in case we don't want to do this for self-raised changes
{
Console.WriteLine("State changed inside Banana handler");
}
}
}
[KeyHandler(Key = "c")]
public class Cheese : HandlerBase
{
public override void Handle()
{
Console.WriteLine("I did cheese work");
this._state.RaiseStateChange(this);
}
public override void OnStateChanged(object sender, EventArgs e)
{
if (sender != this) // optional, in case we don't want to do this for self-raised changes
{
Console.WriteLine("State changed inside cheese handler");
}
}
}
}
have created a ProdIgnoreAttribute which extends from IgnoreAttribute. And I have assigned this attribute to certain tests which I want to run in DEV/QA but not in PROD.
ApplyToTest(Test test) method is not being called in this case. How to resolve this?
public class ProdIgnoreAttribute : IgnoreAttribute
{
private string IgnoreReason { get; }
public ProdIgnoreAttribute(string reason) : base(reason)
{
IgnoreReason = reason;
}
public new void ApplyToTest(Test test)
{
if (test.RunState == RunState.NotRunnable)
return;
if (StaticInfoHelper.VrCurrentEnv == (int)RunEnv.PROD)
{
test.RunState = RunState.Ignored;
test.Properties.Set("_SKIPREASON", (object)IgnoreReason);
}
else
{
base.ApplyToTest(test);
}
}
}
How about extending Attribute rather than IgnoreAttribute?
public class ProdIgnoreAttribute : Attribute, ITestAction
{
public void BeforeTest(TestDetails details)
{
bool ignore = StaticInfoHelper.VrCurrentEnv == (int)RunEnv.PROD;
if (ignore)
Assert.Ignore("Test ignored during Prod runs");
}
//stub out rest of interface
}
If you want a custom ignore message you could make a ProdIgnoreAttribute constructor that accepts a string. You'd then use the attribute on tests like: [ProdIgnore("ignored because xyz")]
I have a block of code similar to this one:
public bool DoMyThings(EnumRootAction root, EnumChildAction child){
switch(root){
case EnumRootAction.Type1:
switch(child){
case EnumChildAction.Ac1:
// DO something
break;
case EnumChildAction.Ac2:
// DO something
break;
default: // child is not child of type root
return false;
}
break;
case EnumRootAction.Type2:
switch(child){
case EnumChildAction.Ac1:
// DO something
break;
case EnumChildAction.Ac3:
// DO something
break;
default: // child is not child of type root
return false;
}
break;
... // etc...
default:
return false;
}
return true;
}
However, I do believe that it is a bad looking piece of code... :) ... the "consumer" of this service does not know the correct combination of root/child that are valid and might pass a wrong one.
I thought of "spiting" it into several methods, something like: DoMyThingsForRootType1(EnumChildActionForType1 child) but in a long term term this is not so easy to change in my case. I explain why: if the signature of my service changes continuously I need to update the service protocol of all my real time clients.... update source code and deploy it again.... and at the present day the client can simply make these changes manually by changing some app.settings values.
At this point I am providing a single sheet of paper with the correct combinations but this is crap as well in my eyes.
Perhaps I am just looking at this from one perspective and somehow I am not being able to expand my horizons... this is why I would like to ear some feedback from you guys/gals...
Is there a better design pattern for this?
At least some kind of way to inform the service's client of the valid combinations....
Thanks.
If you can use interfaces or base classes instead of enums you can harness the power of object-orientation to determine how the combinations are to be evaluated. This allows you to group the root/child action functionality in an easy-to-understand and easy-to-maintain way. It is somewhat long-winded however:
public interface IChildAction
{
}
public class ChildAction1 : IChildAction
{
}
public class ChildAction2 : IChildAction
{
}
public class ChildAction3 : IChildAction
{
}
public abstract class BaseRootAction
{
public virtual bool Process(ChildAction1 action)
{
return false;
}
public virtual bool Process(ChildAction2 action)
{
return false;
}
public virtual bool Process(ChildAction3 action)
{
return false;
}
}
public class RootAction1 : BaseRootAction
{
public override bool Process(ChildAction1 action)
{
Console.WriteLine("Root action 1, Child action 1");
return true;
}
public override bool Process(ChildAction2 action)
{
Console.WriteLine("Root action 1, Child action 2");
return true;
}
}
public class RootAction2 : BaseRootAction
{
public override bool Process(ChildAction1 action)
{
Console.WriteLine("Root action 2, Child action 1");
return true;
}
public override bool Process(ChildAction3 action)
{
Console.WriteLine("Root action 2, Child action 3");
return true;
}
}
public class RootAction3 : BaseRootAction
{
public override bool Process(ChildAction2 action)
{
Console.WriteLine("Root action 3, Child action 2");
return true;
}
}
public bool DoMyThings(BaseRootAction rootAction, IChildAction childAction)
{
return rootAction.Process((dynamic)childAction);
}
I also include my test method for completeness:
private void Test()
{
List<BaseRootAction> rootActions = new List<BaseRootAction>() { new RootAction1(), new RootAction2(), new RootAction3()};
List<IChildAction> childActions = new List<IChildAction>() { new ChildAction1(), new ChildAction2(), new ChildAction3()};
foreach (BaseRootAction rootAction in rootActions)
{
foreach (IChildAction childAction in childActions)
{
bool result = DoMyThings(rootAction, childAction);
Console.WriteLine(String.Format("Processed '{0}' / '{1}': Result = {2}", rootAction.GetType().Name, childAction.GetType().Name, result));
}
}
}
If you need the Enums the action classes can be derived from them, but the solution becomes more bloated.
The first step could be that in every case you call a method.
case EnumRootAction.Type1:
switch(child){
case EnumChildAction.Ac1:
Type1_Ac1();
break;
The second step could be that you use a matrix of delegates instead of the function.
delegate bool DoMyThingsAction();
DoMyThingsAction[,] doMyThings;
public void InitializeDoMyThings()
{
doMyThings = new DoMyThingsAction[10, 10]; // number of actions and type
doMyThings[0, 0] = Type1_Ac1;
// and so on
}
To call it you can use
doMyThings[(int)root, (int)child];
If you don't like the cast to int in doMyThings call you can use a different structure and override the indexer.
Another option is to use reflection to get the method (I don't like it)
public bool DoMyThings(EnumRootAction root, EnumChildAction child){
return GetType().GetMethod(string.Format("{0}_{1}", root, child).Invoke(this);
}
EDIT
Looking at your program you should return false if there is not the method.
In case of matrix you can check if there is the function or not before call it, in case of reflection you can check if GetMethod returns null.
You could apply the Visitor Pattern. Your RootActions are Visitors and ChildActions are Elements. Here is the code, note how powerful of overloading in OOP:
List<RootAction_Visitor> visitors = new List<>();
visitors[EnumRootAction.Type1] = new RootAction1_Visitor();
visitors[EnumRootAction.Type2] = new RootAction2_Visitor();
List<ChildAction_Element> elements = new List<>();
elements[EnumChildAction.Ac1] = new ChildAction1_Element();
elements[EnumChildAction.Ac2] = new ChildAction2_Element();
elements[EnumChildAction.Ac3] = new ChildAction3_Element();
public void doMyThing(EnumRootAction root, EnumChildAction child) {
elements[child].accept( visitors[root] );
}
//=======================================================================
// Visitors
abstract class RootAction_Visitor {
public void visit(ChildAction1_Element childAction) { /*.. reject by default ...*/ }
public void visit(ChildAction2_Element childAction) { /*.. reject by default ...*/ }
public void visit(ChildAction3_Element childAction) { /*.. reject by default ...*/ }
}
class RootAction1_Visitor : RootAction_Visitor {
public override void visit(ChildAction1_Element childAction) {
// ... do something
}
public override void visit(ChildAction2_Element childAction) {
// ... do something
}
}
class RootAction2_Visitor : RootAction_Visitor {
public override void visit(ChildAction1_Element childAction1) {
// ... do something
}
public override void visit(ChildAction3_Element childAction3) {
// ... do something
}
}
//=======================================================================
// Elements
interface ChildAction_Element {
void accept(RootAction_Visitor visitor);
}
class ChildAction1_Element : ChildAction_Element {
public void accept(RootAction_Visitor visitor) { visitor.visit(this); }
}
class ChildAction2_Element : ChildAction_Element {
public void accept(RootAction_Visitor visitor) { visitor.visit(this); }
}
class ChildAction3_Element : ChildAction_Element {
public void accept(RootAction_Visitor visitor) { visitor.visit(this); }
}
Because your client and server communicate through network (inter-process communication). There's no way to ensure data sent by client is valid, we need to validate the data and reject wrong request. However, you should provide another service so client can know which combinations of actions are correct before requesting to your main service.
P/S: choosing between RootAction and ChildAction, which is Visitor, which is Element depends on how stable are they. If RootActions are unstable, i.e. new kinds of RootAction will come, then they should be Visitors.
I'm currently working on a simple Client/Server model which sends packets within TCP packets (like HTTP) and the commands are basically ints (the first 4 bytes of each packet) and I'd like to work out an efficient way of how to process these commands.
The most obvious answer would be to write thousands of if's or do one huge switch statement with thousand cases, but isn't there any better way?
I'd like to create an array of events and then just raise the corresponding index so each int refers to one event which is named (such as MessageReceived). I'd also save time I think, so how could I work this out?
EDIT: The Server handles multiple connections, one for each client that is connected, so creating seperate connections for each command(s) isn't that useful in my case.
Sound like a job for enums!
enum YourEnum
{
DoThis,
DoThat
}
YourEnum foo = (YourEnum)yourInt;
Visual studio can even create your entire switch statement using the built in snippets and your code becomes very readable.
switch(foo)
becomes
switch(foo)
{
case YourEnum.DoThis:
break;
case YourEnum.DoThat:
break;
default:
break;
}
Update 1
This is a little scary from a maintainability point of view, but if you created a class like:
public class ActionProcessor
{
public void Process(int yourInt)
{
var methods = this.GetType().GetMethods();
if (methods.Length > yourInt)
{
methods[yourInt].Invoke(this, null);
}
}
public DoThis()
{
}
public DoThat()
{
}
or a little nicer but harder to maintain:
[AttributeUsageAttribute(AttributeTargets.Method,
Inherited = false,
AllowMultiple = false)]
public sealed class AutoActionAttribute : Attribute
{
public AutoActionAttibute(int methodID)
{
this.MethodID = methodID;
}
public int MethodID { get; set; }
}
public class ActionProcessor
{
public void Process(int yourInt)
{
var method = this.GetType().GetMethods()
.Where(x => x.GetCustomAttribute(typeof(AutoActionAttribute),
false) != null
&& x.GetCustomAttribute(typeof(AutoActionAttribute),
false).MethodID == yourInt)
.FirstOrDefault();
if (method != null)
{
method.Invoke(this, null);
}
}
[AutoAction(1)]
public DoThis()
{
}
[AutoAction(2)]
public DoThat()
{
}
}
Update 2 (Coding what I think Josh C. was talking about)
// Handles all incoming requests.
public class GenericProcessor
{
public delegate void ActionEventHandler(object sender, ActionEventArgs e);
public event ActionEventHandler ActionEvent;
public ProcessAction(int actionValue)
{
if (this.ActionEvent != null)
{
this.ActionEvent(this, new ActionEventArgs(actionValue));
}
}
}
// Definition of values for request
// Extend as needed
public class ActionEventArgs : EventArgs
{
public ActionEventArgs(int actionValue)
{
this.ActionValue = actionValue;
}
public virtual int ActionValue { get; private set; }
}
This you create the SomeActionProcessor that is responsible for some value:
// Handles a specific (or multiple) requests
public class SomeActionProcessor
{
public void HandleActionEvent(object sender, ActionEventArgs e)
{
if (e.ActionValue == 1)
{
this.HandleAction();
}
}
private void HandleAction()
{
}
}
Then create the classes and wire them up:
GenericProcessor gp = new GenericProcessor();
SomeActionProcessor sap = new SomeActionProcessor();
gp.ActionEvent += sap.HandleActionEvent;
The fire away and sending the generic processor requests:
gp.ProcessAction(1);
You could possibly implement a publisher-subscriber model. Instead of having one listener, you would have many. Each listener would listen for at least one command. Then you can split your switch across multiple classes.
Hi I am new to design pattern and apologize if this question is creating any confusion although i am trying to describe the issue in best possible way.I have implemented sample abstract factory pattern in winforms. Front end contains two check boxes to create the objects. Note: If both the check box are checked, both the objects are created.
I am using objs.CreateProduct(Maxima,Ultima) method and passing the boolean values to create the objects. Here I am passing the values of both the properts whether I want to create object for ultima or maxima. Can you suggest any other better way to achieve this ? I don't want to pass the properties for maxima and ultima if I am creating the objects.
public partial class Form1 : Form
{
public bool Maxima
{
get;
set;
}
public bool Ultima
{
get;
set;
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Factory[] obj = new Factory[2];
obj[0] = new B();
obj[1] = new C();
foreach (Factory objs in obj)
{
iProduct prod = objs.CreateProduct(Maxima,Ultima);
if (prod != null)
{
prod.GetDetails();
}
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked)
Maxima = true;
else
Maxima = false;
if (checkBox1.Checked)
Ultima = true;
else
Ultima = false;
}
}
abstract class Factory
{
public abstract iProduct CreateProduct(bool maxima, bool ultima);
}
class B : Factory
{
public override iProduct CreateProduct(bool maxima,bool ultima)
{
if (ultima)
{
return new NissanUltima();
}
else return null;
}
}
class C : Factory
{
public override iProduct CreateProduct(bool maxima,bool ultima)
{
if (maxima)
{
return new NissanMaxima();
}
else return null;
}
}
interface iProduct
{
void GetDetails();
}
class NissanUltima:iProduct
{
public void GetDetails()
{
MessageBox.Show("NissanUltima is created");
}
}
class NissanMaxima:iProduct
{
public void GetDetails()
{
MessageBox.Show("NissanMaxima is created");
}
}
I would suggest to redesign that code. Abstract Factory is to create an abstract product say a car in your sample. A specific factory addss a trait of the product. Lets say Nissanfactory and Fordfactory
then in each CreateFactory() you may scecify a model of the car you want to create.
abstract class Factory
{
public abstract iProduct CreateProduct(int Model);
}
class NissanFactory : Factory
{
public override iProduct CreateProduct(int Model)
{
// say 1 is Maxima
//say 2 is Untima
if (Model ==1)
{
return new NissanMaxima();
}
if(Model ==2)
{
return new NissanUltima();
}
return null;
}
}
class FordFartory : Factory
{
public override iProduct CreateProduct(int Model)
{
if (Model == 1)
{
return new GrandTorino();
}
if (Model == 2)
{
return new Mustang();
}
return null;
}
}
//
private void button1_Click(object sender, EventArgs e)
{
Factory[] obj = new Factory[1];
obj[0] =new NissanFactory();
private List<iProduct> products = new List<iProduct>();
//create maxima if it's chacked
if (checkBox2.Checked)
products.Add(obj.CreateProduct(1));
//create ultima
if (checkBox1.Checked)
products.Add(prod = obj.CreateProduct(2));
//now you can navigate via list of created products
foreach (IProduct car in products)
{
prod.GetDetails();
}
}
A factory base class interface should be allow clients to create any kind of descendant instance, based only on the parameters provided to its create method. The whole point is decoupling object creation from knowledge about specific concrete types, in order to allow e.g. dependency injection.
If you want to provide distinct initialization data to various descendant factories, that data should be contained in or provided to the factory class itself (since whatever code is creating and configuring the factories is the only part that should know about the concrete type). So, initialize B with the bool value for Ultima and C with the value of Maxima.
Frankly, you may have edited your example a bit too heavily: I'm not really sure of what you are trying to do. If the WinForms code should be unaware of the concrete types, you're going to need to introduce some kind of decoupling interface between that and your factory creation code in order to pass initialization data.