Cú pháp lập trình tôi thích nhất: “pipelining”
(herecomesthemoon.net)- Pipelining là một tính năng quan trọng trong ngôn ngữ lập trình, giúp tăng khả năng đọc và bảo trì của mã
- Đây là cách giúp biểu diễn luồng dữ liệu một cách tự nhiên từ trái sang phải, từ trên xuống dưới
- Trong các ngôn ngữ như Rust, pipelining làm rõ luồng mã và nâng cao năng suất phát triển nhờ tính năng tự động hoàn thành của IDE
- Nó được áp dụng trong nhiều ngôn ngữ như Haskell, Elm, SQL; builder pattern hay method chaining cũng được xem là một dạng pipelining
- Tác động tích cực đến khả năng đọc, sự thuận tiện khi chỉnh sửa, hỗ trợ IDE, và cả công cụ quản lý phiên bản (diff, blame)
- So với cách lồng hàm, nó giúp viết mã ngắn gọn và rõ ràng hơn, nên cũng có lợi cho cộng tác và bảo trì
Cú pháp lập trình tôi thích nhất: pipelining
Pipelining là gì?
- Là tính năng cho phép truyền giá trị trước đó để có thể lược bỏ một đối số trong danh sách tham số
- Giúp tăng khả năng đọc của mã và khiến việc thêm chú thích trở nên dễ dàng hơn
- Là phong cách cú pháp tập trung vào dữ liệu, trong đó các bước xử lý liên tiếp được áp dụng tuần tự
- Trong mã theo phong cách hàm, nó thường xuất hiện dưới dạng method chaining như
.map().filter().collect() - Trong Rust, đoạn mã sau là ví dụ tiêu biểu:
data.iter() .filter(|w| w.alive) .map(|w| w.id) .collect() - Ngược lại, nếu lồng toàn bộ hàm vào nhau thì sẽ thành cấu trúc phải đọc từ trong ra ngoài như sau:
collect(map(filter(iter(data), |w| w.alive), |w| w.id))
Vì sao pipelining lại tốt?
-
1. Khả năng đọc và bảo trì
- Dễ đọc từ trên xuống dưới → luồng dữ liệu trùng với thứ tự con người đọc
- Dễ thêm chú thích cho từng dòng
- Ngắn gọn và rõ ràng mà không cần lồng ngoặc trên những dòng dài
-
2. Sự thuận tiện khi chỉnh sửa
- Có thể dễ dàng thêm một hàm mới trên một dòng, như
.map(), vào giữa chuỗi xử lý - Trong
git diffhaygit blame, việc theo dõi thay đổi cũng hiện ra gọn gàng, rõ ràng hơn
- Có thể dễ dàng thêm một hàm mới trên một dòng, như
-
3. Hỗ trợ IDE / LSP
- Rất phù hợp với cấu trúc mà khi nhấn phím
.sẽ hiện ra danh sách tự động hoàn thành - Có lợi cho phân tích tĩnh, vốn yêu cầu phải biết rõ kiểu dữ liệu
- Để tính năng này hoạt động tốt, ngôn ngữ cần dựa trên kiểu tĩnh (e.g. Rust, TypeScript)
- Rất phù hợp với cấu trúc mà khi nhấn phím
SQL cũng có pipelining?
- Có những đề xuất chuyển các truy vấn SELECT lồng nhau trong SQL sang phong cách pipeline
- Ví dụ:
FROM customer |> LEFT OUTER JOIN orders ON ... |> AGGREGATE COUNT(...) GROUP BY ... |> ORDER BY ... - So với SQL hiện tại, cách này cho luồng rõ ràng hơn và tăng khả năng đọc
- Nhược điểm: khi mệnh đề
SELECTbị đẩy lên trên, có thể khó nắm được kiểu trả về hơn → nhưng có thể giải quyết
Liên hệ với builder pattern
- Dạng như
Builder::new().option().option().build()trong Rust là một cấu trúc pipeline điển hình - Khi các thiết lập tùy chọn được cấu thành bằng method, việc theo dõi mã và quản lý thay đổi trở nên dễ dàng
Cải thiện pipelining trong Haskell
- Các toán tử như
$,&,|>trong Haskell cho phép dùng pipeline thay cho hợp thành hàm - So sánh trước và sau:
-- 기존 checkPalindromes content = unlines $ map (show . isPalindrome) $ lines $ map toLower content -- 개선 checkPalindromes content = content & map toLower & lines & map (show . isPalindrome) & unlines
Ưu điểm của pipelining trong Rust
- Method chaining, suy luận kiểu, và khả năng mở rộng có cấu trúc dựa trên trait đều kết hợp rất tốt với pipelining
- Rust có cấu trúc như thể chỉ chọn lấy ưu điểm của cả cú pháp hàm lẫn hướng đối tượng, nên việc dùng pipelining trở nên tự nhiên nhất
Kết luận
- Pipelining không chỉ là một cú pháp đơn thuần mà là một tính năng cốt lõi ảnh hưởng đến luồng mã, khả năng chỉnh sửa và cả cộng tác
- Thay vì kiểu lồng như
f(g(h(x))), cấu trúcx |> h |> g |> fthân thiện với con người hơn - Dưới quy tắc đơn giản “mỗi dòng một thao tác”, pipelining là cách tốt nhất để biểu đạt một luồng xử lý tự nhiên
“Mỗi mảnh ống nhận dữ liệu chính, thực hiện đúng một công việc. Cuối cùng, nếu đặt cho nó một cái tên rõ ràng, đó sẽ là cấu trúc mã lý tưởng nhất.”
11 bình luận
https://github.com/tc39/proposal-pipeline-operator
Có lẽ cũng theo ngữ cảnh tương tự như việc xuống dòng và thụt lề quan trọng với khả năng đọc của bất kỳ văn bản nào.
LINQ là số một!
Gleam cũng hỗ trợ cái này nên có thể viết code khá gọn gàng.
Mà không biết có phải vì trong bài có khối code không, mà trên di động nó cũng hiện theo bố cục desktop.
Nghĩ lại thì elm cũng làm được.
Với lượng dữ liệu nhỏ và mức độ mã đơn giản như ví dụ ở trên thì tôi nghĩ nhìn cũng ổn, không có gì tệ.
Nhưng khi code dần được nhét thêm vào trong
map()... thì nó có xu hướng khiến mã ngày càng phình to hơn,và tuy còn tùy ngôn ngữ hay thư viện triển khai mà mức độ ảnh hưởng khác nhau, nhưng khi lượng dữ liệu tăng lên thì so với cách đơn giản là chất dữ liệu vào cấu trúc dữ liệu hoặc vừa thao tác vừa xử lý, nó cũng có thể dễ dàng chậm hơn đến hàng nghìn lần.
Và rồi lại có thêm một lý do mới khiến tôi không còn thích nó nữa: khi xem bài này trên điện thoại, chiều rộng kiểu như trên PC vẫn bị giữ nguyên nên cỡ chữ bé tí như hạt bụi, thành ra đọc bài quá khó T.T
Về cơ bản tôi không thích nó, và cũng không cố tình nỗ lực để viết theo kiểu đó.
Cho
jsnữa đi |> cúi đầu nài nỉ|>quá đẹpĐây là cú pháp tôi ghét nhất
Chỉ cần stack trace hơi rối một chút thôi là việc debug đã tệ kinh khủng
Chuẩn luôn
Ý kiến trên Hacker News
Tác giả gọi đây là "pipelining", nhưng tôi nghĩ thuật ngữ đúng phải là "method chaining"
Cá nhân tôi ủng hộ việc giữ bộ tính năng của ngôn ngữ nhỏ gọn và nhanh chóng đạt đến một bộ tính năng hoàn chỉnh
|>của ElixirMacro Lisp cung cấp một lời giải tổng quát, không chỉ cho các toán tử thao tác trên collection theo chuỗi mà còn cho việc quyết định thứ tự của chuỗi lời gọi
Tôi học thuật ngữ này là fluent interface. Pipelining là thứ khác
Toán tử pipeline là một dạng partial application, cho phép bind nhiều đối số để tạo hàm mới rồi truyền đầu ra của nó sang hàm khác
Người dùng tidyverse của R đã dùng nó từ lâu
Pipelining khó debug. Việc xử lý ngoại lệ khó khăn nên phải thêm phân nhánh vào pipeline
Cú pháp SQL phức tạp một cách không cần thiết
|>thiếu tính biểu đạt và làm tăng nhiễu thị giácTác giả nói rằng "ngữ nghĩa thắng cú pháp", nhưng lại đang tập trung vào sở thích về cú pháp
effect-ts cho phép viết cả pipeline lẫn mã mệnh lệnh