Skip to content

Coding Conventions

This page documents the enforced coding standards across the NPipeline codebase. All rules are checked at build time - TreatWarningsAsErrors means violations fail the build.

Language and Build Settings

Defined in Directory.Build.props:

SettingValue
LangVersion12.0
TreatWarningsAsErrorstrue
Nullableenable
ImplicitUsingsenable
GenerateDocumentationFiletrue
EnableNETAnalyzerstrue
AnalysisLevellatest
TargetFrameworksnet8.0;net9.0;net10.0

Style Rules

From .editorconfig:

  • var preferred when the type is apparent or built-in (csharp_style_var_*: true)
  • System directives first in using blocks (dotnet_sort_system_directives_first: true)
  • No separated import groups (dotnet_separate_import_directive_groups: false)
  • StyleCop ordering enforced: SA1201 (element order), SA1202 (access modifier order), SA1203 (constants first), SA1204 (static before instance)
  • UTF-8 encoding, CRLF line endings, trailing whitespace trimmed, final newline inserted

XML Documentation

All public APIs require XML documentation (GenerateDocumentationFile=true). Include at minimum:

csharp
/// <summary>Transforms a raw order into an enriched order.</summary>
/// <param name="item">The raw order to transform.</param>
/// <param name="context">The pipeline execution context.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The enriched order.</returns>
/// <exception cref="InvalidOperationException">Thrown when the order ID is missing.</exception>

Connector and test projects suppress CS1591 (missing XML docs) via WarningsNotAsErrors.

Custom Analyzers

NPipeline ships 20+ Roslyn analyzers in NPipeline.Analyzers. They run during every build.

Configuration & Setup

IDSeverityRule
NP9001WarningRestartNode requires ResilientExecutionStrategy, MaxNodeRestartAttempts > 0, and MaxMaterializedItems to be set
NP9002ErrorMaxMaterializedItems must not be null - prevents unbounded memory growth
NP9003WarningInappropriate parallelism configuration (too high for CPU-bound, too low for I/O)
NP9004WarningBatch size / timeout mismatch (large batch + short timeout or vice versa)
NP9005WarningInappropriate timeout values (zero, negative, too short for I/O, too long for CPU)

Performance & Optimization

IDSeverityRule
NP9101WarningBlocking calls in async methods (.Result, .Wait(), Thread.Sleep())
NP9102WarningSync-over-async anti-patterns
NP9103WarningLINQ allocations in hot-path methods (TransformAsync, ConsumeAsync, OpenStream)
NP9104WarningString concatenation with + in loops
NP9105WarningAnonymous object allocations in hot paths
NP9106InfoTransformNode uses Task.FromResult but could override ExecuteValueTaskAsync for zero-allocation
NP9107WarningSourceNode.OpenStream materializes data into List/Array instead of streaming
NP9108InfoNode could benefit from a parameterless constructor for compiled-expression instantiation

Reliability & Error Handling

IDSeverityRule
NP9201WarningCatch block swallows OperationCanceledException without re-throwing
NP9202WarningInefficient exception handling in hot paths
NP9203WarningCancellationToken parameter not forwarded to async calls or checked in loops

Data Integrity & Correctness

IDSeverityRule
NP9301ErrorSinkNode.ConsumeAsync does not consume the input parameter
NP9302WarningUnsafe access on nullable PipelineContext properties

Design & Architecture

IDSeverityRule
NP9401InfoTransformAsync returns IAsyncEnumerable - consider IStreamTransformNode instead
NP9402WarningIStreamTransformNode paired with a non-stream execution strategy
NP9403WarningNode missing public parameterless constructor (requires DI or pre-configured instance)
NP9404WarningDI anti-patterns in nodes (service locator, static singleton access)

Test Conventions

Framework and Libraries

  • Framework: xUnit
  • Assertions: AwesomeAssertions (.Should().Be(...), .Should().HaveCount(...))
  • Mocking: FakeItEasy (A.Fake<T>(), A.CallTo(...))
  • Coverage: Coverlet

Naming

Test methods follow MethodName_Condition_ExpectedBehavior:

csharp
[Fact]
public async Task TransformAsync_NullInput_ThrowsArgumentNullException()

[Fact]
public async Task OpenStream_ValidConfig_ReturnsExpectedItems()

[Fact]
public async Task ConsumeAsync_CancellationRequested_StopsProcessing()

Structure

  • Test project mirrors source: tests/NPipeline.Connectors.Json.Tests/ for src/NPipeline.Connectors.Json/
  • One test class per production class: JsonSourceNodeTests.cs tests JsonSourceNode.cs
  • Integration tests in separate files: {Feature}IntegrationTests.cs
  • Shared helpers in tests/NPipeline.Tests.Common/ (e.g., InMemoryDataStream, TransformNodeTestExtensions)
  • Test projects set <IsPackable>false</IsPackable>
  • Test projects suppress CA1873, CA1848, CA2253, CA2254, CA1727 (logging-related warnings)

Pattern

csharp
public sealed class MyNodeTests
{
    [Fact]
    public async Task TransformAsync_ValidInput_ReturnsExpected()
    {
        // Arrange
        var node = new MyNode();
        var context = new PipelineContext();

        // Act
        var result = await node.TransformAsync("input", context, CancellationToken.None);

        // Assert
        result.Should().Be("expected");
    }
}

Next Steps

Released under the MIT License.