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);
};
Related
I have many interfaces for different listeners, the all look like this:
class ListenerA
{
public:
virtual void
onEventA(const EventA&) = 0;
};
class ListenerB
{
public:
virtual void
onEventB(const EventB&) = 0;
};
When testing, I always end up just collecting those events in a std::vector for analyzing them afterwards in a specific test suite. Those event collectors all look the same like this one for example:
class EventACollector : public ListenerA
{
public:
const auto&
events() const
{
return m_events;
}
private:
void
onEventA(const EventA& event) override
{
m_events.emplace_back(event);
}
std::vector<EventA> m_events;
};
Is there a way to template an EventTCollector, so that I do not have to write it every time? Given that the virtual function name does change for every listeners?
C++ does not have introspection, so you cannot find the virtual function in ListenerA. The other parts can go in a templated base class, but the override you'll need to define manually.
Modern C++ would use a std::function<void(EventA)> instead of a named interface, but that won't help you as a user of that old interface.
Currently I'm writing the message handling system for my game server. I'm using double-dispatch design pattern to pick the needed handler according to message id, which retrieved from a data buffer. But I ran into a following problem: I need to determine the derived class of the message to pass it into a double-dispatch handler object. the only solution I found is to write a factory method in base class with the switch inside, that will create needed derived class according to message id.
class Message
{
public:
void dispatch(Handler& handler)
{
dispatchImpl(handler);
}
protected:
virtual void dispatchImpl(Handler& handler) = 0;
};
template <typename TDerived>
class BaseMessage : public Message
{
public:
BaseMessage(unsigned short messageId)
: id(messageId) {};
virtual ~BaseMessage() = default;
unsigned short getId() const { return id; }
static std::unique_ptr<Message> create(BitStream& data)
{
switch (data.ReadShort())
{
case 1: return std::make_unique<FirstMessage>();
case 2: return std::make_unique<SecondMessage>();
case 3: return std::make_unique<ThirdMessage>();
// ...
}
}
protected:
unsigned short id;
virtual void dispatchImpl(Handler& handler) override
{
handler.handle(static_cast<TDerived&>(*this));
}
};
How can I improve my design to avoid big-switch statement? Thanks in advance.
You might use a std::map<short,std::function<std::unique_ptr<Message> (BitStream& data)> and allow registration of those factory functions dynamically:
std::map<short,std::function<std::unique_ptr<Message> (BitStream& data)> createMessageHandlers;
void registerCreateMessageHandler(short id,std::function<std::unique_ptr<Message> (BitStream& data)> fn) {
createMessageHandlers[id] = fn;
}
and use it like
registerCreateMessageHandler(1, [](BitStream& data) { return std::make_unique<FirstMessage>();});
registerCreateMessageHandler(2, [](BitStream& data) { return std::make_unique<SecondMessage>();});
Your message type constructors should probably take the BitStream& as a constructor parameter.
You should consider to use a tool like google protocol buffers to define your communication protocols.
That would help a lot in properly versioning, and parsing message packets (endianess neutral) over the wire (or wireless).
In combination with e.g. boost::asio or zeromq for the transport handling, that should give you the maximum flexibility and proper mechanisms to separate the transport and semantical layers of communication.
Is there a way to do the following with templates? The following code throws unknown type compile time errors.
I'm trying to create two different types of Application, those that inherit from Application, and those that inherit from Service, which inherits from Application. All Applications have one service called Cron, which will inherit from Service. Applications will be threaded and detached, while Services that derive from Application will be threaded and joined. I broke this down to simplest terms.
#include <iostream>
class Application
{
public:
Service service; //Throws unknown type... Forward decl. will not work either.
};
class Service:public Application
{
};
int main(int argc, const char * argv[])
{
// insert code here...
std::cout << "Hello, World!\n";
return 0;
}
Thanks,
Bruce
No, there is no way to do what you want, because what you want to do is nonsense. Hold on, I'll explain.
Service is derived from Application, but Application has a member of type Service.
This is a cyclic dependancy but beyond that, I just don't understand it. Since Service is derived from Application, which has a member of type Service, which is derived from Application, which has a member of type Service... you get the idea. It's like standing in front of a mirror with a mirror and trying to find the end.
Now the question becomes, what are you really trying to do?
In your comments, you said:
I'm trying to create two different types of Application, those that
inherit from Application, and those that inherit from Service, which
inherits from Application. All Applications have one service called
Cron, which will inherit from Service.
There's still a little ambiguity here. How can Application derive from Application?
I suspect that what you're after is having two different concrete instantiations of the class which implements Service. One only implements Service, and the other implements other stuff too.
In that case:
class Service
{
public:
void Cron();
};
class Application
{
public:
void OtherStuff();
};
But you also said:
Applications will be threaded and detached, while Services that derive
from Application will be threaded and joined.
That sounds like a job for a policy-based design.
class DetatchedPolicy
{
public:
void StartThread(); // this function would start the thread and detatch
};
class JoinedPolicy
{
public:
void StartThread(); // this function would start the thread and join
};
template <typename ThreadingPolicy>
class BasicService
:
public ThreadingPolicy
{
public:
Service()
{
StartThread();
}
void Cron();
};
typedef BasicService <JoinedPolicy> Service;
typedef BasicService <DetatchedPolicy> Application;
I think what you actually want to do is to use a pointer.
class Service;
class Application
{
std::shared_ptr<Service> m_service;
};
class Service : public Application
{
};
It sounds to me like you may benefit from separating the interfaces from the implementations:
struct ApplicationInterface
{
virtual ~ApplicationInterface() {}
virtual void do_application_stuff_1() = 0;
virtual void do_application_stuff_2() = 0;
};
struct ServiceInterface
: public ApplicationInterface
{
virtual ~ServiceInterface() {}
virtual void do_service_stuff_1() = 0;
virtual void do_service_stuff_2() = 0;
};
class CronService
: ServiceInterface
{
public:
// ApplicationInterface
virtual void do_application_stuff_1() {}
virtual void do_application_stuff_2() {}
// ServiceInterface
virtual void do_service_stuff_1() {}
virtual void do_service_stuff_2() {}
};
class Application
: ApplicationInterface
{
protected:
CronService cron;
public:
virtual void do_application_stuff_1() {}
virtual void do_application_stuff_2() {}
};
I would like to ask a couple of questions of design patterns.
Lets take for example strategy design pattern:
class Printer{
public:
void print(Message){
}
};
class Message{
public:
void print();
};
class SingleMessage : public Message{
string s;
public:
void print();
};
class Messages : public Message{
vector<Message> v;
public:
void print();
};
According to UML of this pattern, Printer should have method print(Message). What I don't understand (and sorry if this is idiotic question) is do we need to call Message class print method or what? We need to print out message, but we can't create new Message object in class Printer, because then it would be composition. So what should we do then?
Also, maybe you can share some sort of tutorial in which design patterns would be explained (how to use them, when to use them, etc.)?
First off, the concept of composition is on a whole different level than design patterns. Most design patterns use composition – that’s totally fine.
Secondly, no, you don’t use composition here. You invoke the print function of the argument that’s passed to the printer:
class Printer{
public:
void print(Message& m) {
m.print();
}
};
I’ve gone ahead and fixed a bug: the argument needs to be passed by reference (or as a pointer), otherwise you lose the dynamic type. For that reason, the Message::print function also needs to be declared as virtual.
What I don't understand (and sorry if this is idiotic question) is do we need to call Message class print method or what?
Yes. The Message::print function should be abstract, and implemented (as a different strategy) in each class inheriting from Message.
We need to print out message, but we can't create new Message object in class Printer, because then it would be composition. So what should we do then?
You don't need to create a new instance in the printer (i.e. you don't need composition here). All you do here is choose the implementation strategy for printing by deciding what concrete implementation will be passed into the Printer::print function.
Also, maybe you can share some sort of tutorial in which design patterns would be explained (how to use them, when to use them, etc.)?
Normally design patterns are idiomatic solutions to re-occurring design problems. You can find details on wikipedia regarding when to use them. For example, this page says:
"In computer programming, the strategy pattern (also known as the
policy pattern) is a software design pattern, whereby an algorithm's
behaviour can be selected at runtime."
As a side note, this is not a very good example for the strategy pattern. A better one would have been to abstract what printing means, not what a message means:
class Message{
public:
void display(Printer& p) {
p.print(*this); // what printing strategy is applied to
// display the message depends on the
// concrete type of the parameter (on what
// Printer specialization you call
// the function with)
}
};
struct Printer{
virtual void print(Message& m);
};
struct BWPrinter: Printer {
virtual void print(Message& m);
};
struct ColorPrinter: Printer {
virtual void print(Message& m);
};
struct IOStreamPrinter: Printer {
IOStreamPrinter(std::iostream& s);
virtual void print(Message& m);
};
What you probably want to do is to provide a Printer as Strategy. You can spezialize a CoutPrinter FilePrinter or PrinterPrinter...
class Printer{
public:
virtual void print(const string& message) = 0;
};
class CoutPrinter{
public:
void print(const string& message) override {
std::cout << message << "\n";
}
};
You can then use this concept to print messages:
class Message{
public:
virtual print(Printer& printer) = 0;
};
class SingleMessage : public Message {
string s;
public:
void print(Printer& printer) override
{
printer.print(s)
}
};
class Messages {
vector<Message> messages;
std::unique_ptr<Printer> printer;
public:
/// Inject the concrete Printer strategy here
Messages(std::unique_ptr<Printer> printerStrategy) :
printer(move(printer))
{}
void print() {
for(auto& m : messages)
m.print(*printer);
}
};
You can know use constructor injection to select different printers for your Messages
int main()
{
Messages messages {std::make_unique<CoutPrinter>()};
messages.print(); // will print all messages to std::cout
}
Composite Pattern
In your example you derived Messages from Message. This is the Composite Pattern. You can combine both:
class Messages : public Messages {
vector<Message> messages;
public:
void print(Printer& printer) override {
for(auto& m : messages)
m.print(*printer);
}
};
int main()
{
Messages messages;
CoutPrinter printer;
messages.print(printer); // will print all messages to std::cout
}
class ITransportProvider
{
public:
virtual ~ITransportProvider() { }
protected:
virtual void SendData() = 0;
// Concrete TransportProvider will call OnReceiveDataEvent
// virtual void RegisterHandlers(std::function<void()> onReceiveDataEvent);
}
class Device
{
public:
Device(shared_ptr<ITransportProvider> transport)
: m_Transport(transport)
{
// transport->RegisterHandlers(boost::bind(&Device::OnReceiveData, this));
}
void SendData()
{
m_Transport->SendData();
}
// Which design pattern to use to get concrete TransportProvider's OnReceiveData event?
//void OnReceiveData()
//{
//}
private:
shared_ptr<ITransportProvider> m_Transport;
};
I've always added a "RegisterHandlers" in my ITransportProvider and make Device call it in its c'tor.
I'd like to know if its correctness in the eyes of DI/IoC gurus and would love to hear all suggestions.
EDIT:
To clarify, I'm asking if there's a better way of decoupling TransportProvider from Device besides the above way which is via DI and the Observer pattern.
You have a reasonable design. Decoupling can be handled at many different levels in different ways with various trade-offs. Your design is good for the case where you know the sending and receiving are related, but there is no particular compile-time relationship between Device instances and Transport implementations. If there was a compile-time relationship, you might use policy-based design:
class TransportProviderA
{
public:
void SendData();
virtual void OnReceiveData() = 0;
}
template <typename TransportPolicy>
class Device : public TransportPolicy
{
public:
Device(const TransportPolicy &transport_policy)
: TransportPolicy(transport_policy)
{
}
// SendData provided by TransportPolicy
virtual void OnReceiveData(); // overrides TransportPolicy's template method.
};
Then use it like this:
Device<TransportPolicyA> my_device(TransportPolicyA());