Skip to content

Refactor Method to Reduce Cognitive Complexity #592

@ziagham

Description

@ziagham

What version of FlowSynx?

1.2.2

Describe the bug

The Format method currently contains nested conditional logic and mixed responsibilities (template parsing, property reflection, and formatting), which result in a Cognitive Complexity score of 22. This exceeds the allowed threshold of 15, making the method harder to maintain and test.

File: src/FlowSynx.Infrastructure/Logging/LogTemplate.cs
Method: Format(LogMessage logMessage, string template)

Current Complexity:
Cognitive Complexity: 22
Allowed: 15

Proposed Refactor

internal static string Format(LogMessage logMessage, string template)
{
    var sbResult = new StringBuilder(template.Length);
    var sbCurrentTerm = new StringBuilder();
    var inTerm = false;

    foreach (var ch in template)
    {
        if (HandleOpeningBrace(ch, ref inTerm))
            continue;

        if (HandleClosingBrace(ch, ref inTerm, sbCurrentTerm, sbResult, logMessage))
            continue;

        AppendCharacter(ch, inTerm, sbCurrentTerm, sbResult);
    }

    return sbResult.ToString();
}

private static bool HandleOpeningBrace(char ch, ref bool inTerm)
{
    if (ch != '{') return false;
    inTerm = true;
    return true;
}

private static bool HandleClosingBrace(char ch, ref bool inTerm, StringBuilder sbCurrentTerm, StringBuilder sbResult, LogMessage logMessage)
{
    if (ch != '}') return false;

    var term = sbCurrentTerm.ToString();
    sbResult.Append(GetValueForTerm(term, logMessage));
    sbCurrentTerm.Clear();
    inTerm = false;
    return true;
}

private static void AppendCharacter(char ch, bool inTerm, StringBuilder sbCurrentTerm, StringBuilder sbResult)
{
    if (inTerm)
        sbCurrentTerm.Append(ch);
    else
        sbResult.Append(ch);
}

private static string GetValueForTerm(string term, LogMessage logMessage)
{
    if (string.Equals(term, "NewLine", StringComparison.OrdinalIgnoreCase))
        return Environment.NewLine;

    var propertyInfo = logMessage.GetType()
        .GetProperty(term, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

    if (propertyInfo == null)
    {
        var message = Localization.Get("Logging_Invalid_Property", term);
        throw new FlowSynxException((int)ErrorCode.LoggerTemplateInvalidProperty, message);
    }

    var value = propertyInfo.GetValue(logMessage);

    if (string.Equals(propertyInfo.Name, "level", StringComparison.OrdinalIgnoreCase))
        value = GetShortLogLevel((LogLevel)value!);

    return value?.ToString() ?? string.Empty;
}

Expected Outcome

  • Cognitive Complexity ≤ 15
  • Improved readability and maintainability
  • Easier unit testing for template parsing and value resolution

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions