summaryrefslogtreecommitdiff
path: root/docs/gui-decoupling-plan.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/gui-decoupling-plan.md')
-rw-r--r--docs/gui-decoupling-plan.md318
1 files changed, 318 insertions, 0 deletions
diff --git a/docs/gui-decoupling-plan.md b/docs/gui-decoupling-plan.md
new file mode 100644
index 0000000..4c2ad88
--- /dev/null
+++ b/docs/gui-decoupling-plan.md
@@ -0,0 +1,318 @@
+# DS-Sim GUI Decoupling Plan
+
+## Problem Analysis
+
+### Current Architecture Issues
+
+1. **VSSimulatorVisualization extends Canvas**
+ - Inherits from java.awt.Canvas, making it inherently a GUI component
+ - paint() method is called automatically by AWT/Swing framework
+ - Cannot function without a valid GUI peer in headless mode
+
+2. **Tight Coupling Points**
+ ```
+ Protocol → Process.sendMessage() → Visualization.sendMessage() → VSMessageLine → paint()
+ ↓
+ Creates visual elements
+ Triggers canvas repaint
+ ```
+
+3. **Violations of Separation of Concerns**
+ - Business logic (simulation) mixed with presentation (visualization)
+ - Message passing logic coupled with visual message lines
+ - Process state management tied to canvas updates
+
+## Decoupling Strategy
+
+### Phase 1: Create Abstraction Layer
+
+#### 1.1 Define Core Interfaces
+
+```java
+// Core simulation interface
+public interface SimulationEngine {
+ void sendMessage(VSMessage message);
+ void addProcess(VSInternalProcess process);
+ void removeProcess(VSInternalProcess process);
+ List<VSInternalProcess> getProcesses();
+ VSTaskManager getTaskManager();
+ long getTime();
+ void setTime(long time);
+ void reset();
+ void play();
+ void pause();
+}
+
+// Visualization interface (optional)
+public interface SimulationVisualizer {
+ void onMessageSent(VSMessage message);
+ void onProcessAdded(VSInternalProcess process);
+ void onProcessRemoved(VSInternalProcess process);
+ void onTimeChanged(long time);
+ void onSimulationReset();
+ void onSimulationStarted();
+ void onSimulationPaused();
+}
+
+// Message handler interface
+public interface MessageHandler {
+ void handleMessage(VSMessage message);
+ void visualizeMessage(VSMessage message); // Optional
+}
+```
+
+#### 1.2 Create Headless Implementation
+
+```java
+public class HeadlessSimulationEngine implements SimulationEngine {
+ private final List<VSInternalProcess> processes;
+ private final VSTaskManager taskManager;
+ private final List<SimulationVisualizer> visualizers;
+ private long time;
+
+ public void sendMessage(VSMessage message) {
+ // Pure logic - no visualization
+ message.updateTimestamps();
+
+ // Notify visualizers (if any)
+ for (SimulationVisualizer viz : visualizers) {
+ viz.onMessageSent(message);
+ }
+
+ // Process the message
+ deliverMessage(message);
+ }
+}
+```
+
+### Phase 2: Refactor VSSimulatorVisualization
+
+#### 2.1 Extract Simulation Logic
+
+Create new class hierarchy:
+```
+SimulationEngine (interface)
+├── AbstractSimulationEngine
+│ ├── HeadlessSimulationEngine
+│ └── VisualizableSimulationEngine
+```
+
+#### 2.2 Refactor VSSimulatorVisualization
+
+```java
+public class VSSimulatorVisualization extends Canvas implements SimulationVisualizer {
+ private SimulationEngine engine; // Composition instead of doing everything
+
+ @Override
+ public void onMessageSent(VSMessage message) {
+ if (isDisplayable() && getBufferStrategy() != null) {
+ createMessageLine(message);
+ repaint();
+ }
+ }
+
+ // Delegate simulation operations to engine
+ public void sendMessage(VSMessage message) {
+ engine.sendMessage(message);
+ }
+}
+```
+
+### Phase 3: Refactor Message Handling
+
+#### 3.1 Separate Message Logic from Visualization
+
+```java
+public class MessageDispatcher {
+ private final Map<Integer, VSInternalProcess> processes;
+
+ public void dispatchMessage(VSMessage message) {
+ VSInternalProcess destination = processes.get(message.getDestinationId());
+ if (destination != null) {
+ destination.receiveMessage(message);
+ }
+ }
+}
+
+public class VisualMessageHandler implements MessageHandler {
+ private final MessageDispatcher dispatcher;
+ private final Canvas canvas;
+
+ public void handleMessage(VSMessage message) {
+ dispatcher.dispatchMessage(message);
+ visualizeMessage(message);
+ }
+
+ public void visualizeMessage(VSMessage message) {
+ if (canvas != null && canvas.isDisplayable()) {
+ new VSMessageLine(message, canvas);
+ }
+ }
+}
+
+public class HeadlessMessageHandler implements MessageHandler {
+ private final MessageDispatcher dispatcher;
+
+ public void handleMessage(VSMessage message) {
+ dispatcher.dispatchMessage(message);
+ }
+
+ public void visualizeMessage(VSMessage message) {
+ // No-op in headless mode
+ }
+}
+```
+
+### Phase 4: Modify Core Classes
+
+#### 4.1 Update VSInternalProcess
+
+```java
+public class VSInternalProcess extends VSAbstractProcess {
+ private MessageHandler messageHandler; // Injected
+
+ public void sendMessage(VSMessage message) {
+ incSentMessages();
+ messageHandler.handleMessage(message);
+ }
+}
+```
+
+#### 4.2 Create Factory for Mode Selection
+
+```java
+public class SimulationFactory {
+ public static SimulationEngine createEngine(boolean headless) {
+ if (headless) {
+ return new HeadlessSimulationEngine();
+ } else {
+ return new VisualizableSimulationEngine();
+ }
+ }
+
+ public static MessageHandler createMessageHandler(boolean headless,
+ MessageDispatcher dispatcher,
+ Canvas canvas) {
+ if (headless) {
+ return new HeadlessMessageHandler(dispatcher);
+ } else {
+ return new VisualMessageHandler(dispatcher, canvas);
+ }
+ }
+}
+```
+
+### Phase 5: Integration Points
+
+#### 5.1 Modify VSSimulator
+
+```java
+public class VSSimulator extends JPanel {
+ private final SimulationEngine engine;
+ private final VSSimulatorVisualization visualization; // Optional
+
+ public VSSimulator(VSPrefs prefs, VSSimulatorFrame frame) {
+ boolean headless = System.getProperty("ds.sim.headless", "false").equals("true");
+
+ this.engine = SimulationFactory.createEngine(headless);
+
+ if (!headless && frame != null) {
+ this.visualization = new VSSimulatorVisualization(prefs, this, engine);
+ engine.addVisualizer(visualization);
+ }
+ }
+}
+```
+
+#### 5.2 Update Serialization
+
+```java
+public class VSSerialize {
+ public VSSimulator openSimulator(String filename, VSSimulatorFrame frame) {
+ // Detect headless mode
+ boolean headless = frame == null ||
+ System.getProperty("ds.sim.headless", "false").equals("true");
+
+ // Load with appropriate components
+ if (headless) {
+ return loadHeadlessSimulator(filename);
+ } else {
+ return loadVisualSimulator(filename, frame);
+ }
+ }
+}
+```
+
+## Implementation Steps
+
+1. **Create new package structure**
+ ```
+ simulator.engine/
+ ├── SimulationEngine.java
+ ├── AbstractSimulationEngine.java
+ ├── HeadlessSimulationEngine.java
+ └── VisualizableSimulationEngine.java
+
+ simulator.messaging/
+ ├── MessageHandler.java
+ ├── MessageDispatcher.java
+ ├── HeadlessMessageHandler.java
+ └── VisualMessageHandler.java
+
+ simulator.visualization/
+ ├── SimulationVisualizer.java
+ └── VSMessageLine.java (moved)
+ ```
+
+2. **Gradual refactoring approach**
+ - Start with message handling
+ - Extract simulation logic from VSSimulatorVisualization
+ - Create headless implementations
+ - Update dependent classes
+ - Maintain backward compatibility
+
+3. **Testing strategy**
+ - Create unit tests for new components
+ - Ensure existing GUI functionality still works
+ - Verify headless mode has zero GUI dependencies
+
+## Benefits
+
+1. **Clean Architecture**
+ - Separation of concerns
+ - Testable components
+ - Flexible deployment options
+
+2. **True Headless Operation**
+ - No GUI errors in headless mode
+ - Faster test execution
+ - Suitable for CI/CD pipelines
+
+3. **Maintainability**
+ - Clear interfaces
+ - Easier to extend
+ - Better code organization
+
+## Risks and Mitigation
+
+1. **Breaking Changes**
+ - Mitigation: Use adapter pattern to maintain compatibility
+ - Provide migration guide
+
+2. **Performance Impact**
+ - Mitigation: Profile and optimize critical paths
+ - Use efficient data structures
+
+3. **Complexity**
+ - Mitigation: Incremental implementation
+ - Comprehensive documentation
+
+## Timeline Estimate
+
+- Phase 1: 2-3 days (interfaces and abstractions)
+- Phase 2: 3-4 days (refactor VSSimulatorVisualization)
+- Phase 3: 2-3 days (message handling)
+- Phase 4: 3-4 days (core class updates)
+- Phase 5: 2-3 days (integration and testing)
+
+Total: 12-17 days for complete implementation \ No newline at end of file