I'm making a simple game as a practice project based around random events, to make it easier to add new events I’ve decided to use a keyword system where each event gets keywords assigned to them that are then used to process the event, this can be as simple as displaying as message, changing data in the model or rolling again on the random table.
I have a class that randomly decides an event and returns a List of strings with keywords.
I want to make a class where all the keywords are stored as methods that can then be called with the list.
Something like this:
class Keyword
{
public void InputKeywords(List<string> Ikeywords)
{
foreach (var item in Ikeywords)
{
switch (item)
{
case "keyword0":
keyword0();
break;
case "keyword1":
keyword0();
break;
case "keyword2":
keyword0();
break;
}
}
}
private void keyword0()
{
//do something
}
private void keyword1()
{
//do something
}
private void keyword2()
{
//do something
}
}
Now the problem I’m facing is updating the data in the model from the keywords class.
Because the events are chosen at random I don't know for each event what data to send to the class to have it update it.
The solutions I've come up with myself:
Make my model static, no more issues with accessing data, Google tells me this is frowned upon and should be avoided.
Send the model to the Keyword class, do some magic, and return the model. Would be an easy solution but feels wrong to me, from what I've come to understand about MVVM is that the data should be updated from the viewmodel, but I could be thinking too much inside of the box.
Gather all possible data to be changed into a seperate class, send that to the keyword class and update the model afterwards. This sounds like a hassle and feels like I'm just moving the problem elsewhere.
I feel like I'm missing the "right" way of doing this. What would be the "best" approach?
First of all the naming of the keyword class feels misleading here. It is basically an event handler, so I would also name it like on (e.g. RandomEventGenerator)
To your problem I would also not recommend you to use static models. Your testability will suffer from it since you won't use dependency injection there. This being said your second approach seems to go into the right direction. I would suggest to use inject an EventInvoker Interface.
public interface IEventInvoker
{
public void RaiseEvent();
}
This can be implemented in an operator, which has access to your data model and has predefined actions to modify your data.
public class WeatherOperator : IEventInvoker
{
private readonly WeatherEngine _weatherEngine;
public WeatherOperator(WeatherEngine weatherEngine)
{
_weatherEngine = weatherEngine;
}
public void RaiseEvent()
{
StartSunshine();
}
public void StartSunshine()
{
_weatherEngine.RemoveClouds();
_weatherEngine.SetSunPosition(DayTimes.Noon);
}
public void LetItRain()
{
_weatherEngine.SetCloudes(CloudModes.FullCover);
_weatherEngine.SetRain(RainIntesity.Medium);
}
}
With a list of the IEventInvoker you can then go to your EventHandler.
public class RandomEventGenerator
{
private readonly List<IEventInvoker> _eventInvoker;
private readonly Dictionary<string, Action> _eventDictionary;
public RandomEventGenerator(List<IEventInvoker> eventOperator, List<string> keywords)
{
_eventInvoker = eventOperator;
_eventDictionary = RegisterKeywordsToRandomEvents(keywords);
}
private Dictionary<string,Action> RegisterKeywordsToRandomEvents(List<string> keywords)
{
var eventDictionary = new Dictionary<string, Action>();
foreach (var keyword in keywords)
{
var random = new Random();
var index = random.Next(_eventInvoker.Count);
eventDictionary.Add(keyword,_eventInvoker[index].RaiseEvent);
}
return eventDictionary;
}
public void EventByKeyword(string Keyword)
{
_eventDictionary[Keyword].Invoke();
}
public void RandomEvent()
{
var random = new Random();
var index = random.Next(_eventInvoker.Count);
_eventInvoker[index].RaiseEvent();
}
}
Please note that I, to keep it small, didn't used null checks or input validations here, which is highly recommended.
With this approach you have a clear cut bettween your model/data and your viewmodel/data accesor.
Related
I have a class with about 10 or more different boolean values that record whether a user has done a particular action that will give them a specific reward (e.g. send a message to someone).
here is the code for one method for ONE bool/action:
private ReqRewardResult setMsgSent(RewardClass reward, RewardInfo info)
{
if (reward.msgSent)
return ReqRewardResult.RewardAlreadyGiven;
reward.msgSent = true;
reward.earned += info.msgSentReward;
return ReqRewardResult.ReqSuccess;
}
I have tried to create a generic method for this but it seems you can't pass a class variable as a reference?
private ReqRewardResult setRewardAction(ref bool bAction, RewardClass reward, int reward)
{
if (bAction)
return ReqRewardResult.RewardAlreadyGiven;
bAction = true;
reward.earnedTokens += reward;
return ReqRewardResult.ReqSuccess;
}
I have then looked at a couple of methods such as using a delegate function... but this is then kinda pointless as i'd have to repeat several lines again...
I have also seen you could use Reflection... but this is really slow and as this is a web app i'd rather use more repeated code if it improves the overall speed...
The question: Is there anyway to have a class function that can repeat for several variables of the same type without any performance hit?
NOTE: This class is data that is loaded from a database and is unique to each user (there could be millions of users)
Many Thanks,
Phil.
class RewardCredit
{
public bool Rewarded { get; set; }
public int Points { get; set; }
}
You could use a Dictionary<string, RewardCredit>, fill it with reward names as strings and have a function like
void ApplyReward(string rewardName)
{
if (!rewards.ContainsKey(rewardName))
{
return;
}
RewardCredit credit = rewards[rewardName];
if (!credit.Rewarded)
{
tokens += credit.Points;
credit.Rewarded = true;
}
}
You'd then end up using it like so
Dictionary<string, RewardCredit> rewards = new Dictionary<string, RewardCredit>
{
{ "Message", new RewardCredit { Points = 10 } },
};
ApplyReward("Message");
First it looks like you have a finish and known set of possible user actions that can be rewarded with "tokens" if done by a user.
This can be implemented with the following class:
public sealed class UserAction
{
public static UserAction SendMessage = new UserAction(3);
public static UserAction PhonedFriend = new UserAction(4);
public static UserAction LikedPost = new UserAction(1);
public static UserAction CommentedOnPost = new UserAction(2);
private UserAction(int tokens) => Tokens = tokens;
public int Tokens { get; }
}
Notes:
The constructor is made private and only the few instances of this class that must exist are available with predefined names and tokens
The class is sealed to avoid being inherited, so that it effectively is impossible to create other instances than the one you provided
Then, so far I understand, each user may have done each action (or not) but must be rewarded no more than once for each. This make me think that you need to store a set of these UserActions into a User. You also need a way to add an action to a user (when he effectively does in on the UI, for example) and also be able to know how much tokens each user has earned. The following class implements such behavior:
public sealed class User
{
private readonly HashSet<UserAction> _doneActions;
public User() => _doneActions = new HashSet<UserAction>();
public ReqRewardResult AddAction(UserAction action) => _doneActions.Add(action) ? ReqRewardResult.ReqSuccess : ReqRewardResult.RewardAlreadyGiven;
public int EarnedTokens => _doneActions.Sum(ua => ua.Tokens);
}
Note:
I'm taking advantage of the HashSet.Add()'s return value to determine if the action had already been done in the past or not
Advantages of this "object-thinky" solution:
No more booleans and if, which I believe makes your code more maintainable and clear
Simplicity to add a new UserAction (one LoC)
Say I have a class with a number of methods - some private, some public.
In one of the public methods, I create a list of objects. This is then used across a number of other methods, which have simply been abstracted out to make code simpler.
So I might have:
public class MyClass
{
public void CreateList()
{
List<MyClass> MyList = new List<MyClass>();
... populate list
DedupeList();
ValidateList();
}
void DedupeList()
{
// do something using MyList
}
void ValidateList()
{
// do something using MyList
}
}
I was wondering what the best approach would be in this instance.
Make the list created by CreateList() a class level variable;
Pass the list a parameter to each of the sub-methods.
Ok, so it depends on what you're trying to achieve and what your classes responsibility is.
If you class represents a real thing which represents part of your domain, and which has state, then your private methods act on that state and I would therefore choose the former.
So
public class Basket
{
private IList<string> Contents;
public Basket()
{
Contents = new Contents();
}
public void Add(string Item)
{
Contents.Add(Item);
}
public void Empty()
{
Contents.Clear();
}
}
This is a trite example, but all I could think of.
If however your class doesn't represent an object with state, such as the calculator below which takes some input, acts on it, and returns it without storing anything, then the latter is better.
That said, there are other considerations, such as keeping code clean and easy to read (should be very high on your priority list), limiting the number of parameters etc being passed (any more than three is often regarded as messy). Example below of when I would elect to pass parameters.
public class InvestmentCalculator
{
pubilc IEnumerable<Stock> CalculateInvestmentValue(IEnumerable<Stock> Stocks)
{
foreach (var stock in stocks)
{
var itemValue = GetSotckValueFromMarket(stock);
stock.UpdateValue(itemValue)
AddProjection(stock);
}
}
public decimal GetStockValueFromMarket(Stock stock)
{
//Do something
}
public decimal AddProjection(Stock stock)
{
//Do something
}
}
I hope that this helps
It depends on meaning of the list. You have to find some answers. Should it be a part of the class or just a temporary variable that should live just along the method call? Is it a part of behavior of the class? How about threading? Even you may rethink if DedupeList and ValidateList methods have to be part of this class or do they deserve a separate class?
I recommend you to read "Implementation Patterns" by Kent Beck and "Clean Code" by Robert C. Martin. There are dozens of very helpful tips for these kind of little but frequent cases.
I'm creating an sudoku in c#.
A user can create an new sudoku.
My sudoku class:
public class Sudoku
{
#region Datamembers
private Field[,] grid;
private byte blockRows;
private byte blockColumns;
private Hashtable peers;
The user can save the newly created sudoku. When doing so, some validations are performed. For example: Look if not all fields are filled, look if not all fields are empty, look if no identical digits in same row, column, block, ...
My validation ends up looking like this: (it is situated in the sudoku class)
public bool IsValid()
{
bool isValidSetup = this.IsValidSetup();
if (!isValidSetup) return isValidSetup;
return this.IsTrulyValid();
}
private bool IsValidSetup()
{
bool isEntirelyFilled = this.Is_EntirelyFilled();
bool isEntirelyEmpty = this.Is_EntirelyEmpty();
bool hasIdenticalDigits = this.Has_IdenticalDigits();
this.Add_SetupValidationMessages(isEntirelyFilled, isEntirelyEmpty, hasIdenticalDigits);
return !isEntirelyEmpty && !isEntirelyFilled && !hasIdenticalDigits;
}
private bool IsTrulyValid()
{
this.Clean();
this.Solve();
bool hasNoSolutions = !this.Is_EntirelyFilled();
bool hasMultipleSolutions = false;
if (!hasNoSolutions) hasMultipleSolutions = this.Has_MultipleSolutions();
this.Add_TrulyValidationMessages(hasNoSolutions, hasMultipleSolutions);
return !hasNoSolutions && !hasMultipleSolutions;
}
I would like to split validation from sudoku, to make it OOP.
I looked into the strategy pattern, since that looked like something I could use, and is used a lot in validation. But as far as I understand the pattern, it's not what I need after all; Reason for that is because it's based on selecting a validation based on certain factors. I'm probably wrong, but I can't seem to realize why I would need that in my situation.
I Need one of the seperated validations (Is_EntirelyFilled() ) in another class. That's the only one not only used to validate the sudoku.
So, should I just put all this validation in 1 class? Or should make separate classes for each validation and call them seperatly? Any other suggestions?
You should have a ValidationHandle as Abstract Implement it differently for your needs and pass it to your client code. Something like that as I remember.
The IBrakeBehaveior should be your IValidationHandle
The sub ones are validation types.
Car is the cllient class and you need an instance of IValidationHandle in client code.
Where you need in client code you call IValidationHandleInstance.Validate()
by polymorphism it knows how validation execute.
Something like that
public interface IValidationHandle
{
bool Validate();
}
//TODOs: Separate classes
public class IsTrulyValidValidator:IValidationHandle;
public class IsValidValitor:IValidationHandle;
public class EntirelyFilledValidator:IValidationHandle;
class Client
{
private IValidationHandle validator=null;
public void SetValidationHandler(IValidationHandle validator)
{
this.validator=validator;
}
//Where You need call
validator.Validate();
}
I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.
I’m trying to manage multiple models in a messaging based system. Each model might have values that are dependent on other models. For example:
public class V2Model : BaseModel
{
private int mSomeVal;
private byte mSomeByte;
// …
// Update mSomeByte based on multiple models values
public void SetMultipleDependecyValue(int someIntFromModel1, short someShawteeyFromModel3)
{
mSomeByte = Convert.ToByte((someShawteeyFromModel3 / someIntFromModel1) + mSomeVal);
}
}
I would also like to use the MVC pattern, but instead of passing a Model instance, I thought I would pass in a ‘Repository’ instance. The ‘Repository’ instance would act as a manager for handling all the Model instances. The result would look something like this:
public class V1Controller<ViewType, ModelType>
where ViewType : IV1View
where ModelType : BaseModel
{
ViewType mView;
BaseRepository mBaseRep;
public V1Controller(ViewType view, BaseRepository rep)
{
mView = view;
mBaseRep = rep;
mBaseRep.GetModel<ModelType>().PropertyChanged += new PropertyChangedEventHandler(V1ModelPropertyChanged);
}
void V1ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "SomeVal":
// Update the view
int some_val = mBaseRep.GetModel<ModelType>().SomeVal;
mView.HexSomeValue = some_val;
// Oh BTW, we know V2Model's value depends on this... update it with V1Model and V3Model's values
short some_short = mBaseRep.GetModel<V3Model>().SomeShawteey;
mBaseRep.GetModel<V2Model>().SetMultipleDependecyValue(some_val, some_short);
break;
}
}
public void UpdateVal(int someValue)
{
mBaseRep.GetModel<ModelType>().SomeVal = someValue;
}
}
In this situation, if V1Model’s property changed, in V1ModelPropertyChanged, I would know the dependency on V2Model’s object, and update it with the appropriate values. Is there a better way of handling this interdependent model scheme, or would this be an acceptable solution? I am not really looking for anything 3rd party.
If you want to handle this elegantly, you're going to need to have some component track the dependencies between the models. When a property changes, you would iterate over all of the dependencies for that property and then update them appropriately.
Perhaps your BaseRepository might hold a reference to a DependencyManager class. That class would have to have a list of all properties which depend on one another.
A simple implementation might look like this:
class PropertyDescriptor
{
public Type ModelType { get; set; }
public string Property { get; set; }
}
class DependencyManager
{
private Dictionary<PropertyDescriptor, List<PropertyDescriptor>> _dependencies = new Dictionary<PropertyDescriptor, List<PropertyDescriptor>>();
public void RegisterDependency(PropertyDescriptor property, PropertyDescriptor dependentProperty)
{
if (!_dependencies.ContainsKey(property))
{
_dependencies.Add(property, new List<PropertyDescriptor>());
}
_dependencies[property].Add(dependentProperty);
}
public IEnumerable<PropertyDescriptor> GetDependentProperties(PropertyDescriptor property)
{
if (!_dependencies.ContainsKey(property))
{
yield break;
}
else
{
foreach (PropertyDescriptor p in _dependencies[property])
{
yield return p;
}
}
}
}
Then when you detect a property change, you can query the DependencyManager for what else needs to change. But be careful to check for circular dependencies when you cascade!
Maybe I'm missing something, but isn't this what the observer pattern is for? If you set up the models as observers of each other (i.e., with delegates or events), then the controller should be able to remain blissfully ignorant of the dependencies.