I have a legacy C# library (a set of interrelated algorithms) in which there is a global god object which is passed to all classes. This god object (simply called Manager :D ) has a Parameters member, and an ObjectCollection member (among lots of others).
public class Manager
{
public Parameters {get; private set;}
public ObjectCollection {get; private set;}
...
...
}
I am unable to test the algorithms because everything takes the manager as dependency, and initializing that means I have to initialize everything. So I want to refactor this design.
Parameters has more than 100 fields in it, the values control the different algorithms. The ObjectCollection has the entities required for the overall execution of the engine, stored by Id, by Name, etc.
The following are the approaches I've though of, but not satisfied with:
Pass Parameters and ObjectCollection (or IParameters and IObjectCollection) instead of the Manager, but I don't think this solves any issue. I wouldn't know which of the parameters the algorithms would depend on.
Splitting the parameters class to smaller ones also is difficult as one parameter may affect many algorithms, so a logical separation is difficult. Plus the dependencies for each algorithm may end up to be many.
A singleton pattern like is usually done for a Logger, but that too is not testable.
Some of the parameters control the algorithm logic, some of the parameters are just required for the algorithm. I'm thinking of making each algorithm a separate class implementing an interface, and at the application start, deciding which algorithm to instantiate based on the parameter. I might end up splitting the current set of algorithm classes to many more, and I'm afraid I'll end up complicating it more and losing the structure of the algorithms.
Is there any standard way to deal with this, or is just splitting big classes to smaller ones and passing dependencies by constructor the only general advice?
In order to allow yourself to make small steps I'd start with a single algorithm and identify the parameters it requires. These can then be exposed in an interface so...
public interface IAmTheParametersForAlgorithm1
{
int OneThing {get;}
int AnotherThing {get;}
}
Then you can alter Manager so that it implements that interface and as in #marcel's answer expose those parameters directly on Manager.
Now you can test Algorithm1 with a very small mock or self-shunt because you don't need to initialise a gigantic Manager in order to run your test. And Algorithm1 no longer knows it takes a Manager object.
public Manager : IAmTheParametersForAlgorithm1 {}
public class Algorithm1
{
public Algorithm1(IAmTheParametersForAlgorithm1 parameters){}
}
Bit by bit you can continue expanding this to each of the sets of parameters and dealing with small, specific interfaces will allow you to identify where different algorithms have common parameters.
public Manager :
IAmTheParametersForAlgorithm1,
IAmTheParametersForAlgorithm2,
IAmTheParametersForAlgorithm3,
IAmTheParametersForAlgorithm4 {}
It also means that as you identify algorithms whose parameters are no longer accessed outside of their interface you can stop injecting Manager into those algorithms, take the parameters out of Manager, and create a new class which only provides those parameters.
This means you can keep your application running the whole time you're making this change if you aren't able to dedicate time to make one gigantic breaking change
For the Parameters, I would go with something like this:
public class Parameters
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
}
public class AlgorithmParameters1
{
private Parameters parameters;
public int MyProperty1 { get { return parameters.MyProperty1; } }
public int MyProperty3 { get { return parameters.MyProperty3; } }
public AlgorithmParameters1(Parameters parameters)
{
this.parameters = parameters;
}
}
public class Algorithm1
{
public void Run(AlgorithmParameters1 parameters)
{
//Access only MyProperty1 and MyProperty3...
}
}
Usage would look like:
var parameters = new Parameters()
{
MyProperty1 = 4,
MyProperty2 = 5,
MyProperty3 = 6,
};
new Algorithm1().Run(new AlgorithmParameters1(parameters));
By the way, I don't see how you could differ between parameters that control an algorithm and are required for it. By control do you mean they are used to make a decision which algorithm to take?
Related
I have a summary objects, who's responsibilities actually to combine a lot of things together and create a summary report, who later going to be serialized into the XML.
In this objects I have a lot of structures like this:
public class SummaryVisit : Visit, IMappable
{
public int SummaryId { get; set; }
public int PatientId { get; set; }
public int LocationId { get; set; }
public IMappable Patient
{
get
{
return new SummaryPatient(PatientBusinessService.FindPatient(this.PatientId));
}
}
public IMappable Location
{
get
{
return new SummaryLocation(LocationBusinessService.FindLocation(this.LocationId));
}
}
public IEnumerable<IMappable> Comments
{
get
{
return new SummaryComments(CommentBusinessService.FindComments(this.SummaryId, Location));
}
}
// ... can be a lot of these structures
// ... using different business services and summary objects
public IEnumerable<IMappable> Tasks
{
get
{
return new SummaryTasks(TaskBusinessService.FindTasks(this));
}
}
}
PatientBusinessService, LocationBusinessService etc. are statics.
And each of these SummaryPatient, SummaryLocation etc. have the same type of structure inside.
What is the best approach to refactor and unit test this?
Tried to replace static calls with calls via the interfaced proxies (or refactor statics to non-static classes & interfaces), but this class just got a lot of these interfaces as the constructor injection stuff and start to be super greedy. In addition, these interfaces have a one used method inside (if I going to create it just to this summary needs).
And as soon as this is a summary object, commonly this static services used just once for the whole structure to get appropriate properties for output.
You could change your tests to be more integrational (test more than one class at the time). You could try to modify your services to be more universal and be able to take data from different sources (like TestDataProvider and your current data provider).
Better solution I think is to modify classes you want to test:
Use strong typing for properties and gain all benefits. I think you should return more specific types instead of IMappable
It looks like some of your data is stored inside class (ids) some data is not (IMappable object references). I would refactor this to hold references to objects inside class:
private SummaryPatient _patient;
public SummaryPatient Patient
{
get
{
if (_patient == null)
_patient = new SummaryPatient(PatientBusinessService.FindPatient(this.PatientId));
return _patient;
}
}
Then you can assign your tests data in constructor or create static method CreateDummy(...) just for unit tests. This method then should use CreateDummy for child objects. You can use it in your unit tests.
We have a Transaction class that's very loaded; so loaded that I originally ended up passing almost 20 argument to the ctor. After extracting a few value objects, there are still 12 arguments left, which I still think is too much.
How would I go at avoiding this? I think it's reasonable the arguments are passed to the constructor since they're all required, and I want to make that explicit. I also like how if I add a property, I can add it to the ctor and let my compiler find the places it broke, instead of having to rely on tests for this per se. I don't think object initializers, or builders do the problem any good. It might become more obvious in the next coming days which arguments belong together, and could be composed though.
public class MyEntity()
{
public MyEntity(ValueType prop2, ValueType prop3, ...)
{
Id = Guid.NewGuid();
Prop2 = prop2;
Prop3 = prop3;
...
}
public Guid Id { get; private set; }
public ValueType Prop2 { get; private set; }
public ValueType Prop3 { get; private set; }
public ...
}
Are you sure that all the parameters are required? The word "required" is deceptive, the compiler may force me to provide a string argument, for example, but it can't force me to provide a value that is not null or empty.
The only way to truly force valid data to be provided is to validate it at the point of use. Sometimes this has to be in the constructor, e.g. a class that wraps something that only has meaning when initialised, like an I/O object. However, it's usually sufficient to allow the calling code to set properties any old way, then validate their values in the method call that requires them.
I'm rambling a bit. My point is, don't get hung up on constructor parameters as the only way to provide initialisation data to a class. They give very little additional compiler protection beyond simple properties.
How about encapsulating the parameters in a structure, and passing the structure in?
public struct ParamsStruct
{
Type1 param1;
Type2 param2;
...
}
public void Method(ParamsStruct p)
{
...
}
public void Main(String[] args)
{
ParamsStruct p;
p.param1 = ...
p.param2 = ...
Method(p);
}
When you output the full transaction details in a user or system interface, you will need all the parts. This is unlikely to help you find a split.
But, have a look at your internal processing - are there situations where you use only a subset of the fields on the transaction? Are there places where you pass in a Transaction, but only use 4 of the fields? If you literally always use all fields, then keep them in one object.
In the case of a banking transaction, I would consider a split along these lines:-
Where the money came from
Where the money went to
How the money was moved - which payment instrument or facility was used
Why the money was moved - reference numbers, etc
Amount and currency
Date
Status of the transaction
(Obviously this depends on your exact domain).
public class MyEntity()
{
public ValueType Prop1 { get; set; }
public ValueType Prop2 { get; set; }
// And so on...
public MyEntity()
{
Id = Guid.NewGuid();
}
}
Then:
MyEntity entity = new MyEntity();
entity.Prop1 = prop1;
entity.Prop2 = prop2;
// And so on...
You can eventually consider two different design approaches:
The
essence
pattern.
The fluent
interface
pattern.
I have an object that takes plenty of parameters to its constructor (from 9 to 13 depending on use).
I want to avoid the ugliness of new MyObject(param1, param2, param3 ... param13).
My first attempt was to create a class MyObjectParams with properties with public getters and setters, it gives something like that :
var objectParams = new MyObjectParams
{
Param1 = ...,
Param2 = ...,
...
};
I see some big projects like SlimDX for their PresentParameters use this design. It looks better. But the class is not immutable.
I'd like my MyObjectParams to be immutable while still using a clean construction style. This is how it would look like with an immutable class :
var objectParams = new MyObjectParams
(
param1,
param2,
...
);
Note: it's just the long constructor line broken into several, so it's cleaner but still not as readable as initializers.
I was thinking of using named parameters to get both an immutable class and a more or less clean code, but I'm not sure whether this actually is a good idea:
var objectParams = new MyObjectParams
(
param1: ...,
param2: ...,
...
);
Should I use named parameters? Can you think of a better approach to solve this problem?
Edited regarding an answer below: unfortunately, I don't really think the design is bad. The 9 parameters really are required and remain constant throughout the entire life of the object. I cannot provide a default value for them as it is completely usage-dependant.
Have you looked into designing a solution in which you wouldn't need this amount of parameters? Having a lot of parameters makes the code very tightly coupled which reduces maintainability. Maybe you can redesign a small amount of code to a design which better separates the responsibilities of the class?
I really like the way The Zen of Python says a few things:
Simple is better than complex.
Complex is better than complicated.
[...]
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
I believe that having a dedicated Options class of some kind with the exhaustive list of all possible parameters is a good idea. Allow your MyObject constructor to require an Options instance, and then store a reference to the instance as a field on MyObject and refer to its getters/setters. (Storing the reference will be much superior to trying to parse the options and transfer their values to the MyObject instance. Now that would be messy.) With all data access delegated to the Options class, you will have successfully encapsulated the object's configuration, and you've designed a simple API for option access as the same time.
If Options has no reason to be publicly accessible, make it a private class definition and then you're free to maintain changes to Options logic without modifying MyObject. I believe that is a fair solution to you as the developer, and doesn't commit atrocities.
The constructor could have only a small number of parameters, the ones required for proper object initialization. You could then have a number of properties that can be set after the object has been constructed. You can set default values for those properties in the constructor and the client can set the ones he/she requires.
class Person
{
public Person(string name, int age)
{
Name = name;
Age = age;
Address = "Unknown";
Email = "Unknown";
}
public string Name {get; private set;}
public int Age {get; private set;}
public string Email {get; set;}
public string Address {get; set;}
}
Person p = new Person("John Doe", 30);
p.Email = "john.doe#example.org";
You could use the builder pattern to construct an immutable object.
public sealed class ComplexObject
{
public int PropA { get; private set; }
public string PropB { get; private set; }
public sealed class Builder
{
int _propA;
string _propB;
public Builder SetPropA(int propA)
{
// validate
_propA = propA;
return this;
}
public Builder SetPropB(string propB)
{
// validate
_propB = propB;
return this;
}
public CustomObject ToCustomObject()
{
return new CustomObject
{
PropA = _propA,
PropB = _propB
};
}
}
}
Usage
var custom =
new CustomObject.Builder()
.SetPropA(1)
.SetPropB("Test")
.ToCustomObject();
Final Thoughts
Despite my previous suggestion I am in no way against using named parameters if they are available.
I am attempting to apply the Strategy pattern to a particular situation, but am having an issue with how to avoid coupling each concrete strategy to the context object providing data for it. The following is a simplified case of a pattern that occurs a few different ways, but should be handled in a similar way.
We have an object Acquisition that provides data relevant to a specific frame of time - basically a bunch of external data collected using different pieces of hardware. It's already too large because of the amount of data it contains, so I don't want to give it any further responsibility. We now need to take some of this data, and based on some configuration send a corresponding voltage to a piece of hardware.
So, imagine the following (much simplified) classes:
class Acquisition
{
public Int32 IntegrationTime { get; set; }
public Double Battery { get; set; }
public Double Signal { get; set; }
}
interface IAnalogOutputter
{
double getVoltage(Acquisition acq);
}
class BatteryAnalogOutputter : IAnalogOutputter
{
double getVoltage(Acquisition acq)
{
return acq.Battery;
}
}
Now, every concrete strategy class has to be coupled to my Acquisition class, which is also one of the most likely classes to be modified since it's core to our application. This is still an improvement over the old design, which was a giant switch statement inside the Acquisition class. Each type of data may have a different conversion method (while Battery is a simple pass-through, others are not at all that simple), so I feel Strategy pattern or similar should be the way to go.
I will also note that in the final implementation, IAnalogOutputter would be an abstract class instead of an interface. These classes will be in a list that is configurable by the user and serialized to an XML file. The list must be editable at runtime and remembered, so Serializable must be part of our final solution. In case it makes a difference.
How can I ensure each implementation class gets the data it needs to work, without tying it to one of my most important classes? Or am I approaching this sort of problem in the completely wrong manner?
Strategy Pattern encapsulates a - usually complex - operation/calculation.
The voltage you want to return is dependent on
pieces of configuration
Some of the acquisition data
So I would put these into another class and pass it to strategy implementors.
Also in terms of serialisation, you do not have serialise the strategy classes, perhaps only their name or type name.
UPDATE
Well, it seems that your implementations need only one piece of the acquisition data. That is a bit unusual for a strategy pattern - but I do not believe it fits Visitor better so strategy is fine. I would create a class which has as property, acquisition data (perhaps inherits from it) in addition to configuration that implementors need.
One thing you could do is use factory methods to construct your Strategies. Your individual strategies can take in their constructor only the individual data elements they need, and the factory method is the only thing that needs to know how to fill in that data given an Acquisition object. Something like this:
public class OutputterFactory
{
public static IAnalogOutputter CreateBatteryAnalogOutputter(Acquisition acq)
{
return new BatteryANalogOutputter(acq.Battery);
}
}
Ok, I hate to not give someone else the credit here, but I found a hybrid solution that works very well for my purposes. It serializes perfectly, and greatly simplifies the addition of new output types. The key was a single interface, IOutputValueProvider. Also note how easily this pattern handles the retrieval of varying ways of storing the data (such as a Dictionary instead of a parameter).
interface IOutputValueProvider
{
Double GetBattery();
Double GetSignal();
Int32 GetIntegrationTime();
Double GetDictionaryValue(String key);
}
interface IAnalogOutputter
{
double getVoltage(IOutputValueProvider provider);
}
class BatteryAnalogOutputter : IAnalogOutputter
{
double getVoltage(IOutputValueProvider provider)
{
return provider.GetBattery();
}
}
class DictionaryValueOutputter : IAnalogOutputter
{
public String DictionaryKey { get; set; }
public double getVoltage(IOutputValueProvider provider)
{
return provider.GetDictionaryValue(DictionaryKey);
}
}
So then, I just need to ensure Acquisition implements the interface:
class Acquisition : IOutputValueProvider
{
public Int32 IntegrationTime { get; set; }
public Double Battery { get; set; }
public Double Signal { get; set; }
public Dictionary<String, Double> DictionaryValues;
public double GetBattery() { return Battery;}
public double GetSignal() { return Signal; }
public int GetIntegrationTime() { return IntegrationTime; }
public double GetDictionaryValue(String key)
{
Double d = 0.0;
return DictionaryValues.TryGetValue(key, out d) ? d : 0.0;
}
}
This isn't perfect, since now there's a gigantic interface that must be maintained and some duplicate code in Acquisition, but there's a heck of a lot less risk of something being changed affecting the other parts of my application. It also allows me to start subclassing Acquisition without having to change some of these external pieces. I hope this will help some others in similar situations.
I'm working on modeling a business domain object in a class and am wondering what would be the best way to properly encapsulate private fields that only apply to a few methods.
When I started, my code originally looked like this:
public class DiscountEngine
{
public Cart As Cart { get; set;}
public Discount As Discount { get; set;}
public void ApplySKUGroupDiscountToCart()
{
...
}
}
However, ApplySKUGroupDiscountToCart() was starting to get ugly, so I decided to refactor the code into smaller private methods that get called from ApplySKUGroupDiscountToCart(). I started by passing in lots of local variables into the helper method, but then decided to pull out variables common to both routines and make them private modular variables. The new code looks like this:
public class DiscountEngine
{
public Cart As Cart { get; set;}
public Discount As Discount { get; set;}
private int _SKUGroupItemDiscountsApplied = 0
private int _SKUGroupTotalDiscounts = 0
private int _SKUGroupID = 0
public void ApplySKUGroupDiscountToCart()
{
...
}
private void ApplyDiscountToSingleCartItem(ref CartItem cartI,
ref DiscountItem discountI)
{
...
}
}
On the one hand, the three private integer fields are useful for allowing the related methods to share common variables without needing to pass them back and forth as parameters. However, these variables are only applicable to these related methods and any other methods I might add would have no need to see them.
Is there a way to encapsulate the private fields and their related methods while still remaining a part of the DiscountEngine class? Is there a better way altogether of dealing with this problem?
Normally, making a class field private implies "I have enough discipline to ensure that this field is only used in an appropriate manner inside this class". If your class is too big for you to say that with confidence, then maybe the class is trying to do too many different things, and should be split up (see SRP).
Anyway, enough of the theory :-). If you want to stick with one class then you could always encapsulate those three fields into a private nested class, e.g.
public class DiscountEngine
{
public Cart As Cart { get; set;}
public Discount As Discount { get; set;}
private class SKUGroup
{
public int ItemDiscountsApplied = 0
public int TotalDiscounts = 0
public int ID = 0
}
public void ApplySKUGroupDiscountToCart()
{
...
}
private void ApplyDiscountToSingleCartItem(ref CartItem cartI,
ref DiscountItem discountI)
{
...
}
}
That gives you a bit more freedom to pass instances of the class around your code as method parameters.
You could take this a step further, and move any private methods that act on the SKU data into the nested class as well.
First things first, you very likely don't need to pass the parameters to ApplyDiscountToSingleCartItem as ref. Short version: unless you're actually assigning a value to the variable that you want to be visible to the calling code, you don't need ref. Modifying variable and property values on them will be visible to the calling code without passing them as ref.
Second, there is no way to scope a variable in between instance and local, which is what you're asking. The only way to accomplish this would be to refactor this functionality into another class (likely a nested private class).
Don't, however, use instance variables as a way to pass data between functions. If the data becomes "stale" after the function is called, then it should be a parameter, not an instance variable.
I would say the only other way that I can think of to handle this would be to extract all the methods and private variables that are associated with them into a separate class. That way you keep all that encapsulated. But not sure if that would make sense in the context of your domain objects.
You could always create a nested (inner) class to bundle together parameters that have a common use. In this way you could still pass them to your private methods without having to pass around l.ots of arguments - you'd just pass an instance of the private type.
"these variables are only applicable to these related methods and any other methods I might add would have no need to see them."
First of all, keep in mind that one of the first rules of OO development is to build what the customer wants THEN apply OO design like basic OO rules and patterns. Your quote verges on saying you want to plan for the unknown. Be careful that the unknown is "more of the same" not NEW requirements. Otherwise, this class is going to end up becoming a God Object.
If you find you have many members that aren't used by the methods, then divide and conquer.