I wasn't sure of the best name for this thread, but I'm trying to refactor some code and remove some decoupling. I am forced to use Visual Studio 2005 C++ without boost, don't ask... (So not c++11, or newer)
I have a protocol that receives messages, and the protocol contains a parser and processor. Parser extracts the information out of the message, and populates a structure. The structure is then passed into the processor to take further action on it.
class Protocol
{
Parser parser;
Processor processor;
public:
Protocol() : parser(processor)
{
}
handleMessage(Message& message)
{
ParsedData parsedData;
parser.parse(message, parsedData);
}
}
class Parser
{
Processor processor;
public:
Parser()
{
}
Parser(Processor& p) : processor(p)
{
}
parse(Message& message, ParsedData& parsedData)
{
if(message.type == "whatever")
{
parseLevel2(message.message, parsedData);
}
//else if Other message types
}
parseLevel2(MessageLevel2& message, ParsedData& parsedData)
{
//Keep going down the rabbit hole, but for simplicity it ends here
parsedData.blah = "some data";
processor.ProcessBlahMessage(parsedData);
}
}
class Processor
{
public:
Processor()
{
}
ProcessBlahMessage(ParsedData& parsedData)
{
//Do logic
}
}
I was hoping to strip the Processor from the Parser so it became more like this...
class Protocol
{
Parser parser;
Processor processor;
public:
Protocol() : parser(processor)
{
}
handleMessage(Message& message)
{
ParsedData parsedData;
parser.parse(message, parsedData); //This will not call the processor from within it
processor.process(parsedData); //This is the new
}
}
The only issue that is preventing me from doing this is I will have to have a bunch of if statements in the process method.
process(ParsedData& parsedData)
{
if(parsedData.type == "blah")
{
ProcessBlahMessage()
}
else if(parsedData.type == "grah")
{
ProcessGrahMessage()
}
//etc...
}
My question is how do I avoid all those if statements where I'm essentially just parsing it again? If I give the parsedData a function pointer, or lambda then I'm still going to need a reference to the processor in the parser.
you can try this:
1) in your parsed data instead of .blah and .grah store vector<void*>
2) assuming create new blah object ( or whatever message type is) and put pointer to it into vector (using type as index).
3) in your processor store vector of handlers. pass into processor type along with parsed data, so you can call correct handler for correct pointer
4) in your handler cast void* to blah* (or whatever real type is)
Related
I am creating a text based monopoly game in Rust as a personal project. My current setup is to have the various kinds of spaces as their own structs (for example, Property)
use space::Event;
pub struct Property {
message: String,
}
impl Property {
pub fn new() -> Property {
let message = String::from("Hello World!");
Property { message: message }
}
}
impl Event for Property {
fn event(&self) {
print!("{}", &self.message);
}
}
and a generic Space struct that contains an instance of one of the types of spaces (Space<Property> or Space<Chance> for example).
pub trait Event {
fn event(&self);
}
pub struct Space<T> {
item: T,
}
impl<T: Event> Space<T> {
pub fn new(item: T) -> Space<T> {
Space { item: item }
}
pub fn event(&self) {
&self.item.event();
}
}
Each type of space implements a trait that requires it to have an "event" method, which the generic Space struct can call. Then I have a Game struct that will contain some sort of collection of spaces (among other things).
pub struct Game {
spaces: Vec<Space>, // Does not work
}
Unfortunately I'm running into an issue creating this collection. No matter which one I try it tells me I have to specify a type argument for Space. How can I make a collection of structs that are generically typed? It would be preferable if I can pull up a particular space by its index, as that will make it easier when I start to implement certain Chance cards that move you to particular spaces later down the line. Apologies if I'm missing something obvious, I'm new-ish to Rust so I don't always necessarily know what to look for.
The Rust compiler needs to know how big each element in your Vec will be to decide how to lay out memory (each element must take up the same amount of space). Your Space struct has a type parameter T so it's not clear how much space a Space will take unless you provide the type parameter too. E.g. Vec<Space<i32>> would work.
If you want a Vec of differently sized objects, a common approach is to use a vector of trait objects. In your example you could have a Vec<Box<Event>>, a vector of objects that implement the Event trait, each element of the vec here is a Box (smart pointer) to a heap-allocated type that implements Event.
pub trait Event {
fn event(&self);
}
pub struct Property {
message: String,
}
impl Property {
pub fn new(message: String) -> Property {
Property { message }
}
}
impl Event for Property {
fn event(&self) {
println!("{}", &self.message);
}
}
pub struct Utility {
message: String,
}
impl Utility {
pub fn new(message: String) -> Utility {
Utility { message }
}
}
impl Event for Utility {
fn event(&self) {
println!("{}", &self.message);
}
}
pub struct Game {
pub spaces: Vec<Box<Event>>,
}
fn main () {
let game = Game{
spaces: vec![
Box::new(Utility::new(String::from("Water works"))),
Box::new(Property::new(String::from("Fleet Street"))),
Box::new(Utility::new(String::from("Electric company"))),
Box::new(Property::new(String::from("Bond Street"))),
]
};
for space in game.spaces {
space.event();
}
}
// Water works
// Fleet Street
// Electric company
// Bond Street
I'm sorry if I don't know the right word for what I'm trying to accomplish.
Basically I have an event handler object which only has a single member. The member is a Stage object.
When the event handler receives an event, I want it to simply use the stage object to call the relevant method. For example:
Event event; //this event is not part of my code, but rather the library I'm using.
Stage s; // my custom class object
EventHandler event_handler; //also my custom class object
event_handler.stage = &s;
if(event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
So what I'm trying to accomplish is that, there will be seperate scopes that my program goes into over time, and I want each scope to have access to the event_handler such that they can do something like:
void some_other_scope(EventHandler* eh) {
Stage* some_new_stage = new Stage(...);
eh->stage = some_new_stage;
}
This way, the original event code stays the same, and the event handler will be calling handle_shutdown on a different object than it was originally going to.
So what I want to do is to overload the handle_shutdown method so that there can be different implementations of it. I know how basic overloading works, it can be done by specifying different parameters, but is there any way to have different definitions of the same class method based on the file that the object was created in?
I was hoping to have several files, each with their own some_other_scope() function, and each file can redefine the handle_shutdown method to do different things based on what that file needs.
I'm sure there's a way to do what I want, I just don't know the right words to use.
It seems you want to use polymorphism:
class IStage
{
public:
virtual ~IStage() = default;
virtual void handle_shutdown() = 0;
// ...
};
class Stage1 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
class Stage2 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
And then
struct EventHandler
{
std::unique_ptr<IStage> stage;
// ...
};
EventHandler event_handler;
event_handler.stage = std::make_unique<Stage1>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
// Later
event_handler.stage = std::make_unique<Stage2>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
I am trying to learn TypeScript, and need some advice on implementing generic collection types. I put the dictionary and HashSet in another question, here I'd like any advice on my list type.
Especially the ForEach-Operation looks a bit strange. I think I found it in another question here, and "improved" by returning true or false to give feedback if the iteration was stopped early or completed.
import { IForEachFunction } from "./IForEachFunction"
export class List<T> {
private _items: Array<T>;
public constructor() {
this._items = [];
}
public get Count(): number {
return this._items.length;
}
public Item(index: number): T {
return this._items[index];
}
public Add(value: T): void {
this._items.push(value);
}
public RemoveAt(index: number): void {
this._items.splice(index, 1);
}
public Remove(value: T): void {
let index = this._items.indexOf(value);
this.RemoveAt(index);
}
public ForEach(callback: IForEachFunction<T>): boolean {
for (const element of this._items) {
if (callback(element) === false) {
return false;
}
}
return true;
}
}
The ForEach-Iteration relies on an interface from another file:
export interface IForEachFunction<T> {
(callback: T): boolean | void;
}
You would use my list and the ForEach-Method like this:
let myList: List<a_type> = new List<a_type>();
let completed: boolean = myList.ForEach(xyz => {
// do something with xyz
return false; // aborts the iteration
return true; // continues with the next element
});
if (completed) // we can see what happened "during" the iteration
I think this is not bad, but I'd appreciate any input. I am not sure if I use the === correctly.
Another question which I really like to know: How could I define a function with the interface IForEachFunction? I do not really "re-use" that interface visibly, I always declare an anonymous method as shown above. If I wanted to call a method having the interface definition, is that possible?
Thanks!
Ralf
One problem I see is that you have an interface instance:
callback: IForEachFunction<T>
This contains a method called
callback()
But you only call callback once. You would have call callback() method inside your interface:
callback.callback()
Also your code looks like it is inspired by C# or Java. In TypeScript you would often just use an array. This simplifies certain code constructs.
I'd like to write a unit-test for a method that prints to the standard output.
I have already changed the code so it prints to a passed-in File instance instead that is stdout by default. The only thing I am missing is some in-memory File instance that I could pass-in. Is there such a thing? Any recommendation? I wish something like this worked:
import std.stdio;
void greet(File f = stdout) {
f.writeln("hello!");
}
unittest {
greet(inmemory);
assert(inmemory.content == "hello!\n")
}
void main() {
greet();
}
Any other approach for unit-testing code that prints to stdout?
Instead of relying on File which is quite a low level type, pass the object in via an interface.
As you have aluded to in your comment OutputStreamWriter in Java is a wrapper of many interfaces designed to be an abstraction over byte streams, etc. I'd do the same:
interface OutputWriter {
public void writeln(string line);
public string #property content();
// etc.
}
class YourFile : OutputWriter {
// handle a File.
}
void greet(ref OutputWriter output) {
output.writeln("hello!");
}
unittest {
class FakeFile : OutputWriter {
// mock the file using an array.
}
auto mock = new FakeFile();
greet(inmemory);
assert(inmemory.content == "hello!\n")
}
I have a state machine with one state which dispatches some message (e.g. text) to an external receiver. Before transiting to this state (let's call it Dispatching) previous state needs somewhere to store that message so Dispatching can fetch it later. As message is created in one context and consumed in another, it will be created on the heap and State Manager object (which manages states, transitions and event loop) keeps a reference/pointer to it. State objects are created and destroyed as state machine transits through states. Each state inherits abstract base class State:
enum StateID
{
STATE_A,
STATE_B,
...
};
class State
{
public:
State(StateID stateID, StateManager& sm) :
stateID_(stateID), sm(sm_){}
virtual ~State(){};
virtual StateID HandleEvent(const Event& e) = 0;
StateID id() const {return stateID_;}
protected:
StateID stateID_;
StateManager& sm_;
};
In order to make passing data to the next state generic, I came up with the idea of StateData - a piece of information passed from one state to the next one. It is stored in dynamic memory, State Manager keeps a reference to it so each state can access it. As it is possible that different types of data will be passed to different states, StateData can be made abstract base class, specialized for each particular state:
struct StateData
{
virtual ~StateData() = 0;
};
struct StateAData : public StateData
{
int n_;
StateAData(int n) : n_(n){}
};
struct StateBData : public StateData
{
std::string str_;
StateBData(const std::string& str) : str_(str){}
};
...
class StateManager
{
boost::scoped_ptr<State> pCurrState_;
boost::scoped_ptr<StateData> pStateData_;
...
public:
void runEventLoop()
{
while(true)
{
...
//get event from a queue
...
StateID nextStateID = pCurrState_->HandleEvent(e);
if(nextStateID == pCurrState_->id())
continue;
pCurrState_.reset(0);
switch(nextStateID)
{
case STATE_A:
pCurrState_.reset(new StateA(*this));
break;
case STATE_B:
pCurrState_.reset(new StateB(*this));
break;
case STATE_C:
pCurrState_.reset(new StateC(*this));
break;
...
}
}
}
...
};
class StateA
{
public:
StateA(StateManager& sm) : State(STATE_A, sm){}
StateID HandleEvent(const Event& e)
{
switch(e.ID)
{
case EVENT_1:
{
StateAData* pData = reinterpret_cast<StateAData*>(stateMachine_.pStateData_.get());
// do something with data, e.g. use it for transition logic
if(pData->n_ % 2)
{
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_B;
}
else
{
...
}
break;
}
...
}
}
...
}
There is a pitfall in following lines:
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_B;
If transition logic changes so from here we need to go to STATE_C, developer can forget to change the type of StateBData to StateCData:
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_C;
...which would lead to undesired behaviour when StateC tries to cast down StateData to StateCData.
How to avoid this? How to enforce matching the type of created object and returned enum value?
Yeah, this code stinks and this is the consequence of using two piece information and using enum to distinguish state types instead of types themselves. HandleEvent could return StateXData and depending on this returned type (as it carries the information about the next state) State Manager would determine (by using RTTI) the next state to transit to (X) but I don't like this solution.
Another idea is to create an instance of the next state and pass its data into its constructor but this approach would pollute state machine design as one state would be created before previous state is destroyed.
Make the enum part of the base class or provide a pure virtual function in the base class to return this enum. This way, the state itself will advertise its type.