There is something I do not understand about open-close principle. Let's say that you have done this code:
public abstract class Player
{
public string Name { get; set; }
public int Level { get; set; }
}
public sealed class Fighter : Player { /* ... */ }
public sealed class Warrior : Player { /* ... */ }
This code works perfectly, you've done a first release, eveyrthing is OK.
Now you want to add some features, like a player can equip a ring. Open-close principle says open to extension, close to modification. How could I implement the fact that my players can have rings if I shouldn't modify these class?
You can modify class Player by adding new methods and fields. It is open to extension. But if you already have some methods like Jump or Fight and you want to modify them - that is breaking the principle.
Imagine, your class Fighter has method Fight() and it uses only bare hands:
public Fighter() : Player
{
...
public virtual void Fight()
{
//use bare hands
}
}
If you want Fighter to fight with a stick (for example) you should not modify initial method Fight() but add another class like FighterWithStick : Fighter and override method Fight() there:
public FighterWithStick() : Fighter
{
...
public override void Fight()
{
//use stick
}
}
First think why this kind of rule might be useful. Closed to modification, open to extension. This makes sense for libraries or code that must be backwards compatible. Think of this example:
I've written "BestLibrary" library which exposes interface:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
}
}
But in the next release I want to decide what Goodies to give based on a parameter, so I change the interface to:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
public enum GoodiesType { All, Type1, Type2 }
Now everyone who uses my library has to fix their code, because their projects will stop building. This brakes Open/Closed principle. Instead I should make another method, like this:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
Here I didn't modify anything. Old code still works. Someone wants random Goodies? They can still get it. I extended GoodStuff interface with additional method. This way everything compiles and people can use new functionality.
If you work on a project that is not a library or api, then I don't see any reason to follow this principle. Requirements change and code should follow.
Related
I'm trying to practice with inheritance and just in general having scripts interact with each other and I thought doing a simple effect system could be fun, but I'm a bit stuck on how to structure things.
I keep wanting to do this
public abstract class BaseEffect : ScriptableObject
{
//not sure if this is a good use of enum
public enum EffectType
{
harm, //can be applied to enemies
help, //can be applied to allies
self //can be applied to yourself
}
public string name;
public string description;
public float duration;
public bool canStack; //can the effect be applied multiple times
public EffectType type;
//I'd probably also write my apply and remove effect methods here
}
And then a bunch of derived classes like this
public class TestEffect : BaseEffect
{
//maybe include some variables specific to this effect
//when the effect gets applied have this run every frame to od whatever the effect does
public void DoEffect()
{
}
}
I have a feeling though that this isn't a good way to go about doing this or at least the way I've written it isn't good so looking for some advice to get on the right track
This arrangement may benefit from an abstract method or usage of an Interface consumed by an abstract class to enforce derived classes to respond to events. Speaking of events, you could also wire the derived calls up through events. In simple terms, introduce an abstract method in the base class, which must be implemented in derived classes. Then call the method in the base classes "plumbing" when everything special about the event is ready.
public abstract class BaseEffect : ScriptableObject
{
protected abstract void DoEffect();
private SomeMethod()
{
if(canDoEffect)
DoEffect();
}
}
Basically I'm trying to create a attatchment system for a 2D platform/shooter game, the weapon system is working great but I want to implement some attachments, diferent barrels, magazines even ammo types.
For the simpler ones that just modify a stat I was thinking of just creating a class or even a struct with all the possible stats (damage, recoil, spread etc) and just setting them to the appropiate values (+1, -5, 0 if it doesn't use it). However, there are some ideas that might require a separate method/function, like shooting different bullets.
My main question is would it be more effective/efficient to just make smaller scripts for the edge cases and a main one for the simple stat changers. Or should I just overload a main script/class with methods for all the possible attachments?
There aren't that many "special" attachments, but i'd like to make a system that expandable if possible.
Im not an expert programmer (I just learned about enums a couple days ago!) so any suggestions are greatly appreciated.
I would use Unity's ScriptableObject class to create an abstract class then inherit from that abstract class to create more spesific classes and abstract classes.
Then I would create my attachments etc. in unity editor and modify whatever value I want from it.
An example armor piece would inherit the following ArmorItem class and use the ApplyEffect method to make the player bigger to show that you can make any type of modification.
ItemBase class
using UnityEngine;
public abstract class ItemBase: ScriptableObject
{
public string ItemName;
public abstract void ApplyEffect();//override this method for any edge case items
}
ArmorItem
public abstract class ArmorItem: ItemBase
{
public float Armor;//use this however you want
}
EdgeCaseArmor
[CreateAssetMenu(menuName = "Items/Armor/EdgeCaseArmor")]
public class EdgeCaseArmor: ArmorItem
{
public override void ApplyEffect()
{
//find player and make it bigger
GameObject.FindGameObjectWithTag("Player").transform.localScale *= 1.5f;
}
}
Obviously you will need to load items and somehow call ApplyEffect. You can do it at the start of the game by adding this to a start method.
var item = Resources.Load("path to your scriptable object that inherits ItemBase") as ItemBase;
item.Activate();
How you load the items and call them is up to you. You will need to save your scriptable objects in Assets>Resources folder(create one if you haven't created one already).
You can also make multiple armors with different names, armor values etc. like this.
Note that if you want to have an armor with no special effect you will need to make ArmorItem a normal class or make a NormalArmor class that inherits ArmorItem. Just leave the ApplyEffect function empty if you don't want any special effects.
This is a fairly general question so keep in mind that you may get several varying opinion-related answers.
With that said, the biggest suggestion that I would give is to look into Inheritance. Using a series of interfaces and classes to more refine the base concept of "item modifications".
For instance, I would create an interface:
interface IItemModification
{
void Apply();
}
Any more refined modification class or interface would implement (in the case of a class) or inherit (in the case of another interface) this interface.
In this example we will just create a base class that implements that interface:
public class ItemModification : IItemModification
{
public void Apply()
{
// Logic to apply modifications to the item.
}
}
In the case above, you now have a very basic class that represents an item modification which contains the implementation of the interface.
Next you might want to go into further detail, perhaps by creating item type implementations:
public class WeaponItemModification : ItemModification
{
public ArmorItemModification(StatModifiers modifiers, AttackType attackType)
{
this.Modifiers = modifiers;
this.Attack= attackType;
}
public AttackType Attack
{
get; set;
}
public StatModification Modifiers { get; set; }
}
public class ArmorItemModification : ItemModification
{
public ArmorItemModification(StatModifiers modifiers, DefenseType defenseType)
{
this.Modifiers = modifiers;
this.Defense = defenseType;
}
public DefenseType Defense
{
get; set;
}
public StatModification Modifiers { get; set; }
}
Of course a logical progression of that would be more specific item types:
public class VestModification : ArmorItemModification
{
public VestModification(StatModification modifiers, DefenseType defenseType, AreaProtectionType areaProtectionType)
{
this.Modifiers = modifiers;
this.Defense = defenseType;
this.AreaProtection = areaProtectionType;
}
public AreaProtectionType AreaProtection
{
get; set;
}
}
These are just some basic examples to point you in the right direction. I would suggest reading up on inheritance concepts to get a better understanding of it.
I wonder since there is no way how to implement a generic Decorator class in C# (is it?) like this:
public class Decorator<TDecoratorIterface> : TDecoratorInterface
{
public TDecoratorInterface Component {get; private set;}
protected Decorator(TDecoratorInterface component)
{
Component = component;
}
}
use like this:
public interface IDogDecorator
{
void Bark();
}
public class Dog : IDogDecorator
{
public void Bark()
{
Console.Write("I am a dog");
}
}
public class StinkingDog : Decorator<IDogDecorator>
{
public StinkingDog(IDogDecorator dog):base(dog)
{
}
public void Bark()
{
Component.Bark();
Console.WriteLine(" and I stink");
}
}
can such a thing be managed via PostSharp or any other AOP framework for .NET?
thank fro your answers, I spent half a day trying to create such a construct without any success, so any help is appreciatted:)
There's no direct equivalent to this construct, as C# doesn't allow the base class of a type to be dynamic. Remember that the generic type must be fully defined at compile time, not at usage time.
There's multiple possible ways to go: In the example above, the StinkingDog should just implement the IDogDecorator interface. So just specify that there. You're forwarding calls anyway.
public class StinkingDog : Decorator<IDogDecorator>, IDogDecorator
There would probably be frameworks that do what you want exactly (i.e. Rhino.Mocks is actually creating Mocks this way), but for production code, I'd really suggest not doing any AOP approach. It's clumsy and slow.
If I have a class that is based off another class, how do I access the properties of the first class if it can have any name? I was thinking of using generics to access the properties, but the generics are "generic" for a reason...
For example:
public class AGameInXNA : Microsoft.Xna.Framework.Game
{
int ExampleGameProperty;
}
// ... another class ... //
public class ReferenceToAGameInXNA
{
Game gameInstance;
public void SetGameInstance(Game game)
{
gameInstance = game;
}
public void SetExampleGameProperty()
{
gameInstance.ExampleGameProperty = 21; // I don't know the name of
// AGameInXNA, so I want to
// access it using a generic
// class.
}
}
I know that that does not work, so how would I use generics in this case to access the AGameInXNA's properties in another class if I don't know AGameInXNA's name?
EDIT: I am trying to make it so that I can reuse this code later on. I want to be able to have a class that is unknown, such as public class unknownclassname that extends another class, such as Microsoft.Xna.Framework.Game, and be able to access the class unknownclassname without directly calling/implementing it in the library code.
I would recommend looking into XNA Services.
So for example, you would create a service which could be as simple as an
interface IExamplePropertyService
{
int ExampleProperty { get; set; }
}
public class AGameInXNA : Microsoft.Xna.Framework.Game, IExamplePropertyService
{
int ExampleGameProperty { get; set; }
void Initialize()
{
// Do other initialization
Services.Add( typeof(IExamplePropertyService), this );
}
}
public class ReferenceToAGameInXNA
{
IExamplePropertyService propertyService;
public void GetGameInstance(Game game)
{
propertyService = (IExamplePropertyService)game.GetService( typeof(IExamplePropertyService) );
}
public void SetExampleGameProperty()
{
propertyService.ExampleGameProperty = 21;
}
}
Implement it, and register it with the Game component, then in your ReferenceToAGameInXNA, you would query for this service and store it (rather than the Game) for use later.
As a bonus benefit, The IExamplePropertyService no longer even needs to be implemented by the Game class, it could be implemented by any GameComponent.
This makes for an easy way to seperate classes from having to know about the inner workings of other classes in the Game. So long as the services exist somewhere, your ReferenceToAGameInXNA can be used.
I don't think generics are what you are actually looking for here. In your second class, just change the type of all of the gameInstance to the type of the class you created for your game, in this case AGameInXNA. There should only be a need for one subclass of the Game type in each XNA game. That will allow you to access any public members of AGameInXNA from the Reference class.
If this isn't what you are after, please give a more detailed explanation of what you are trying to accomplish and I'll try to help you.
I don't know XNA, but if you want to have several classes that inherit from Game and have the same property on all of them, you could create an abstract class that inherits from Game and let the other classes inherit from that instead.
(Also, your GetGameInstance() is badly named, because it sets the field, it doesn't get it. And it's probably better as property anyway.)
public abstract class GameBase : Microsoft.Xna.Framework.Game
{
public int ExampleGameProperty { get; set; }
}
public class AGameInXNA : GameBase
{
// code specific to AGameInXNA
}
public class ReferenceToAGameInXNA
{
public GameBase GameInstance { get; set; }
public void SetExampleGameProperty()
{
GameInstance.ExampleGameProperty = 21;
}
}
If the other classed that have ExampleGameProperty shouldn't inherit from Game, you could create an interface instead. AGameInXNA would then inherit from Game directly and it would also implement the interface. And you would work with that interface in ReferenceToAGameInXNA.
using "Game gameInstance;" you can not acess ExmpleProp. You should use "AGameInXNA gameInstance;" too access ExampleProp.
I'll explain my problem with an example.
I have an AnimalService, allowing me to increase the amount of show time the favourite animal gets for a specific zoo:
public sealed class AnimalService<TZoo> : IAnimalService<TZoo> where TZoo : IZoo
{
private readonly IFavouriteAnimalResolver<TZoo> favouriteAnimalResolver;
private readonly IAnimalShowTimeService animalShowTimeService;
public AnimalService(
IFavouriteAnimalResolver<TZoo> favouriteAnimalResolver,
IAnimalShowTimeService animalShowTimeService)
{
this.favouriteAnimalResolver = favouriteAnimalResolver;
this.animalShowTimeService = animalShowTimeService;
}
public void IncreaseShowTimeForFavouriteAnimal(TZoo zoo)
{
var favouriteAnimal = favouriteAnimalResolver.GetFavouriteAnimal(zoo);
animalShowTimeService.IncreaseShowTimeForAnimal(favouriteAnimal);
}
}
The AnimalService uses a resolver to get the favourite animal for TZoo, and then it calls an instance of IAnimalShowTimeService to increase the amount of show time the favourite animal will get. Below is the definition of the IFavouriteAnimalResolver interface and implementation of it that allows me to resolve the favourite animal for LondonZoo:
public interface IFavouriteAnimalResolver<TZoo> where TZoo : IZoo
{
IAnimal GetFavouriteAnimal(TZoo londonZoo);
}
public class LondonZooFavouriteAnimalResolver : IFavouriteAnimalResolver<LondonZoo>
{
public IAnimal GetFavouriteAnimal(LondonZoo londonZoo)
{
return new Lion();
}
}
Oki, so all good so far. Now for the complication. I would like to perform some animal specific logic once the IncreaseShowTimeForFavouriteAnimal is run. So my base AnimalShowTimeService stub looks like this:
public class AnimalShowTimeService : IAnimalShowTimeService
{
public void IncreaseShowTimeForAnimal(IAnimal animal)
{
// Update the show time for the animal
// Now call out to the AnimalUpdatedService<> instance to do any logic required for the animal
}
}
I would like to be able to call an update service that will get resolved via structuremap for the specific animal type, so I can run some update logic related to that specific type of animal. I have the following animalupdated interfaces for this purpose:
public interface IAnimalUpdatedService<T> where T : IAnimal
{
void LogTheUpdate(T animal);
}
public class DefaultAnimalUpdatedService<T> : IAnimalUpdatedService, IAnimalUpdatedService<T> where T : IAnimal
{
public void LogTheUpdate(T animal)
{
}
}
public class LionUpdatedService : IAnimalUpdatedService<Lion>
{
public void LogTheUpdate(Lion animal)
{
Console.WriteLine("The lion was updated");
}
}
As you can see, I have a DefaultAnimalUpdatedService which I want to be used when no specific update service was registered for an animal. I also have a LionUpdatedService which I would like to use every time a Lion's show time was increased for a zoo.
My problem is that because the favourite animal for a zoo can be any animal, the IFavouriteAnimalResolver returns an IAnimal type back and not a concrete. So I am not sure how I can use structuremap within IncreaseShowTimeForAnimal to get the LionUpdatedService service when a Lion's show time has been updated. I have played around with following code, but this won't work because I don't know the concrete at design time:
public class AnimalShowTimeService : IAnimalShowTimeService
{
public void IncreaseShowTimeForAnimal(IAnimal animal)
{
// Update the show time for the animal
var animalUpdatedService = ObjectFactory.ForGenericType(typeof(IAnimalUpdatedService<>))
.WithParameters(animal.GetType())
.GetInstanceAs<IDONTKNOWTHECONCRETE>();
animalUpdatedService.LogTheUpdate(animal);
}
}
I hope this all is clear. :)
I am not very well versed in StrutureMap, so would appreciate if anyone knows of an elegant way to approach this problem.
I have zipped up a test project I created using the above described code. You can download it here if you want to have a quick environment to fool around in:
[removed this link - no longer needed]
EDIT:
This is just a test project I created to illustrate the problem I am currently having in a much larger and more complex project. Unfortunately I can't redesign the entire architecture of the project to find a better design more geared towards this solution as I simply don't have the time. Being able to get the structuremap call simply return the correct concrete based on requirements above would be my immediate win. Learning about a better design to ensure things like this don't happen to me again would be a secondary win.
Thanks people :)
A few points:
a) Following the principle of "Tell, don't ask", it is not the AnimalShowTimeService's reposibility to resolve the type. Push the Animal to another object to make the choice.
b) Hardcoding references to ObjectFactory inside your domain is a bad design. The purpose of a DI container is to decouple your objects, not move the coupling somewhere else (StructureMap in this case).
Edit:
With regards to a) don't solve it in a polymorphic manner. You don't need generics to share behaviour, and inheritance hierachies only increase coupling. If you really do need to go down this path, I think implementing your own Convention might be what you're looking for. Or you could name every instance of IAmimal, and resolve the service with ObjectFactory.GetInstance(animal.GetType().ToString()), but that is clearly not ideal.
I think the point is however, that you're doing this as an exercise for DI & DI containers (I think), and if you can't get your design to fit, maybe you need to scrap it and start again, rather than trying to force a square peg into a round hole.
Oki, I have got a solution for my problem. Namely, the Visitor pattern. :-)
Quick reference: The Visitor Pattern
So I define a show time updated visitor, which can contain logic for each specific animal type:
public interface IShowTimeUpdatedVisitor
{
void Visit(Lion lion);
void Visit(Elephant lion);
void Visit(IAnimal animal);
}
public class ShowTimeUpdatedVisitor : IShowTimeUpdatedVisitor
{
public void Visit(Lion lion)
{
//do stuff with a lion
}
public void Visit(Elephant elephant)
{
//do stuff with an elephant
}
public void Visit(IAnimal animal)
{
// this will be the default which will be hit if no Visit method for the concrete exists
}
}
Then I have made modifications to the IAnimal interface to allow each implementation to call the correct method against ShowTimeUpdatedVisitor:
public interface IAnimal
{
void ShowTimeUpdated(IShowTimeUpdatedVisitor updatedVisitor);
}
public class Lion : IAnimal
{
public void ShowTimeUpdated(IShowTimeUpdatedVisitor updatedVisitor)
{
updatedVisitor.Visit(this);
}
}
Now, I can implement my AnimalShowTime service like this:
public class AnimalShowTimeService : IAnimalShowTimeService
{
readonly IShowTimeUpdatedVisitor showTimeUpdatedVisitor;
public AnimalShowTimeService(
IShowTimeUpdatedVisitor showTimeUpdatedVisitor)
{
this.showTimeUpdatedVisitor = showTimeUpdatedVisitor;
}
public void IncreaseShowTimeForAnimal(IAnimal animal)
{
animal.ShowTimeUpdated(showTimeUpdatedVisitor);
}
}
So in the end I didn't have to do any messy StructureMap code. :)
Hope this helps someone else.