Game player object design - database

I'm supporting a server for an online card game and while thinking about refactoring it into a better state I have found myself unable to decide what is a proper object model for my needs.
I have a Player class which has a lot of attributes. The first problem is just that - the class is too big. The second problem is that I don't know how to refactor it. I will list some of the attributes and issues with these.
Some attributes are very tightly bound to a player: nick, email, last login &c. These, I suppose, are to be kept directly in the player class and in the same table in the DB.
Now, some attributes are a little more difficult, like money and gold amount. The problem with these is that they are historically stored in a different table, there might be some more currencies later on and that they MUST be synched into the database at their own pace.
Third category of attributes are loosely coupled to the player, like status string, experience, achievements, statistics &c. These are stored in different tables in the DB and MUST be stored, retrieved, cached and synchronized at their own pace.
Note that one of the big problems here is that we have to implement relatively complex database synchronization schemes because we have a lot of online players and our game is soft-realtime and we have to make load on the DB as low as possible.
My questions are:
How to determine which attributes to store within a player class and which not to? Say, experience, nickname, money amount?
When one has some attributes that may be grouped together like (strength, agility, endurance, &c.) and (handItem, headItem, feetItem, weapon) when they should be grouped and when not?
What to do with complex database synchronization schemes? Make a separate model for each attribute that needs to be synched independently or make some DataManager classes to take them apart and work with them?
What to do with the need for a class to have several different "data representations" for external consumers? Like XML, Json, another XML for some external service, human-readable string, &c.
I'm sorry if my questions are bogus, I'm not really good at OOP design, I'm more an FP guy. And my English is not very good =).

There is no "limit" to what you can store in a player class. As long as it is concerning him and him only, it should be in his class. But one thing you should consider is to make several player classes. The idea is : if you don't need is, don't query it. You may have PlayerView_Small, PlayerBuying, PlayerFighting, PlayerSettings (depending on your game, they may not be fulfilling the exact same purpose)... This way for each "need" of info on a player, you only load the player data you need, and can handle it properly. Also, you may use inheritance if some class is only a more detailed version of the other.
If you are talking about the class, it may be in a sub-class PlayerAttributes of which an instance is contained into PlayerFighting and PlayerView_Detailed. In the database, it might be interesting to store it as a string (conveniently outputted by our class, and accepted in constructor), to avoid having too much fields, but you will lose the sorting ability. That's probably not a problem in our case, but might be in some others.
Blank for now, I don't understand where there is synchronization, will edit when informed.
In your PlayerViewDetailInfo(or in your PlayerAllData depending what you need), you place some methods such as ToXmlClient1(), ToJson(), ToHumanReadableString() (although that might be a bit confusing to the eye, you should consider HTML^^). The class having the method should be the class with the least (but sufficient to provide the answer) data. When requested, you load the Player... which has the method giving the correct output, and you write it directly in the response.

Related

Using of graphql service within desktop application that "follows" MVVM and DDD

We have a WPF desktop application that uses MVVM pattern and DDD (well, let's say that at least my model classes that store data named by entities taken from the real world). APP uses several microservices through REST API. And it worked perfectly. Until we thought that it's time to use some facade for back-end part to unite all those microservices and get only data that we need for particular screen.
BUT. The question is, how to make them live together.
On the one hand, we have dynamically returned data from graphql. It
means that, for example, if we have list of people on the one screen,
we will request id, name, surname and role of the person. On the
different screen for dropdown of people we will request the same data
but without role.
On the other hand we have class Person that has static set of fields Name, Surname, Role and Id, which person has in "real life"
If we use the same Person class with graphql, converting data from JSON to model Person, both screens will work fine, but behind the scene one screen that doesn't need Role wouldn't request it from graphQL. And we will have a situation when model class Person will have field Role but it will be just empty (which is i believe is kind of smells. At least I don't feel like it would be easy to maintain such a code. Developer needs to add some information to the screen, opens model, sees that Role is there, bind the field to the screen and goes to drink cofee. And then oops, there is the fields but there was no data assigned ).
Two variants I have on my mind are:
either to not use models and DDD and map data directly to ViewModel
(which personally feels like ruining everything we had before).
or we map that dynamic data to our existing models and different field for different screens (for the same class Person e.g.) will be
empty (because not requested).
Maybe somebody has already used such a combination. How do you use it and what pros and cons are?
It's a fairly common situation where you have a data layer returns many columns but only some are used in a given view.
There is no absolute "best" solution independent of how much impact the full set of columns will have on performance. Which might in turn be linked to things like caching.
You could write services that return subsets of data and then you only use the necessary bandwidth. Sort of a CQRS pattern but with maybe more models than just read + write.
Often this is unnecessary and the complications introduced do not compensate for the increased cost of maintenance.
What is often done is just to map from model to viewmodel (and back). The viewmodel that needs just 4 columns just has 4 properties and any more returned by the model are not copied. The viewmodel that needs 5 has 5 properties and they are copied from the model.

django templates in model logic

I wish to generate automated messages that are associated with a finite (>20, < 100) number of types:
class Message(models.Model):
MSG_CHOICES = (
('MEETING', 'Meeting Reminder'),
('STATUS', 'Status Change Reminder'),
...
)
message = models.CharField(max_length=100)
msg_type = models.CharField(max_length=10, choices=MSG_CHOICES)
The actual message of each will depend on the type and arguments I must feed it at some point. For example, a 'MEETING' message will basically be:
"Hi, you have a meeting at %s with %s." % (time, person_to_meet)
while a 'STATUS' message will be something like
"Hi, this is a reminder that you changed your %s status to %s." % (status_type, new_status)
Now, the complexity here is that we have to render the message differently for the different types. Here's my attempt at brainstorming some different approaches:
revamp the model to have a base message model and a derived one for each, with its own type of constructor, saving the "string templates" inside the constructors for each model. This fits the pattern of separating models with different logic (and I'd usually do this for a model of different "types"), but feels clunky because besides the logic of creating the messages, these guys are basically the same. The only difference in logic comes from creating the messages themselves, and it seems like a waste to split just because of it.
keep the model as is, create class methods in the code to make a factory for each type, saving the "string templates" inside the class (or even inside the database). This is the easiest, but it feels dirty.
this is the creative/crazy one (hence the title): keep the model as is, and save the string templates as actual template files. In the constructors, use the Django template library to render those files and return the strings. This seems good because it separates out hard-coded data from code-logic, but it feels wonky since I'm using templates at two different levels of the code (one for making models and one for the views). It "feels" wrong but I can't really pinpoint why.
So the main questions:
What is the best-practice for this situation? Is it one of these or is it some other approach?
is there a "model" example of this practice somewhere? I feel lots of systems generate automated alerts/messages, so if one has particularly good code I'd like to look at it.
Thanks!
-Yan
IMHO, you shouldn't be storing the message in the db at all. You are storing the msg_type. That should really be enough. Your logic to display the information to the user (via the template) should handle this. This would allow you to localize the message if you needed to at some point in the future based on the Accept-Language header. In my experience, it's a bad idea to store user messages in the db. And, at least to my way of thinking, it's not really true business logic. It seems to belong in the UI layer. Ok. Just my opinion on it. This question is pretty old. I would be curious to read what you ultimately ended up doing here.

Class between database and UI

I have a class that handles writing and reading data from my database. What is a proper name to call this class?
There are a couple of conventions. Assuming a Person model, you could use:
PersonDataAccessObject,
PersonDao,
PersonRepository,
PersonDataAccess,
...
It is also dependent on the technology you are using. I mean, who knows what conventions exist for the language you are using. Let us know what language and what data access framework and the answer may vary.
I used to append "Dao" because it's short and clear. But then I moved over more to Martin Fowler's vocabulary and patterns, so now I use Repository. A little more long winded, but I'm long winded by nature, so it fits my style. In the end, that's the key. It's stylistic and there is no across the board standard that I'm aware of. What's most important is that you pick something that is clear and you use it consistently. If you decide, later on, to switch to something else, have mercy on any programmers that may follow you and rename everything so that all your data access components are consistently named.
Edit: in rereading this, I realized I am assuming you are going to have multiple such classes, one for each of your model entities. Who knows what your setup is. If you aren't going to do it like that, and you're just looking for a standard name for a single point of entry to all data access, you could use:
DataMapper
Gateway
Typically, the assumption is that you are going to have several of these around, one for each of your "tables"/model entities. More than a naming convention, that is probably a standard coding convention. This way, when you change or add some aspect of how you interact with your "persons" table, you don't have to modify a class in which you have code to access the "addresses" table. Check out Martin Fowler's Patterns of Enterprise Application Architecture (PofEAA), for more
PofEAA catalog of patterns (check out Data Source Architectural Patterns
and
Domain Driven Design Quickly (free pdf) esp. Ch. 3
Depending on the entity this class represents it could be for example Person. Then you design a PersonViewModel which is passed to the GUI. So the Person you got from the database is mapped to a PersonViewModel which is passed to the UI layer for being shown under some form. The view model is just a representation of the domain model you fetched from the database and containing only the necessary information that you need to display on the given UI.

Self Tracking Entities Traffic Optimization

I'm working on a personal project using WPF with Entity Framework and Self Tracking Entities. I have a WCF web service which exposes some methods for the CRUD operations. Today I decided to do some tests and to see what actually travels over this service and even though I expected something like this, I got really disappointed. The problem is that for a simple update (or delete) operation for just one object - lets say Category I send to the server the whole object graph, including all of its parent categories, their items, child categories and their items, etc. I my case it was a 170 KB xml file on a really small database (2 main categories and about 20 total and about 60 items). I can't imagine what will happen if I have a really big database.
I tried to google for some articles concerning traffic optimization with STE, but with no success, so I decided to ask here if somebody has done something similar, knows some good practices, etc.
One of the possible ways I came out with is to get the data I need per object with more service calls:
return context.Categories.ToList();//only the categories
...
return context.Items.ToList();//only the items
Instead of:
return context.Categories.Include("Items").ToList();
This way the categories and the items will be separated and when making changes or deleting some objects the data sent over the wire will be less.
Has any of you faced a similar problem and how did you solve it or did you solve it?
We've encountered similiar challenges. First of all, as you already mentioned, is to keep the entities as small as possible (as dictated by the desired client functionality). And second, when sending entities back over the wire to be persisted: strip all navigation properties (nested objects) when they haven't changed. This sounds very simple but is not at all trivial. What we do is to recursively dig into the entities present in trackable collections of say the "topmost" entity (and their trackable collections, and theirs, and...) and remove them when their ChangeTracking state is "Unchanged". But be carefull with this, because in some cases you still need these entities because they have been removed or added to trackable collections of their parent entity (so then you shouldn't remove them).
This, what we call "StripEntity", is also mentioned (not with any code sample or whatsoever) in Julie Lerman's - Programming Entity Framework.
And although it might not be as efficient as a more purist kind of approach, the use of STE's saves a lot of code for queries against the database. We are not in need for optimal performance in a high traffic situation, so STE's suit our needs and takes away a lot of code to communicate with the database. You have to decide for your situation what the "best" solution is. Good luck!
You can find an Entity Framework project item at http://selftrackingentity.codeplex.com/. With version 0.9.8, I added a method called GetObjectGraphChanges() that returns an optimized entity object graph with only objects that have changes.
Also, there are two helper methods: EstimateObjectGraphSize() and EstimateObjectGraphChangeSize(). The first method returns the estimate size of the whole entity object along with its object graph; and the later returns the estimate size of the optimized entity object graph with only object that have changes. With these two helper methods, you can decide whether it makes sense to call GetObjectGraphChanges() or not.

How to model Data Transfer Objects for different front ends?

I've run into reoccuring problem for which I haven't found any good examples or patterns.
I have one core service that performs all heavy datasbase operations and that sends results to different front ends (html, silverlight/flash, web services etc).
One of the service operation is "GetDocuments", which provides a list of documents based on different filter criterias. If I only had one front-end, I would like to package the result in a list of Document DTOs (Data transfer objects) that just contains the data. However, different front-ends needs different amounts of "metadata". The simples client just needs the document headline and a link reference. Other clients wants a short text snippet of the document, another one also wants a thumbnail and a third wants the name of the author. Its basically all up to the implementation of the GUI what needs to be displayed.
Whats the best way to model this:
As a lot of different DTOs (Document, DocumentWithThumbnail, DocumentWithTextSnippet)
tends to become a lot of classes
As one DTO containing all the data, where the client choose what to display
Lots of unnecessary data sent
As one DTO where certain fields are populated based on what the client requested
Tends to become a very large class that needs to be extended over time
One DTO but with some kind of generic "Metadata" field containing requested metadata.
Or are there other options?
Since I want a high performance service, I need to think about both network load and caching strategies.
Does anyone have any good patterns or practices that might help me?
What I would do is give the front end the ability to request the presence of the wanted metadata ( say getDocument( WITH_THUMBNAILS | WITH_TEXT_SNIPPET ) )
Then this DTO is built with only this requested information.
Adding all the possible metadata is as you said, unacceptable.
I will surely stay with one class defining all the possible methods (getTitle(), getThumbnail()) and if possible it will return a placeholder when the thumbnail was not requested. Something like "Image not available".
If you want to model this like a pattern, take a look at the factory patterns.
Hope this helps you.
Is there any noticable cost to creating a DTO that has all the data any of your views could need and using it everywhere? I would do that, especially since it insulates you from a requirement change down the line to have one of the views incorporate data one of the other views uses
ex. Maybe your silverlight/flash view doesn't show the title itself b/c it's in the thumb now, but they decide they want to sort by it later.
To clarify, I do not necesarily think you need to pass down all of the data every time, but I think your DTO class should define all of them. Just don't fall into the pits of premature optimization or analysis paralysis. Do the simplest thing first, then justify added complexity. Throw it all in and profile it. If the perf is unacceptable, optimize and try again.

Resources