I am trying to represent the following situation in a UML Class Diagram.
We have a class named Selection where the user select how will the
next screen be.
The selection class has a property screen: Screen, where screen is an interface.
There are multiple implementations of the interface screen. ex. SimpleScreen, SuperScreen, etc.
The screen property in selection class should be able to contain an instance of any implementation of screen depending on user choice.
My questions are:
Is it possible to do this in OO?
How would the Class Diagram representation look like for this case?
Right now I have a diagram like this: http://yuml.me/1dcb2f2f
If you want to modify the diagram I used yuml.me this is the link http://yuml.me/edit/1dcb2f2f
Thank you for your help
Yes it is possible to do it in OO. The correct UML notation is:
http://app.genmymodel.com/engine/xaelis/nextScreen.jpg
In order to act upon an abstract 'screen' polymorphically the implementations would have to adhere to a common interface or inherit from a common base class.
I'm not sure of the proper way to UML this, I think you've got the diagram about right.
Get acquainted with design patterns.
Use factory method (produce instance based on the user choice) +
singleton (makes factory easily accessible and ensures that only one factory exists) for producing instance of needed class +
object composition with bridge pattern(allows to decouple interface from implementation and allows to switch implementation in a run-time/)
Related
In the UML class diagram the interface is equivalent to the interface concept in programming languages (a set of methods that the class that implement the interface should implement). I want to know if the interface in the component diagram has the same meaning. Are the interfaces mentioned in the component diagram the same interfaces that are detailed in the class diagram or should I treat every method in the component diagram as a separate interface?
There is actually no real difference between both. You can realize an interface with a class as well as with a component. Also you can show the realization in both cases with the socket/lollipop notation.
Components are not much different to classes. You can think of a component as a container that hosts a number of different classes. And if one of those classes realizes an interface you can expose that through the component (if you so wish). Additionally a component can have a lot of internal interfaces for its hosted classes.
Assuming I have an interface and 3 or 4 classes that implement the interface. Now let's say I have another method but it is relevant only for one or two implementing classes.
So as I see it there are two approaches
Declare the method in the interface, implement in all the classes. In classes that the method is not relevant - throw "not supported" exception.
Declare the method only in the implementing classes where relevant but then you have to downcast the instance from interface type to the specific type in order to call the method.
So would be your design here and why?
You should apply the interface segregation principle here, part of the SOLID principles. Instead of having one large interface, split the interfaces up into a few smaller interfaces. Implement the interfaces only in the classes that need it.
I would choose a parent interface. Make the classes that satisfy the interface implement that interface. Create a second interface that extends the first one and adds the extra methods and then make the remaining classes implement that interface. You would still be coding to an interface rather than an implementation and all your design principles are satisfied.
Ask yourself this, will the object that consume the interface necessarily expect this function to be there? Is it important that no matter which instance of the interface you pass, you'll still have that method available?
If the answer to that question is yes, 1. If no, 2.
Say I have an interface Interface and a concrete class ConcreteClass that implements Interface. Now consider a third class MyClass. If instances of MyClass hold a reference to ConcreteClass:
Interface ref = new ConcreteClass();
then should I associate MyClass with Interface or ConcreteClass in UML class diagram?
Thanks
That depends on what the public interface of MyClass defines.
If the public interface makes an Interface available, then you should link to that on the diagram. This would be the usual approach as the Interface is the general type and specifies the contract. Unless you have a reason to limit to ConcreteClass, don't.
If the public interface makes a ConcreteClass available, then you should link to that on the diagram.
The fact that at runtime a variable of type Interface actually holds an instance of ConcreteClass is beside the point. The diagram represents the relationships.
Solely with the Interface. The point is that you want the behavior of the interface. Whatever the implementation is of that interface is for the picture of no importance. MyClass has a relation with the interface, not with the implementation of the interface.
This principle is called Design By Interface. In the answer given by nakosspy is it his first picture. But it would even be better to leave the implementation of ConcreteClass out of the picture. The implementation is of no importance at that conceptual level. If there is a variable pointing to an interface, then is it obvious to the educated reader that there should be a concrete implementation as well.
If you would make a reference to the ConcreteClass then would you have to change the diagram everytime you change the implementation of the interface. That is not what you want. It is bad coding practice and bad uml practice.
It is good coding practice to separate the declaration of the relationship between MyClass and the Interface and the practical implementation of the Interface. By example:
Interface ref = new ConcreteClass();
should never happen in the class MyClass.
You should have something like this instead:
class MyClass
Interface ref;
setRef(){
ref = InterfaceImplementation();
}
}
This way can you change the implementation of Interface without changing one line of code in MyClass. Altough this might look much ado when you write one class, think of it when you are managing hundreds of classes.
So: it depends.
It's equally legal to associate MyClass with ConcreteClass or Interface. You won't find the answer to your question in the UML spec. Why? Because the answer lies in your problem domain, not the modelling language.
Consider two contrived examples to illustrate the point.
Example 1: Association between Classes
Substitute:
ICanBark for Interface
Dog for ConcreteClass
Trainer for MyClass
Let's assume the association we want to capture is Trains, i.e.
Each Trainer trains many Dogs
Each Dog is trained by at most one Trainer
In this case the association exists because of the 'Dogginess', not the 'Barkiness'. So it properly exists between the two classes.
Example 2: Association between Class and Interface
Substitute:
ILogger for Interface
FileLogger for ConcreteClass
Application for MyClass
In this case the relationship is about the 'Logginess', not the 'Fileness'. Application shouldn't care how the interface is implemented; it just wants a way to log messages. So the Association exists between the Class and the Interface
Summary
As is nearly always the case with Associations, the key to solving the problem lies in the problem domain itself - not the modelling language.
hth.
There are 2 ways to present the ref variable of MyClass: You can present it as attribute or as association. Then there are two alternative notations for the Interface interface: Square with the interface stereotype or circle. This makes 2*2=4 alternatives.
Show ref as association and use square interface notation.
Here you can't show the initial value that ref takes. That's because you can't show default values in associations.
Show ref as association but use the circle notation for the Interface.
As it was with the previous alternative, again here you can't show the initial value.
Show ref as attribute and use square interface notation.
Here you can show the default value, because you can do that for attributes. The relationship between MyClass and Interface is presented as a dependency. The same happens for the dependency between MyClass and ConcreteClass.
Note that this dependency (MyClass depends on ConcreteClass) can be presented also in the alternatives 1 and 2, you can add a dependency arrow (dashed) pointing from MyClass to ConcreteClass.
Show ref as attribute and use circle interface notation.
Again here you can show the default value.
If we count also the alternatives derived from presenting or not the dependencies, then there are at least 6 ways to present the same thing. Now the question is which to chose.
It depends on what do you want to visualize with the diagram and for whom the diagram is intended. In this case if the initialization of ref is the message, then you should use an alternative that presents it. If it's less important, then you might prefer a diagram that shows ref as association.
In a real problem you have more elements, so it makes much more alternatives. It's always up to you to decide what to present and how.
EDIT: Some references to help you understand the notation of interface implementation.
According to wikipedia:
A realization is a relationship between classes, interfaces,
components, and packages that connects a client element with a
supplier element. A realization relationship between classes and
interfaces and between components and interfaces shows that the class
realizes the operations offered by the interface.
You can find some quick reference examples and a lot of information at uml-diagrams.org.
This excellent answer Explanation of the UML arrows will help you with more examples.
Here you can also find some more info on realization.
You can define reference to concrete class as:
Attribute typed as Interface (or ConcreteClass) defined in MyClass, or
Association between MyClass and Interface (or ConcreteClass).
no more options are avialable
Suppose I have such requirement:
The objects in the system all derive from a base class named IObject, and it may have objects with color, objects with transformations, and both.
Now there are 2 approach to design the class hierarchy.
The first one is:
just let concrete class derived from
IObject, and also select "capability"
interfaces as its base class to
indicate it support such behavior,
like interface: IHasColor,
IHasTransformation
The second one is:
Organize the base classes, and let
concrete classes derived from one of
them: IObject, IColorObject,
ITransfromationObject ,
IColorAndTransformationObject
I prefer the first one (Does it have a formal name? ) as it is more flexible, and as you can see the second one may have class combination explosion problem when there are many attributes like color, transformation...
I would like to know your ideas and suggestions.
Thanks.
Classes abstract the real concept of types of objects.
Interfaces abstract the real concept of behaviors or abilities for an object.
So the questions becomes, is the "color" a property of the object or is it a capability of the object?
When you design a hierarchy you are constraining the world into a narrower space. If you take the color as a property of the object then you will have two kind of objects, the ones that have colors and the ones that do not. Does that fit your "world"?
If you model it as a capability (Interface) then you'll have objects that are able to provide, lets say cast, colors to the world.
For the transformation the same logic applies. You can either split the world into two kind of objects, the ones who can transform and the ones who can not, or you can view it as a capability, an object may have the ability to transform itself into another thing.
For me, from that point of view, what would make sense would be:
Color is a property of the object. In fact every object should have a color, even if its transparent, even if is reflection, even if its "none" (good luck figuring out what an object with color = none means in the real world, still it might make sense in your program logic).
Transformation is a capability, that is, an interface, something the object is capable of doing, among other things the object may or may not be able of doing.
I'm working on classes hierarchy in my project and basically I have similar situation like you described in your question.
Let's say I have base type Object which is absolute root of all other classes in my toolkit. So naturally everything derives from it directly or through it's subclasses. There is a common functionality that every Object-derived class has to provide but in some leaf classes effects are little different than in others. For example every object have size and position which can be changed with properties or methods like Position = new Point(10, 10), Width = 15, etc. But there are classes that should ignore setting of a property or modify it according to self inner state. Think about control docked to left side of parent window. You can set Height property all you like but it will be generally ignored because this property really depend on Height of parent container control (or it's ClientArea height or sth like that).
So having Object abstract class implementing basic common functionality is ok until you reach a point of where you need "customize" behavior. If Object provides protected virtual SetHeight method that is called in setter of Height property you can override it in you DockedControl class and allow change of height only if docking is None, in other cases you limit it or ignore completely.
So we are happy but now we have requirement for object that react on mouse events like Click or Hover. So we derive MouseAwareObject from abstract Object class and implement events and stuff.
And now client want dockable, mouse aware objects. So we derive from DockableObject and... hmm, what now? If we can do multiple inheritance we can do it but we hit diamond problem with ambiguity of duplicated interface and we need to deal with it. We can have two memeber of Dockable and MouseAware types in new class and proxy external calls to them to provide functionality.
And last thing that comes to mind is to make IDockable and IMouseAware interfaces and let them define functionality and add them freely only to objects that need to deliver concrete behaviors/implementations.
I think I will split my base class into parts and leave my Object with very limited "core" set of properties and methods and rest of functionality that is in fact optional to Objects as a type but needed in concrete cases move to interfaces like IResizable, IDockable, IMakeAWorldABetterPlaceAble, etc. With this solution it is possible to "attach" behaviors to Object-derived classes without need for draggin virtual or pure virtual (abstract) methods from root base class all the way down to leaf class.
There is of course inconvenience of implementing interfaces in all affected classes but you can always implement some "adapters" and just forward calls to them. That way you don't have duplicated implementation (to some extend of course) and have decoupling between realization of task (Resize can mean different things for different classes) and expectation of client code.
Probably this is not ideal answer for your question but maybe it will hint you to your own solution.
I think you jump directly into interfaces, skipping classes. Is it required for you app. to have a "IObject" interface ? Maybe a "CObject" root class for your class hierarchy, may help you.
It think the winner is No. 1 solution, you may have a "MyObject", whether is an implementation of an interface, or direct class. Later you can add additional classes or interfaces in your class hierarchy, as you need.
After seeing several applications (some mine, some others), I think there should be a "My Custom Application Class Hierarchy Root Object" or "My Custom Application Class Hierarchy Root Interface" Design Pattern.
I have a few questions for you wise people involving OO design with Interfaces and abstract base classes. Consider the following scenario:
I have an abstract bass class "DataObjectBase" and a derived class "UserDataObject." I also have an interface "IDataObject." The interface of course exposes all of the public methods and properties that my Data Objects must expose, and you can probably guess that the abstract base implements the methods and properties common to all Data Objects.
My question is, if the abstract bass class DataObjectBase implements everything specified in the interface IDataObject, should the interface be declared on the base class, or on the derived classes(s)?
In C# interfaces declared on the base class are implicity applied to the derived classes, but is this the best practice? It seems to me that implementing the interface on the base class makes it less obvious that the derived class implements the interface, but then again requires the Interface to be specified for each derived class.
Additionally, if the base class was NOT abstract, would the reccomendation change?
A second sub-question: If the base class implements all of the methods/properties of the IDataObject interface, is the interface even needed? The base class typename can simply be used in place of the interface name, ie:
private DataObjectBase _dataObject;
private IDataObject _dataObject;
In the above example (where again the base implements everything exposed by the interface) both can be assigned the same derived types. Personally I always use the interface in these situations, but I am intrested in hearing peoples thoughts.
Thanks in advance.
My way of thinking about such problems is to consider the different people reading the code, the "roles" if you like. Also consider the overall maintainability of the system.
First there is some code expecting to use the Interface. It's written in terms of the interface, the author has (should have) no interest in the implementation. That's why we provide the Interface class. From that perspective the Abstract Base Class is just one of many possible implementation hierarchies. Don't tell this role about implementation details. Keep the Interface.
Then we have the role who is designing an implementation. They come up with one possible approach and discover some variations, so they want to pull common code together. Abstract Base Class - fill in the common stuff here, let detailed implementers fill in the gaps. Help them by providing abstract methods saying "your code goes here". Note that these methods need not only be the ones in the Interface. Also note that this Abstract Base Class might even implement more that one Interface! (eg. It's CleverThingWorker but also a IntermediateWorkPersister.)
Then we have the role who actually do the fine detailed implementation. Fill in the gaps here. Dead easy to understand. In this case you don't even need to consider the Interface as such. Your job is to make that abstract class concrete.
Bottom line ... I use both Interfaces and Base classes. You put the Interface on the Base Class. We don't add value by adding it to the implementation class.
If your user classes will always inherit from one base class, then you don't need the interface. If there is a possibility that you will have classes that match the interface but are not derived from the base class, then use the interface.
As for the interface being hidden in the base class and hence not immediately visible in the user class, this is normal and can be dealt withg by the compiler. This is also where good naming conventions come in - your UserDataObject has a name that matches IDataObject, as does DataObjectBase. You could add a comment to the class file that says it inherits from IDataObject, but it will be visible that it inherits from DataObjectBase, which in turn looks like it inherits from IDataObject by its name.
The other thing that needs to be mentioned is that the use of interfaces makes it easier to implement automated tests.
Say, for example, that one of the methods of the interface is supposed to throw a exception - such as 'DatabaseConnectionLostException' - and you want to test client code to check that it behaves correctly in such a situation.
It is a simple matter to provide an implementation of the interface that throws the exception, allowing the test to be written.
If you used the abstract base class instead of the interface, this operation would be quite a bit trickier (OK, you can use Mocks, but the interface solution is much cleaner)