Aid with code organization? - c++

I have been working on the server code for my game. It works really well, but 90% of the functions are in 1 class.
Usually I find it pretty easy to know how to divide things up. Either each object is a class or each dialog is a class and handles logic for its children.
In this case, the server receives a request, and then either tells the other players or processes and notifies the appropriate players.
Here is the header file:
class ServerCore : public ServerHost, public NetEventListener,
public ServerEventProvider
{
NetEventDecoder m_dec;
NetEventEncoder m_enc;
LoginManager m_login;
ServerPlayerManager m_playerMan;
ServerTableManager m_tableMan;
void sendToTarget();
void sendToAllActive();
void sendToActiveNotTarget();
void sendToTable(int tableNo);
public:
ServerCore();
virtual void onConnect (Lacewing::Server::Client &client);
virtual void onDisconnect (Lacewing::Server::Client &client);
virtual void onError (Lacewing::Error &error);
virtual void onReceive (Lacewing::Server::Client &client, char * data, int size);
virtual void sendChatMessageC(const std::string& message,ChatAreaEnum area);
virtual void requestTableC(int tableNo, int seatNo);
virtual void playerRequestSitC(int tableNumber, int seatNumber);
virtual void playerStoodUpC();
virtual void hostGameC(const SpadesGameInfo& info);
virtual void gameMessageC(SpadesCSMessageEnum message, const std::vector<int>& params);
virtual void modifyListC(const std::string& player, GroupTypeEnum group, bool add);
virtual void canceledHostingRequestC();
virtual void sendInviteC(int tableNo, const std::string& player);
virtual void loginResult(const std::string& name, ServerPlayer* player,
const std::string& sessionID, bool success, bool newSession);
virtual void readyToReceiveLobbyDataC();
virtual void playerAbandonedGameC();
virtual void watchTableC(int tableNo);
virtual void gameCompleted(int tableId);
virtual void playerWantsPlayAgainC();
virtual ~ServerCore(void);
};
}
I do not really know how I could break this down into smaller classes. The tasks they perform are handed to other objects, such as authentication, and data retrieval from database, but all events are currently processed in this 1 file.
The net event decoder calls the appropriate method after converting it from the string received over the wire.
Doing it this way works very well, but the game is going to get bigger and I want to stay clean and modular.
Is this design a good idea? If not, what type of patterns are usually used in game server development to keep things more object oriented?
Thanks

Looking at your class, the command pattern comes to mind. Indeed, the methods ending in C look very much like commands. If you have a command interface:
class Command {
virtual void execute() = 0;
}
and a separate subclass for each command, then the NetEventDecoder could decode the received string into a specific command.
Also, anytime you find yourself passing the same data to multiple methods, that's a hint that there's a class hiding in there. For example, you could pull all the methods taking a tableNumber into a Table class. I would also get rid of the Manager classes and model the associations more directly.
For example:
// A game server contains players and tables
class GameServer {
map<string, Player *> players;
map<int, Table *> tables;
Player *findPlayer(const string &name);
Table *findTable(int tableNumber);
...
}
// A player can perform various actions
class Player {
string name;
bool requestSeat(Table *table);
void standUp();
...
}
// A table maintains the status of seats
class Table {
int tableNumber;
bool requestSeat(int seatNumber);
...
}
The GameServer class above simply models the game and does not deal with networking at all. The NetEventDecoder and ServerCore can then coordinate to provide networking functionality and invoke commands on the GameServer. An example command might look like:
class PlayerStandUpCommand : public Command {
GameServer *server;
string playerName;
void execute() {
Player *player = server->findPlayer(playerName);
player->standUp();
}
}

Related

Running into c++ virtual template function issue due to interface based programming

We are designing a new system where we have created interfaces for most of our classes so that we can create mocks (google mocks) for them for unit testing. As a result, all the functions are virtual but the issue is that I am often running into template virtual function issue due to this. I have seen some examples on how to do multi dispatch but they all seem to be using some variation of templates, it doesn't seem straightforward. So does it mean that my entire codebase will now end up with templates making it difficult to read/use and debug?
Or am I not designing good interfaces. Here is a simple example where I am writing an interface for a message queue.
Class IMessageQueue {
Public:
Virtual int send(const T & value); // I can't do this but this is exactly what I want to do, as send should be able to send any type
};
Class MessageQueue : public IMessageQueue {
Public:
Virtual int send(const T & value) { ... }
};
Class MockMQ : public IMessageQueue {
Public:
Virtual int send(const T & value) {
// mock implementation
}
};
How do I get around this problem? This is just one example but I run into lots of these type of issues due to interface based programming.
It depends if you need your IMessageQueue to dispatch specific unknown type or any type. That's not the same thing.
A specific unknown type can be managed by
template<typename T>
class IMessageQueue {
public:
virtual int send(const T& value);
}
So that you can have your IMessageQueue<MyMessage> and IMessageQueue<OtherMessage>.
If, instead, you need to be able to send any type with the same type of message queue then your option is to declare a specific interface common to all messages as in
class Message
{
protected:
Message() : { .. }
};
class MyMessage : public Message
{
..
};
class MessageQueue
{
public:
void send(const Message& message);
};

What is the simplest Event design pattern

Lately, I've been pondering about the following problem for a while. For the code bellow, what is the easiest way to modify Game::counter via Event::Perform() method which is called from Game class?
I considered Observer and Command design patterns, but it seems that there is a much simpler way to do this.
class Game
{
public:
Game();
private:
int counter;
vector<Event*> Events;
};
class Event
{
public:
virtual void Perform() = 0;
};
Thank you
Directly from Perform, none. counter is private, so it can only be accessed by Game, as part of one of the functions of the interface it provides.
Calling this function is then just a matter of having access to the right Game instance. You can pass that one as a parameter to Perform:
virtual void Perform(Game &) = 0;
... or inject it into derived Events:
struct MyEvent : Event {
MyEvent(Game &game) : _game{&game} { }
void Perform() const override {
// Do something with *game
}
private:
Game *_game;
};
Since I guess we are talking about the Events referenced by Game::Events, which Game itself will process, the parameter looks like the most cohesive approach.

graphic drawing class organisation

I have a basic 4x20 character LCD that I would like to use for displaying a menu with buttons using an Arduino as the driver (limited standard library support).
Example LCD menu and buttons
I'm thinking of producing an interface class GraphicObject that all graphical objects then inherit from (such as Button, MenuItem etc.). It seems logical that the GraphicObject class should have a draw method which can be overridden.
At the moment, I have a class called Lcd which covers the low level drawing of text and character positioning. In order to draw anything, I will need access to one of these Lcd objects. If I include a pointer to the Lcd object within my GraphicObject or derived objects, I couple them and make them Lcd only objects. If I change the type of display device these classes aren't suitable any more.
How can the classes be organised to keep them loosely coupled and allow for a change in display types at a later date? Should I have LCDButton LCDMenuItem which then inherit from a Button and MenuItem interface, then create additional objects for the other display device (OtherDisplayButton OtherDisplayMenuItem)?
Any suggested reading? I've looked at many examples, but none of them seem to go into details about the function of a draw method and whether the device should be accessed directly or through another controlling object.
Thanks
Edit 1
Brief code idea overview
#include "Arduino.h"
class Lcd {
public:
struct Parameters {
uint_fast8_t numberLines;
uint_fast8_t numberCharacters;
// uint_fast8_t* lineOffsets;
Print* serial; // Can be any Serial device (all inherit from Print).
};
protected:
Parameters parameters_;
const uint_fast8_t escapeCode_ = 0x1B;
const uint_fast8_t directCode_ = 0xFE;
void sendCommand_(uint_fast8_t command, uint_fast8_t parameter = 0);
void sendCommandDirect_(uint_fast8_t command);
public:
Lcd(Parameters parameters);
void clearDisplay(void);
void moveCursor(uint_fast8_t line, uint_fast8_t character);
void resetDisplay(void);
void customCharacter(const uint_fast8_t address,
const uint_fast8_t characterMap[8]);
void write(uint8_t character);
// Boilerplate print forwarders.
void print(const char character);
void print(const String &string);
void print(const char string[]);
// Boilerplate println forwarders.
void println(const char character);
void println(const String &string);
void println(const char string[]);
void println(void);
};
class GraphicObject {
virtual void draw(void)=0;
};
class Button: public GraphicObject {
public:
typedef void (*buttonAction)(void);
virtual void setText(const String text)=0;
virtual const String getText() =0;
virtual bool isActive()=0;
virtual void setActive(bool)=0;
virtual void setAction(buttonAction action)=0;
};
class MenuItem: public Button {
public:
typedef void (*menuAction)(void);
virtual MenuItem* parentItem()=0;
virtual const MenuItem* addItem(String text, menuAction action)=0;
};
class VScrollbar: public GraphicObject {
public:
virtual void setAtTop(bool atTop);
virtual void setAtBottom(bool atBottom);
};
class LcdButton: public Button {
private:
Lcd* lcd_;
String text_;bool active_;
public:
LcdButton(Lcd* lcd);
void draw(void);
void setText(String text);
const String getText();bool isActive();
void setActive(bool);
void setAction(Button::buttonAction action);
};
class LcdWindow: public GraphicObject {
private:
LcdButton* lcdButtons_ = nullptr;
public:
enum class Position
: uint_fast8_t {
LEFT,
RIGHT
};
bool addButton(LcdButton* lcdButton, uint_fast8_t line, uint_fast8_t offset);
bool addVScrollbar(VScrollbar* vScrollbar, Position position);
void draw();
};
int main(void) {
Lcd::Parameters lcdParameters;
lcdParameters.numberCharacters = 20;
lcdParameters.numberLines = 4;
lcdParameters.serial = &Serial1;
Lcd lcd = Lcd(lcdParameters);
LcdButton myButton(&lcd);
myButton.setText("Select");
myButton.setActive(true);
LcdWindow lcdWindow;
lcdWindow.addButton(&myButton, 1, 1);
lcdWindow.draw();
while (1){}
return 0;
}
There are different ways to do this. In principle, you should define an interface (API) to your low-level LCD driver module(s) and call only functions of your low level api to draw something. The implementations of this api can then exchanged without the need to change the high level code.
The simplest way to do this is to define an abstract c++ base class where all lcd driver implementations have to be derived from. The base class should have virtual methods that need to be overloaded by the derived implementations.
But a litte information: virtual methods in c++ classes requires the compiler to generate a method pointer table for every object that is created when the object is instantiated; this needs some more memory. Also, all function calls to objects of these classes are indirect (the compiler generates code that first lookup the real function pointer and then calls the function using this pointer), which makes the resulting code slightly slower.

How to implement pure virtual functions with different parameter structures

I'm building a class with pure virtual functions called Database. The idea is to have a class that handles all the database interfaces (ie: open and close) and can be used on my business layers.
The Database class will be implemented in several 'flavours' for different databases, like mySqlDatabase and OracleDatabase.
I imagined Database having pure virtual methods with no code - just a header file as follows:
Database.hpp
class Database {
public:
Database();
virtual ~Database();
virtual void open(const std::string databasename) = 0;
virtual void open(const std::string databasename, const std::string username, const std::string password) = 0;
virtual void open(const std::string databasename, const std::string schema, const std::string username, const std::string password) = 0;
.
<Other stuff>
.
}
The three open variations are there to support different database connection requirements, from the simplest one (like Sqlite3 that needs only a filename), to Oracle (that needs all of that variables to connect).
I have some questions about the implementations (let's take oracle for example):
a) Shall I need to redeclare the virtual methods again on the derived class header file, like:
class OracleDatabase : public Database {
public:
OracleDatabase ();
virtual ~OracleDatabase ();
void open(const std::string databasename);
void open(const std::string databasename, const std::string username, const std::string password);
void open(const std::string databasename, const std::string schema, const std::string username, const std::string password);
}
b) How do I structure the implementation of the open methods in the derived class (let´s take Sqlite3)?
void Sqlite3Database::open(const std::string databasename){
...do some stuff...
}
void Sqlite3Database::open(const std::string databasename, const std::string username, const std::string password) {
...do some stuff...
}
void Sqlite3Database::open(const std::string databasename, const std::string schema, const std::string username, const std::string password) {
...do some stuff...
}
Am I using the right strategy? I've been browsing around virtual and pure virtual strategies and think this is the best approach for my problem.
Any suggestions/hints?
OBS: I'm coming from C# world so I do apologize if there is some misconception here.
For writing query functions (ie. same interface for all databases), pure virtual functions are the way to go.
Here, you are trying to write an open function, for which you might want to consider the Factory Design Pattern: you write your Database withour any open function; and you write a function such as static std::unique_ptr<Database> Sqlite3Database::open(/*...*/).
Using a virtual function like the one you are advocating is not a good idea: anyway you have 3 different functions that completely depend on the database that is used; and worse, your mother class depends on its children: to add a new database with another logging scheme, you have to add a function prototype to Database.
Another way to go would be to use a pure virtual function (preferably protected and called from constructor to preserve RAII; and following the NVI idiom) that takes as argument an initialization string such as the one used by PDO. Not exactly the same as anyway the database type can be inferred from the type instantiated, but the idea is to keep a single argument so as not to have multiple versions of open
(Old answer kept for the principles it tried to explain)
Actually you can do much easier: forget about open, and just do all of your initialization inside Sqlite3Database::Sqlite3Database(/* ... */).
After all, there is no way you can open a database without knowing which kind of DB it is (as you have to know a username/password, and even more: you have to know what arguments are required), so there is no sense in trying to make a virtual pure function out of this.
So, an example of what you could do:
class Database {
public virtual void create(/* ... */) = 0;
// ...
};
class Sqlite3Database : public Database {
Sqlite3Database(string filename);
public virtual void create(/* ... */) override;
// ...
};
class MySqlDatabase : public Database {
MySqlDatabase(int host, short port, string username, string password);
public virtual void create(/* ... */) override;
};

Visitor pattern and constness

I am running into a problem concerning the visitor pattern and constness.
Assume a visitor pattern implementation in C++ for a small game in which you draw stuff on the screen (depending on the internal state of the drawable objects) and at the same time run a logic that can change their internal state (pretty much any game you can imagine). Please, forgive any errors in code as this is done on the fly.
//Forward declaration of classes and visitor...
//class Game_actor; This one will be abstract, virtual, whatever.
class Game_actor_item;
class Game_actor_player;
class Game_actor_invisible;
class Visitor
{
public:
// virtual void visit(Game_actor& r)=0;
virtual void visit(Game_actor_player& r)=0;
virtual void visit(Game_actor_item& r)=0;
virtual void visit(Game_actor_invisible& r)=0;
};
Then, some interface-like basics:
//This one defines stuff that can be on the screen.
class Drawable
{
public:
virtual void draw(Screen&)=0;
};
//This one defines stuff that changes its state. Let's assume that do_logic
//returns an integer that means something to the controller and can be
//interpreted via a long list of "message_codes" (1=Add score, 2=Substract
//score, 3=Something else...). Each actor will run its logic and return its
//message, that will be stored and interpreted later. This is mostly crap,
//I know, but makes for a quick example.
class Game_actor
{
private:
float x;
float y;
public:
virtual int do_logic()=0;
void accept_visitor(Visitor& v)=0;
};
Next, our object hierarchy: Items and the player are derived from the actor, that defines part of their internal state. They can, of course, be drawn to the screen. There's a particular actor that won't be drawn, because it is invisible and controls something else.
class Game_actor_item: public Drawable, public Game_actor
{
//Lines and lines of code.
virtual void draw(Screen& s) {/* [...] */}
virtual int do_logic() {/* [...] */}
};
class Game_actor_player: public Drawable, public Game_actor
{
//Lines and lines of code.
virtual void draw(Screen& s) {/* [...] */}
virtual int do_logic() {/* [...] */}
};
class Game_actor_invisible: public Game_actor
{
//Lines and lines of code.
virtual int do_logic() {/* [...] */}
};
Finally, visitor specialization. We're gonna define two visitors, one is going to collect all drawable actors and other is going to dispatch messages to the game controller. Drawable actors will be collected from
a vector of its base class
class Visitor_drawing:public Visitor
{
private:
std::vector<Drawable *> draw_all_these;
public:
// virtual void visit(Game_actor& r)
virtual void visit(Game_actor_player& r) {draw_all_these.push_back(&r);}
virtual void visit(Game_actor_item& r) {draw_all_these.push_back(&r);}
//This one won't be drawn.
virtual void visit(Game_actor_invisible&) {}
std::vector<Drawable *> get_me_the_drawables() {return draw_all_these;}
}
class Visitor_logic:public Visitor
{
private:
std::vector<int> messages;
public:
// virtual void visit(Game_actor& r)
virtual void visit(Game_actor_player& r) {messages.push_back(r.do_logic());}
virtual void visit(Game_actor_item& r) {messages.push_back(r.do_logic());}
virtual void visit(Game_actor_invisible&) {messages.push_back(r.do_logic());}
std::vector<int> fetch_me_the_messages() {return messages;}
}
So, that's our setup. It is missing the "accept_visitor" methods, but I'm sure you get the idea here. Every final branch of the hierarchy just does void accept_visitor(Visitor& v) {v.visit(*this);}.
At any given time in our loop we collect drawable things and run logic:
std::vector<Game_actor*> actors;
while(loop)
{
Visitor_drawing dw;
Visitor_logic dl;
for(Game_actor * g : actors)
{
dw.visit(g);
dl.visit(g);
}
std::vector<Drawable *> draw_these=dw.get_me_the_drawables();
std::vector<int> messages=dl.fetch_me_the_messages();
for(Drawable * d : draw_these) d->draw(screen);
for(int * m : messages) interpret_message(m);
};
And here's my problem: I really want to keep my objects const where they should be. One requisite for this is that drawing them is never going to change their internal state (save a mutable int times_drawn, for example) so they could (and should (??)) be const. Doing their logic may change their state at each given turn (for example, moving them around the screen).
Given this particular setup, how would you manage having a const and non const visitor?. I have tried splitting the base visitor into const and non const base classes so they do
class Const_visitor
{
virtual void visit(const Thing&)=0;
};
class Non_const_visitor
{
virtual void visit(Thing&)=0;
};
class Visitor_drawing:public Const_visitor
{
virtual void visit(const Thing&)=0;
};
class Visitor_logic:public Non_const_visitor
{
virtual void visit(Thing&)=0;
};
But it seems that I would have to implement separate "accept_visitor" methods as the compiler doesn't distinguish between calls:
void accept_visitor_const(Const_visitor& v)=0;
void accept_visitor(Non_const_visitor& v)=0;
This leads to all kinds of duplication in the base visitor classes (basically writing everything twice, const and non const versions) and then separating the calls in the main loop: there's no single accept_visitor anymore and you have to know in advance what kind of visitor are you expecting (the side effect is that it really reads "I will accept this visitor that promises not to change my internals", which is somewhat desirable).
Anyway, Am I missing any other option that does not radically change this setup?. Is this a suitable and desirable option?
As always, many thanks in advance.