Architecture Smells Analysis
Source: Garcia et al., Lippert & Roock, Sharma
Context: System-level structural issues affecting maintainability, evolution, and deployment.
Table of Contents
- Considered Architecture Smells
- Garcia et al. (Connector/Component Perspective)
- Lippert & Roock (Symptom-Based)
- Sharma (Dependency Perspective)
- Applied Architecture Smells Analysis
- Hub-like Dependency
- Scattered Functionality
- Implicit Cross-module Dependency
- References
1. Considered Architecture Smells
1.1 Garcia et al. (Connector/Component Perspective)
| Type | Issue Type | Description | Applicable | Reason |
|---|---|---|---|---|
| Connector Envy | Structure | Components handle communication logic that should be in a dedicated connector | ✗ | No connector concept in Jenkins Pipeline |
| Extraneous Connector | Structure | Two components communicate through a connector when direct call suffices | ✗ | Same as above |
| Ambiguous Interface | Structure | Interface offers only single, overly general entry point | ✗ | Weak interface concept in Helper functions |
1.2 Lippert & Roock (Symptom-Based)
| Type | Issue Type | Description | Applicable | Reason |
|---|---|---|---|---|
| Cyclic Dependency | Dependency | Components/Packages form a dependency cycle | ✓ | Sequence diagram analysis confirms unidirectional dependencies only |
| Unstable Dependency | Dependency | Stable component depends on less stable component | ✗ | No change frequency data available |
Cyclic Dependency Analysis Method: Jenkins Pipeline is procedural code, so call flow was traced via sequence diagrams. Analysis confirms
Jenkinsfile → Helper → External (Python/CLI)unidirectional dependencies only. No inter-Helper dependencies found.
1.3 Sharma (Dependency Perspective)
| Type | Issue Type | Description | Applicable | Reason |
|---|---|---|---|---|
| Hub-like Dependency | Dependency | Component with too many incoming/outgoing dependencies | ✓ | generalHelper → all 5 pipelines depend on it |
| Scattered Functionality | Structure | Single concern implemented across multiple components | ✓ | Same functionality scattered across helper and inline |
| Dense Structure | Structure | Dependency graph is too dense | ✗ | Density measurement meaningless with only 8 files |
| Implicit Cross-module Dependency | Dependency | Hidden dependencies not visible in architecture | ✓ | Python scripts, env vars, Jenkins APIs |
Note: Hub-like Dependency is classified as Design Smell (class level) in Sharma's taxonomy. However, in Jenkins Pipeline context, Helper files serve as core system components, so it is included in Architecture level analysis.
2. Applied Architecture Smells Analysis
2.1 Hub-like Dependency
Data Sources:
| Component | Source | Extracted Data |
|---|---|---|
| Pipelines | Pipeline Sequence Diagrams | Call counts extracted from Delegation Pattern tables |
| generalHelper | Software Smells Analysis (Hub-like Modularization) | Existing count data used |
| jsHelper | jsHelper.groovy source code | External calls counted directly |
| unityHelper | unityHelper.groovy source code | External calls counted directly |
Incoming Dependencies (Pipeline → Helper):
| Pipeline | generalHelper | jsHelper | unityHelper | Total |
|---|---|---|---|---|
| DLX CI | 5 | - | 5 | 10 |
| DLX CD | 3 | - | 4 | 7 |
| JS CI | 6 | 4 | - | 10 |
| JS CD | 3 | 6 | - | 9 |
| Jenkins CI | 4 | - | - | 4 |
| Total | 21 | 10 | 9 | 40 |
Outgoing Dependencies (Helper → External):
| External Type | generalHelper | jsHelper | unityHelper |
|---|---|---|---|
| Git CLI | 18 | - | - |
| Linux CLI | 11 | 3 | 1 |
| SSH | 6 | - | - |
| SCP | 4 | - | - |
| Python | 2 | 1 | 4 |
| SonarQube API | 2 | - | - |
| Node.js CLI | - | 2 | - |
| npm CLI | - | 6 | - |
| Unity CLI | - | - | 1 |
| Unity Hub CLI | - | - | 2 |
| Total Calls | 43 | 12 | 8 |
| Total Types | 6 | 4 | 4 |
Dependency Diagram:
Numbers on edges represent call counts. Solid lines (→) indicate calls through Helper, dashed lines (⇢) indicate direct External calls.
21 calls in] JH[jsHelper
10 calls in] UH[unityHelper
9 calls in] end subgraph External Git[Git CLI] Python[Python Scripts] SSH[SSH/SCP] SonarQube[SonarQube] npm[npm CLI] Unity[Unity CLI] Docker[Docker CLI] Azure[Azure CLI] end %% Pipeline → Helper DLX_CI -->|5| GH DLX_CI -->|5| UH DLX_CD -->|3| GH DLX_CD -->|4| UH JS_CI -->|6| GH JS_CI -->|4| JH JS_CD -->|3| GH JS_CD -->|6| JH Jenkins_CI -->|4| GH %% Helper → External GH -->|18| Git GH -->|10| SSH GH -->|2| Python GH -->|2| SonarQube JH -->|6| npm JH -->|1| Python UH -->|4| Python UH -->|3| Unity %% Pipeline → External (Direct) DLX_CD -.->|4| Git DLX_CD -.->|8| SSH JS_CD -.->|4| Git JS_CD -.->|8| Docker JS_CD -.->|8| Azure
Analysis:
- generalHelper: All 5 pipelines depend on it (100%), 43 outgoing calls to 6 external types → Hub
- jsHelper, unityHelper: Only 2 pipelines each depend on them, 12/8 outgoing calls to 4 types
- Dashed lines: Pipeline → External direct calls (Helper bypass) → inconsistent abstraction
2.2 Scattered Functionality
Data Sources:
| Source | Extracted Data |
|---|---|
| Pipeline Sequence Diagrams | Pipeline Comparison tables |
Evidence:
| Concern | Implementation Location | Issue |
|---|---|---|
| Git operations | generalHelper (CI) vs Jenkinsfile direct calls (CD) | Same functionality, different implementation |
| Build status sending | Via initializeEnvironment (CI) vs direct sendBuildStatus call (CD) |
Same functionality, different call pattern |
| Bitbucket reporting | unityHelper (sendTestReport), Jenkinsfile direct Python calls |
Same domain, scattered across multiple locations |
| Web Server deployment | generalHelper (CI) vs Jenkinsfile direct SSH/SCP (CD) | Same functionality, different implementation |
Analysis: - Same concern implemented differently depending on CI/CD pipeline type - Changes require modifications in multiple locations → triggers Shotgun Surgery
2.3 Implicit Cross-module Dependency
Data Sources:
| Source | Extracted Data |
|---|---|
| 2.1 Hub-like Dependency | Dependency Diagram, Outgoing Dependencies table |
| Pipeline Sequence Diagrams | Delegation Pattern tables (direct External calls) |
| Helper source code | Environment variable usage list |
Hidden Dependencies via sh calls:
All External calls are made through
shcommand. Dependencies only revealed at runtime withoutimportin Groovy code.
| Source | External Types | Total Calls |
|---|---|---|
| Helpers | 10 | 63 |
| Pipelines (direct) | 10 | 50 |
| Total | - | 113 |
Hidden Dependencies via Environment Variables:
| Environment Variable | Used In | Set In |
|---|---|---|
WORKSPACE |
jsHelper | Jenkins (automatic) |
COMMIT_HASH |
jsHelper | Jenkinsfile |
PR_BRANCH |
unityHelper | Jenkinsfile |
CI_PIPELINE |
unityHelper | Jenkinsfile |
SSH_KEY |
generalHelper | Jenkins credentials |
DLX_WEB_HOST_URL |
generalHelper | Jenkins configuration |
UNITY_EXECUTABLE |
unityHelper | Jenkinsfile |
PROJECT_DIR |
unityHelper | Jenkinsfile |
REPORT_DIR |
unityHelper | Jenkinsfile |
BUILD_URL |
unityHelper | Jenkins (automatic) |
Analysis:
- All 113 external calls are implicit dependencies via sh
- Cannot determine required external tools by reading Helper code alone
- Tracing environment variable origins requires examining Jenkinsfile