James Ashford Design Study

From CSSEMediaWiki
(Difference between revisions)
Jump to: navigation, search
(What I don't like so far...)
(What I don't like so far...)
Line 166: Line 166:
 
== Second Attempt ==
 
== Second Attempt ==
 
=== What I don't like so far... ===
 
=== What I don't like so far... ===
* DataBreakpointStore is called by the BreakpointChangeEvent class. Perhaps it should subscribe to the event rather than being directly called
+
* DataBreakpointStore is called by the BreakpointChangeEvent class. It should subscribe to the event rather than being directly called
 +
** Thinking about this further, it is even required? We are essentially keeping a copy of all the breakpoints when we could just query the underlying Eclipse model.
 
* Still too many singletons. Is this necessary?
 
* Still too many singletons. Is this necessary?
 
** Perhaps this could be done with a God Class? Or would this be bad?
 
** Perhaps this could be done with a God Class? Or would this be bad?
 
* I'm not sure I like my 'custom' Observer pattern.  
 
* I'm not sure I like my 'custom' Observer pattern.  
 
* Cleaning up my PsuedoBreakpointRulerActionDelegate / PseudoBreakpointRulerAction - (heaps of unused stub methods)
 
* Cleaning up my PsuedoBreakpointRulerActionDelegate / PseudoBreakpointRulerAction - (heaps of unused stub methods)
* We have a copy of all the breakpoints themselves... However, do we really need this? Should we query the Eclipse model instead?
 
 
* Activator class is used to  attach the BreakpointEventDataStore instance to BreakpointDataEvent event system.
 
* Activator class is used to  attach the BreakpointEventDataStore instance to BreakpointDataEvent event system.
  

Revision as of 05:12, 3 September 2010

Contents

My Project

As part of my honours project, I am developing a plug-in to Eclipse to help illustrate how the state of software changes during runtime. My design study will focus of the data collection subsystem of my project.

Data collection works by inserting a data collection point into a line of code in your document. Every time the application hits this data collection point, a copy of all variables in scope (local, instance and static variables) are recorded and the program resumes. At the conclusion of runtime, the user can review what happened and generate visualisations.

There are two main areas in the data collection subsystem namely:

1. Management (inserting / deleting of data collection points etc)

2. Event Handler (whenever the data collection point is encountered)

Management

The management area of this project is related to the creation, deletion, insertion and management of the data collection points. These data collection points are known as Pseudo Breakpoints within the project. A data collection point is a thinly disguised breakpoint which is handled along side normal Java breakpoints.

Main activities:

  • Creates Pseudo Breakpoints
  • Manages the Pseudo Breakpoint
  • Adds the extension to the Eclipse editor (so the user can toggle the Pseudo Breakpoints on/off

Event Handler

The event handler controls all the data collection events within the system.

Main activities:

  • Handles events when the Pseudo Breakpoint is 'hit'
  • Variable datastore (when the breakpoint is hit a copy of all inscope variables are stored in a datastore)


Event Handler Process Flow:

1. Event Handler is notified that a breakpoint has been hit

2. Event Handler checks to see if it was a PseudoBreakpoint

3. If so, do data collection

4. Event Handler checks to see if there was another breakpoint also hit (a normal breakpoint)

5. If so, suspend application (so normal breakpoint activity can occur)

6. Else resume program

Design Study

Requirements

  1. Maintainability - Easily add new features (such as different data sources etc)
  2. Extensible - Add additional programming languages (such as PHP etc) easily

Constraints

As this is an Eclipse plug-in, our design must fit the Eclipse model.

Initial Design

One Word: horrible.

UML Diagram

Jra82 firstdesign uml.png


Description of Classes

debugassist:

  • Activator (extends AbtractUIPlugin) - Activator class which is run when the Plugin is loaded
  • DebugAssistLogic (implements DataUpdateBreakpointClient, DataUpdateEventClient) - Provides some basic functions to clean up breakpoint data, contains 2 clients which are activated when a breakpoint is inserted/updated/remove and when a breakpoint is 'hit'

debugassist.datasource:

  • DataBreakpointStore - Stores all the pseudo breakpoints in a HashSet.
  • DataEventStoreTime - Store all the data when a breakpoint is hit.

debugassit.events:

  • DataUpdateBreakpointClient - An interface which needs to be implemented if you wish to listen to Breakpoint Events (i.e. when a breakpoint is added/removed etc)
  • DataUpdateBreakpointListener - The service which handles Breakpoint listener clients (where clients subscribe to events etc)
  • DataUpdateEventClient - An interface which needs to be implemented if you wish to listen to Breakpoint Data Events (i.e. when a breakpoint is encountered by the debugger).
  • DataUpdateEventListener - The service which handles Breakpoint data listener clients (where clients subscribe to events)

debugassist.handlers:

  • BreakpointAddRemoveEventHandler (implements IBreakpointListener) - handles the breakpoint events from Eclipse (i.e. when a breakpoint is added / removed from Eclipse) - and notifies DataUpdateBreakpointListener.
  • DebugEventHandler (implements IDebugEventSetListener) - Handles the breakpoint hit events from Eclipse (i.e. when a breakpoint is hit within Eclipse) - this performs data collection (collects all variables in scope), and notifies DataUpdateEventListener.
  • EclipseDebuggerEventListenerManager - Attaches BreakpointAddRemoveEventHandler and DebugEventHandler to Eclipse.

debugassist.model:

  • BreakpointEvent - A model for whenever a breakpoint is hit by the debugger (stores time, variables)
  • ModelGenerator - A utility class for converting IVariable (Eclipse type) to Variable (our model type)
  • Variable - A model for a Variable

debugassist.pseudobreakpoint

  • AddRemovePseudoBreakPointHandler (extends AbstractRulerActionDelegate) - Pseudobreakpoint handler type - so users can right click in Eclipse to add/remove a breakpoint.
  • PseudoBreakpointImpl (extends JavaLineBreakpoint) - The breakpoint used to represent our Pseudobreakpoint. It is actually just a JavaBreakpoint with a different type and icon so the DebugEventHandler knows which breakpoints to collect.

Inherited Classes

A few classes are extended and implemented in this project

AbstractUIPlugin - An abstract class providing some basic functionality required to create an plugin in Eclipse. AbstractUIPlugin Javadoc

IBreakpointListener - An interface used by classes that require notification when breakpoints are added and removed IBreakpointListener Javadoc

IDebugEventSetListener - An interface used by classes that require notification when Debugger Events occur IDebugEventSetListener Javadoc

AbstractRulerActionDelegate - An abstract class to allow contributions to the vertical ruler's context menu in the text editor. AbstractRulerActionDelegate Javadoc

JavaLineBreakpoint - A class which provides the Java Line Breakpoint Implementation (required to insert a breakpoint into the JVM)


Design Critique

Initial Design

Quick notes:

  • The current package design is inconsistant with poor names.
  • DebugAssistLogic doesn't seem to do much, needs a reorg - most functions could be placed in Activator
  • DebugEventHandler handles the Breakpoint data events. This is a clear violation of [Separation of concerns] - which it really should be a DataUpdateEventListener
  • DataUpdateEventListener & DataUpdateBreakpointListener SHOULD be the ones themselves which handle the Eclipse events (the debugassist.handlers are unnecessary)
  • The names of the classes need to be changed
  • ModelGenerator should be fixed (I'm not sure I actually need it???)
  • The Pseudobreakpoint classes should be fixed up - It's directly extending the Javabreakpoint class!!!!
  • Many classes are singleton - perhaps this should be reorganised?
  • It currently is hard-coded to support JavaBreakpoint only - make it more extensible!

There was no initial design - it all evolved out of prototyping - which is why the DebugEventHandler handles the breakpoint events.

Maxims Violated

Avoid inheritance for implementation My PseudoBreakpoint class directly inherits the Javabreakpoint class so that it can interact with the JVM. This effectively stops any other programming language from using our plugin.

[Separation of concerns] DebugEventHandler handles the Breakpoint data events as well as being an Event Listener.

Beware singletons There is a number of singleton classes in here including: ... .. .... Perhaps this could be refactored into a single class?

Single responsibility principle PsuedoBreakpoint class doing too much.

Program to the interface not the implementation Everything uses the direct class (no interfaces used) - Again, this limits our project to Java.

Software reuse DataUpdateBreakpointListener and DataUpdateEventListener both have the same code to handle the adding and removal of listener classes.

Model the real world Not really.

First Attempt Design Improvements

Jra82 secondversion.jpg

Things seem more organised now:

  • Class names have become clearer (PsuedoBreakpointRulerActionDelegate & PseudoBreakpointRulerAction should be clearer than AddRemovePsuedoBreakpointHandler & PseudoBreakpointImpl)
  • PseudoBreakpoint Factory
  • Events Improved
  • Model Generator & Handlers removed

PseudoBreakpoint Factory

Previously the PseudoBreakpoint class was a extension of the JavaBreakpoint class. In order to support other programming languages (in the future) I created a Factory Method to return the appropriate Breakpoint class to insert into the virtual machine.

  • PseudoBreakpoint (extends IBreakpoint) - A placeholder type for our PseudoBreakpoint
  • PseudoBreakpointCreator - Determines which sort of Breakpoint to create and returns the generic PseudoBreakpoint
  • PseudoBreakpointPython / PseudoBreakpointJava (implements PseudoBreakpoint) - an extension of the Java/Python breakpoint class.

Events (BreakpointDataEvent / BreakpointChangeEvent)

Observer - My original design was kind-of an Observer pattern (but poorly implemented - both classes had the same code for adding/removing observers (Don't repeat yourself)). As Java's Observer pattern does not suport generics, I decided to create my own. A generic abstract class 'Subject' handles subscribers.

  • Subject - Abstract class to handle observers attaching/detaching to the event handler
  • DataUpdateEventObserver (was DataUpdateEventClient) - Essentially the same, but now with a proper name
  • DataUpdateBreakpointObserver (was DataUpdateBreakpointClient) - Essentially the same, but now with a proper name
  • BreakpointDataEvent [extends Subject, Implements IDebugEventSetListener (Eclipse)] (was DataUpdateEventListener) - Handles Breakpoint Data Events (i.e. when a breakpoint is 'hit') from the Eclipse Debugger directly and notifies subscribed observers
  • BreakpointChangeEvent [extends Subject, Implements IBreakpointListener (Eclipse)] (was DataUpdateEventListener) - Handles Breakpoint Add/Remove Events from the Eclipse directly and notifies subscribes observers and the DataBreakpointStore (I think I need to modify this)

Variables / BreakpointEvent

I removed the model generator - it is now all handled within the BreakpointEvent class.

Second Attempt

What I don't like so far...

  • DataBreakpointStore is called by the BreakpointChangeEvent class. It should subscribe to the event rather than being directly called
    • Thinking about this further, it is even required? We are essentially keeping a copy of all the breakpoints when we could just query the underlying Eclipse model.
  • Still too many singletons. Is this necessary?
    • Perhaps this could be done with a God Class? Or would this be bad?
  • I'm not sure I like my 'custom' Observer pattern.
  • Cleaning up my PsuedoBreakpointRulerActionDelegate / PseudoBreakpointRulerAction - (heaps of unused stub methods)
  • Activator class is used to attach the BreakpointEventDataStore instance to BreakpointDataEvent event system.

Files

Media:debugassist-swe_init.zip - The initial design.

Installation

  1. Download & Install Eclipse 3.5.2 (with SDK)
  2. Extract the zip file of my project
  3. Run Eclipse
  4. Click File -> Import -> Existing Projects into Workspace
  5. Select root directory of extracted plugin
  6. Click Finish
  7. Create a new Run Configuration: 'Eclipse Application'
Personal tools