Đọc source code Laravel: Helper windows_os() - Tại sao phải viết hàm cho một hằng số có sẵn?
Chào anh em!
Tiếp tục series "mổ xẻ" những hàm helper (hàm hỗ trợ) tưởng chừng như vô tri nhưng lại đầy tinh tế trong lõi của Laravel. Hôm nay, chúng ta sẽ xem xét một đoạn code vô cùng ngắn gọn:
if (! function_exists('windows_os')) {
/**
* Determine whether the current environment is Windows based.
*
* @return bool
*/
function windows_os()
{
return PHP_OS_FAMILY === 'Windows';
}
}
Nhìn vào đây, nhiều lập trình viên sẽ ngay lập tức đặt câu hỏi: "Rõ ràng PHP đã cung cấp sẵn hằng số PHP_OS_FAMILY. Tại sao Framework không dùng thẳng hằng số đó ở những chỗ cần kiểm tra, mà lại phải tốn công bọc nó vào một cái hàm windows_os() làm gì cho cồng kềnh?"
Sự tồn tại của đoạn code này là một minh chứng tuyệt vời cho triết lý Clean Code (Mã sạch) và tính dễ đọc (Readability) mà các hệ thống lớn luôn theo đuổi. Hãy cùng phân tích các tầng ý nghĩa của nó.
1. Ký ức đau thương thời chưa có PHP_OS_FAMILY
Để hiểu giá trị của đoạn code, chúng bản cần lật lại lịch sử của PHP.
Hằng số PHP_OS_FAMILY (trả về các giá trị chuẩn hóa như 'Windows', 'Linux', 'Darwin', 'BSD'...) chỉ mới được bổ sung từ phiên bản PHP 7.2. Trước đó, lập trình viên chỉ có hằng số PHP_OS.
Nhưng PHP_OS lại trả về chính xác cái tên hệ điều hành lúc hệ thống được build (ví dụ: WIN32, WINNT, Windows). Để kiểm tra xem server có đang chạy Windows hay không ở thời điểm PHP 5.x hoặc 7.0, anh em phải viết một đoạn code cực kỳ "đau mắt" như thế này:
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Đây là môi trường Windows
}
Hoặc một mẹo tà đạo khác là check dấu gạch chéo của hệ thống file:
if (DIRECTORY_SEPARATOR === '\') {
// Đây là Windows
}
Laravel, với tư cách là một Framework lâu đời, đã tạo ra hàm windows_os() từ rất sớm để giấu đi những đoạn code kiểm tra xấu xí này. Khi PHP 7.2 ra mắt hằng số mới, Laravel chỉ việc cập nhật phần "ruột" bên trong hàm thành PHP_OS_FAMILY === 'Windows', còn toàn bộ phần code bên ngoài của người dùng sử dụng hàm windows_os() vẫn giữ nguyên, không bị ảnh hưởng (Backward Compatibility).
2. Sức mạnh của Ngữ nghĩa (Semantics)
Ngay cả khi bây giờ chúng ta đã có một hằng số rất tường minh là PHP_OS_FAMILY, việc bọc nó vào một hàm vẫn mang lại giá trị vô giá về mặt ngữ nghĩa học.
Hãy thử đặt hai đoạn code này lên bàn cân:
Cách 1 (Dùng trực tiếp hằng số):
if (PHP_OS_FAMILY === 'Windows') {
$command = 'dir';
} else {
$command = 'ls';
}
Cách 2 (Dùng hàm Helper của Laravel):
if (windows_os()) {
$command = 'dir';
} else {
$command = 'ls';
}
Ở góc độ của một cỗ máy, cả hai cách chạy nhanh y hệt nhau. Nhưng ở góc độ của một lập trình viên (người phải bảo trì code sau 6 tháng nữa), Cách 2 ăn đứt Cách 1.
if (windows_os()) đọc lên giống hệt như ngôn ngữ giao tiếp tự nhiên của con người: "Nếu là hệ điều hành windows thì...". Trong khi đó, PHP_OS_FAMILY === 'Windows' lại mang đậm tính chất kỹ thuật máy tính (so sánh chuỗi với hằng số). Việc giấu đi các phép toán logic (===) vào bên trong các hàm có tên gọi mang tính tự sự (Descriptive Naming) là nguyên tắc cốt lõi giúp mã nguồn trở nên thanh lịch và dễ đọc lướt (scannable) hơn.
3. Tại sao Backend Dev lại cần quan tâm Server dùng OS gì?
Với sự lên ngôi của Docker, đa số code PHP hiện nay đều được chạy trên các container Linux (Alpine, Ubuntu). Vậy tại sao framework vẫn phải liên tục check xem hệ điều hành hiện tại có phải là Windows hay không?
Đây là những tình huống thực tế bắt buộc bạn phải rẽ nhánh code theo hệ điều hành:
- Tương tác với Terminal/Console: Khi ứng dụng của bạn cần gọi các lệnh hệ thống (thông qua
exec()hoặcshell_exec()). Trên Linux bạn dùng lệnhls,rm -rf,cp, nhưng trên Windows bạn phải dùngdir,del,copy. - Xử lý đường dẫn ảo: Mặc dù PHP có hằng số
DIRECTORY_SEPARATORđể xử lý dấu/(Linux) và\(Windows), nhưng khi cấu hình các đường dẫn môi trường (Environment Paths) hoặc làm việc với các phần mềm bên thứ 3, Windows có hệ thống ổ đĩa (C:\,D:\) hoàn toàn khác biệt với cấu trúc cây thư mục gốc (/) của Linux. - Xử lý ký tự xuống dòng: Khác biệt kinh điển giữa CRLF (
\r\ncủa Windows) và LF (\ncủa Linux) khi đọc ghi file log vật lý.
Lời kết
Hàm windows_os() tuy chỉ dài đúng 1 dòng thực thi, nhưng nó là một mảnh ghép hoàn hảo minh họa cho câu nói: "Code là để cho con người đọc, việc máy tính có thể chạy được nó chỉ là sản phẩm phụ".
Bằng cách đóng gói những biểu thức logic kỹ thuật vào những hàm có tên gọi gợi nhớ, Laravel đã giúp hàng triệu lập trình viên trên thế giới giảm tải được gánh nặng nhận thức (Cognitive Load) khi đọc code, từ đó tập trung tốt hơn vào việc giải quyết các bài toán nghiệp vụ phức tạp.
All rights reserved