elastic / elastic/docs-builder
chore: Remove single-implementation C# interfaces
- Dominant language
- C#
- Stars
- 24
- Forks
- 44
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 146
Description
## What
Remove interfaces that have exactly one implementation and no test mocks — they add indirection with no polymorphism benefit.
## Interfaces to remove
| Interface | Single impl | File |
|-----------|-------------|------|
| `IFormatter` | `IrregularSpaceFormatter` | `src/authoring/Elastic.Documentation.Refactor/Formatters/IFormatter.cs` |
| `IPagesProvider` | `LocalPagesProvider` | `src/Elastic.Documentation.LegacyDocs/PagesProvider.cs` |
| `IHtmxAttributeProvider` | `DefaultHtmxAttributeProvider` | `src/Elastic.Documentation.Site/Htmx.cs` |
| `IDescriptionGenerator` | `DescriptionGenerator` — every caller already passes `new DescriptionGenerator()` | `src/Elastic.Markdown/DescriptionGenerator.cs` |
| `IDocumentationFileOutputProvider` | `GlobalNavigationPathProvider` — one optional ctor param consumer | `src/Elastic.Markdown/DocumentationGenerator.cs` |
| `ILinkIndexWriter` + `ILinkIndexReaderWriter` | `AwsS3LinkIndexReaderWriter` — keep `ILinkIndexReader` (2 impls), fold `SaveRegistry` onto the concrete writer | `src/Elastic.Documentation.LinkIndex/ILinkIndexWriter.cs` |
| `IChangesService` | `ChangesService` | `src/services/search/Elastic.Documentation.Search/IChangesService.cs` |
| `IDocumentGateway` | single impl, one consumer | `src/api/Elastic.Documentation.Mcp.Remote/Gateways/IDocumentGateway.cs` |
| `IAskAiMessageFeedbackService` | single impl, one consumer | `src/api/Elastic.Documentation.Api/AskAi/IAskAiMessageFeedbackGateway.cs` |
| `IGitRepository` | `SingleCommitOptimizedGitRepository` — 9-method interface consumed only by same-file helpers that already `new` the concrete type | `src/services/Elastic.Documentation.Assembler/Sourcing/GitFacade.cs` |
| `IProductNameLookup` | `ProductsConfiguration` — depend on the config record directly | `src/services/search/Elastic.Documentation.Search.Contract/Common/IProductNameLookup.cs` |
| `ISitemapParser`, `IAdaptiveCrawler`, `IDocumentExporter` | one impl each; `AddHttpClient` needs no interface | `src/tooling/essc/LabsCrawl/` |
| `IChangelogMarkdownRenderer` | redundant with `MarkdownRendererBase`, which all 6 renderers derive from; type the list as `List` | `src/services/Elastic.Changelog/Rendering/Markdown/IChangelogMarkdownRenderer.cs` |
**Excluded (correctly polymorphic or test-mocked — do NOT remove):**
- `IDocsSyncPlanStrategy` / `IDocsSyncApplyStrategy` — deliberate named strategy pattern
- `IGitHubReleaseService`, `IGitHubPrService`, `IGcpIdTokenProvider`, `IS3EtagCalculator` — mocked via `A.Fake<>` in `tests/` / `tests-integration/`
- `IRepositoryTracker` — 2 impls (`IntegrationGitRepositoryTracker`, `LocalGitRepositoryTracker`)
- `IParserResolvers` — 2 impls (`ParserResolvers` record, `ParserContext`)
- `IDocumentInferrerService` (2 impls), navigation tree interfaces (`INavigationItem`, `ITableOfContentsItem`, etc. — multiple impls)
## How
For each interface: delete the interface declaration, update all constructor parameters and DI registrations to reference the concrete type directly. Update any `services.AddScoped()` to `services.AddScoped()`.
~180 lines removed across the batch.
> [!NOTE]
> Re-audited 2026-07-07: six interfaces originally listed here (`IGitHubReleaseService`, `IGitHubPrService`, `IGcpIdTokenProvider`, `IS3EtagCalculator`, `IRepositoryTracker`, `IParserResolvers`) were false positives — mocked in tests or with a second implementation — and moved to the excluded list. Thirteen newly verified single-impl interfaces were added.
Part of the broader ponytail over-engineering audit tracked in #3574.
Contributor guide
Research direction
Start with the listed interface files and trace their constructor parameters and DI registrations across the referenced API, service, tooling, and rendering paths. Verify the excluded interfaces remain intact, then run the relevant repository checks. Done means the listed single-implementation interfaces are removed, concrete types are wired directly, and the batch builds and tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend, tooling
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100