- Trước đây, môi trường phát triển Ada đã từng giải quyết xong vấn đề định dạng mã
- Các lập trình viên làm việc với mã ở dạng biểu diễn trung gian (IR) DIANA và xem theo thiết lập pretty-printing mà mỗi người mong muốn
- Đến nay vẫn tồn tại sự kém hiệu quả và tranh cãi lặp đi lặp lại xoay quanh linter hay chính sách định dạng
- Máy trạm Rational R1000 khi đó cung cấp môi trường phát triển và các tính năng mang tính đột phá
- Từ vấn đề định dạng code, bài viết gợi ý tham khảo cách làm của một thế hệ trước để thay đổi thực hành phát triển ngày nay
Tranh luận về định dạng mã – lời giải từ thập niên 1980
- Tác giả nhắc lại trải nghiệm với thầy giáo khoa học máy tính của mình, ông Paige, người từng tham gia làm việc trên một trình biên dịch Ada khi còn ở bậc trung học
- Khi phàn nàn về sự bất tiện trong việc thiết lập công cụ linter vào năm 2016 và hỏi rằng “vì sao chúng ta vẫn phải chịu đựng chuyện này”, tác giả được nghe kể rằng vấn đề này đã được giải quyết từ hơn 40 năm trước
Sự xuất hiện của Ada và DIANA
- Thay vì lưu mã nguồn dạng văn bản, các lập trình viên Ada sử dụng một biểu diễn trung gian tên là DIANA (Descriptive Intermediate Attributed Notation for Ada)
- Mỗi lập trình viên có thể xem mã theo thiết lập pretty-printing của riêng mình
- Không tồn tại tranh cãi về định dạng hay vấn đề linter, và trong trình soạn thảo người ta có thể chỉnh sửa trực tiếp cây chương trình (tương tự projectional editing hiện đại)
Rational R1000 – môi trường phát triển tiên phong
- Máy trạm Rational R1000 tích hợp nhiều tính năng cao cấp như biên dịch gia tăng, phân tích tĩnh, quản lý phiên bản, gỡ lỗi
- Nó được dùng trong các dự án phần mềm quan trọng như dự án của DoD, Trạm Vũ trụ Quốc tế (ISS), tiêm kích F-22, và còn góp phần vào sự ra đời của UML
- Theo Grady Booch, R1000 là cỗ máy dựa trên DIANA, không lưu mã nguồn mà chỉ dùng việc pretty-print cây DIANA
Lợi ích của phát triển dựa trên DIANA
- Không cần tranh cãi về định dạng, thiết lập linter hay thống nhất môi trường biên tập
- Nhờ tăng tốc phần cứng, nó mang lại trải nghiệm phát triển đột phá như biên dịch gia tăng, refactoring dễ dàng, tích hợp nhanh
- Điều này có ảnh hưởng quan trọng tới hiệu suất phát triển và công việc trên các hệ thống lớn
Hàm ý cho hiện tại
- Biên dịch tăng tốc bằng phần cứng ngày nay bớt quan trọng hơn, nhưng việc giải quyết bài toán định dạng vẫn còn chưa thỏa đáng
- Dù cách làm chủ đạo hiện nay không phải projectional editing hay môi trường live, đây là lúc nên cân nhắc áp dụng những thực hành phát triển hiệu quả hơn và ít gây tranh cãi hơn như cách tiếp cận trong quá khứ
Tài liệu tham khảo
- Khi tìm hiểu chủ đề này, tác giả đã trích dẫn nhiều tài liệu và báo cáo kỹ thuật liên quan đến R1000
4 bình luận
Theo tôi biết, hiện đã có chức năng tự động định dạng mã nguồn được chia sẻ bằng một cấu hình thống nhất, và các công ty cũng dùng khá nhiều.
Có vẻ trọng tâm không phải là chuyện tự động định dạng, mà là ngay từ việc tồn tại nhận thức rằng một kiểu định dạng cụ thể nào đó vượt trội hơn, hay quá trình phải từ bỏ kiểu định dạng của mình để thích nghi với một kiểu định dạng xa lạ, đã là điều không cần thiết rồi. Vì lập luận ở đây là lưu một biểu diễn trung gian không bị ràng buộc bởi định dạng, rồi tùy người dùng mà pretty-print theo cách họ thấy thuận tiện.
Điều tôi muốn nói là với việc định dạng tự động, ta vẫn có thể làm cùng một việc bằng các ngôn ngữ hiện có mà không cần những biểu đạt trung gian, nhưng có lẽ phần giải thích của tôi còn thiếu.
Ý kiến trên Hacker News
diffcũng gọn hơn. Vì vậy lựa chọn sai sẽ khiến cuộc sống của tôi khó khăn hơn. Với danh sách được sắp xếp hoặcincludecũng vậy; nếu không sắp xếp thì người ta luôn thêm vào cuối, khiến xung đột merge xảy ra thường xuyên hơn. Cũng như lợi ích của auto-formatter, việc sắp xếp cũng nên giúp tiết kiệm thời gian. Và tôi khá nhạy cảm với phong cách không nhất quán. Điều quan trọng nhất là thống nhất chỉ một kiểu duy nhất.githay các PL chỉ xử lý theo từng dòng là không được thanh lịch. Trong 20 năm sự nghiệp, tôi mới chỉ thấy một ví dụ dùng cách tinh tế hơn, như ngôn ngữ Ada. Thật khó để tạo ra thứ gì đó thực sự thanh lịch và hiệu quả, và nếu đã có nhiều lựa chọn đủ tốt rồi thì lại càng khó phổ biến rộng rãi.grep,diff,sed, quản lý phiên bản sẽ giảm đi. Cuối cùng sự phụ thuộc vào công cụ, định dạng hay phần mở rộng IDE chuyên biệt sẽ tăng lên. Điểm mạnh của triết lý Unix là tính kết hợp thông qua plain text. Có một câu hỏi có thể cắt gọn tranh luận này: nếu trong editor chỉ cần có thể tự do thiết lập độ rộng khoảng trắng ban đầu, thì những người thích tab còn lập luận gì nữa không?grepvăn bản rất nhiều, có thể dùng ast-grep;diffthì có thể hỗ trợ di chuyển có cấu trúc hoặc bỏ qua thay đổi không mang ý nghĩa như semanticdiff.com; còn thay thế chosedthì có thể dùng @codemod/cli. Quản lý phiên bản cũng đã được thử nghiệm khá nhiều trong các ngôn ngữ như Unison để tự động tránh xung đột do các thay đổi không mang ý nghĩa như thứ tự, khoảng trắng, v.v.grep,diff,sed, merge theo dòng thật ra là những công cụ tệ để thao tác code. Tôi nghĩ chúng ta nên suy nghĩ về công cụ tốt hơn thay vì tiếp tục tranh cãi ở hướng này.grep/diff/sedvẫn có thể hoạt động. Nếu chỉ dùng formatter dựa trên AST, thì code sẽ được lưu ở dạng đã chuẩn hóa theo một AST nhất định, còn editor sẽ parse AST rồi hiển thị theo định dạng người dùng mong muốn; khi lưu thì lại chuyển về dạng chuẩn hóa.blackcủa Python tách các truy vấn SQLAlchemy ra quá nhiều dòng, khiến độ dễ đọc còn giảm đi.register, trong khi lại dùng dấu sao (*) để biểu diễn con trỏ; từng ký hiệu đều hoàn toàn có thể trực quan và rõ ràng hơn, vậy mà người ta vẫn cố chấp giữ những cách thể hiện phức tạp, khó đọc. Ngay cả ký hiệu hay từ khóa dành riêng cũng có thể đổi sang thuật ngữ quen thuộc và tự nhiên hơn, nhưng vì quá bám vào truyền thống và quy ước cũ nên người ta hy sinh khả năng đọc hiểu. Lấy ví dụ hàmstrcpytrong C, người viết giải thích rằng hoàn toàn có thể tái cấu trúc lại bằng thuật ngữ và cú pháp rõ ràng, dễ đọc hơn nhiều.char *argv[]. Và họ cũng cho rằng kiểu formatting theo phong cách C++ nhưchar* a, bcó thể gây hiểu nhầm, nên nên tránh kiểu đó.shouldvàunnecessary.diff/so sánh, hoặc (6) chưa từng phát triển công cụ tự động hóa cho codebase, hoặc (7) là kiểu chỉ quan tâm đến bản thân mà thiếu ý thức hợp tác.pass/commit, và nếu không qua tự động hóa thì CI báo lỗi là đủ. Thay vì ám ảnh với chi tiết, cứ theo mặc định và từ bỏ phong cách cá nhân đôi khi còn là một lợi thế. Nếu để nguyên mặc định thì bất kỳ ai nhìn vào code cũng sẽ thấy quen thuộc hơn. Hơn nữa, formatting và linting là hai thứ khác nhau, nhưng cả hai đều có thể được giải quyết cùng lúc bằng công cụ tự động.=, hay được thụt vào để làm nổi bật chiều sâu cấu trúc, đều là các lựa chọn khác nhau. Nếu muốn nhấn mạnh giá trị thì có thể căn phải các con số; nếu muốn nhấn mạnh cấu trúc thì có thể căn các member variable cho dễ nhìn. Tùy khía cạnh của code mà tác giả muốn nhấn mạnh, cách trình bày sẽ khác nhau. Họ cho rằng nếu không có metadata bổ sung thì những thông tin này không thể trích xuất từ AST.setValue([bar, glob], 1)hoặc cú pháp comment để override style, v.v.git diffcũng có thể xem dưới dạng projection của IR (biểu diễn trung gian). Nhờ sự xuất hiện của các công cụ AST như treesitter, người ta bắt đầu hình dung ra các giao diện để con người thao tác AST hay IR hiệu quả hơn. Ví dụ, cấu trúc ordered compilation của f# giúp đơn giản hóa code review. Ngược lại, ở các ngôn ngữ hay cấu trúc cho phép thứ tự tự do, để kiểm tra mộtdiffnhỏ đôi khi phải đi qua rất nhiều chỗ khác nhau để nắm được toàn bộ ngữ cảnh thay đổi, khá phiền phức.eslint-config-airbnb. Các vấn đề tiêu biểu là #1271, #1122. Họ đã mất hơn một giờ vật lộn để áp dụng cấu hình Airbnb vào dự án sẵn có, trong khi code vốn đã hoàn toàn ổn; họ cảm thấy những quy tắc không cần thiết đó khiến mọi thứ trở nên kém năng suất. Cuối cùng họ chỉ tắt riêng các quy tắc đó ở local, và từ đó về sau không bao giờ dùng lại trong dự án nữa. Ví dụ này cho thấy các quy tắc lint sai có thể phá hỏng năng suất đến mức nào.