Community
Participate
Working Groups
Old system: We deal only with IMarkers. We can't define our own IMarkers (either by implementing the interface or subclassing the implementation), so we just use them directly. We're implementing the "concept" of breakpoints into the system without a breakpoint class. This is done by adding attributes to IMarkers and doing processing based on the value of these attributes. New system: We add the IBreakpoint interface to the system and go about implementing breakpoints in one of two ways: 1) We subclass the IMarker implementation (Marker) with the contract that all things related to persistence will remain the sole domain of the Marker superclass. This way, the Breakpoint class "is a" Marker. 2) We aggregate an IMarker. This leaves the existing contract in place, but adds an extra level of indirection in that the Breakpoint implementation will constantly be passing messages to its IMarker instance instead of just calling them on itself. This way, the Breakpoint class "has a" Marker. Thanks to the nature of objects, either of these implementation choices will work without affecting the objects that deal with IBreakpoints. The following analysis holds regardless of what implementation we choose. Good things about the current system: 1. It got the job done in a development cycle that was hampered by uncontrollable external forces. Problems with the current system : 1. Inappropriate Intimacy - Processing and data storage related to breakpoints are spread out across the system. 2. Procedural Code Masquerading as Objects - The DebugJavaUtils "object" is the biggest offender here. It is the closest thing to centralization of breakpoint- marker processing, but it is nothing but a large clump of procedures. It is a frequently used "object" in the system but it satisfies none of the goals of OO and breaks most of the rules. 3. Feature Envy - Again, DebugJavaUtils is the biggest offender here. All of its procedures operate on someone else's data (IMarker). 4. Duplicate Code - Code for accomplishing the same thing for different types of breakpoints is frequently repeated. In some cases, code that is identical, or nearly so, is defined for each marker type. 5. Switch Statements - The code is filled with method dispatch based on the IMarker type. Methods must frequently dispatch to specialized (and uniquely named) methods for doing the same thing for each different type of marker. Example 1. A method called addBreakpoint(IMarker marker) defined in the JDIDebugTarget manually checks the type of the marker and then dispatches to addMethodEntryBreakpoint(marker), addExceptionBreakpoint(marker), addLineBreakpoint(marker), etc. 6. Adding a new kind of breakpoint in the current system requires changes (adding dispatches and breakpoint_type specific methods/code) all over the system. Only someone who knows the system inside and out can know all of the places to make these changes. Good things about the new system: 1. Encapsulation - All data and processing related to breakpoints are centralized in the IBreakpoint hierarcy. Removes problems 1, 2, and 3. 2. Inheritance - The new system allows breakpoints to make use of state and behavior defined in superclasses. This means that behavior which is shared by a superclass and its subclasses is defined Once And Only Once. Removes problem 4. 3. Polymorphism - The manual dispatching which litters the code is eliminated through polymorphism. Example 1 is refactored with double dispatch as follows: Example 2 The method addBreakpoint(IBreakpoint breakpoint) calls breakpoint.addToTarget(this). Removes problem 5. 4. Extensibility - Adding a new breakpoint class is easy to do. The implemented interface (IBreakpoint) and/or inherited classes clearly specify exactly what methods need to be written and once they're written the new breakpoint type will just go. Thanks to polymorphism the rest of the system doesn't need to know about new breakpoint types. Removes problem 6. Bad things about the new system: 1. Requires some API parameter changes from IMarkers to IBreakpoints. Some specific examples are IBreakpointManager and IDebugTarget. NOTES: DW (8/13/01 2:30:15 PM) Breakpoint definition: To define a breakpoint, clients will need to define a marker extension, that documents the attributes that their breakpoint marker will have. In addition, a "breakpoint" extension will correspond to the marker definition, defining the "marker type" that the breakpoint corresponds to, as well as the fully qualified name of the class that implements the breakpoint (an implementation of IBreakpoint). Breakpoint creation: Breakpoints are created atomically with a corresponding marker, and added to the breakpoint manager. Breakpoint change notification: The IBreakpointSupport interface will be eliminated. IBreakpointListener will remain, but IDebugTarget will no longer be required to implement it. Any clients interested in breakpoints must listen for changes. Editors will be able to listen to marker changes to update. (Any change in a breakpoint must be reflected in its marker in order for the UI to update properly). The JDIDebugTarget (implementation) will be a breakpoint listener, and will delegate to breakpoints as added/changed/removed.
Breakpoint hierarchy implemented