Strategy Pattern with each algorithm having a different method signature - c#

I am doing a refactor over certain code.
We have a list of investors with amounts assigned to each. The total of amounts should be equal to another total, but sometimes there are a couple of cents of difference, so we use different algorithms to assign these differences to each investor.
The current code is something like this:
public void Round(IList<Investors> investors, Enum algorithm, [here goes a list of many parameters]) {
// some checks and logic here - OMMITED FOR BREVITY
// pick method given algorithm Enum
if (algoritm == Enum.Algorithm1) {
SomeStaticClass.Algorithm1(investors, remainders, someParameter1, someParameter2, someParameter3, someParameter4)
} else if (algoritm == Enum.Algorithm2) {
SomeStaticClass.Algorithm2(investors, remainders, someParameter3)
}
}
so far we only have two algorithms. I have to implement the third one. I was given the possibility to refactor both existing implementations as well as do some generic code to make this function for future algorithms, maybe custom to each client.
My first thought was "ok, this is a strategy pattern". But the problem I see is that both algorithms receive a different parameter list (except for the first two). And future algorithms can receive a different list of parameters as well. The only thing in "common" is the investor list and the remainders.
How can I design this so I have a cleaner interface?
I thought of
Establishing an interface with ALL possible parameters, and share it
among all implementations.
Using an object with all possible parameters as properties, and use that generic object as part of the interface. I
would have 3 parameters: The list of investors, the remainders object, and a "parameters" object. But in this case, I have a similar problem. To instantiate each object and fill the required properties depends on the algorithm (unless I set all of them). I
would have to use a factory (or something) to instantiate it, using all parameters in the interface, am I right? I would be moving the problem of too many parameters to that "factory" or whatever.
Using a dynamic object instead of a statically typed object. Still
presents the same problems as before, the instantiation
I also thought of using the Visitor Pattern, but as I understand, that would be the case if I had different algorithms for different entities to use, like, another class of investors. So I don't think it is the right approach.
So far the one that convinces me the most is the second, although I am still a bit reticent about it.
Any ideas?
Thanks

Strategy has different implementations. Its straightforward when all alternate Concrete Strategies require same type signature. But when concrete implementations start asking for different data from Context, we have to gracefully take a step back by relaxing encapsulation ("breaking encapsulation" is known drawback of strategy), either we can pass Context to strategies in method signature or constructor depending upon how much is needed.
By using interfaces and breaking big object trees in to smaller containments we can restrict the access to most of the Context state.
following code demonstrates passing through method parameter.
public class Context {
private String name;
private int id;
private double salary;
Strategy strategy;
void contextInterface(){
strategy.algorithmInterface(this);
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public double getSalary() {
return salary;
}
}
public interface Strategy {
// WE CAN NOT DECIDE COMMON SIGNATURE HERE
// AS ALL IMPLEMENTATIONS REQUIRE DIFF PARAMS
void algorithmInterface(Context context);
}
public class StrategyA implements Strategy{
#Override
public void algorithmInterface(Context context) {
// OBSERVE HERE BREAKING OF ENCAPSULATION
// BY OPERATING ON SOMEBODY ELSE'S DATA
context.getName();
context.getId();
}
}
public class StrategyB implements Strategy{
#Override
public void algorithmInterface(Context context) {
// OBSERVE HERE BREAKING OF ENCAPSULATION
// BY OPERATING ON SOMEBODY ELSE'S DATA
context.getSalary();
context.getId();
}
}

Okay, I might be going in the wrong direction... but it seems kinda weird that you're passing in arguments to all the algorithms, and the identifier to which algorithm to actually use. Shouldn't the Round() function ideally just get what it needs to operate?
I'm imagining the function that invokes Round() to look something like:
if (something)
algToUse = Enum.Algorithm1;
else
if (otherthing)
algToUse = Enum.Algorithm2;
else
algToUse = Enum.Algorithm3;
Round(investors, remainder, algToUse, dayOfMonth, lunarCycle, numberOfGoblinsFound, etc);
... what if, instead, you did something like this:
public abstract class RoundingAlgorithm
{
public abstract void PerformRounding(IList<Investors> investors, int remainders);
}
public class RoundingRandomly : RoundingAlgorithm
{
private int someNum;
private DateTime anotherParam;
public RoundingRandomly(int someNum, DateTime anotherParam)
{
this.someNum = someNum;
this.anotherParam = anotherParam;
}
public override void PerformRounding(IList<Investors> investors, int remainder)
{
// ... code ...
}
}
// ... and other subclasses of RoundingAlgorithm
// ... later on:
public void Round(IList<Investors> investors, RoundingAlgorithm roundingMethodToUse)
{
// ...your other code (checks, etc)...
roundingMethodToUse.Round(investors, remainders);
}
... and then your earlier function simply looks like:
RoundingAlgorithm roundingMethod;
if (something)
roundingMethod = new RoundingByStreetNum(1, "asdf", DateTime.Now);
else
if (otherthing)
roundingMethod = new RoundingWithPrejudice(null);
else
roundingMethod = new RoundingDefault(1000);
Round(investors, roundingMethod);
... basically, instead of populating that Enum value, just create a RoundingAlgorithm object and pass that in to Round() instead.

Related

More concise way to pass, as constructor parameter, an Action that references private data?

This is stripped down from a more complex situation.
The goal is to construct several instances of class SubAction, each of which uses an action to alter how it uses its internal data.
Consider:
public class SubAction
{
private Action<SubAction> _DoIt;
public SubAction(Action<SubAction> doIt)
{
_DoIt = doIt;
}
public void DoIt()
{
_DoIt(this);
}
static public Action<SubAction> GetAction1 => (it) => it.DoSomething(it._Data.Value1);
static public Action<SubAction> GetAction2 => (it) => it.DoSomething(it._Data.Value2);
private void DoSomething(string value)
{
// ...
}
// This gets set by code not shown.
protected Data _Data;
}
public class Data
{
public string Value1;
public string Value2;
}
public class SubActionTests
{
static SubActionTests()
{
var actions = new List<SubAction>
{
new SubAction(SubAction.GetAction1),
new SubAction(SubAction.GetAction2),
};
// ... code not shown that calls a method to update each instance's _Data...
foreach (var subAction in actions)
{
subAction.DoIt();
}
}
}
This works, but it seems cumbersome. Specifically:
public Action<SubAction> _DoIt { get; set; }
...
static public Action<SubAction> GetAction1 => (it) => it.DoSomething(it._Data.Value1);
...
new SubAction(SubAction.GetAction1)
If I set DoIt AFTER constructing the object, could simply be:
public Action DoIt { get; set; }
...
public Action GetAction1 => () => DoSomething(_Data.Value1);
...
var it = new SubAction();
it.DoIt = it.GetAction1;
Which has simpler action declarations:
The actions don't need <SubAction>.
`GetAction1,2,3.. declarations are much simpler.
But more verbose instance initialization, because access to it is needed to set DoIt.
Unfortunately it isn't possible to refer to "it" during object initializer, so there doesn't seem to be any way to have BOTH the simpler initialization syntax AND the simpler action-declaration syntax.
Am I overlooking some solution?
ALTERNATIVE: factory method
NOTE: This could be approached quite differently, by using an enum to select between the different actions. But that is a different sort of complication; I'm looking for a way to describe these Actions themselves more succinctly.
Specifically, I'm aware there could be a factory method that takes an enum, to hide the complexity:
public enum WhichAction
{
Action1,
Action2
}
...
public static CreateSubAction(WhichAction which)
{
var it = new SubAction();
switch (which)
{
case WhichAction.Action1:
it.DoIt = it.GetAction1;
break;
case WhichAction.Action2:
it.DoIt = it.GetAction2;
break;
}
return it;
}
The downside of this is that each added action requires editing in multiple places.
ALTERNATIVE: sub-classes
Another alternative is to create multiple sub-classes.
That is what I was doing originally, but that was even more verbose - multiple lines per each new action.
And felt like "overkill".
After all, the approach I've got isn't terrible - its a single line for each new GetAction. It just felt like each of those lines "ought" to be much simpler.
Sadly, from what I understand, I don't think you can make the complexity disappear. You probably need to choose an approach from the ones you suggested (or even other solutions like using a strategy pattern).
Advice
When confronted with a design choice like this. I suggest you optimize for the consumer's side of things. In other words, design your classes to make them simple to use.
In your scenario, that would mean opting for your initial solution or the more complex solutions (factory method, sub-classes, strategy pattern, etc.).
The problem with the second solution is that your object can be in a limbo state when initializing it.
var it = new SubAction();
// Before you set DoIt, the object is not fully initialized.
it.DoIt = it.GetAction1;
Consumers can also forget to set DoIt. When possible, you should probably avoid designs that allow such mistakes.
While I'm still curious whether there are syntax alternatives that would streamline what I showed, so I'll accept an answer that shows a simpler syntax, turns out in my situation, I can easily avoid the need for those actions.
Discussing with a colleague, they pointed out that my current actions all have a similar pattern: get a string, pass it to SubAction.DoSomething.
Therefore I can simplify those actions down to a property that gets the appropriate string:
public abstract string CurrentValue { get; }
...
public virtual void DoIt()
{
DoSomething(CurrentValue);
}
Given the above, subclasses become so simple they no longer feel like "overkill":
public class SubAction1 : SubAction
{
protected override string CurrentValue => _Data.Value1;
}
...
// usage
new SubAction1()
That is straightforward; highly readable. And trivial to extend when additional conditions are needed.
There will be more complicated situations that do need to override DoSomething. In those, the "real work" dwarfs what I've shown; so its appropriate to subclass those anyway.

How can I write this class to be fully generic and return different responses according to one request?

I was asked to create a series of reports for an application and as always, I'm looking for ways to reduce the amount of code written. I've started trying to come up with the easiest way to request a single report. Here's what I imagined:
var response = ReportGenerator.Generate(Reports.Report1);
//Reports would be an enum type with all of the available reports.
As soon as I tried to design that, the problems appeared. Every report has a different input and output. The input being the entity (or entities) on which the report is based and the output being the DTO holding the processed data.
Backing this up, I created this:
// The interface for every report
public interface IReport<INPUT, OUTPUT>
{
public OUTPUT GenerateReport(INPUT input);
}
// A base class for every report to share a few methods
public abstract class BaseReport<INPUT, OUTPUT> : IReport<INPUT, OUTPUT>
{
// The method required by the IReport interface
public OUTPUT GenerateReport(INPUT input)
{
return Process(input);
}
// An abstract method to be implemented by every concrete report
protected abstract OUTPUT Process(INPUT input);
}
public class ConcreteReport : BaseReport<SomeEntity, SomeDto>
{
protected override SomeDto Process(SomeEntity input)
{
return default(SomeDto);
}
}
At first I was considering to have every concrete report to specify the logic responsible to determine its own input. I quickly saw that it would make my class less testable. By having the report request an instance of the INPUT generic type I can mock that object and test the report.
So, what I need is some kind of class to tie a report (one of the enum values) to a concrete report class responsible for its generation. I'm trying to use an approach similar to a dependency injection container. This is the class I'm having trouble to write.
I'll write below what I have with comments explainning the problems I've found (it's not supposed to be syntatically correct - it's just a stub since my problem is exactly the implementation of this class):
public class ReportGenerator
{
// This would be the dictionary responsible for tying an enum value from the Report with one of the concrete reports.
// My first problem is that I need to make sure that the types associated with the enum values are instances of the BaseReport class.
private readonly Dictionary<Reports, ?> registeredReports;
public ReportGenerator()
{
// On the constructor the dictionary would be instantiated...
registeredReports = new Dictionary<Reports, ?>();
// and the types would be registered as if in a dependency injection container.
// Register(Reports.Report1, ConcreteReport);
// Register(Reports.Report2, ConcreteReport2);
}
// Below is the most basic version of the registration method I could come up with before arriving at the problems within the method GenerateReport.
// T repository - this would be the type of the class responsible for obtainning the input to generate the report
// Func<T, INPUT> expression - this would be the expression that should be used to obtain the input object
public void Register<T, INPUT>(Reports report, Type reportConcreteType, T repository, Func<T, INPUT> expression)
{
// This would basically add the data into the dictionary, but I'm not sure about the syntax
// because I'm not sure how to hold that information so that it can be used later to generate the report
// Also, I should point that I prefer to hold the types and not instances of the report and repository classes.
// My plan is to use reflection to instantiate them on demand.
}
// Based on the registration, I would then need a generic way to obtain a report.
// This would the method that I imagined at first to be called like this:
// var response = ReportGenerator.Generate(Reports.Report1);
public OUTPUT Generate(Reports report)
{
// This surely does not work. There is no way to have this method signature to request only the enum value
// and return a generic type. But how can I do it? How can I tie all these things and make it work?
}
}
I can see it is not tied with the report interface or abstract class but I can't figure out the implementation.
I am not sure that it is possible to achieve such behaviour with enum, so I can propose you the following solution:
Use some identifier generic class(interface) in place of enum values. To use it as key in dictionary you will also have to have some non-generic base for this class.
Have some static class with aforementioned identifier classes as specific static properties.
Use values from static class properties as keys in ReportGenerator class.
Here are required interfaces:
public interface IReportIdentifier
{
}
public interface IReportIdentifier<TInput, TOutput> : IReportIdentifier
{
}
public interface IReport<TInput, TOutput>
{
TOutput Generate(TInput input);
}
Here is the static "enum" class:
public static class Reports
{
public static IReportIdentifier<String, Int32> A
{
get { return null;}
}
public static IReportIdentifier<Object, Guid> B
{
get { return null; }
}
}
And here is the ReportGenerator class:
public class ReportGenerator
{
IDictionary<IReportIdentifier, Object> reportProducers = new Dictionary<IReportIdentifier, Object>();
public void Register<TInput, TOutput>(IReportIdentifier<TInput, TOutput> identifier, IReport<TInput, TOutput> reportProducer)
{
reportProducers.Add(identifier, reportProducer);
}
public TOutput Generate<TInput, TOutput>(IReportIdentifier<TInput, TOutput> identifier, TInput input)
{
// Safely cast because it is this class's invariant.
var producer = (IReport<TInput, TOutput>)reportProducers[identifier];
return producer.Generate(input);
}
}
As you see, we use cast but it is hidden inside the Generate method and if our Register method is the only access point to the reportProducers dictionary this cast will not fail.
And also as #CoderDennis pointed:
Then you could always use T4 to generate that static class and its
static properties and could even create an extension method that
returns the proper IReportIdentifier from your enum.
It seems to me that you may want to rethink the design.
You essentially have methods that take objects in and spit objects out. Granted, you use generics, but that doesn't mean much since there are no constraints on input/output and thus no way to commonly process them in calling code.
In fact, I think the use of generics is potentially a hindrance with the given approach, because passing in the wrong combination of generic types will result in a error, and it's not clear to the caller what is valid and what is not.
Given the approach, it's unclear what benefit all of the extra classes give over non-abstractions like:
int r1Output = Report1StaticClass.GetOutput(string input);
string r2Output = Report2StaticClass.GetOtherOutput(int input);
double r3Output = Report3StaticClass.GetWhatever(double input);
A different approach might be to encapsulate input/output something similar to this, but adjusted to your needs. This isn't meant to be an exact approach, but just something to demonstrate what I'm suggesting. Also, I haven't actually tested/compile this. Consider it pseudo-code:
//something generic that can be easily mocked and processed in a generic way
//your implementation almost certainly won't look exactly like this...
//but the point is that you should look for a common pattern with the input
interface IInput
{
ReportTypeEnum EntityType{ get; set; }
int EntityId{ get; set; }
}
interface IReportTemplate
{
//return something that can be bound to/handled generically.
//for instance, a DataSet can be easily and dynamically bound to grid controls.
//I'm not necessarily advocating for DataSet, just saying it's generic
//NOTE: the guts of this can use a dynamically assigned
// data source for unit testing
DataSet GetData(int entityId);
}
//maybe associate report types with the enum something like this.
[AttributeUsage (AttributeTargets.Field, AllowMultiple = false)]
class ReportTypeAttribute : Attribute
{
public Type ReportType{ get; set; }
//maybe throw an exception if it's not an IReportTemplate
public ReportTypeAttribute(Type reportType){ ReportType = reportType; }
}
//it should be easy for devs to recognize that if they add an enum value,
//they also need to assign a ReportType, thus your code is less likely to
//break vs. having a disconnect between enum and the place where an associated
//concrete type is assigned to each value
enum ReportTypeEnum
{
[ReportType(typeof(ConcreteReportTemplate1))]
ReportType1,
[ReportType(typeof(ConcreteReportTemplate2))]
ReportType2
}
static class ReportUtility
{
public static DataSet GetReportData(IInput input)
{
var report = GetReportTemplate(input.EntityType);
return report.GetData(input.EntityId);
}
private static IReportTemplate GetReportTemplate(ReportTypeEnum entityType)
{
//spin up report by reflecting on ReportTypeEnum and
//figuring out which concrete class to instantiate
//based on the associated ReportTypeAttribute
}
}

When to declare the entire class as static

I have a math helper class where every single function is static, i.e., params fed in as arguments, value returned. Should I declare the entire class as static? Would adding the static modifier to the class make a difference in performance?
Also, I am not sure what this guideline means in: "do not treat static classes as a miscellaneous bucket." - I have a few classes that are just a bunch of miscellaneous static functions...
It's perfectly fine to make classes like that static, in fact if you look at System.Math you'll see it's static as well:
public static class Math
What the guideline is trying to say is you should not put every static method you have to one static class which would do everything and play a role of a bucket for static methods. Instead, if it's appropriate, create smaller util classes with methods related to the same functionality, like it's done with System.Math and couple more within BCL as well.
Should I declare the entire class as static?
Yes. Adding static to a class says that it contains only static members and that you can't ever instantiate it. Without it, users of your class might get confused and try to create an instance or variable of your class. With static, that's not possible.
It seems like this is exactly your case.
Would adding the static modifier to the class make a difference in performance?
No, call to a static method will always have the same performance characteristics, it doesn't matter whether the containing class is static or not. Actually, the whole concept of static classes doesn't exist at the CIL level, they're just sealed abstract classes (a combination that wouldn't compile in C#).
But even if there was a difference, it would be tiny. Don't optimize prematurely, especially when it comes to micro-optimizations.
Helper classes are normally static classes, so that you don't need to instantiate them. There is no great cost in instantiating a managed .NET object (especially helper classes), it is just a matter of convenience.
It is extremely tempting to just put together a static class with minimal helper methods and get the job done. They have their place in code, and can be used especially when there is deterministic input/output. e.g. ComputeHash of a string, Find Average of numbers etc.
But the one reason, Static classes are discouraged is because they normally interfere with unit testing and present all sorts of problems. (Fakes, Moles, Private Accessors etc.)
An interfaced based approach for even helper classes, helps with the unit testing of the overall code. This is especially true for big projects which involve workflows such that the static helper methods are only a part of the workflow.
e.g. Suppose you need to check if the current year is a leap year. It is tempting to write a quick static method.
public static class DateHelper
{
public static bool IsLeapYear()
{
var currentDate = DateTime.UtcNow;
// check if currentDate's year is a leap year using some unicorn logic
return true; // or false
}
}
and if this method is used in your code somewhere like:
public class Birthday
{
public int GetLeapYearDaysData()
{
// some self-logic..
// now call our static method
var isLeapYear = DateHelper.IsLeapYear();
// based on this value, you might return 100 or 200.
if (isLeapYear)
{
return 100;
}
return 200;
}
}
Now, if you go and try to unit test this method public int GetLeapYearDaysData(), you might end up in trouble since the return value is indeterminate.. i.e. depends on the current year and it is not recommended to have unit tests behaving unpredictably/deteriorate as time progresses.
// this unit test is flaky
[Test]
public void TestGetLeapYearDaysData()
{
var expected = 100;
// we don't know if this method will return 100 or 200.
var actual = new Birthday().GetLeapYearDaysData();
Assert.AreEqual(expected, actual);
}
The above problem happens because we cannot control/mock the method IsLeapYear() in the above code. so we're at its mercy.
Now imagine the following design:
public interface IDateHelper
{
bool IsLeapYear();
}
public class DateHelper : IDateHelper
{
public bool IsLeapYear()
{
var currentDate = DateTime.UtcNow;
// check if currentDate's year is a leap year using some unicorn logic
return true; // or false
}
}
Now our birthday class can be injected with a helper:
public class Birthday
{
private IDateHelper _dateHelper;
// any caller can inject their own version of dateHelper.
public Birthday(IDateHelper dateHelper)
{
this._dateHelper = dateHelper;
}
public int GetLeapYearDaysData()
{
// some self-logic..
// now call our injected helper's method.
var isLeapYear = this._dateHelper.IsLeapYear();
// based on this value, you might return 100 or 200.
if (isLeapYear)
{
return 100;
}
return 200;
}
}
// now see how are unit tests can be more robust and reliable
// this unit test is more robust
[Test]
public void TestGetLeapYearDaysData()
{
var expected = 100;
// use any mocking framework or stubbed class
// to reliably tell the unit test that 100 needs to be returned.
var mockDateHelper = new Mock<IDateHelper>();
// make the mock helper return true for leap year check.
// we're no longer at the mercy of current date time.
mockDateHelper.Setup(m=>m.IsLeapYear()).Returns(true);
// inject this mock DateHelper in our BirthDay class
// we know for sure the value that'll be returned.
var actual = new Birthday(mockDateHelper).GetLeapYearDaysData();
Assert.AreEqual(expected, actual);
}
As you can see, the moment the helper methods were Interface based, they were easily testable. Over the course of a big project, many such smaller static methods ultimately result in bottlenecks in testing key functional flows.
So it pays to be aware of this pitfall in advance and make the additional investment upfront. Basically identify what classes/methods need to be static and what shouldn't be.
It all starts from when should I have a static method, and that is when you don't have any dependency on instance variables.
Now that said if none of you methods are depending on instance variable, you can make your class static.
Static class serve several benefits, and many more.

C# : Generic factory object instantiation by passing type (type retrieved from another static object)

I created a little abstract domain to illustrate the problem I am facing, so there it is.
There is a medieval game, where the players are generals of their army and the entire battle is mostly affected by the battle plan, which is made before the battle begins, in let's say preparation mode.
To achieve what's needed, I created an interface IBattleUnit and kept things pretty simple:
public interface IBattleUnit
{
void Move();
void Attack();
string Salute();
}
Having three types of units will do the job for now, so Archer.cs, Pikeman.cs and Swordsman.cs implement the interface in pretty much the same way:
public class Swordsman : IBattleUnit
{
private Swordsman() {}
public void Move()
{
//swordsman moves
}
public void Attack()
{
//swordsman attacks
}
public string Salute()
{
return "Swordsman at your service, master.";
}
}
Note the private constructor, it is intended for battle units to be recruited only in Barracks, this is the generic factory
public static class Barracks<T> where T : class, IBattleUnit
{
private static readonly Func<T> UnitTemplate = Expression.Lambda<Func<T>>(
Expression.New(typeof(T)), null).Compile();
public static T Recruit()
{
return UnitTemplate();
}
}
Note: precompiled lambda expressions for the empty constructor make (on my machine) unit creation faster, and whereas the army can get really big, fast generic creation is exactly what I want to achieve.
For having covered everything a battle needs to be started, the BattlePlan explanation is the only missing part, so here we come:
public static class BattlePlan
{
private static List<Type> _battleUnitTypes;
private static List<Type> _otherInterfaceImplementors;
//...
private static Dictionary<string, string> _battlePlanPreferences;
private static Type _preferedBattleUnit;
private static Type _preferedTransportationUnit;
//...
static BattlePlan()
{
//read the battle plan from file (or whereever the plan init data originate from)
//explore assemblies for interface implementors of all kinds
//and finally fill in all fields
_preferedBattleUnit = typeof (Archer);
}
public static Type PreferedBattleUnit
{
get
{
return _preferedBattleUnit;
}
}
//... and so on
}
Now if you have reached this, you are aware of the whole domain - it even compiles and everything looks bright, until...
Until now: I create a console application, add references to the above mentioned, and try to profit from what's under the hood.
For complete description of my confusion, I note what IS WORKING first:
If I want the Barracks to give me a specific BattleUnit, I can instantiate it and let it fight, move and salute. If the instantiation is done this way:
IBattleUnit unit = Barracks<Pikeman>.Recruit();
If I want to know what is the prefered unit based on battle plan, I can get it, I can ask for its AssemblyQualifiedName, I get the Type (in fact it is Archer, just as it stays in BattlePlan) , long story short, I get what I expect to, when I call:
Type preferedType = BattlePlan.PreferedBattleUnit;
And here, when I expect the BattlePlan to supply me with a Type and me just passing the Type to Barracks in order to instantiate some kind of Unit, VisualStudio2012 (resharper of current version) stops me and does not compile the code, while the code, that leads to the error is:
Type t = Type.GetType(BattlePlan.PreferedBattleUnit.AssemblyQualifiedName);
IBattleUnit u = Barracks<t>.Recruit();
No matter what I do, no matter whether I pass the t, or pass it as typeof(t), or try converting it to IRepository ... I still end up not being able to compile such code, with (at least) two errors in the error list:
Error 1 Cannot implicitly convert type 't' to 'BattleUnits.cs.IBattleUnit' Program.cs
Error 2 The type or namespace name 't' could not be found (are you missing a using directive or an assembly reference?) Program.cs
So to the actual questions:
Is there some way, I could pass the type to Barracks, not having to change underlying infrastructure?
Or is there anything I am doing wrong by design?
I have spent the last two days googling around and still, with the only clear way being changing the Barracks, which in fact is what I would not want to.
EDIT no.1: When re-thinking the concept and everything : IBattleUnit was first described as a set of core battle actions every Unit will be able to do (and we want it to be this way). I did not want to introduce base classes, just because I knew, there could possibly be GroundUnitBase and FlyingUnitBase abstract classes for the sake, we would like to have clear and logical design... But there absolutely has to be only one static Barracks.
Still for the BattleUnits - putting one base class in my eyes now seems could change the things for code being runnable and I'm right on my way of trying that out ... reading, what I wrote made me think about UnitBase class could possibly help not even the design but in some way its compilability. So this is the first idea in my mind after rethinking what's written.
You don't really need Barracks to be generic.
This solution doesn't use reflection so it's much more efficient:
public static class Barracks
{
private static readonly IDictionary<Type, Func<IBattleUnit>> FactoryMethods = new Dictionary<Type, Func<IBattleUnit>>();
public static void Register<T>(Func<IBattleUnit> factory) where T : IBattleUnit
{
FactoryMethods.Add(typeof(T), factory);
}
public static IBattleUnit Recruit<T>() where T : IBattleUnit
{
return Recruit(typeof (T));
}
public static IBattleUnit Recruit(Type type)
{
Func<IBattleUnit> createBattleUnit;
if (FactoryMethods.TryGetValue(type, out createBattleUnit))
{
return createBattleUnit();
}
throw new ArgumentException();
}
}
public class Swordsman : IBattleUnit
{
static Swordsman()
{
Barracks.Register<Swordsman>(() => new Swordsman());
}
}
public static class Barracks
{
public static IBattleUnit Recruit(Type preferredType)
{
return (IBattleUnit)typeof(Barracks<>).MakeGenericType(preferredType).GetMethod("Recruit", BindingFlags.Public|BindingFlags.Static).Invoke(null,null);
}
}
then call
Barracks.Recruit(BattlePlan.PreferredBattleUnit)
You can do this using reflection, something like this:
IBattleUnit unit = typeof(Barracks).GetMethod("Recruit").MakeGenericType(BattlePlan.PreferedBattleUnit).Invoke(null, null) as IBattleUnit;
If you have an instance of the PreferedBattleUnit you simply need to use the dynamic keyword. Please have a look at this question (John Skeet answer): (EDIT: This might not be very helpful as your method is not generic)
Pass concrete object type as parameter for generic method
If you don't have an instance of the object than have a look at the following question (again, John Skeet answer):
Generics in C#, using type of a variable as parameter
My strategy would be to create a Dictionary<Type, Barracks<IBattleUnit>>, assuming you intend to have all the barracks defined before you try to retrieve from them. That way you can match by the key and cast safely.
This would require the Barracks<> to not be a static class. Unless you have very specific reasons like some kind of external resource you're managing (and arguably even then), you probably have no need for a static class.
While it may seem like creating statics for all of these will make everything easier, ultimately you create a dependency on a resource that may change. If you invent another unit type, you have to register it with the barracks, which is in no real way different than the reason you don't want to make base classes, and if you forget you'll throw exceptions, which is even worse, because it violates the Principle of Least Surprise.

C# Singleton Pattern over Inherited Classes

I'll begin this question with apologizing for the length of the post. So that I save you some time, my problem is that the class pattern I've got stuck in my head is obviously flawed, and I can't see a good solution.
In a project I'm working on, I need to use operate algorithms on a chunks of data, let's call them DataCache. Sometimes these algorithms return results that themselves need to be cached, and so I devised a scheme.
I have an Algorithm base class that looks like so
abstract class Algorithm<T>
{
protected abstract T ExecuteAlgorithmLogic(DataCache dataCache);
private readonly Dictionary<DataCache, WeakReference> _resultsWeak = new Dictionary<DataCache, WeakReference>();
private readonly Dictionary<DataCache, T> _resultsStrong = new Dictionary<DataCache, T>();
public T ComputeResult(DataCache dataCache, bool save = false)
{
if (_resultsStrong.ContainsKey(dataCache))
return _resultsStrong[dataCache];
if (_resultsWeak.ContainsKey(dataCache))
{
var temp = _resultsWeak[dataCache].Target;
if (temp != null) return (T) temp;
}
var result = ExecuteAlgorithmLogic(dataCache);
_resultsWeak[dataCache] = new WeakReference(result, true);
if (save) _resultsStrong[dataCache] = result;
return result;
}
}
If you call ComputeResult() and provide a DataCache you can optionally select to cache the result. Also, if you are lucky result still might be there if the GC hasn't collected it yet. The size of each DataCache is in hundreds of megabytes, and before you ask there are about 10 arrays in each, which hold basic types such as int and float.
My idea here was that an actual algorithm would look something like this:
class ActualAgorithm : Algorithm<SomeType>
{
protected override SomeType ExecuteAlgorithmLogic(DataCache dataCache)
{
//Elves be here
}
}
And I would define tens of .cs files, each for one algorithm. There are two problems with this approach. Firstly, in order for this to work, I need to instantiate my algorithms and keep that instance (or the results are not cached and the entire point is mute). But then I end up with an unsightly singleton pattern implementation in each derived class. It would look something like so:
class ActualAgorithm : Algorithm<SomeType>
{
protected override SomeType ExecuteAlgorithmLogic(DataCache dataCache)
{
//Elves and dragons be here
}
protected ActualAgorithm(){ }
private static ActualAgorithm _instance;
public static ActualAgorithm Instance
{
get
{
_instance = _instance ?? new ActualAgorithm();
return _instance;
}
}
}
So in each implementation I would have to duplicate code for the singleton pattern. And secondly tens of CS files also sounds a bit overkill, since what I'm really after is just a single function returning some results that can be cached for various DataCache objects. Surely there must be a smarter way of doing this, and I would greatly appreciate a nudge in the right direction.
What I meant with my comment was something like this:
abstract class BaseClass<K,T> where T : BaseClass<K,T>, new()
{
private static T _instance;
public static T Instance
{
get
{
_instance = _instance ?? new T();
return _instance;
}
}
}
class ActualClass : BaseClass<int, ActualClass>
{
public ActualClass() {}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(ActualClass.Instance.GetType().ToString());
Console.ReadLine();
}
}
The only problem here is that you'll have a public constructor.
I refined my previous answer but as it is rather different than the other approach I proposed, I thought I might just make another answer. First, we'll need to declare some interfaces:
// Where to find cached data
interface DataRepository {
void cacheData(Key k, Data d);
Data retrieveData(Key k, Data d);
};
// If by any chance we need an algorithm somewhere
interface AlgorithmRepository {
Algorithm getAlgorithm(Key k);
}
// The algorithm that process data
interface Algorithm {
void processData(Data in, Data out);
}
Given these interfaces, we can define some basic implementation for the algorithm repository:
class BaseAlgorithmRepository {
// The algorithm dictionnary
Map<Key, Algorithm> algorithms;
// On init, we'll build our repository using this function
void setAlgorithmForKey(Key k, Algorithm a) {
algorithms.put(k, a);
}
// ... implement the other function of the interface
}
Then we can also implement something for the DataRepository
class DataRepository {
AlgorithmRepository algorithmRepository;
Map<Key, Data> cache;
void cacheData(Key k, Data d) {
cache.put(k, d);
}
Data retrieveData(Key k, Data in) {
Data d = cache.get(k);
if (d==null) {
// Data not found in the cache, then we try to produce it ourself
Data d = new Data();
Algorithm a = algorithmRepository.getAlgorithm(k);
a.processData(in, d);
// This is optional, you could simply throw an exception to say that the
// data has not been cached and thus, the algorithm succession did not
// produce the necessary data. So instead of the above, you could simply:
// throw new DataNotCached(k);
// and thus halt the whole processing
}
return d;
}
}
Finally, we get to implement algorithms:
abstract class BaseAlgorithm {
DataRepository repository;
}
class SampleNoCacheAlgorithm extends BaseAlgorithm {
void processData(Data in, Data out) {
// do something with in to compute out
}
}
class SampleCacheProducerAlgorithm extends BaseAlgorithm {
static Key KEY = "SampleCacheProducerAlgorithm.myKey";
void processData(Data in, Data out) {
// do something with in to compute out
// then call repository.cacheData(KEY, out);
}
}
class SampleCacheConsumerAlgorithm extends BaseAlgorithm {
void processData(Data in, Data out) {
// Data tmp = repository.retrieveData(SampleCacheProducerAlgorithm.KEY, in);
// do something with in and tmp to compute out
}
}
To build on this, I think you could also define some special kinds of algorithms that are just in fact composites of other algorithms but also implement the Algorithm interface. An example could be:
class AlgorithmChain extends BaseAlgorithm {
List<Algorithms> chain;
void processData(Data in, Data out) {
Data currentIn = in;
foreach (Algorithm a : chain) {
Data currentOut = new Data();
a.processData(currentIn, currentOut);
currentIn = currentOut;
}
out = currentOut;
}
}
One addition I would make to this is a DataPool, that would allow you to reuse exisiting but unused Data objects in order to avoid allocating lots of memory each time you make a new Data().
I think this set of classes could give a good basis to your whole architecture, with the additional benefit that it does not employ any Singleton (always passing references to the concerned objects). Which means also that implementing dummy classes for unit tests would be rather easy.
You could have your algorithms independant of their results:
class Engine<T> {
Map<AlgorithmKey, Algorithm<T>> algorithms;
Map<AlgorithmKey, Data> algorithmsResultCache;
T processData(Data in);
}
interface Algorithm<T> {
boolean doesResultNeedsToBeCached();
T processData(Data in);
}
Then you Engine is responsible for instanciating the algorithms which are only pieces of code where the input is data and the output is either null or some data. Each algorithm can say whether his result needs to be cached or not.
In order to refine my answer, I think you should give some precisions about how the algorithms are to be run (is there an order, is it user adjustable, do we know in advance the algorithms that will be run, ...).
Can you register your algorithm instances with a combined repository/factory of algorithms that'll keep references to them? The repository could be a singleton, and, if you give the repository control of algorithm instantiation, you could use it to ensure that only one instance of each existed.
public class AlgorithmRepository
{
//... use boilerplate singleton code
public void CreateAlgorithm(Algorithms algorithm)
{
//... add to some internal hash or map, checking that it hasn't been created already
//... Algorithms is just an enum telling it which to create (clunky factory
// implementation)
}
public void ComputeResult(Algorithms algorithm, DataCache datacache)
{
// Can lazy load algoirthms here and make CreateAlgorithm private ..
CreateAlgorithm(algorithm);
//... compute and return.
}
}
This said, having a separate class (and cs file) for each algorithm makes sense to me. You could break with convention and have multiple algo classes in a single cs file if they're lightweight and it makes it easier to manage if you're worried about the number of files -- there are worse things to do. FWIW I'd just put up with the number of files ...
Typically when you create a Singleton class you don't want to inherit from it. When you do this you lose some of the goodness of the Singleton pattern (and what I hear from the pattern zealots is that an angel loses its wings every time you do something like this). But lets be pragmatic...sometimes you do what you have to do.
Regardless I do not think combining generics and inheritance will work in this instance anyway.
You indicated the number of algorithms will be in the tens (not hundreds). As long is this is the case I would create a dictionary keyed off of System.Type and store references to your methods as the values of the dictionary. In this case I used
Func<DataCache, object> as the dictionary value signature.
When the class instantiates for the first time register all your available algorithms in the dictionary. At runtime when the class needs to execute an algorithm for type T it will get the Type of T and look up the alogorithm in the dictionary.
If the code for the algorithms will be relatively involved I would suggest splitting them off into partial classes just to keep your code readable.
public sealed partial class Algorithm<T>
{
private static object ExecuteForSomeType(DataCache dataCache)
{
return new SomeType();
}
}
public sealed partial class Algorithm<T>
{
private static object ExecuteForSomeOtherType(DataCache dataCache)
{
return new SomeOtherType();
}
}
public sealed partial class Algorithm<T>
{
private readonly Dictionary<System.Type, Func<DataCache, object>> _algorithms = new Dictionary<System.Type, Func<DataCache, object>>();
private readonly Dictionary<DataCache, WeakReference> _resultsWeak = new Dictionary<DataCache, WeakReference>();
private readonly Dictionary<DataCache, T> _resultsStrong = new Dictionary<DataCache, T>();
private Algorithm() { }
private static Algorithm<T> _instance;
public static Algorithm<T> Instance
{
get
{
if (_instance == null)
{
_instance = new Algorithm<T>();
_instance._algorithms.Add(typeof(SomeType), ExecuteForSomeType);
_instance._algorithms.Add(typeof(SomeOtherType), ExecuteForSomeOtherType);
}
return _instance;
}
}
public T ComputeResult(DataCache dataCache, bool save = false)
{
T returnValue = (T)(new object());
if (_resultsStrong.ContainsKey(dataCache))
{
returnValue = _resultsStrong[dataCache];
return returnValue;
}
if (_resultsWeak.ContainsKey(dataCache))
{
returnValue = (T)_resultsWeak[dataCache].Target;
if (returnValue != null) return returnValue;
}
returnValue = (T)_algorithms[returnValue.GetType()](dataCache);
_resultsWeak[dataCache] = new WeakReference(returnValue, true);
if (save) _resultsStrong[dataCache] = returnValue;
return returnValue;
}
}
First off, I'd suggest you rename DataCache to something like DataInput for more clarity, because it's easy to confuse it with objects that really act as caches (_resultsWeak and _resultsStrong) to store the results.
Concerning the need for these caches to remain in memory for future use, maybe you should consider placing them in one of the wider scopes that exist in a .NET application than the object scope, Application or Session for example.
You could also use an AlgorithmLocator (see ServiceLocator pattern) as a single point of access to all Algorithms to get rid of the singleton logic duplication in each Algorithm.
Other than that, I find your solution to be a nice one globally. Whether or not it is overkill will basically depend on the homogeneity of your algorithms. If they all have the same way of caching data, of returning their results... it will be a great benefit to have all that logic factored out in a single place. But we lack context here to judge.
Encapsulating the caching logic in a specific object held by the Algorithm (CachingStrategy ?) would also be an alternative to inheriting it, but maybe a bit awkward since the caching object would have to access the cache before and after calculation and would need to be able to trigger algorithm calculation itself and have a hand on the results.
[Edit] if you're concerned with having one .cs file per algorithm, you can always group all Algorithm classes pertaining to a particular T in the same file.

Categories

Resources