Poy Chang's Blog

試試看管線導向程式設計 (Pipeline-oriented programming)

NDC Porto 2023 有一場議程在講管線導向程式設計 (Pipeline-oriented programming),和平常常見的程式設計方法不同,雖然我不會完全改用這樣的設計方法,但有時間的時候嘗試看看,可以讓思考方法變得更多元一些。

這裡不做解釋,想了解關於管線導向程式設計,請直接看這個影片:Pipeline-oriented programming - Scott Wlaschin - NDC Porto 2023

下面的程式碼,是在看完影片之後隨手寫的簡單範例,這個範例是在 C# 中實作管線導向程式設計,透過 Pipe 方法,將數字依序經過不同的方法處理,並透過 Show 方法顯示處理結果,透過 Log 方法輸出處理過程中的備註訊息。

你可以自行把這整段程式碼貼到 dotnetfiddle 或是 LINQPad 上執行看看,感受一下管線導向的運作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public void Main()
{
// Demo number operate with Pipe extensino
5
.Show()
.Pipe(Math.Double)
.Log("It shoould double the number.")
.Show()
.Pipe(Math.Add, 1)
.Pipe(Math.Square)
.Show();

Console.WriteLine("----------");

// Using a LINQ pipeline with a "strategy" parameter
var list = new List<int> { 1, 2, 3 };
var fn = (IEnumerable<int> p) => p.Select(Math.Square);
list
.Pipe(fn)
.Show();
}

// You can define other methods, fields, classes and namespaces here
public static class PipeExtension
{
public static TOut Pipe<TIn, TOut>(this TIn input, Func<TIn, TOut> fn) => fn(input);
public static TOut Pipe<TIn, TParam, TOut>(this TIn input, Func<TIn, TParam, TOut> fn, TParam p1) => fn(input, p1);

public static T Log<T>(this T t, string message)
{
Console.WriteLine($"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd:HH:mm:ss}] {message}");
return t;
}
public static T Show<T>(this T t)
{
switch (t)
{
case ValueType:
case string:
Console.WriteLine($"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd:HH:mm:ss}] {t}");
break;
default:
Console.WriteLine($"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd:HH:mm:ss}] {JsonSerializer.Serialize(t)}");
break;
}
return t;
}
}

public static class Math
{
public static int Add(int i, int j) => i + j;
public static int Mult(int i, int j) => i * j;
public static int Double(int i) => i * 2;
public static int Square(int i) => i * i;
}

參考資料: