Image

每天睜開眼,我們都在寫程式,
不是敲在鍵盤上,而是敲在時間裡、選擇裡,
生活的每一個 if 和 else 裡。

我們總說要專注主線任務,要成為自己人生的主角。
但又說,我們在這宇宙間只是滄海一粟,只是一粒塵埃,現實從不按劇本走,許多事情總不由我不所控,因此人生更像一個超複雜的專案管理系統,Bug 叢生,就連自己也無法 Debug,我們活得像一個沒掛 Filter 的 Controller,誰都能 Call 你,還不需授權。結果不是 Timeout,就是 500 Error

所以啊,到了這個時候,我們可以嘗試為人生加上一點 AOP

讓 Aspect-Oriented Programming 靜靜守護主線任務

AOP 到底是什麼?它解決了什麼問題?

本質上,AOP 是一種設計概念,它幫助我們把與主功能沒關係,但到處都要用到的邏輯,例如「紀錄 Log」、「驗證權限」、「計時」等等,從主邏輯中分離出來,集中管理。

把「共通邏輯(Cross-Cutting Concerns)」從每個類別或方法中分離出來,讓主功能更乾淨、可讀性更高,而且這些共通邏輯可以集中維護。它幫你把那些不該佔據腦海的瑣事抽離出來,集中管理,讓你把心力,留給真正重要的事。

1️⃣ ☕ 用 Middleware 攔截迷失的 Request

你可以把 Google Calendar 想像成人生的 Middleware,幫你攔下那些正在迷航的 Request。當你此刻載入想耍廢的行為時,它提醒你:「光頭的任務還沒交付呢。」燈愣

API 的 Middleware 就像剝洋蔥,一層層進入,一層層返回。在不中斷核心邏輯的前提下,悄悄地加入功能,這此演示客製 LogMiddleware,想要在 Request 管線掛上一些 Request 資訊的標籤在 Log 上可以這麼做

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

//// 自製 Middleware
public class LogMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<LogMiddleware> _logger;

public LogMiddleware(RequestDelegate next, ILogger<LogMiddleware> logger)
{
_next = next;
_logger = logger;
}

public async Task Invoke(HttpContext context)
{
ControllerActionDescriptor controllerActionDescriptor = context.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>();
string controllerName = controllerActionDescriptor?.ControllerName;
string actionName = controllerActionDescriptor?.ActionName;
string requestMethod = context.Request.Method;
string ipAddress = context.Connection.RemoteIpAddress?.ToString() ?? "UnknownIP";
using (_logger.BeginScope("Controller={Controller}, Action={Action}, IP={IP}", controllerName, actionName, ipAddress))
{
await _next(context);
}
}
}


//// 加入 Middleware
app.UseYoYoLinMiddleware();
app.UseMiddleware<TestMiddleware>();


//// Controller 端加上 Log
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
_logger.LogInformation("標籤出來!!!");
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}

Image

一個站台在維護需求上一定會動很多手腳,實現自己的 AOP

2️⃣ Filter(ActionFilter / ExceptionFilter / AuthorizationFilter)

Filter 是在「Controller 執行前 / 執行後」幫你掛鉤一些共用邏輯的幫手,與 Middleware 最大的差異就是他偏向方法級別的使用,以處理例外來說,我們有所謂的 Exception Filter,如果你想,他也可以讓你對人生的不完美,給予溫柔的理解,而不是苛責的報錯。

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

public class AlwaysHappy200ExceptionFilter : IExceptionFilter
{
private readonly ILogger<AlwaysHappy200ExceptionFilter> _logger;
private readonly IWebHostEnvironment _env;
public AlwaysHappy200ExceptionFilter(ILogger<AlwaysHappy200ExceptionFilter> logger, IWebHostEnvironment env)
{
_logger = logger;
_env = env;
}
public void OnException(ExceptionContext context)
{
_logger.LogError(context.Exception, "[例外攔截] 人生總是充滿了例外阿...");

var errorResponse = new
{
Success = true,
Message = _env.IsDevelopment() ? "開發環境麻~" : "我們的系統絕對沒問題不要誣賴我 > <",
ErrorType = context.Exception.GetType().Name,
StatusCode = 200
};

context.Result = new ObjectResult(errorResponse);
context.ExceptionHandled = true;
}
}


//// Action 掛上 Excpetion Filter 並且拋出錯誤
[HttpGet(Name = "GetWeatherForecast")]
[ServiceFilter(typeof(AlwaysHappy200ExceptionFilter))]
public IEnumerable<WeatherForecast> Get()

Image

OOP vs AOP

AOP 和 OOP 是兩種不同的設計理念,但它們可以互補、一起使用,讓我們娓娓道來!

OOP 就是把「真實世界的東西」轉成「程式裡的物件」,讓你的程式更接近人的思考方式。你設計的程式就像是在「建立一個世界」,這世界有「角色(物件)」、「他們有特徵(屬性)」、「他們能做的事情(方法)」,每個角色分工清楚,互不干擾,這樣維護起來會更輕鬆。

📖 比如設計一個「訂單系統」:

  1. 訂單(Order)是物件
  2. 每個訂單有訂單編號、金額(屬性)
  3. 可以執行「計算折扣」、「確認付款」(方法)
  4. 如果你還會處理「一般訂單」跟「特別訂單」,就可以用「繼承」去分出來,然後根據類型實作不同的折扣邏輯(多型)。

OOP 很擅長「模擬真實世界的角色與行為」,但在實務上,常常會遇到一些「跟業務無關但到處都要做的事情」,像是:

  • Logging(紀錄日誌)
  • Exception Handling(錯誤處理)
  • 驗證(Validation)
  • 權限檢查(Authorization)
  • 計時、統計分析
  • 資料快取(Caching)

這些事情不屬於訂單本身的邏輯,但你又不得不在很多地方寫,久了就會讓程式「混亂、重複、不好維護」。這種情況下,OOP 的封裝、繼承就不太夠用了,這時就可以出動 AOP!

✅ AOP 強調的是「切出橫向的關注點(concern),統一管理」

結語

這些小設計,不改變你人生的主程式碼,但它們像註記一樣,悄悄滑入你生活的每一段流程把你接住,讓你不用每天重新決定該幹嘛,讓你保留更多心力給真正重要的事。

所以,如果你總覺得人生太亂,不是你不夠努力,可能只是你還沒為人生加上 [Schedule]、[EmotionFilter]

🧘‍♂️ AOP 的哲理提醒我們:

       與其讓雜事侵入每個生活片段,不如設計一套能自我修復的架構,讓自己更自由,更平靜地走在主線上。