vendredi 26 mai 2023

What design pattern should be implemented to make my code accord with Open-Closed Principle

Here is the code that violates the open-closed principle:

public Node? Run(Node node)
{
    if (node.NodeType == Enum.NodeTypeEnum.ManualTask)
    {
        // do something
        return node.NextNodes.FirstOrDefault();

    }
    else if (node.NodeType == Enum.NodeTypeEnum.ScriptTask)
    {
        // do something
        return node.NextNodes.FirstOrDefault();
    }
    else if (node.NodeType == Enum.NodeTypeEnum.ExclusiveGateway)
    {
        // do something
        return node.NextNodes.FirstOrDefault();
    }
}

Node entity:

public class Node: EntityBase
{
    public NodeTypeEnum NodeType { get; set; }
    public List<Node>? NextNodes { get; set; }
    public string? NodeCondition { get; set; }
    public int ScriptId { get; set; }
}

In the code, we have a node entity which has many types. For each types, we should do some specific operation.

I try to refactor the method as follows:

NodeRunner.cs file:

public class NodeRunner: INodeRunner
{
    public virtual bool IsMatch(NodeEntity node)
    {
        throw new NotImplementedException();
    }

    public virtual Node Run(NodeEntity node)
    {
        throw new NotImplementedException();
    }
}

ManualTask class:

public class ManualTask : NodeRunner
{
    public override bool IsMatch(NodeEntity node)
    {
        return node.NodeType == NodeType.Manual;
    }

    public override Node Run(NodeEntity node)
    {
        return node.NextNodes.FirstOrDefault();
    }
}

ScriptTask class:

public class ScriptTask : NodeRunner
{
    // ...
    public override bool IsMatch(NodeEntity node)
    {
        return node.NodeType == NodeType.Script;
    }

    public override Node Run(NodeEntity node)
    {
        _scriptService.Execute(node.ScriptId);
        return node.NextNodes.FirstOrDefault();
    }
}

ExclusiveGateway.cs:

public class ExclusiveGateway: NodeRunner
{
    public override bool IsMatch(NodeEntity node)
    {
       return node.NodeType == NodeType.ExclusiveGateway;
    }

    public override Node Run(Node node)
    {
        if (node.NextNodes != null)
        {
            foreach (var nextNode in node.NextNodes)
            {
                if (_evaluateGatwayCondition.Evaluate(nextNode.NodeCondition, ""))
                {
                    return nextNode;
                }
            }
        }

        return new Node();
    }
}

And the ProcessService.cs:

public class ProcessService : IProcessService
{
    private readonly List<NodeRunner> NodeBrances;

    public ProcessService()
    {
        NodeBrances = new List<NodeRunner>
        {
            new ManualTask(),
            new ScriptTask(),
            new ExclusiveGateway()
        };
    }

    public Node Run(Node node)
    {
        return NodeBrances.First(nb => nb.IsMatch(node)).Run(node);
    }
}

ExclusiveGateway does not work and throws a NotImplementedException().

What should I do?

Aucun commentaire:

Enregistrer un commentaire