Part of duplicate code analysis: #2257
Summary
internal/difc/labels.go defines two wrapper types — SecrecyLabel and IntegrityLabel — that both wrap the same underlying *Label type and expose near-identical method sets. Six method pairs are structurally parallel across the two types (constructors, getLabel, CanFlowTo, CheckFlow, Clone). The shared behavioural logic is already centralised in checkFlowHelper, but the wrapper boilerplate is repeated.
Duplication Details
Pattern: SecrecyLabel / IntegrityLabel Parallel Wrapper Methods
- Severity: Low
- Occurrences: 6 parallel method/function pairs (≥3 similar patterns — meets threshold)
- Locations:
| Method |
SecrecyLabel |
IntegrityLabel |
| Constructor (empty) |
line 161 |
line 296 |
| Constructor (with tags) |
line 166 |
line 301 |
getLabel() |
line 171 |
line 306 |
CanFlowTo() |
line 181 |
line 317 |
CheckFlow() |
line 276 |
line 323 |
Clone() |
line 281 |
line 328 |
Example parallel pair — Clone():
// SecrecyLabel (line 281)
func (l *SecrecyLabel) Clone() *SecrecyLabel {
if l.getLabel() == nil {
return NewSecrecyLabel()
}
return &SecrecyLabel{Label: l.Label.Clone()}
}
// IntegrityLabel (line 328)
func (l *IntegrityLabel) Clone() *IntegrityLabel {
if l.getLabel() == nil {
return NewIntegrityLabel()
}
return &IntegrityLabel{Label: l.Label.Clone()}
}
Impact Analysis
- Maintainability: Adding a new label type (e.g., a third flow dimension) would require writing all six methods again
- Bug Risk: Low — the actual flow logic is in
checkFlowHelper; the wrappers themselves are trivial
- Code Bloat: ~50 lines of structural repetition that could be reduced
Refactoring Recommendations
Note: Go generics or interface-based approaches should be evaluated against readability. This duplication is idiomatic in Go for type-safe domain wrappers and the severity is Low. Refactoring is only recommended if a third label type is planned.
-
Generic wrapper approach (Go 1.18+): Define a generic FlowLabel[T] with the constructor and Clone logic, letting the type-specific check semantics live in a strategy/callback. This reduces boilerplate but adds abstraction.
-
Document the pattern explicitly (lower-effort): Add a brief comment at the top of the SecrecyLabel section noting that IntegrityLabel follows the same structure, to make intentional parallelism clear to reviewers.
-
No action needed if no new label types are planned — the duplication is bounded and the logic is already shared via checkFlowHelper.
Implementation Checklist
Parent Issue
See parent analysis report: #2257
Related to #2257
Generated by Duplicate Code Detector · ◷
Part of duplicate code analysis: #2257
Summary
internal/difc/labels.godefines two wrapper types —SecrecyLabelandIntegrityLabel— that both wrap the same underlying*Labeltype and expose near-identical method sets. Six method pairs are structurally parallel across the two types (constructors,getLabel,CanFlowTo,CheckFlow,Clone). The shared behavioural logic is already centralised incheckFlowHelper, but the wrapper boilerplate is repeated.Duplication Details
Pattern: SecrecyLabel / IntegrityLabel Parallel Wrapper Methods
getLabel()CanFlowTo()CheckFlow()Clone()Example parallel pair —
Clone():Impact Analysis
checkFlowHelper; the wrappers themselves are trivialRefactoring Recommendations
Generic wrapper approach (Go 1.18+): Define a generic
FlowLabel[T]with the constructor andClonelogic, letting the type-specific check semantics live in a strategy/callback. This reduces boilerplate but adds abstraction.Document the pattern explicitly (lower-effort): Add a brief comment at the top of the
SecrecyLabelsection noting thatIntegrityLabelfollows the same structure, to make intentional parallelism clear to reviewers.No action needed if no new label types are planned — the duplication is bounded and the logic is already shared via
checkFlowHelper.Implementation Checklist
Parent Issue
See parent analysis report: #2257
Related to #2257