Skip to content

Refactor: Reduce Cognitive Complexity in ParseWorkflowTaskPlaceholders method #587

@ziagham

Description

@ziagham

What version of FlowSynx?

1.2.2

Describe the bug

The method ParseWorkflowTaskPlaceholders currently has a Cognitive Complexity of 34, exceeding the allowed limit of 15. This makes it harder to understand, maintain, and test. The method combines multiple concerns — such as handling placeholders for task properties, parameters, manual approvals, dependencies, and plugin contexts — all within a single long method.

File: src/FlowSynx.Infrastructure/Workflow/WorkflowTaskExecutor.cs
Method: ParseWorkflowTaskPlaceholders(WorkflowTask task, IExpressionParser parser)
Current Complexity: 34
Allowed Limit: 15

Proposed Refactoring Goals

  • Reduce Cognitive Complexity to ≤ 15.
  • Improve readability, maintainability, and testability.
  • Follow the Single Responsibility Principle (SRP) by extracting focused helper methods.

Suggested Refactoring Approach

public void ParseWorkflowTaskPlaceholders(WorkflowTask task, IExpressionParser parser)
{
    if (task == null) return;

    ReplaceTopLevelStrings(task, parser);
    ProcessParameters(task, parser);
    ProcessManualApproval(task, parser);
    ReplaceListItems(task.Dependencies, parser);
}

private void ReplaceTopLevelStrings(WorkflowTask task, IExpressionParser parser)
{
    task.Name = ReplaceIfNotNull(task.Name, parser);
    task.Description = ReplaceIfNotNull(task.Description, parser);
    task.Output = ReplaceIfNotNull(task.Output, parser);
}

private void ProcessParameters(WorkflowTask task, IExpressionParser parser)
{
    if (task.Parameters == null || task.Parameters.Count == 0) return;

    foreach (var key in task.Parameters.Keys.ToList())
    {
        var value = task.Parameters[key];
        task.Parameters[key] = ProcessParameterValue(value, parser);
    }

    _placeholderReplacer.ReplacePlaceholdersInParameters(task.Parameters, parser);
}

private object ProcessParameterValue(object value, IExpressionParser parser)
{
    switch (value)
    {
        case JObject jObject:
            var context = TryDeserializePluginContext(jObject);
            if (context == null) return value;
            ApplyPlaceholdersToPluginContext(context, parser);
            return context;

        case JArray jArray:
            var list = TryDeserializePluginContextList(jArray);
            if (list == null) return value;
            foreach (var ctx in list)
                ApplyPlaceholdersToPluginContext(ctx, parser);
            return list;

        case string s:
            return ReplaceIfNotNull(s, parser);

        default:
            return value;
    }
}

private void ProcessManualApproval(WorkflowTask task, IExpressionParser parser)
{
    var approval = task.ManualApproval;
    if (approval == null) return;

    approval.Instructions = ReplaceIfNotNull(approval.Instructions, parser);
    approval.DefaultAction = ReplaceIfNotNull(approval.DefaultAction, parser);

    ReplaceListItems(approval.Approvers, parser);
}

private void ReplaceListItems(List<string>? list, IExpressionParser parser)
{
    if (list == null || list.Count == 0) return;

    for (int i = 0; i < list.Count; i++)
    {
        list[i] = ReplaceIfNotNull(list[i], parser);
    }
}

Acceptance Criteria

  • Cognitive Complexity reduced to ≤ 15
  • Code passes all existing tests
  • No behavior changes
  • Code readability improved
  • Smaller, well-named private methods with clear intent

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