Cannot understand "contradiction" in Robert Martin's ISP article - c++

I read the Robert Martin's article about the Interface Segregation Principle here. At the end of the article, when solving a problem with ATM UI architecture he stated:
Consider also that each different transaction that the ATM can perform is encasulated as a derivative of the class Transaction. Thus we might have classes such as DepositTransaction, WithdrawlTransaction, TransferTransaction, etc. Each of these objects issues message to the UI. For example, the DepositTransaction object calls the RequestDepositAmount member function of the UI class. Whereas the TransferTransaction object calls the RequestTransferAmount member function of UI. This corresponds to the diagram in Figure 5.
Notice that this is precicely the situation that the ISP tells us to avoid. Each of the transactions is using a portion of the UI that no other object uses. This creates the possibility that changes to one of the derivatives of Transaction will force coresponding change to the UI, thereby affecting all the other derivatives of Transaction, and every other class that depends upon the UI interface.
So we have the following situation: if one of Transaction's derivatives is changed, then UI is changed and any other class that uses UI is changed too.
Then that problem is being solved by the following changes:
This unfortunate coupling can be avoided by segregating the UI
interface into induvidual abstract base classes such as DepositUI,
WithdrawUI and TransferUI. These abstract base classes can then be
multiply inherited into the final UI abstract class. Figure6 and
Listing 6 show this model.
But next Robert Martin states that:
It is true that, whenever a new derivative of the Transaction class is
created, a coresponding base class for the abstract UI class will be
needed. Thus the UI class and all its derivatives must change.
However, these classes are not widely used. Indeed, they are probably
only used by main, or whatever process boots the system and creates
the concrete UI instance. So the impact of adding new UI base classes
is contained.
And that's the question: how is it possible that UI's changed but no other classes are changed too? After all, if some kind of TransactionX uses XUI and XUI is superclass of UI and UI is changed (because of some ZUI), then (as far as i'm concerned) compiler needs to recompile all the classes that use XUI too, because vtable (in terms of C++) or maybe some function base addresses have been changed by change of UI. Could someone make it clean for me?

if some kind of TransactionX uses XUI and XUI is superclass of UI and UI is changed, then (as far as i'm concerned) compiler needs to recompile all the classes that use XUI too
Yes but in this case, only TransactionX depends on XUI. All other TransactionY and YUI are not impacted and do not need to be recompiled.
because vtable (in terms of C++) or maybe some function base addresses have been changed by change of UI.
You would recompile main (or ui_globals.cc in the text) which is where the address to the X/Y/Z UI interfaces are obtained to be passed to the Transaction X/Y/Z instances.

Related

OOP Design Player and AI Controlled Unit. dynamic_cast?

Lets say I have a Actor type, which can be any placeable object on my Game Level.
I also have Unit which is a child class of Actor. A Unit can be either a player or a AI controlled hero.
And Unit also got 2 child classes: Player (the player) and Hero (AI controlled unit).
In the Unit class, there will be movement info, rotation, and other general settings which will be needed for both Player and Hero. In the child classes AI will have different and more functions than the player.
Right now I'm facing the following problem:
A function only accepts Actor as parameter (e.g. OnOverlap(Actor a*))
but OnOverlap() should only do something if it is a Unit class (hero or player).
Therefore I would need something like instanceof() from Java in C++.
A workaround would be either to use dynamic_cast, but I'm not sure if thats a good idea for performance. Or use virtual, but this won't work when Hero has more functions than Player.
Or should I attempt a whole new OOP design?
I'd say that a dynamic_cast is code smell. Not necessary bad per se, but a sign that something might be going wrong with your design.
One of the important concepts in OOP is polymorphism: the idea that objects behave differently depending on their type, and that this behavior is encapsulated, hidden behind an interface. If you explicitely check the type of an object to change the logic you want to apply to it, then you're violating polymorphism.
Now virtual methods aren't that great either, they indeed incur runtime costs, and can sometimes bring too much complexity to the table. C++ makes virtual methods the exception, not the default, I believe for these very reasons.
One thing you should know is that virtual methods are only one kind of polymorphism, called dynamic polymorphism. There's another way to get different behaviors depending on a type that is less impeding for the runtime: static polymorphism, AKA template metaprogramming. But this isn't really helping on the complexity side.
Now what you really should do in this case is treat separate things separately. You probably want to have this OnOverlap() method on Units for a reason: let's say you're doing collision check on Units only, not all Actors. Then maintain a separate list of Units, and have that OnOverlap() method non-virtual on the Unit class. Thinking this way is often key.
This technique is called Run-Time Type Information (RTTI), and checking if the output of a dynamic_cast is NULL is a valid implementation.
Another method is to #include <typeinfo> and use typeid(*a).name() to get the string name of a's type.
The need to use dynamic_cast is often (though not always) a sign that you have a design flaw. In this case, I think you do.
Without further comment on the overall design of the architecture you've described, I would say using virtual methods is the right approach. Have OnOverlap takes it's actor and call an OnOverlapped method on the actor, perhaps giving it a pointer to the thing executing the initial OnOverlap method (it's not clear from your question what that is(*)).
void X::OnOverlap (Actor * actor) {
actor->OnOverlapped(this);
}
OnOverlapped is itself virtual. This allows you to "do the right thing" in the case of an actor unit, but do nothing or some other default behavior everywhere else. You are correct that in this case that means you can only work with the public API of Actor. You'd have to move anything requiring Player's additional methods into the Player implementation of OnOverlapped. If you really think you cannot do that for some reason, you should perhaps consider an alternative design at a higher level (and may need to edit your question to provide more details about your architecture).
(*) My initial read of your question made me think OnOverlap is not a method of Actor already; that it was part of something unrelated. If it is part of Actor, you may be instead interested in a pattern called double dispatch, which can be used for this sort of "collision handling" type of problem, and is also a technique using dynamic dispatch (virtual)).
These function is predefined by my Engine, where the parameter must
but the parent function "Actor". So if any Actor collides with the
Mesh, the function is called. In this case for me i see no other
solution, than getting the instance of the Actor object to know if its
a player of just something else
A simple virtual function in the Actor base class can be a noop. Override it in Unit class, and specialize it even more in Hero and Player if needed. Non-Unit Actor's will call an empty method. Cleaner than RTTI and the instanceof idiom.
It is ok to have a default base implementation that expects to be overridden by specialized descendants. That is the point of abstract base classes, except in this case you are providing a default implementation that does nothing. The idea is that you are dispatching the "DoCollision" message (a virtual function in C++). You don't care which classes handle it or how. Just that the object has the DoCollision compile-time "interface" and that you dispatched it correctly.

How should a basic class hierarchy be constructed? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I know how to code and use simple classes, and I even know how inheritance works and how to use it. However, there's a very limited amount of guides on how to actually design the structure of your class hierarchy, or even how to design a simple class? Also, when and why should I inherit (or use) a class?
So I'm not really asking about how, I'm asking when and why. Example codes are always a good way to learn, so I would appreciate them. Also, emphasize the progress of designing rather than simply giving one sentence on when and why.
I program mainly in C++, C# and Python, but I'll probably understand the simple examples in most languages.
If any of the terms seem mixed up or so, feel free to edit my question. I'm not a native and I'm not sure of all the words.
I'll use C++ as an example language, since it relies so much on inheritance and classes.
Here's a simple guide on how to build controls for a simple OS, such as windows.
Controls include simple objects on your windows, such as buttons, sliders, textboxes, etc.
Building a basic class.
This part of the guide applies for (almost) any class.
Remember, well planned is half done.
What kind of class are we working on?
Which are it's attributes and what methods does it need?
These are the main questions we need to think of.
We're working on OS controls here, so let's begin with a simple class, shall it be Button. Now, what are the attributes on our button? Obviously it needs a position on the window. Also, we don't want every button to be exact same size, so size is an other attribute. Button also "needs" a label (the text drawn on the button). This is what you do with each class, you design it and then code it. Now I know which attributes I need, so lets build the class.
class Button
{
private:
Point m_position;
Size m_size;
std::string m_label;
}
Notice how I've left out all the getters and setter and other methods for the sake of shorter code, but you'd have to include those too. I'm also expecting us to have Point and Size classes, normally we'd have to struct them ourselves.
Moving onto the next class.
Now that we got one class (Button) finished, we can move to the next class.
Let's go with Slider, the bar which e.g. helps you scroll web pages up and down.
Let's begin like we did on button, what does our slider class need?
It's got location (position) on the window and size of the slider. Also, it's got minimum and maximum values (minimum means that the scroller is set to the top of the slider, and maximum means it's on the bottom). We also need the current value, i.e. where the scroller is at the moment. This is enough for now, we can build our class:
class Slider
{
private:
Point m_position;
Size m_size;
int m_minValue;
int m_maxValue;
int m_currentValue;
}
Creating a base class.
Now that we got two classes, the first thing we notice is we just defined Point m_position; and Size m_size; attributes on both classes. This means we have two classes with common elements and we just wrote the same code twice, wouldn't it be awesome if we could write the code only once and tell both of our classes to use that code instead of rewriting? Well, we can.
Creating a base class is "always" (there are exceptions, but beginners shouldn't worry about them) recommended if we have two similar classes with common attributes, in this case Button and Slider. They are both controls on our OS with size and position. From this we get a new class, called Control:
class Control
{
private:
Point m_position;
Size m_size;
}
Inheriting similar classes from common base class.
Now that we got our Control class, which includes the common items for every control, we can tell our Button and Slider to inherit from it. This will save us time, computer's memory and eventually time. Here's our new classes:
class Control
{
private:
Point m_position;
Size m_size;
}
class Button : public Control
{
private:
std::string m_label
}
class Slider : public Control
{
private:
int m_minValue;
int m_maxValue;
int m_currentValue;
}
Now some people might say that writing Point m_position; Size m_size; twice is much easier than writing twice : public Control and creating the Control class.
This might be true in some cases, but it's still recommended not to write the same code twice, especially not when creating classes.
Besides, who knows how many common attributes we'll eventually find. Later on we might realize we need Control* m_parent member to the Control class, which points to the window (or panel or such) in which our control is held in.
An other thing is, if we later on realize that on top of Slider and Button we also need TextBox, we can just create a textbox control by saying class TextBox : public Control { ... } and only write the textbox specific member variables, instead of size, position and parent again and again on every class.
Final thoughts.
Basically always when you have two classes with common attributes or methods, you should create a base class.
This is the basic rule, but you are allowed to use your own brain since there might be some exceptions.
I am not a professional coder myself either, but I'm learning and I've taught you everything as my educators have taught it to me. I hope you (or atleast someone) will find this answer useful.
And even though some people say that python and other duck typing languages don't even need to use inheritance, they're wrong.
Using inheritance will save you so much time and money on larger projects, and eventually you'll thank yourself for creating the base classes.
The reusability and management of your project will become billion times easier.
You need to use inheritance, when you have a situation where there are two classes, that contains the attributes of a single class, or when there are two classes, in which one is dependant on the other. Eg)
class animal:
#something
class dog(animal):
#something
class cat(animal):
#something
Here, there are two classes , dog and cat, that have the attributes of the class animal. Here , inheritance plays its role.
class parent:
#something
class child(parent):
#something
Here, parent and child are two classes, where the child is dependant of the parent, where the child has the attributes of the parent and its own unique ones. So, inheritance is used here.
It depends on the language.
In Python for example you normally don't need a lot of inheritance because you can pass any object to any function and if the objects implements the proper methods everything will be fine.
class Dog:
def __init__(self, name):
self.name = name
def sing(self):
return self.name + " barks"
class Cat:
def __init__(self, name):
self.name = name
def sing(self):
return self.name + " meows"
In the above code Dog and Cat are unrelated classes, but you can pass an instance of either to a function that uses name and calls method sing.
In C++ instead you would be forced to add a base class (e.g. Animal) and to declare those two classes as derived.
Of course inheritance is implemented and useful in Python too, but in many cases in which it's necessary in say C++ or Java you can just avoid it thanks to "duck typing".
However if you want for example to inherit implementation of some methods (in this case the constructor) then inheritance could be use with Python too with
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def sing(self):
return self.name + " barks"
class Cat(Animal):
def sing(self):
return self.name + " meows"
The dark side of inheritance is that your classes will be more coupled and more difficult to reuse in other contexts you cannot foresee now.
Someone said that with object oriented programming (actually class oriented programming) sometimes you just need a banana and instead you get a gorilla holding a banana and a whole jungle with it.
I'd start with definition of class from wikipedia:
In object-oriented programming, a class is a construct that is used to
create instances of itself – referred to as class instances, class
objects, instance objects or simply objects. A class defines
constituent members which enable its instances to have state and
behavior. Data field members (member variables or instance variables)
enable a class instance to maintain state. Other kinds of members,
especially methods, enable the behavior of class instances. Classes
define the type of their instances
Often you see examples that uses dogs, animals, cats and so on. But let's get to something practical.
First and most straight forward case when you need a class is when you need (or rather you should) to encapsulate certain functions and methods together, because they simply make sense together. Let's imagine something simple: HTTP request.
What do you need when creating HTTP request? Server, port, protocol, headers, URI... You could put all that into dict like {'server': 'google.com'} but when you use class for this, you'll just make it explicit that you need these attributes together and you'll be using them to do this one particular task.
For the methods. You could again create method fetch(dict_of_settings), but whole functionality is bound to attributes of HTTP class and just doesn't make sense without them.
class HTTP:
def __init__(self):
self.server = ...
self.port = ...
...
def fetch(self):
connect to self.server on port self.port
...
r1 = HTTP(...)
r2 = HTTP(...)
r1.port = ...
data = r1.fetch()
Isn't it nice and readable?
Abstract classes/Interfaces
This point, just quick... Assume you want to implement dependency injection in your project for this particular case: you want your application to be independent on database engine.
So you propose interface (represented by abstract class) which should each database connector implement and then rely on generic methods in your application. Lets say that you define DatabaseConnectorAbstract (you don't have to actually define in python, but you do in C++/C# when proposing interface) with methods:
class DatabaseConnectorAbstract:
def connect(): raise NotImplementedError( )
def fetch_articles_list(): raise NotImplementedError( )
...
# And build mysql implementation
class DatabaseConnectorMysql(DatabaseConnectorAbstract):
...
# And finally use it in your application
class Application:
def __init__(self,database_connector):
if not isinstanceof(database_connector, DatabaseConnectorAbstract):
raise TypeError()
# And now you can rely that database_connector either implements all
# required methods or raises not implemented exception
Class hierarchy
Python exceptions. Just take a look for a second on the hierarchy there.
ArithmeticError is generic Exception and in some cases it can get as particular as saying FloatingPointError. This is extremely useful when handling exceptions.
You can realize this better on .NET forms when object has to be instance of Control when adding to form, but can be practically anything else. The whole point is that object is DataGridView while still being Control (and implementing all methods and properties). This is closely connected with abstract classes and interfaces and one of many real-life examples could be HTML elements:
class HtmlElement: pass # Provides basic escaping
class HtmlInput(HtmlElement): pass # Adds handling for values and types
class HtmlSelect(HtmlInput): pass # Select is input with multiple options
class HtmlContainer(HtmlElement): pass # div,p... can contain unlimited number of HtmlElements
class HtmlForm(HtmlContainer): pass # Handles action, method, onsubmit
I've tried to make it as brief as possible, so feel free to ask in comment.
Since you are primarily interested in the big picture, and not the mechanics of class design, you might want to familiarize yourself with the S.O.L.I.D. principles of object-oriented design. It's not a strict procedure, but a set or rules to support your own judgement and taste.
The essence is that a class represents a single responsiblity (the S). It does one thing and does it well. It should represent an abstraction, preferably one representing a piece of your application's logic (encapsulating both behavior and data to support that behavior). It could also be an aggregation abstraction of multiple related data field. The class is the unit of such encapsulation and is responsible for maintaining the invariants of your abstractions.
The way to build classes is to be both open to extensions and closed to modifications (the O). Identify likely changes in your class's dependencies (either types or constants that you used in its interface and implementation). You want the interface to be complete enough so that it can extended, yet you want its implementation to be robust enough so that it won't have to be changed for that.
That's two principles about the class as the basic building block. Now on to building hierarchies, which represents class relationships.
Hierarchies are built through inheritance or composition. The key principle here is that you only use inheritance to model strict Liskov-substitutability (the L). This is a fancy way of saying that you only use inheritance for is-a relationships. For anything else (barring some technical exceptions to get some minor implementation advantages) you use composition. This will keep your system as loosely coupled as possible.
At some point many different clients might depend on your classes for different reasons. This will grow your class hierarchy and some of the classes lower in the hierarchy can get overly large ("fat") interfaces. When that happens (and in practice it's a matter of taste and judgement) you seggregate your general-purpose class interface into many client-specific interfaces (the I).
As your hierarchy grows even further, it might appear to form a pyramid when you draw it with the basic classes on top and their subclasses or composities below it. This will mean that your higher-level application layers will depend on lower-level details. You can avoid such brittleness (which for example manifests itself through large compile times or very big cascades of changes following minor refactorings) by letting both the higher-level layer and the lower-level layer depend on abstractions (i.e. interfaces, which in C++ e.g. can be implemented as abstract classes or template parameters). Such dependency inversion (the D) once again helps to loosen couplings between the various parts of your application.
That's it: five solid pieces of advice that are more or less language independent and have stood the test of time. Software design is hard, these rules are to keep you out of the most frequently occuring types of trouble, everything else comes through practice.

Dependency inversion and pervasive dependencies

I'm trying to get dependency inversion, or at least understand how to apply it, but the problem I have at the moment is how to deal with dependencies that are pervasive. The classic example of this is trace logging, but in my application I have many services that most if not all code will depend on (trace logging, string manipulation, user message logging etc).
None of the solutions to this would appear to be particularly palatable:
Using constructor dependency injection would mean that most of the constructors would have several, many, standard injected dependencies because most classes explicitly require those dependencies (they are not just passing them down to objects that they construct).
Service locator pattern just drives the dependencies underground, removing them from the constructor but hiding them so that it's not even explicit that the dependencies are required
Singleton services are, well, Singletons, and also serve to hide the dependencies
Lumping all those common services together into a single CommonServices interface and injecting that aswell a) violates the Law of Demeter and b) is really just another name for a Service Locator, albeit a specific rather than a generic one.
Does anyone have any other suggestions for how to structure these kinds of dependencies, or indeed any experience of any of the above solutions?
Note that I don't have a particular DI framework in mind, in fact we're programming in C++ and would be doing any injection manually (if indeed dependencies are injected).
Service locator pattern just drives the dependencies underground,
Singleton services are, well, Singletons, and also serve to hide the
dependencies
This is a good observation. Hiding the dependencies doesn't remove them. Instead you should address the number of dependencies a class needs.
Using constructor dependency injection would mean that most of the
constructors would have several, many, standard injected dependencies
because most classes explicitly require those dependencies
If this is the case, you are probably violating the Single Responsibility Principle. In other words, those classes are probably too big and do too much. Since you are talking about logging and tracing, you should ask yourself if you aren't logging too much. But in general, logging and tracing are cross-cutting concerns and you should not have to add them to many classes in the system. If you correctly apply the SOLID principles, this problem goes away (as explained here).
The Dependency Inversion principle is part of the SOLID Principles and is an important principle for among other things, to promote testability and reuse of the higher-level algorithm.
Background:
As indicated on Uncle Bob's web page, Dependency Inversion is about depend on abstractions, not on concretions.
In practice, what happens is that some places where your class instantiates another class directly, need to be changed such that the implementation of the inner class can be specified by the caller.
For instance, if I have a Model class, I should not hard code it to use a specific database class. If I do that, I cannot use the Model class to use a different database implementation. This might be useful if you have a different database provider, or you may want to replace the database provider with a fake database for testing purposes.
Rather than the Model doing a "new" on the Database class, it will simply use an IDatabase interface that the Database class implements. The Model never refers to a concrete Database class. But then who instantiates the Database class? One solution is Constructor Injection (part of Dependency Injection). For this example, the Model class is given a new constructor that takes an IDatabase instance which it is to use, rather than instantiate one itself.
This solves the original problem of the Model no longer references the concrete Database class and uses the database through the IDatabase abstraction. But it introduces the problem mentioned in the Question, which is that it goes against Law of Demeter. That is, in this case, the caller of Model now has to know about IDatabase, when previously it did not. The Model is now exposing to its clients some detail about how it gets its job done.
Even if you were okay with this, there's another issue that seems to confuse a lot of people, including some trainers. There's as an assumption that any time a class, such as Model, instantiates another class concretely, then it's breaking the Dependency Inversion principle and therefore it is bad. But in practice, you can't follow these types of hard-and-fast rules. There are times when you need to use concrete classes. For instance, if you're going to throw an exception you have to "new it up" (eg. threw new BadArgumentException(...)). Or use classes from the base system such as strings, dictionaries, etc.
There's no simple rule that works in all cases. You have to understand what it is that you're trying to accomplish. If you're after testability, then the fact that the Model classes references the Database class directly is not itself a problem. The problem is the fact that the Model class has no other means of using another Database class. You solve this problem by implementing the Model class such that it uses IDatabase, and allows a client to specify an IDatabase implementation. If one is not specified by the client, the Model can then use a concrete implementation.
This is similar to the design of the many libraries, including C++ Standard Library. For instance, looking at the declaration std::set container:
template < class T, // set::key_type/value_type
class Compare = less<T>, // set::key_compare/value_compare
class Alloc = allocator<T> > // set::allocator_type
> class set;
You can see that it allows you to specify a comparer and an allocator, but most of the time, you take the default, especially the allocator. The STL has many such facets, especially in the IO library where detailed aspects of streaming can be augmented for localization, endianness, locales, etc.
In addition to testability, this allows the reuse of the higher-level algorithm with entirely different implementation of the classes that the algorithm internally uses.
And finally, back to the assertion I made previously with regard to scenarios where you would not want to invert the dependency. That is, there are times when you need to instantiate a concrete class, such as when instantiating the exception class, BadArgumentException. But, if you're after testability, you can also make the argument that you do, in fact, want to invert dependency of this as well. You may want to design the Model class such that all instantiations of exceptions are delegated to a class and invoked through an abstract interface. That way, code that tests the Model class can provide its own exception class whose usage the test can then monitor.
I've had colleagues give me examples where they abstract instantiation of even system calls, such as "getsystemtime" simply so they can test daylight savings and time-zone scenarios through their unit-testing.
Follow the YAGNI principle -- don't add abstractions simply because you think you might need it. If you're practicing test-first development, the right abstractions becomes apparent and only just enough abstraction is implemented to pass the test.
class Base {
public:
void doX() {
doA();
doB();
}
virtual void doA() {/*does A*/}
virtual void doB() {/*does B*/}
};
class LoggedBase public : Base {
public:
LoggedBase(Logger& logger) : l(logger) {}
virtual void doA() {l.log("start A"); Base::doA(); l.log("Stop A");}
virtual void doB() {l.log("start B"); Base::doB(); l.log("Stop B");}
private:
Logger& l;
};
Now you can create the LoggedBase using an abstract factory that knows about the logger. Nobody else has to know about the logger, nor do they need to know about LoggedBase.
class BaseFactory {
public:
virtual Base& makeBase() = 0;
};
class BaseFactoryImp public : BaseFactory {
public:
BaseFactoryImp(Logger& logger) : l(logger) {}
virtual Base& makeBase() {return *(new LoggedBase(l));}
};
The factory implementation is held in a global variable:
BaseFactory* baseFactory;
And is initialized to an instance of BaseFactoryImp by 'main' or some function close to main. Only that function knows about BaseFactoryImp and LoggedBase. Everyone else is blissfully ignorant of them all.

Virtual event handlers from several classes: multiple inheritance or composition?

My team has written several C++ classes which implement event handling via pure virtual callbacks - for example, when a message is received from another process, the base class which handles IPC messaging calls its own pure virtual function, and a derived class handles the event in an override of that function. The base class knows the event has occurred; the derived class knows what to do with it.
I now want to combine the features provided by these base classes in a higher-level class, so for example when a message arrives from another process, my new class can then forward it on over its network connection using a similar event-driven networking class. It looks like I have two options:
(1) composition: derive classes from each of the event-handling base classes and add objects of those derived classes to my new class as members, or:
(2) multiple inheritance: make my new class a derived class of all of the event-handling base classes.
I've tried both (1) and (2), and I'm not satisfied with my implementation of either.
There's an extra complication: some of the base classes have been written using initialisation and shutdown methods instead of using constructors and destructors, and of course these methods have the same names in each class. So multiple inheritance causes function name ambiguity. Solvable with using declarations and/or explicit scoping, but not the most maintainable-looking thing I've ever seen.
Even without that problem, using multiple inheritance and overriding every pure virtual function from each of several base classes is going to make my new class very big, bordering on "God Object"-ness. As requirements change (read: "as requirements are added") this isn't going to scale well.
On the other hand, using separate derived classes and adding them as members of my new class means I have to write lots of methods on each derived class to exchange information between them. This feels very much like "getters and setters" - not quite as bad, but there's a lot of "get this information from that class and hand it to this one", which has an inefficient feel to it - lots of extra methods, lots of extra reads and writes, and the classes have to know a lot about each other's logic, which feels wrong. I think a full-blown publish-and-subscribe model would be overkill, but I haven't yet found a simple alternative.
There's also a lot of duplication of data if I use composition. For example, if my class's state depends on whether its network connection is up and running, I have to either have a state flag in every class affected by this, or have every class query the networking class for its state every time a decision needs to be made. If I had just one multiply-inherited class, I could just use a flag which any code in my class could access.
So, multiple inheritance, composition, or perhaps something else entirely? Is there a general rule-of-thumb on how best to approach this kind of thing?
From your description I think you've gone for a "template method" style approach where the base does work and then calls a pure virtual that the derived class implements rather than a "callback interface" approach which is pretty much the same except that the pure virtual method is on a completely separate interface that's passed in to the "base" as a parameter to the constructor. I personally prefer the later as I find it considerably more flexible when the time comes to plug objects together and build higher level objects.
I tend to go for composition with the composing class implementing the callback interfaces that the composed objects require and then potentially composing again in a similar style at a higher level.
You can then decide if it's appropriate to compose by having the composing object implement the callback interfaces and pass them in to the "composed" objects in their constructors OR you can implement the callback interface in its own object possibly with a simpler and more precise callback interface that your composing object implements, and compose both the "base object" and the "callback implementation object"...
Personally I wouldn't go with an "abstract event handling" interface as I prefer my code to be explicit and clear even if that leads to it being slightly less generic.
I'm not totally clear on what your new class is trying to achieve, but it sounds like you're effectively having to provide a new implementation somewhere for all of these abstract event classes.
Personally I would plump for composition. Multiple inheritance quickly becomes a nightmare, especially when things have to change, and composition keeps the existing separation of concerns.
You state that each derived object will have to communicate with the network class, but can you try and reduce this to the minimum. For instance, each derived event object is purely responsible for packaging up the event info into some kind of generic packet, and then that packet is passed to the network class to do the guts of sending?
Without knowing exactly what your new class is doing it's hard to comment, or suggest better patterns, but the more I code, the more I am learning to agree with the old adage "favour composition over inheritance"

Enterprise Architect - Inherit methods from interface in class diagram

In Enterprise Architect ( Version 9.2.921 ) I want to make a class diagram. I have a class MyInterface which acts as an Interface . So in EA I choose stereotype <<interface>> and also marked it as abstract.
Now to keep it simple, my abstract interface defines one virtual function. Now I have a class MyChild , which is a child of my interface ( class MyChild :: MyInterface ) and which shall implement this function.
To do so in EA, I created a new class. Then right-click on it --> Advanced --> Parent .
As type I pick implementsand then I choose my Interface class.
On my class diagram the arrow from child to parent is correct ( dashed line, with empty arrow head in direction of the interface ).
Now the problem is, I would expect EA to add my abstract function from the interface right into the implementation class itself. So for example if I change/add/delete a virtual function in the Interface class it gets right away changed in the child classes. But the problem is, the function doesn't show up in the body of the child class.
Is there any way to do make Enterprise Architecht do this?
First off, there's another way of drawing connections which you may find easier. If you select the class in the diagram, you'll see a little arrow icon appear just above/right of the class. Click this, drag to the interface and drop, and EA will provide you with a set of possible connectors, with the most relevant ones first. This list is context-sensitive based on both the source and target element types (in this case, class and interface).
When it comes to the "Overrides & Implementations" dialog, there are some subtleties involved.
If a class realizes an interface, the class actually has the operations specified by the interface, although hidden, even if you don't select them to be implemented (which is why the interface operations are deselected by default in this dialog).
If you use the class in a sequence diagram, and make a call to it, you will see that you can select the interface-defined operation in the "Message Properties" dialog (provided "Show Inherited Methods" is selected). This name will be updated automatically if you rename the operation in the interface.
If you draw a generalization between two classes, you get the same behaviour in the sequence diagram. In addition, you can select display of a class' inherited (through generalization) operations by right-clicking it, selecting "Feature Visibility" and ticking "Show Operations." Note that this only works for operations arrived at through generalizations (from other classes), not realizations (from interfaces). I consider this a bug, but it may be by design.
If you do select an operation in the "Overrides & Implementations" dialog, that means you are making a copy of it. EA will not remember where the overridden operation came from, and won't update the name if you change it in the interface / abstract class.
Using the right-click - Advanced - Parent method bypasses the "Overrides & Implementations" dialog but creates the connector, as you've noted.
Now you mention that you create a class and then set the "interface" stereotype. This isn't the way to do it; you should instead create the interface using the interface symbol in the toolbox. A Class with the "interface" stereotype is not the same as an Interface and I'm not sure which of the behaviours I've described you'll get with that construct.
If it's an Interface you want, use that. If on the other hand you're talking about an abstract class, then Class is right and neither the abstract nor the concrete class should have the "interface" stereotype.
Note also that if you've got a code base you want to draw diagrams for, chances are that EA can reverse-engineer it for you (if it's in C++, C#, Java, or about a dozen other languages).
Okay I found a way:
Delete the connection between the two classes ( if there already was one )
Select Realization from the Class Relationships in the Toolbox
Draw a line from your Child class to the interface
When releasing the mouse you will be prompted to chose the function which your child shall implement
This way you don't have to retype all the function prototypes time and time again - but if you change the prototype in the interface, it won't change the according function in the implementations. ( Maybe there is another way too, but I don't know it yet... )
I had the same problem.
I'm not really happy with the answer. How to "Delete" the Realization
If "Delete"="Hide on Diagram", you will have two Realization-Assocs at the end
If "Delete"="Delete from Model" this Assoc be removed in other Diagrams, where it was used