groovy/unityHelper.groovy - Software Smells Analysis
Classification based on industry-standard taxonomy: Code Smells (Fowler) → Design Smells (Suryanarayana)
Domain Classification: 3 domains, 8 functions. See Domain Mapping
1. Code Smells
Source: Fowler, M. (1999). Refactoring: Improving the Design of Existing Code
Applicable Categories: Since Jenkins Pipeline Helper files are procedural scripts, only the following categories are applicable:
Category Applicable Applied Smells Bloaters ✓ Long Method, Switch Statements Change Preventers ✓ Divergent Change, Shotgun Surgery Dispensables ✗ (no Dead Code or Duplicated Code found) Object-Orientation Abusers ✗ (not applicable - no inheritance/polymorphism) Couplers ✗ (not applicable - no class relationships)
1.1 Change Preventers (with Severity Criteria)
Severity Criteria
| Metric | Low | Medium | High |
|---|---|---|---|
| Impact Scope | 1 pipeline | 2 pipelines | - |
| Modification Cost | 1-2 locations | 3-5 locations | 6+ locations |
Note: unityHelper serves only 2 pipelines (DLX CI, DLX CD), so Impact Scope is capped at Medium.
Divergent Change (Scope: File Level)
Click to see details
Definition: "A single class/file is frequently changed for several different reasons"
Divergent Change Cases in unityHelper.groovy:
Change Reason Affected Functions Count Unity batch mode CLI change runUnityBatchMode,getCodeCoverageArguments,fetCoverageOptionsKeyAndValue,buildCoverageOptions4 Python script interface change sendTestReport,getUnityExecutable2 Bitbucket report format change sendTestReport1 Unity Code Coverage settings change loadPathsToExclude,getCodeCoverageArguments2 Severity Evidence: - Impact Scope: Medium (2 pipelines depend on this file) - Modification Cost: Medium (4 different change reasons in single file)
Shotgun Surgery
Click to see details
Definition: "A single change requires modifications to multiple locations"
Cross-file (helper function signature change):
Function DLX CI DLX CD Total Locations runUnityStage5 4 9 getUnityExecutable2 1 3 Within-file (adding new Stage):
# Location Change Required 1 Stage constant definition Add this.ANDROID = 'Android'2 setLogFilePathAndUrlmappingAdd (ANDROID): [path: ..., url: ...]3 getTestRunArgsconditionDecide whether to include Android 4 getCodeCoverageArgumentsconditionDecide whether to include Android 5 getAdditionalArgsmappingAdd Android: '...'6 Command assembly branch Add else if 7 Graphics/quit options Add Android condition Severity Evidence: - Impact Scope: Medium (2 pipelines) - Modification Cost: High (9 cross-file + 7 within-file)
1.2 Other Code Smells (Evidence Only)
Bloaters
| Smell | Evidence |
|---|---|
| Long Method | runUnityBatchMode (126 lines, 7 responsibilities) |
| Switch Statements | Stage-specific conditionals repeated in 9 locations |
Switch Statements 9 locations
# Location Code Line 1 Test arguments [EDIT_MODE, PLAY_MODE].contains(stageName)209 2 Coverage arguments [EDIT_MODE, PLAY_MODE, COVERAGE].contains(stageName)212 3 Additional arguments [WEBGL, RIDER].contains(stageName)216 4 Command assembly (EditMode/PlayMode) if ([EDIT_MODE, PLAY_MODE].contains(stageName))220 5 Command assembly (Coverage) else if (stageName == COVERAGE)222 6 Command assembly (WebGL/Rider) else if ([WEBGL, RIDER].contains(stageName))224 7 Graphics options (stageName != WEBGL && stageName != PLAY_MODE)229 8 Quit options (stageName != PLAY_MODE && stageName != EDIT_MODE)233 9 Coverage options if ([EDIT_MODE, PLAY_MODE].contains(stageName))303
2. Design Smells (Principle-Based)
Source: Suryanarayana, G. et al. (2014). Refactoring for Software Design Smells
Applicable Categories: Since Jenkins Pipeline Helper files are procedural scripts, the following categories are applicable:
Category Applicable Applied Smells Abstraction ✓ Multifaceted Abstraction Encapsulation ✓ Missing Encapsulation Modularization ✗ (file size 357 lines is acceptable) Hierarchy ✓ Missing Hierarchy (Strategy pattern applicable)
2.1 Abstraction Smells
Multifaceted Abstraction
Click to see details
Definition: "An abstraction has multiple responsibilities assigned to it"
Evidence: - 3 domains in single file: Unity CLI (6), Unity Installation (1), Bitbucket (1) - 8 functions across 3 different domains
2.2 Encapsulation Smells
Missing Encapsulation
Click to see details
Definition: "The encapsulation of implementation variations in a type is missing"
Evidence: Stage-specific conditional branches scattered:
Location Stage Logic Lines Log path mapping Map logConfig = [(EDIT_MODE): [...], ...]139-160 Test arguments [EDIT_MODE, PLAY_MODE].contains(stageName)209 Coverage arguments [EDIT_MODE, PLAY_MODE, COVERAGE].contains(stageName)212 Additional arguments [WEBGL, RIDER].contains(stageName)216 Command assembly if ([EDIT_MODE, PLAY_MODE].contains(stageName)) {...}220-226 Graphics options (stageName != WEBGL && stageName != PLAY_MODE)229-233 Coverage options if ([EDIT_MODE, PLAY_MODE].contains(stageName)) {...}303-310 Impact: Adding new Stage "Android" requires modifying all 7 locations
2.3 Hierarchy Smells
Missing Hierarchy
Click to see details
Definition: "Conditional logic is used instead of subclasses or delegation"
Evidence: Stage-specific branches can be replaced with Strategy pattern:
Current Branch Pattern Strategy Replacement [EDIT_MODE, PLAY_MODE].contains(stageName)stage.requiresTestRun()[EDIT_MODE, PLAY_MODE, COVERAGE].contains(stageName)stage.requiresCoverage()[WEBGL, RIDER].contains(stageName)stage.getAdditionalArgs()stageName != WEBGL && stageName != PLAY_MODEstage.requiresNographics()stageName != PLAY_MODE && stageName != EDIT_MODEstage.requiresQuit()
Conclusion
Software Smells Summary: - Code Level: Divergent Change (4 change reasons), Shotgun Surgery (9 cross-file + 7 within-file), Long Method (126 lines, 7 responsibilities), Switch Statements (9 locations) - Design Level: 3 domains mixed, Stage-specific logic not encapsulated, Missing Hierarchy (Strategy pattern applicable)