Skip to content

Code smell: File class duplicates logging pattern in every method #1585

@thomhurst

Description

@thomhurst

Location

  • File: src/ModularPipelines/FileSystem/File.cs
  • Lines: 36-122 (multiple methods)

Problem

Almost every method starts with the same logging pattern:

public Task<string> ReadAsync(CancellationToken cancellationToken = default)
{
    ModuleLogger.Current.LogInformation("Reading File: {Path}", this);
    return System.IO.File.ReadAllTextAsync(Path, cancellationToken);
}

public IAsyncEnumerable<string> ReadLinesAsync(CancellationToken cancellationToken = default)
{
    ModuleLogger.Current.LogInformation("Reading File: {Path}", this);
    return System.IO.File.ReadLinesAsync(Path, cancellationToken);
}

public Task<byte[]> ReadBytesAsync(CancellationToken cancellationToken = default)
{
    ModuleLogger.Current.LogInformation("Reading File: {Path}", this);
    return System.IO.File.ReadAllBytesAsync(Path, cancellationToken);
}

// And many more with similar pattern...

Why it's a problem

  1. DRY Violation: The same logging call is repeated in 15+ methods
  2. Inconsistent Messages: Some say "Reading", some say "Writing to", making it harder to search logs
  3. Cross-Cutting Concern: Logging is scattered throughout business logic
  4. Hard to Disable: No way to disable file operation logging without modifying each method
  5. AOP Candidate: This is a classic case for aspect-oriented programming

Suggested Fix

  1. Create a helper method or use an interceptor pattern:
private void LogOperation(string operation)
{
    ModuleLogger.Current.LogInformation("{Operation} File: {Path}", operation, this);
}

public Task<string> ReadAsync(CancellationToken cancellationToken = default)
{
    LogOperation("Reading");
    return System.IO.File.ReadAllTextAsync(Path, cancellationToken);
}
  1. Or use a logging wrapper:
private async Task<T> WithLogging<T>(string operation, Func<Task<T>> action)
{
    ModuleLogger.Current.LogInformation("{Operation} File: {Path}", operation, this);
    return await action().ConfigureAwait(false);
}
  1. Consider making logging optional via configuration

Category

  • Magic numbers/strings
  • DRY violation
  • SOLID violation
  • Code that could be done better

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