Here briefly are the business requirements.
I have an entity called PricingSchedule that represents a "subscription" to a system. We use the term "Pricing Schedule", not "subscription" in our team's ubiquitous language, but in theory, a subscription is the same thing.
What determines the Price of the PricingSchedule is the combination of two things:
1. the "duration" of the PricingSchedule (aka, how long is your subscription... 1 year, 2 years, etc...
2. how many Styles (another entity) you want to include in your PricingSchedule. You have two options for how to include Styles; 1. pay per Style, 2. pay for all Styles
Number two is a newly added requirement. Before, it was primarily the PricingSchedule's Duration that determined the Price.
My problem is this... the Price of a PricingSchedule doesn't mean anything when either the Duration, or StylePricingType is applied by itself. I can only get the final Price when they're combined together; aka, 2 years duration with 5 styles.
We have four possible pre-determined durations, ranging from a couple of days, to a 3 or 4 years.
We have two possible ways to bill Style selection; 1. per Style or 2. all Styles. These two things combined then determined the overall Price.
I started thinking the Strategy design pattern could help me here, aka;
public interface IDurationPricingStrategy
public decimal GetDurationPriceFor(PricingSchedule)
public interface IStylePricingStrategy
public decimal GetStylePriceFor(PricingSchedule)
This is a good way to separate things that probably will change going forward, but herein lies the rub; I can't implement one Strategy without knowing the other Strategy's "conditionals."
For example, for the IStylePricingStrategy, I implement the unlimited style pricing option like so:
public class UnlimitedStylePricingStrategy : IStylePricingStrategy
{
public decimal GetStylePriceFor(PricingSchedule)
{
if (PricingSchedule.Duration.Type == DurationType.OneYear)
{
return decimal x;
}
if (PricingSchedule.Duration.Type == DurationType.TwoYears)
{
return decimal x;
}
}
}
if I take this approach, that means if and when I have to add or change a Duration pricing type, then I have to change my StyleStrategy implementation class, which breaks SRP, and basically puts me back to square one.
It's easy if there is only one "thing" that determines the Price for the PricingSchedule, but when I have two things like this, that's where I'm hitting a wall.
Is there another pattern I can use, or somehow use the Strategy pattern differently? I feel that the problem still pulls me towards Strategy, but I'm not sure how to incorporate two Strategies instead of one.
Thanks so much!
Mike
I think one way might be to create an interface for the duration:
public interface IDuration
{
int GetDuration();
decimal CalculatePrice(object whatever); // int something, or whatever.
}
The have your schedule class use it:
public class PricingSchedule
{
public IDuration Duration { get; set; }
}
Then your payment style classes could use the duration like so:
public class UnlimitedStylePricingStyle : PricingStyle
{
public override void GetStylePriceFor(PricingSchedule schedule)
{
int duration = schedule.Duration.GetDuration();
//.....
}
}
The tricky one is days, I'm not sure how you would deal with that, but I would think that using an interface is your best bet here. If you need to add a new duration, you simply implement the interface IDuration.
You could then calculate the price by something like:
public override void GetStylePriceFor(PricingSchedule schedule)
{
int duration = schedule.Duration.GetDuration();
int temp = 34;
decimal result = schedule.Duration.CalculatePrice(temp);
}
Hope this give you a rough idea.
Related
I am making a simple turn-based farming simulator game where players make choices whether to buy land or crops and have turn-count based growing. Different crops grow for different times, and have different purchase prices and sale values. Objective is to be the first to reach a dollar amount.
My question is how to develop these crops programmatically. I currently have each crop variation as a subclass of a Crop, however, this leads to a lot of redundancy (mostly different field/attribute values, or image paths). Since these objects are very similar save for some values, should they be subclasses, or would it be better practice to make one class Crop with an Enum of type and use logic to determine the values it should have?
Superclass Crop
subclass Wheat
subclass Corn
subclass Barley
Or
Crop.Type = CropType.Wheat
if(this.Type == CropType.Wheat) { return StockMarket.Wheat_Sell_Value; }
else if(this.Type == CropType.Corn) { return StockMarket.Corn_Sell_Value; }
If you make a single crop class it risks becoming very large and unwieldly, especially if you want to add a new crop type you'll have to update the 100's of if statements littered through your code (e.g. if(this.Type == CropType.Wheat) { return StockMarket.Wheat_Sell_Value; }).
To echo #oswin's answer, use inheritance sparingly. You are probably ok using a base-class with a few "dumb" properties, but be especially careful when adding anything that implements "behaviour" or complexity, like methods and logic; i.e. anything that acts on CropType within Crop is probably a bad idea.
One simple approach is if crop types all have the same properties, but just different values; and so crop instances just get acted on by processes within the game, see below. (Note: If crops have different properties then I would probably use interfaces to handle that because they are more forgiving when you need to make changes).
// Crop Types - could he held in a database or config file, so easy to add new types.
// Water, light, heat are required to grow and influence how crops grow.
// Energy - how much energy you get from eating the crop.
Name:Barley, growthRate:1.3, water:1.3, light:1.9, heat:1.3, energy:1.4
Name:Corn, growthRate:1.2, water:1.2, light:1.6, heat:1.2, energy:1.5
Name:Rice, growthRate:1.9, water:1.5, light:1.0, heat:1.4, energy:1.8
The crop type values help drive logic later on. You also (I assume) need crop instance:
class CropInstance
{
public CropType Crop { get; set; }
public double Size { get; set; }
public double Health { get; }
}
Then you simply have other parts of your program that act on instances of Crop, e.g:
void ApplyWeatherForTurn(CropInstance crop, Weather weather)
{
// Logic that applies weather to a crop for the turn.
// E.g. might under or over supply the amount of water, light, heat
// depending on the type of crop, resulting in 'x' value, which might
// increase of decrease the health of the crop instance.
double x = crop.WaterRequired - weather.RainFall;
// ...
crop.Health = x;
}
double CurrentValue(CropInstance crop)
{
return crop.Size * crop.Health * crop.Crop.Energy;
}
Note you can still add logic that does different things to different crops, but based on their values, not their types:
double CropThieves(CropInstance crop)
{
if(crop.health > 2.0 & crop.Crop.Energy > 2.0)
{
// Thieves steal % of crop.
crop.Size = crop.Size * 0.9;
}
}
Update - Interfaces:
I was thinking about this some more. The assumption with code like double CurrentValue(CropInstance crop) is that it assumes you only deal in crop instances. If you were to add other types like Livestock that sort of code could get cumbersome.
E.g. If you know for certain that you'll only ever have crops then the approach is fine. If you decide to add another type later, it will be manageable, if you become wildly popular and decide to add 20 new types you'll want to do a re-write / re-architecture because it won't scale well from a maintenance perspective.
This is where interfaces come in, imagine you will eventually have many different types including Crop (as above) and Livestock - note it's properties aren't the same:
// growthRate - how effectively an animal grows.
// bredRate - how effectively the animals bred.
Name:Sheep, growthRate:2.1, water:1.9, food:2.0, energy:4.6, bredRate:1.7
Name:Cows, growthRate:1.4, water:3.2, food:5.1, energy:8.1, breedRate:1.1
class HerdInstance
{
public HerdType Herd { get; set; }
public int Population { get; set; }
public double Health { get; }
}
So how would interfaces come to the rescue? Crop and herd specific logic is located in the relevant instance code:
// Allows items to be valued
interface IFinancialValue
{
double CurrentValue();
}
class CropInstance : IFinancialValue
{
...
public double CurrentValue()
{
return this.Size * this.Health * this.Crop.Energy;
}
}
class HerdInstance : IFinancialValue
{
...
public double CurrentValue()
{
return this.Population * this.Health * this.Herd.Energy - this.Herd.Food;
}
}
You can then do things with objects that implement IFinancialValue:
public string NetWorth()
{
List<IFinancialValue> list = new List<IFinancialValue>();
list.AddRange(Crops);
list.AddRange(Herds);
double total = 0.0;
for(int i = 0; i < list.Count; i++)
{
total = total + list[i].CurrentValue();
}
return string.Format("Your total net worth is ${0} from {1} sellable assets", total, list.Count);
}
You might recall that above I said:
...but be especially careful when adding anything that implements
"behaviour" or complexity, like methods and logic; i.e. anything that
acts on CropType within Crop is probably a bad idea.
...which seems to contradict the code just above. The difference is that if you have one class that has everything in it you won't be able to flex, where as in the approach above I have assumed that I can add as many different game-asset types as I like by using the [x]Type and [x]Instance architecture.
The answer depends on the difference in functionality between the crop types. The general rule is to avoid unnecessary complexity where possible and inheritance should be used sparingly because it introduces hard dependencies.
So if all crops are functionally similar and only differ by their attribute values then you would want to use a single class for crop, but if your game logic demands the crop types to behave very differently and/or carry very different sets of data, then you may want to consider creating separate structures.
If inheritance would be the best choice (in case you need separate structures) cannot be answered without knowing the exact details of your game world either. Some alternatives you could consider are:
interfaces (or another type of mix-in), which allows you to re-use behavior or data across multiple types, e.g. if crops can be harvested, maybe forests can be harvested as well.
structs (or data-classes), which only define the data structure and not the behavior. This is generally more efficient and forces you to do a simpler design with less abstractions.
a functional programming approach where the crops only exist as primitives being passed around functions. This has all the benefits of functional programming, such as no side effects, less bugs, easier to write tests, easier concurrency designs which can help your game scale larger.
This is a question regarding the concept of OOP.
Let's say I'm creating a game and I have a few objects:
Field - representig some field on the map.
User - representing a player.
Item - representing an item that user can have (for example shovel)
Now I know that player can dig a field using shovel. And this action will be a method of one of those classes. Is there some rule to determine which of those classes should have this method.
The most obvious performer of this action is the player (User), so User class could have method like digField(Field field). But actually the field itself is most affected by this action, so maybe it shold be the Field class method, like dig(User performer) or dig(Item toolUsed). Or maybe the Item itself should have a child class like Tool with a method like digField(Field field).
There are lots of ways to solve this problem and I was just wondering if there is some kind of simple best practice there.
Like said in other answers, it depends on what else is happening (or can happen in the future).
For example, for digging there can be some options:
user.digField(field, tool): this way can be helpful when your user also needs to spend time, or maybe he gets tired, i.e. use this way if you want to FOCUS on the user.
field.dig(user, tool): this way can be helpful when the field itself should be focussed on, like setting the status of the field.
tool.dig(user, field): this way can be used to change e.g. the status of the tool, or the maintenance needed.
However, in most cases there are a multiple of statuses/changes need to be set. So maybe it is best to create a separate class Action like:
public class Action
{
public void DigField(User user, Location location, Tool tool)
{
user.Status = Digging;
user.Energy -= 50;
location.Status = Digging;
tool.Status = Digging;
tool.Usage++;
}
}
As you can see this function may grow as action might get more complex. So what is a good way to call separate functions in the appropriate classes, like a mix:
public class Action
{
public void DigField(User user, Location location, Tool tool)
{
user.DigField();
location.Dig();
tool.Dig();
}
}
public class User
{
public void DigField()
{
Status = Digging;
Energy -= 50;
}
}
public class Field
{
public void Dig()
{
Status = Digging;
}
}
public class Tool
{
public void Dig()
{
Status = Digging;
Usage++;
}
}
This has the advantage to keep the functionality where it belongs.
Nothing prevents you from passing parameters, like if the energy drain for auser depends on the type of field, use:
public class User
{
public void DigField(Field field)
{
Status = Digging;
Energy -= field.Type == Clay ? 30 : 20;
}
}
It depends on the rest of your game. You can't architect your classes without thinking about all of it. So questions such as:
Are there many tools, do they perform different actions on different objects?
Are there many types of land masses (field, stream, etc)
Does the user have any effect (such as with strength) on the action
These types of questions are useful to think about before laying out your classes. As an example, if you have many different tools, then you could tie the digging with the shovel, which will detail what it does to different types of land (and which ones it can work with). Then maybe there is a tractor, which does something different to the land.
One last thought, the closer your classes match the real world, the better the classes work as the code expands. In other words, if you were describing a shovel to someone who has never seen one, your class should model itself after that kind of description.
This not a case of overloading, I think you have recognise the complexity but you are trying to escape it. It's been you take time to model it now,it may be costly later.
Here is what I think:
User object performs the action so it must have the User.Dig() method. Maybe you can decide to pass in an Item object (eg Shovel).
Field object reacts to the action (Dig) of the User object. You now have to determine what this reaction is. Also you determine what the action is.
Like you said there are likely many approach and I think game engines have solved problems like this but I don't use them so I can't recommend. If I would have to model what explain I first try out Observable Pattern https://en.wikipedia.org/wiki/Observer_pattern?wprov=sfla1
Good luck
Probably going to get shot down for this, but I have an issue with my parameters.
Say I need to store a race (Which I do)
During planning, I realized I needed to store things like:
Terrain of the race
location of the race
time the race starts
time admission ends.
Name of the Race
Types of member permitted to join
etc
In short, it's a ton of underivable data that can't really come from elsewere
and all in all, I have like, 22 parrameters for my JuniorRace object, and like 26 Parameters for my SeniorRace object, I've already coded it but it's messy and I don't like my work.
This wouldn't be a massive problem, and it actually won't be a problem AT ALL for the users since they won't see the business model, just the view model, but it is for me having to constantly comment these same parameters multiple times.
What is the best way I can stop using so many parameters every time I make a constructor, and every time I create a new object instance?
do I just try to use less and store data elsewhere, if so, where?
use more classes like Person would have Address and Details?
I'm really stumped here, will post my code, but yeah, it's a ton of parameters pretty much everywhere -- I'm not a very experienced OO programmer.
You could store all the parameters as a map and just pass in the map, something like:
Map myParams = new HashMap<String,Object>();
myParams.add("Terrain","terrible");
myParams.add("Location","Bobs back yard");
myParams.add("Length (yards)", 100);
myParams.add("Hazards", new String[] {"Bob's cat","The old tire","the fence"});
Then you could calll your routine like this:
SaveRaceCourse(myParams);
Maps and suchlike are great for passing around data.
As I can't see all 22 parameters this is a guess but most probably a correct one.
Are some of those 22 parameter related. If so group the related ones in another class and make SeniorRace a composition of all these classes.
For example: location and terrain seem related, admission period and allowed member types seems related to admission (maybe a fee is part of it too).
This way you will end up with a limited set of objects to pass, all related info lives together and evolve together.
Break it down by encapsulating similar properties in objects. It's called decomposition.
For example, your Race can accept a TimeCard encapsulating all the timing details, a Location which has the terrain and what not (maybe directions), an object encapsulating the requirements, ect...
class RaceTimeCard {
private final Timestamp admissionStart;
private final Timestamp admissionEnd;
private final Timestamp raceStart;
private Timestamp raceEnd;
public RaceTimeCard(Timestamp admissionStart, Timestamp admissionEnd, Timestamp raceStart) {
//init final fields
}
public void endRace() {
//clock the time that the race ended
}
}
class RaceLocation {
private final Terrain terrain;
private final Directions directions;
private final GPSCoordinates coordinates;
public RaceLocation(Terrain terrain, Directions directions, GPSCoordinates coordinates) {
//init final fields
}
}
class Race {
private RaceTimeCard timeCard;
private RaceLocation location;
public Race(RaceTimeCard timeCard, RaceLocation) {
//init fields
}
}
If you'd like, you could subclass Location and TimeCard to create specific instances:
final class Mountains extends RaceLocation {
public Mountains() {
super(Terrain.ROCKY, new Directions(...), new GPSCoordinates(...));
}
}
final class EarlyBirdTimeCard extends RaceTimeCard {
public EarlyBirdTimeCard() {
//specify super constructor with params
}
}
Now instantiating your Race object is as simple as:
RaceTimeCard timeCard = new EarlyBirdTimeCard();
RaceLocation location = new Mountains();
...
Race race = new Race(timeCard, location, ...);
If it's still too long, you can probably decompose more. The way I see it, you could have a RaceDetails object containing all the (already decomposed) details, then pass that to Race. Make sure to profile your application, make sure the overhead from object creation doesn't get too bad.
I have an OOP design question.
Let's assume that I have a class that contains several numerical scalar properties like maximum, minimum, frequency etc. Since data are flowing in continuously I eventually end up with a list of such class instances. To obtain, say, the global minimum I loop over all classes in the list to find it.
Alternatively, I could instantiate one class (possibly a singleton) that contains lists instead of scalars for each property, and function members that loop over the lists. This approach however seems to generate code that looks more like procedural than object oriented programming.
The question is: What criterions define which approach to choose? If efficiency is important, should I choose one class that contains lists for each properties? If readability is key, should I choose a list of classes?
Thanks for suggestions.
Basically you're askyng if it's more preferable to have an "Array of Structures (AoS)" or "Structure of Arrays (SoA)"
The answer depends on what you need to do with this data. If you want to write a more readable code than go for an Array of Structures, if you want to use SSE or CUDA to optimize your computation-heavy code then go for a Structure of Arrays.
If you search in literature the terms "Array of Structures (AoS)" and "Structure of Arrays (SoA)" you will find many in depth dissertations on this topic, i link just some discussions here:
Structure of arrays and array of structures - performance difference
http://hectorgon.blogspot.it/2006/08/array-of-structures-vs-structure-of.html
http://people.maths.ox.ac.uk/~gilesm/hpc/NVIDIA/NVIDIA_CUDA_Tutorial_No_NDA_Apr08.pdf
http://en.wikipedia.org/wiki/Stream_processing
You were asking for decision criteria. Let me recommend one:
You should think about what constitutes a data point in your application. Let's assume you are measuring values, and one data point consists of several numerical properties. Then you would certainly want a list of classes, where the class represents all of the properties that go together (what I called 'data point' for lack of a better term).
If you must perform some aggregation of these 'data points', such as finding a global minimum over a longer time period, I would suggest designing an extra component for this. So you'd end up with a data gathering component which consists mainly of a 'list of classes', and an aggregation component which may utilize different data structures, but processes parts of your 'list of classes' (say, the part over which the global minimum is to be found).
Basically, OOP is not a solution to every question in programming, sometimes you have to see beyond this,below this. The thing is you have to concentrate on the problem. Efficiency should be more preferable. But if your code is taking too much time to load or you can say its time complexity is too much high then again you'll have trouble. You have to keep to keep both ends in hands. What i'll prefer is the list of classes not the class of list. But different people have different point of views and so we should respect them. Why i am chosing list of classes because,i'll have each object with the respected data, say , i have one object with higher frequency,one with lower,one with a medium,it will be easier to manage all that,plus not much time will be taken. i think in both cases it will be O(n) where n is the number of elements or classes in my case.
In your case, list of data
struct Statistic{
int max;
int min;
std::vector<int> points;
int average;
};
int main(){
std::vector<Statistic> stats;
return 0;
}
You could also store the values and the statistics together in one class and do the calculations on the fly when adding a new value (example in Java):
public class YourClass {
private List<Integer> values = new ArrayList<Integer>();
private long sum = 0;
private int minimum = Integer.MAX_VALUE;
private int maximum = Integer.MIN_VALUE;
// add more stuff you need
public synchronized void add(Integer value) {
values.add(value);
sum += value;
if (value < minimum) {
minimum = value;
}
if (value > maximum) {
maximum = value;
}
}
public List<Integer> getValues() {
return Collections.unmodifiableList(values);
}
public long getSum() {
return sum;
}
public long getAvg() {
return values.isEmpty() ? 0 : sum / values.size();
}
public int getMaximum() {
return maximum;
}
public int getMinimum() {
return minimum;
}
}
This is quite a common problem I run into. Let's hear your solutions. I'm going to use an Employee-managing application as an example:-
We've got some entity classes, some of which implement a particular interface.
public interface IEmployee { ... }
public interface IRecievesBonus { int Amount { get; } }
public class Manager : IEmployee, IRecievesBonus { ... }
public class Grunt : IEmployee /* This company sucks! */ { ... }
We've got a collection of Employees that we can iterate over. We need to grab all the objects that implement IRecievesBonus and pay the bonus.
The naive implementation goes something along the lines of:-
foreach(Employee employee in employees)
{
IRecievesBonus bonusReciever = employee as IRecievesBonus;
if(bonusReciever != null)
{
PayBonus(bonusReciever);
}
}
or alternately in C#:-
foreach(IRecievesBonus bonusReciever in employees.OfType<IRecievesBonus>())
{
PayBonus(bonusReciever);
}
We cannot modify the IEmployee interface to include details of the child type as we don't want to pollute the super-type with details that only the sub-type cares about.
We do not have an existing collection of only the subtype.
We cannot use the Visitor pattern because the element types are not stable. Also, we might have a type which implements both IRecievesBonus and IDrinksTea. Its Accept method would contain an ambiguous call to visitor.Visit(this).
Often we're forced down this route because we can't modify the super-type, nor the collection e.g. in .NET we may need to find all the Buttons on this Form via the child Controls collection. We may need to do something to the child types that depends on some aspect of the child type (e.g. the bonus amount in the example above).
Strikes me as odd that there isn't an "accepted" way to do this, given how often it comes up.
1) Is the type conversion worth avoiding?
2) Are there any alternatives I haven't thought of?
EDIT
Péter Török suggests composing Employee and pushing the type conversion further down the object tree:-
public interface IEmployee
{
public IList<IEmployeeProperty> Properties { get; }
}
public interface IEmployeeProperty { ... }
public class DrinksTeaProperty : IEmployeeProperty
{
int Sugars { get; set; }
bool Milk { get; set; }
}
foreach (IEmployee employee in employees)
{
foreach (IEmployeeProperty property in employee.Propeties)
{
// Handle duplicate properties if you need to.
// Since this is just an example, we'll just
// let the greedy ones have two cups of tea.
DrinksTeaProperty tea = property as DrinksTeaProperty;
if (tea != null)
{
MakeTea(tea.Sugers, tea.Milk);
}
}
}
In this example it's definitely worth pushing these traits out of the Employee type - particularly because some managers might drink tea and some might not - but we still have the same underlying problem of the type conversion.
Is it the case that it's "ok" so long as we do it at the right level? Or are we just moving the problem around?
The holy grail would be a variant on the Visitor pattern where:-
You can add element members without modifying all the visitors
Visitors should only visit types they're interested in visiting
The visitor can visit the member based on an interface type
Elements might implement multiple interfaces which are visited by different visitors
Doesn't involve casting or reflection
but I appreciate that's probably unrealistic.
I would definitely try to resolve this with composition instead of inheritance, by associating the needed properties/traits to Employee, instead of subclassing it.
I can give an example partly in Java, I think it's close enough to your language (C#) to be useful.
public enum EmployeeProperty {
RECEIVES_BONUS,
DRINKS_TEA,
...
}
public class Employee {
Set<EmployeeProperty> properties;
// methods to add/remove/query properties
...
}
And the modified loop would look like this:
foreach(Employee employee in employees) {
if (employee.getProperties().contains(EmployeeProperty.RECEIVES_BONUS)) {
PayBonus(employee);
}
}
This solution is much more flexible than subclassing:
it can trivially handle any combination of employee properties, while with subclassing you would experience a combinatorial explosion of subclasses as the number of properties grow,
it trivially allows you to change Employee properties runtime, while with subclassing this would require changing the concrete class of your object!
In Java, enums can have properties or (even virtual) methods themselves - I don't know whether this is possible in C#, but in the worst case, if you need more complex properties, you can implement them with a class hierarchy. (Even in this case, you are not back to square one, since you have an extra level of indirection which gives you the flexibility described above.)
Update
You are right that in the most general case (discussed in the last sentence above) the type conversion problem is not resolved, just pushed one level down on the object graph.
In general, I don't know a really satisfying solution to this problem. The typical way to handle it is using polymorphism: pull up the common interface and manipulate the objects via that, thus eliminating the need for downcasts. However, in cases when the objects in question do not have a common interface, what to do? It may help to realize that in these cases the design does not reflect reality well: practically, we created a marker interface solely to enable us to put a bunch of distinct objects into a common collection, but there is no semantical relationship between the objects.
So I believe in these cases the awkwardness of downcasts is a signal that there may be a deeper problem with our design.
You could implement a custom iterator that only iterates over the IRecievesBonus types.