Pipeline Pattern
This is a behavioral pattern where the main goal is to split a complex job into multiple steps, each with a specific functionality. It�s really good for several types of architectures. For a system composed of various microservices with numerous components, this is a way to keep things easier to read and maintain. This pattern has several key concepts similar to the chain of responsibility one.
IPipeline
public interface IPipeline<T>
{
public string Name { get; set; }
public IReadOnlyCollection<IStep> Steps { get; }
void WithStep(IStep step);
Task<T> StartAsync(IData data);
}
IStep
public interface IStep
{
Task<IData> ExecuteAsync(IData data);
}
Pipeline generic
public class Pipeline<T> : IPipeline<T> where T : IData
{
private readonly List<IStep> _steps = new();
public string Name { get; set; }
public IReadOnlyCollection<IStep> Steps => _steps;
public Pipeline(string name)
{
Name = name;
}
public void WithStep(IStep step)
{
_steps.Add(step);
}
public async Task<T> StartAsync(IData input)
{
IData result = input;
foreach (var step in Steps)
{
try
{
result = await step.ExecuteAsync(result);
}
catch (Exception)
{
throw;
}
}
return (T)result;
}
}
Example Usage
var pipeline = new Pipeline<OutputData>("MyFirstPipeline");
pipeline.WithStep(new ToUpperStep());
pipeline.WithStep(new TextLengthStep());
var input = new InputData
{
Text = "Hello World!"
};
var output = await pipeline.StartAsync(input);
Console.WriteLine($"Starting pipeline {pipeline.Name}...");
Console.WriteLine($"Input text: '{input.Text}'");
Console.WriteLine($"Length of text is: {output.Result}");
Idea from Tiago Martins.
Result pattern
Result
This class can be used for using the result pattern.
Usage
public Result<string> GetUserNameById(int userId)
{
if (userId <= 0)
{
return Result<string>.Failure("Invalid user ID");
}
// We simulate obtaining a username
string userName = "John Doe"; // This would be the actual logic to get the name
return Result<string>.Success(userName);
}
public void ProcessUserName()
{
var result = GetUserNameById(1);
if (result.IsSuccess)
{
Console.WriteLine($"User name: {result.Value}");
}
else
{
Console.WriteLine($"Error: {result.ErrorMessage}");
}
}
More
More about that on: David May