Skip to content

[v2.0 Breaking] Simplify Module result access API - remove dual type parameters #1988

@thomhurst

Description

@thomhurst

Summary

The GetModule<TModule, TResult>() method requires developers to specify both the module type AND the result type, even though the result type is already known from the module's type parameter. This creates a poor developer experience.

Current Behavior

File: src/ModularPipelines/Context/IModuleContext.cs (lines 22-31)

ModuleResult<TResult> GetModule<TModule, TResult>()
    where TModule : Module<TResult>;

Usage:

// Developer must know and specify both types
var buildResult = context.GetModule<BuildModule, BuildOutput>();

Problems

  1. Redundant: TResult is already known from TModule : Module<TResult>
  2. Poor IntelliSense: IDE cannot auto-complete the result type
  3. Error-prone: Possible mismatches between requested and actual types
  4. Discoverability: Developers must look up what each module returns

Proposed Solutions

Option A: Single type parameter with interface constraint

ModuleResult<TResult> GetModule<TModule>()
    where TModule : IModule, IModuleWithResult<TResult>;

Option B: Source-generated extension methods

Generate extension methods for each module type:

// Auto-generated
public static ModuleResult<BuildOutput> GetBuildModule(this IModuleContext context)
    => context.GetModule<BuildModule, BuildOutput>();

Option C: Expression-based API

var result = await context.GetResult(m => m.BuildModule);

Recommended Approach

Option B (source-generated extensions) provides the best developer experience while maintaining type safety and avoiding runtime reflection.

Impact

  • Breaking change: API signature change, suitable for v2.0
  • Improves: Developer experience, type safety, discoverability

Labels

  • breaking-change
  • v2.0
  • enhancement
  • developer-experience

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions