PaulDesignStudy
(→AbstractActivity and subclasses.) |
(→Final Layout) |
||
(14 intermediate revisions by one user not shown) | |||
Line 19: | Line 19: | ||
==Initial Design== | ==Initial Design== | ||
− | [[image:uml1.png|Original UML]] | + | [[image:uml1.png|center|frame|Original UML]] |
===Classes=== | ===Classes=== | ||
MPML3DGUI.Classes<br> | MPML3DGUI.Classes<br> | ||
Line 72: | Line 72: | ||
*[[Data_class_smell|Data class smell]] / [[Eliminate_irrelevant_classes|Eliminate irrelevant classes]]:A few of the subclasses of AbstractActivity do not require any additional functionality. | *[[Data_class_smell|Data class smell]] / [[Eliminate_irrelevant_classes|Eliminate irrelevant classes]]:A few of the subclasses of AbstractActivity do not require any additional functionality. | ||
+ | |||
+ | *[[Avoid downcasting]] / [[Beware type switches]]: I sometimes need to check what activity I have and cast them to a type. This is ugly. | ||
==Aims for my first design== | ==Aims for my first design== | ||
Line 80: | Line 82: | ||
==AbstractActivity and subclasses.== | ==AbstractActivity and subclasses.== | ||
− | [[image:firstactivityuml.jpg]]<br><br> | + | [[image:firstactivityuml.jpg|center|frame]]<br><br> |
The parallel and selected activity classes have no additional functionality to the super class. The ActionActivity cannot contain any other activities so the add remove activity method from the super are no ops. My first guess is to use a Composite design pattern but I feel as though I need to move some of the classes around. On closer inspection the PerceptionActivity should not be here as I misread the information on what a perception is so I will move this class to a new hierarchy with two other classes.<br> | The parallel and selected activity classes have no additional functionality to the super class. The ActionActivity cannot contain any other activities so the add remove activity method from the super are no ops. My first guess is to use a Composite design pattern but I feel as though I need to move some of the classes around. On closer inspection the PerceptionActivity should not be here as I misread the information on what a perception is so I will move this class to a new hierarchy with two other classes.<br> | ||
− | [[image: | + | [[image:elementumql.jpg]]<br><br> |
By following a similar pattern for the AbstarctActivity hierarchy I run into the problem of what to do with TaskActivity as it can add Activites to its list but cannot be part of any other activities list.<br> | By following a similar pattern for the AbstarctActivity hierarchy I run into the problem of what to do with TaskActivity as it can add Activites to its list but cannot be part of any other activities list.<br> | ||
− | <br>[[image:nextactivityuml.jpg]]<br><br> | + | <br>[[image:nextactivityuml.jpg|center|frame]]<br><br> |
At Paul's request... I came up with an adjustment to the design. --[[User:Matthew Harward|Matthew Harward]] 01:48, 6 August 2009 (UTC) | At Paul's request... I came up with an adjustment to the design. --[[User:Matthew Harward|Matthew Harward]] 01:48, 6 August 2009 (UTC) | ||
Line 93: | Line 95: | ||
<br><br><br><br><br><br><br><br><br><br><br>Thanks to Michal, Mathew and class for there input here is the final design that I choose I thought I was close to a solution with my AbstractElement solution but by adding the interface wrapable it helped to fix the problem with task activity with it being able to hold other activities but could not actually be wrapped.<br><br> | <br><br><br><br><br><br><br><br><br><br><br>Thanks to Michal, Mathew and class for there input here is the final design that I choose I thought I was close to a solution with my AbstractElement solution but by adding the interface wrapable it helped to fix the problem with task activity with it being able to hold other activities but could not actually be wrapped.<br><br> | ||
− | [[image: | + | [[image:AbstractElement2.jpg]] |
==Model-View-Controller== | ==Model-View-Controller== | ||
The model consists of the MPML3DHeader and MPML3DBody. The view consists of a all encompassing starting GUI that can has a HeaderGui and a BodyGui. For now I will not concentrate on where the heck the MPML3DWriter should be as I am as of yet undecided. | The model consists of the MPML3DHeader and MPML3DBody. The view consists of a all encompassing starting GUI that can has a HeaderGui and a BodyGui. For now I will not concentrate on where the heck the MPML3DWriter should be as I am as of yet undecided. | ||
− | Will a clear cut between model and viewer i now need to create a controller and decide how to design it. | + | Will a clear cut between model and viewer i now need to create a controller and decide how to design it. Using it more as a mediator pattern I have decided to break it up in two separate controllers as they control two separate things the header and the body of the script. |
+ | |||
+ | [[image:MVC1.png|center|frame]]<br><br> | ||
+ | |||
+ | ==Followed design principles== | ||
+ | *[[Avoid downcasting]] : This was accomplished using the way Wal does it | ||
+ | |||
+ | *[[Single responsibility principle]] / [[One responsibility rule]] : This is the main reasoning for having a MPML3D header, body and writer. Each one of these classes takes care of the 3 distinct areas of a MPML3D script. | ||
+ | |||
+ | *[[Keep related data and behavior in one place]]: Also for the above reasonings. | ||
+ | |||
+ | *[[Avoid no-op overrides]] : By using a variation of the composite design pattern and using a wrapable interface the problem of no ops has been addressed. | ||
+ | |||
+ | *[[MVC]] : Adding the MVC pattern allows the backend and gui to be totally uncoupled making it easier to create a new front end gui. | ||
+ | |||
+ | *[[Open closed principle]] : By using inheritance for the activitys and elements it is easy to add new members to these hierarchys. | ||
+ | |||
+ | ==Design patterns used== | ||
+ | |||
+ | * [[Composite]] : This pattern was used twice with a slight alteration in than all leaf values are placed outside the composite part. It was used for activities and elements | ||
+ | |||
+ | * [[MVC]] : This pattern was used to totally decouple front and back ends | ||
+ | |||
+ | ==Design conflicts== | ||
+ | * [[Eliminate irrelevant classes]] - I have created a couple of subclasses selected and parallel that do nothing more than what the super class does. Although this goes against this hieristic I feel for better understanding and separating the activities apart I have decided to keep this classes in the design. | ||
+ | |||
+ | ==Summary== | ||
+ | I feel the new design has a more pleasing or less smelly feel to it. With the use of the MVC the whole system just looks a lot less coupled. As well as the modified composite design patterns adding extensibility as well as freeing from no ops. | ||
+ | |||
+ | |||
+ | ==Final Layout== | ||
+ | |||
+ | [[image:finals.png|center|frame]] | ||
− | [[ | + | [[Media:ScriptWriterMPML3D.zip]] |
Latest revision as of 01:13, 5 October 2009
This layout was copied from Janina's design.
For my research project for Cosc366 I developed a simple GUI that would allow a user to construct MPML3D scripts that control Non Player Characters (NPCs) in 3D Virtual World.
I was under pressure to complete the project so I basically threw design out the window and started hacking away. By chance I did implement some parts that were not too smelly but would be unable to tell what pattern they followed.
I will first decide on the requirements for my program and what I would like the program to do. I will give a brief explanation of MPML3D. Then, present and critique my current version to help me to highlight areas I feel require refactoring.
Contents |
Requirements
- The GUI needs to be intuitive and easy to use.
- The GUI must produce valid lines of MPML3D script.
- The GUI must incorporate all the options under MPML3D.
Constraints
- I cannot change the MPML3D language syntax and semantics or change its code.
MPML3D
MPML3D is a XML-based scripting language to describe the behaviour of computer controlled agents. Although it is not bound to a single platform by design, the current version only supports avatars inhabiting Second Life (SecondLife).It can be extended to OpenSimulator as well (OpenSim). With MPML3D, it is easy to construct agents that can give appealing presentation, including speech, gestures and movement. For a more in-depth explanation of the language goto Manual.
Initial Design
Classes
MPML3DGUI.Classes
NPCCreator –
Class that has the main runs the whole application. Basically creates an instance of MainGui and displays it.
Entity –
An Entity is a representation of a Second Life avatar. It has all the information required to log on to Second Life.
MPML3D.Classes.gui
MainGui –
This creates the parent GUI that the other types of GUI get created and displayed within. This class runs the whole show and creates the HeaderGui and BodyGui objects. When the script is ready to be written this class creates an MPML3DWriter and passes it the HeaderGui and BodyGui to be written to a script.
HeaderGui –
This GUI is used by the user to create the header of the script. It holds a list of Entities which are used to write to the script and a list of strings that have are used to write out the External perceptions created. This class also creates an instance of MPML3DHeader.
BodyGui –
The user uses this GUI to create the body of the script. This class creates an instance of an MPML3DBody.
MPML3D.Classes.Writer
MPML3DHeader –
This class has all the data required to write the header of a valid MPML3D script. It has a list of entities and a list of external perceptions.
MPML3DBody –
This class has all the data required to write the body of a valid MPML3D script. It has a list of activities that can also have a list of activities nested with in it.
MPML3DWriter –
This class gets the MPML3DHeader and MPML3DBody classes from the MainGui and writes all the data from the header and body to a file.
MPML3D.Classes.activities
These classes inherit from the AbstractActivity class. Each activity contains the data to create the required lines of valid MPML3D code. Each activity performs a unique action on the avatar.
AbstractActivity
ActionActivity
ParallelActivity
PerceptionActivity
SequentialActivity
SelectedActivity
TaskActivity
For more information of what each activity does please refer to the manual Manual.
Walkthrough
When first running the program the MainGui interface is presented. From here the user can create a new script or edit an existing script. Once an option is selected a HeaderGui window is opened and the user can create entities and external perceptions that they require. Once finished the user clicks the “Create body” button. This calls a method within the MainGui that opens a BodyGui. The user can then enter the activities that control the entities here. When finished the user clicks “Write script” where a file browser opens and the user can navigate to the required folder, as well as naming the script.
Design Critique
I feel there are a lot of things that can be improved with in this design.
Specific design maxims that are violated by the initial design:
- No-op overrides/Design by contract/Liskov Principle: Some of the subclasses of AbstractActivity donot require some of the super classes methods and have been overwritten with a stub that says this method not required.
- Coupling: The Gui and backend are strongly coupled making it hard to create a new Gui for the system.
- Data class smell / Eliminate irrelevant classes:A few of the subclasses of AbstractActivity do not require any additional functionality.
- Avoid downcasting / Beware type switches: I sometimes need to check what activity I have and cast them to a type. This is ugly.
Aims for my first design
- Create a MVC pattern
- Use a composite design pattern for AbstractActivity and subclasses
- or try and remove the no-op methods
AbstractActivity and subclasses.
The parallel and selected activity classes have no additional functionality to the super class. The ActionActivity cannot contain any other activities so the add remove activity method from the super are no ops. My first guess is to use a Composite design pattern but I feel as though I need to move some of the classes around. On closer inspection the PerceptionActivity should not be here as I misread the information on what a perception is so I will move this class to a new hierarchy with two other classes.
By following a similar pattern for the AbstarctActivity hierarchy I run into the problem of what to do with TaskActivity as it can add Activites to its list but cannot be part of any other activities list.
At Paul's request... I came up with an adjustment to the design. --Matthew Harward 01:48, 6 August 2009 (UTC)
Thanks to Michal, Mathew and class for there input here is the final design that I choose I thought I was close to a solution with my AbstractElement solution but by adding the interface wrapable it helped to fix the problem with task activity with it being able to hold other activities but could not actually be wrapped.
Model-View-Controller
The model consists of the MPML3DHeader and MPML3DBody. The view consists of a all encompassing starting GUI that can has a HeaderGui and a BodyGui. For now I will not concentrate on where the heck the MPML3DWriter should be as I am as of yet undecided.
Will a clear cut between model and viewer i now need to create a controller and decide how to design it. Using it more as a mediator pattern I have decided to break it up in two separate controllers as they control two separate things the header and the body of the script.
Followed design principles
- Avoid downcasting : This was accomplished using the way Wal does it
- Single responsibility principle / One responsibility rule : This is the main reasoning for having a MPML3D header, body and writer. Each one of these classes takes care of the 3 distinct areas of a MPML3D script.
- Keep related data and behavior in one place: Also for the above reasonings.
- Avoid no-op overrides : By using a variation of the composite design pattern and using a wrapable interface the problem of no ops has been addressed.
- MVC : Adding the MVC pattern allows the backend and gui to be totally uncoupled making it easier to create a new front end gui.
- Open closed principle : By using inheritance for the activitys and elements it is easy to add new members to these hierarchys.
Design patterns used
- Composite : This pattern was used twice with a slight alteration in than all leaf values are placed outside the composite part. It was used for activities and elements
- MVC : This pattern was used to totally decouple front and back ends
Design conflicts
- Eliminate irrelevant classes - I have created a couple of subclasses selected and parallel that do nothing more than what the super class does. Although this goes against this hieristic I feel for better understanding and separating the activities apart I have decided to keep this classes in the design.
Summary
I feel the new design has a more pleasing or less smelly feel to it. With the use of the MVC the whole system just looks a lot less coupled. As well as the modified composite design patterns adding extensibility as well as freeing from no ops.