12 Replies - 9994 Views - Last Post: 26 December 2012 - 09:12 AM

Modelling/Design problem

Posted 18 December 2012 - 11:55 PM

Hi.

So I've decided to create a software for a forum game I really enjoy (it's called "mafia"). It seemed "easy" enough to develop using an object-oriented design so what the hell I decided to try it.
I don't have much experience in this though, I've only done 2 projects in my life basically in this year in uni, but I know a thing or two.

So anyways, I started to model the system, and in the Analysis/Design phase (basically in Analysis, although taking design into account) I encountered a bump.

Basically my problem is this:

There are certain concepts that are all "part" of another concept. Speaking in UML, basically a generalization.
Each of these concepts however, has a specific behaviour. Their behaviour is "similar" in a way, but different in others.
They are also "unique" concepts. I.e in the reality itself they are "abstract" concepts and not particular objects. They are also limited, but theoretically should be dynamically created.

Okay, that's the "general" view of the problem. I dunno if I should post the specific example I'm talking about since it'd need some background information about the project I think, so I'll try to use another example:

Imagine in a videogame there are players with abilities or powers. One ability is the ability to fly, another ability is the ability to shoot fireballs, and another one is the ability to shoot bullets.
There may be an ability that lets you shoot bullets while you fly, or shoot fireballs while you fly, or let you shoot 2 fireballs at the same time, or let you shoot fireballs that do double damage, etc. That aspect of the abilities is variable from ability to ability.
So now.....how do you model it?

Getting a little bit into design, I'd say there are 2 ways to do so:
1)Create an "Ability" class, and create a class that extends it for every ability there is. So there'd be "FlyingAbility extends Ability", "FireballAbility extends Ability", "ShootingAbility extends Ability", etc.
Each of these classes would then implement the specific behaviour of each ability.
2)Create an "Ability" class, but make each ability just an instance of it. Let something else handle the behaviour of these objects, maybe with a composition of other objects that handle the behaviour.

Which one should be used?
(1) seems like the "obvious" one to use, but I'm not that sure. For one, I don't think it's that flexible, specially if it just uses inheritance. For instance creating the "ability that lets you cast 2 fireballs at the same time while flying" doesn't seem that trivial to create. It also doesn't let abilities be created dynamically, for instance let someone create an "ability that lets you shoot a fireball while flying, then as soon as you land shoot 2 bullets" or something if the user wanted to
Also, each ability would not be "unique", it's just be a blueprint for an instance to be created (since it's a class).
There could theoretically be several instances of "FireballAbility", when it doesn't make much sense since abstractly the ability is the same.
I.e if there are 2 objects that are instances of "FireballAbility".....then they are both an ability that shoots fireballs, which abstractly is the same concept so they should be the same objects shouldn't they?
I don't really know how to handle this either if this is used

(2) is the one I'm kind of leaning towards to, but I'm not that sure either. In here every ability would just be an object, so you can have finite abilities and they are all unique and "single". The thing is that I don't know if it's actually good design, or how to actually handle their behaviour, or how it would affect the system, etc.

I'm trying to design this to allow as much flexibility as possible. For instance the creation of those "weird" abilities I've mentioned before.
I've also encountered this problem in several spots of the design.

Replies To: Modelling/Design problem

Re: Modelling/Design problem

Posted 19 December 2012 - 03:17 AM

I think your answer depends on the language. If your language supports multiple inheritance or mixins, the application may be easier to design.

Let's take Java for instance. I'd use a mix of inheritance, interfaces, and composition. Obviously, there's quite a bit of reuse here, so ignoring inheritance would seem wrong. Interfaces are basically the solution to an absence of multiple inheritance, and you'll need composition to bind the two. E.g.

The only issue with that example is that it doesn't allow you to add an ability that the class doesn't already implement (you can change an implementation though). To resolve this it might worth it to review design patterns to see if any are applicable. The decorator (and possibly vistor) pattern(s) look helpful.

Re: Modelling/Design problem

Imagine there's a use case "Create an Ability" and then a use case "Create a Player" where you choose already created abilities.

There is another use case called "Get List of Abilities".

If you want the new abilities created in "Create an Ability", then they need to be single unique objects stored in a container or something so that they can be easily retrieved in "Get List of Abilities" right?

If that's the case you'd need a single object per class, so you'd need a single object for the "ShootingAbility" class, and for the "FireballAbility" and the "DoubleFireballAbility", etc, right?

I take it the decorator pattern would work, doing something like "Ability ability = new ShootingAbility(new FireballAbility(new FlyingAbility))" or something like that.
How would this work in the "Get List of Abilities" use case? Remember I want each different ability to be unique, maybe even have a unique name added to them (like "Super Ability" for the ability created above).

Re: Modelling/Design problem

Posted 19 December 2012 - 05:17 PM

Quote

If you want the new abilities created in "Create an Ability", then they need to be single unique objects stored in a container or something so that they can be easily retrieved in "Get List of Abilities" right?

Yeah, I was going to initially suggest having each player keep a List of abilities, for which you could just add abilities to, but it just seemed a little awkward. How do go you about executing an ability? You really can't code to interfaces anymore if you don't what abilities the object has up front (as in my code example). Do you iterate over the list doing type checks until you find it? Do you send the name (or class) of the ability to the object and let it execute it (if it even has it)? Seems like it could work. Is it the best way? Not sure.

As I said before, it's hard to make suggestions about something you have no knowledge of. Have you thought about prototyping each alternative (list vs decorator)? If you still can't resolve the issue, you could try asking at StackOverflow.

Re: Modelling/Design problem

Posted 19 December 2012 - 09:46 PM

You're confusing classes and objects. Think of it this way. I have a blueprint for a house. I can make any number of houses to this blueprint. You're saying things analogous to "it doesn't make sense to have more than one house, since abstractly the design is the same." Obviously not true when you look at it that way. /> (In my example, blueprint is a class, and houses are instances of the class or objects.) So no, each wizard instance would have a fireballability instance to go along with it, along with other abilities such as moving around.

Other than that, it looks like you understand inheritance pretty well. Investigate also aggregation and composition (in UML a white diamond and a black diamond respectively) and understand the difference. Decide what you will use them for.

Next aspect of that confusion is the idea that you want to create abilities dynamically. Dynamically means during runtime, and that isn't what you want to do. You want to be able to create new combinations of abilities from existing abilities, but in design time. Aggregation and composition.

So, use both. Each concrete ability class implements an abstract ability class, which defines the way that the ability is "consumed". Then you can have compound ability classes which are aggregates of other concrete ability classes, and you have characters which are aggregates of objects including ability objects.

You might also want to investigate the Composite pattern for this, and see if it gives you ideas that you can apply.

Re: Modelling/Design problem

Posted 20 December 2012 - 07:15 AM

Yeah I know, which is why I didn't like the "class" approach because a class (i.e a Wizard) is not a blueprint. There can't be several objects that are Wizards or several objects that are Knights, there is only one Wizard and one Knight class.

However I know that in the design phase some of these "views" can be tampered with to make the system more efficient and the like.
So maybe there would be indeed a Wizard class which extends the "Class" class, and when the system/game starts a single instance of that Wizard class is instantiated and we only operate with that one (or maybe the design allows for several instances of them to be floating around somehow).

Yeah...I never really paid attention to aggregation and composition >_> . I thought they were just a "fancy" way to model special relationships in the analysis phase

Quote

Next aspect of that confusion is the idea that you want to create abilities dynamically. Dynamically means during runtime, and that isn't what you want to do. You want to be able to create new combinations of abilities from existing abilities, but in design time.

Well...yeah I want to do so at runtime with input from the user.

For instance a "createAbility(DataAbility da)" function that takes the info from said datatype and creates an ability according to it

I don't really get what you said about "design time" though. Is that what you meant?

Oh haven't thought about Composite pattern yet. That might do the trick.
I'm not that sure how it would work out, considering I think there is a difference between the "ability" itself and the "list of sub-abilities it's composed of", and I don't know if that could be done using Composite.

For instance, imagine each ability has a special name. Then each ability has a type, which is the "fireball" or "flying" type etc.
By composite, I'd have an Ability "name1" type "Fireball", an ability called "name2" type "Flying".
If I wanted to compose those and create a new ability "name3" composed from "Fireball" and "Flying", then I'd instead have an Ability "name3" composed of the ability "name1 type Fireball" and "name2 type Flying", which would be wrong since I don't want names for the sub-abilities that are part of the "big" ability.

But then, that may not even be what I really want, since I want more flexibility >_>

I guess my problem is maybe specifying exactly what I want
I mostly have vague ideas in my head and later see if those ideas hold true for the designs I come up with, and not just have ALL the ideas on paper or in a specification and see which exact design can make that work with that in mind.

Re: Modelling/Design problem

Based on what you are all saying, I think a list should be used to hold the abilities.

Quote

You might also want to investigate the Composite pattern for this, and see if it gives you ideas that you can apply.

Wouldn't using that pattern restrict a player to executing all his abilities at once? If you build a composed ability and execute it, it'll execute all its constituent parts as well, which may not be what we want.

Re: Modelling/Design problem

Based on what you are all saying, I think a list should be used to hold the abilities.

So each Ability has a list of other Abilities? Sounds good I guess.

I was thinking that maybe there was an "Ability" and a "Primitive Ability".
An Primitive Ability is just "Fireball" or "Flying" or "shooting", etc.
An Ability has a special name, a list of Primitive Abilities, and maybe some other info.
I guess these Primitive Abilities would use inheritance though and there'd be no problems.

This would work right?

Quote

Quote

You might also want to investigate the Composite pattern for this, and see if it gives you ideas that you can apply.

Wouldn't using that pattern restrict a player to executing all his abilities at once? If you build a composed ability and execute it, it'll execute all its constituent parts as well, which may not be what we want.

If that was the case there wouldn't be much problems because if an ability is executed each "sub-ability" is executed as well.
If an ability is "Shoot fire bullets", then it executes both "Shoot bullets" and "Fireball", if not that ability wouldn't make much sense.

Still having trouble with the "Wizard" and thingy concepts >_>

The main problem I have is that I think they are objects...but they are "explicit" in a way. So when designing it you know those "objects" should be part of the system....but is that part of the design phase or is it done in runtime (dynamically creating those specific objects when the system/game starts)? They also have different behaviour.

I think another example would be like this:"In this system there are users. "Anna" is a user, "Robert" is a user, and "Maria" is a user. Anna likes dogs and pets them, Robert likes to swim in pools, and Maria is a doctor and operates on people. New users can be registered in the system"

I think the situation is analogous. Is "User" a single class with "Anna", "Robert" and "Maria" specific instances of it? Or is there an "Anna" subclass, a "Robert" subclass and a "Maria" subclass?
Like I stated at the beginning, each "user" has similar but different behaviors. Anna "pets" dogs, Robert "swims" in pools, and Maria "operates" on people as a doctor.

So should each of those users be a separate subclass with their independent behaviors implemented differently? Or should there be a "generic" way of implementing those behaviors by just using the "User" class and letting each user be an instance and not a subclass?

(Of course if a user is a "subclass" at one point it'll be instantiated. Don't really know how this would work in the system though, which is why this vision confuses me).

Re: Modelling/Design problem

Posted 20 December 2012 - 12:11 PM

Quote

If that was the case there wouldn't be much problems because if an ability is executed each "sub-ability" is executed as well.
If an ability is "Shoot fire bullets", then it executes both "Shoot bullets" and "Fireball", if not that ability wouldn't make much sense.

Ah, I see. Makes sense.

Quote

So each Ability has a list of other Abilities? Sounds good I guess.

I was thinking that maybe there was an "Ability" and a "Primitive Ability".
An Primitive Ability is just "Fireball" or "Flying" or "shooting", etc.
An Ability has a special name, a list of Primitive Abilities, and maybe some other info.
I guess these Primitive Abilities would use inheritance though and there'd be no problems.

That is exactly what the composite pattern prescribes. The "primitive" abilities are known as "leafs".

Quote

I think the situation is analogous. Is "User" a single class with "Anna", "Robert" and "Maria" specific instances of it? Or is there an "Anna" subclass, a "Robert" subclass and a "Maria" subclass?
Like I stated at the beginning, each "user" has similar but different behaviors. Anna "pets" dogs, Robert "swims" in pools, and Maria "operates" on people as a doctor.

They are instances.

Quote

Or should there be a "generic" way of implementing those behaviors by just using the "User" class and letting each user be an instance and not a subclass?

I'd say so.

This whole kick about dynamically adding behaviors is a bit confusing. I agree with Bob that you must define the possible behaviors at design time, but you're free to compose or choose an implementation at runtime. For example, say at some point you introduce the user Maria, the doctor, into the program, where doctor is an Ability class that has some specific behavior tied to it. That ability must be defined at design time.

Re: Modelling/Design problem

Posted 22 December 2012 - 09:39 PM

I think you have worked through to your most fundamental problem, that you don't really know what you want. I don't say this to give offense, but until you do, your attempts to describe implementations of what you want are going to be standard developer turd-polishing. You have to get a bit rigorous about defining what you want to do, or you're going to spend a lot of time implementing things that you don't want to do, i. e. polishing a turd.

Now, that said, classes are definitions of objects, objects are instances of classes. Using your User thing, you're getting at an important question, and there is more than one valid way to do it. Let's first assume that each activity has entirely different code to implement it: petting, swimming, and operating are completely different code bases.

First, you can create more specific user types that inherit from user: doglover, swimmer, surgeon. Doglover has the properties (Name, for example) that user has, as well as petDog. Swimmer has swim, and surgeon has operate. This works well if there are inconsistent differences between the subclasses, but they all have the base class functionality in common. Keep in mind here that each subclass "is a" user. "Is a" is a criterion for inheritance.

If the differences between the subclasses are that they have some sort of functionality whose definition is the same but the implementation is different (such as your user activity), you can define an interface. For example, an Activity class, with a method called, say, DoActivity or Invoke. What you are saying here is that the Activity class has to have this method, but it doesn't matter how it implements it. Then you would create classes that implement the interface, such as PetDogActivity, SwimActivity, OperateActivity. This allows the User to be unaware of how the activity is implemented, and the activity to be unaware of who is using it. Then, you associate various activities with various users. This gives you the flexibility to allow doctors to swim and pet dogs as well as operate, while swimmers could just swim. This is aggregation: each User class "has an" activity. "Has a" is a criterion for aggregation. The way that this is usually implemented is that the User class has a property that is an array (or, as blackcompe says, a list--exact implementation depends on what language you're using) of activity objects.

My feeling is that aggregation is what you are looking for, but I'm not quite sure, given that your requirement definition is still a bit nebulous. You might want to spend a bit more time nailing down your requirements.

Re: Modelling/Design problem

Posted 24 December 2012 - 11:37 AM

Quote

I think you have worked through to your most fundamental problem, that you don't really know what you want. I don't say this to give offense, but until you do, your attempts to describe implementations of what you want are going to be standard developer turd-polishing. You have to get a bit rigorous about defining what you want to do, or you're going to spend a lot of time implementing things that you don't want to do, i. e. polishing a turd.

I should have said this a long time ago, but I didn't in case I was the one who was confused. Gonzaw, it really sounds like you could be over-engineering this project or not clear on what you need, so there's really no use in going further. As I stated before, it's very tough to help someone with their own design. At best we can give you general examples and let you handle the rest.

Quote

My feeling is that aggregation is what you are looking for, but I'm not quite sure, given that your requirement definition is still a bit nebulous.

I think we can settle upon aggregation or composites as being what you need. Try implementing prototypes of both and see what happens. Come back with some code examples!

Re: Modelling/Design problem

Posted 26 December 2012 - 09:12 AM

Well, at least come back with a class design.

I'll explain the difference between aggregation and composition. First, a formal definition: composition is a more rigorous form of aggregation wherein all the classes share the same lifetime: the classes of which a class is composed have no context outside of the composed class.

A good example can explain what the hell that means. Suppose you have a Car class. The class has a Chassis class, a Motor class, four instances of a Wheel class, two Axle classes, and so on. Now, in a car factory, you deal with cars. So each car instance has all of this (is an aggregate of all of these composite instances), and once you sell the car to a dealer, all the composite classes (wheels chassis, etc.) get wiped off the books along with the car instance. Now, consider the same car in a junkyard. The car is still an aggregate of all the same stuff, but now you can pull out the motor, say, and sell it, and keep the car class in inventory minus one motor. In other words, the car parts have a lifetime of their own, independent of the car.

That's the difference between composition (black diamond in UML class diagram) and aggregation (white diamond in UML). You can see from the above example that the context in which the aggregated object exists determines whether it is simple aggregation or composition.

Keep in mind also that there are associations that are neither aggregation nor composition, when two objects simply communicate with one another without having their identity dependent on one another. For example, a person may drive a car, but the car is still a car without the person, and the person is still a person without the car. So a person object and a car object are in simple association with one another, with the person in the role of driver. (I won't get into roles just now any further than that!)