1 điểm bởi GN⁺ 2025-01-12 | 1 bình luận | Chia sẻ qua WhatsApp
  • Hiệu ứng Makefile chỉ mẫu hành vi không dùng một công cụ phức tạp hoặc xa lạ ngay từ đầu, mà sao chép một cấu hình từng hoạt động tốt trước đây rồi chỉnh sửa cho phù hợp với tình huống mới
  • Trong giai đoạn giải quyết vấn đề, việc tái sử dụng ví dụ đã được kiểm chứng có thể là một phản ứng kỹ thuật hợp lý giúp giảm rủi ro phát sinh lỗi
  • Tuy nhiên, từ góc độ thiết kế, đây cũng có thể được xem là tín hiệu về tính khả dụng: công cụ khó hoặc phiền phức khi dùng ngay từ đầu, nên các thay đổi cứ tiếp tục tích lũy trên bản sao
  • Không chỉ với Make mà cả trong GitHub Actions, GitLab CI/CD, cấu hình linter·formatter và hệ thống build cũng xuất hiện luồng sao chép rồi chỉnh sửa tương tự
  • Người thiết kế công cụ cần kiểm tra xem cấu hình và cú pháp riêng có thực sự cần thiết không, có thể tái sử dụng các thành ngữ CLI quen thuộc không, và liệu người dùng có đang bị đẩy vào chỗ phải phụ thuộc vào copy-paste hay không

Hiệu ứng Makefile là gì

  • Hiệu ứng Makefile là hiện tượng không viết mới một công cụ có mức độ phức tạp hoặc xa lạ nhất định, mà sao chép rồi chỉnh sửa một ví dụ “đã hoạt động tốt” từ trước
  • Luồng điển hình như sau
    • Cần hoàn thành một tác vụ phổ biến, và một tác vụ rất giống hoặc y hệt như vậy đã từng được thực hiện trước đó
    • Make hoặc công cụ tương tự được chọn là công cụ phù hợp cho tác vụ đó
    • Thay vì viết Makefile mới, kỹ sư sao chép Makefile của tác vụ trước rồi sửa cho đến khi nó chạy được trong môi trường mới
  • Make chỉ là ví dụ tiêu biểu; vì công cụ mà từng nhóm hoặc từng cá nhân thành thạo là khác nhau, nên có những nhóm công cụ dễ bị hiệu ứng này hơn và có những nhóm ít bị hơn tương đối
  • Trò đùa “heritage Makefile” chỉ tình huống một Makefile được truyền lại từ kỹ sư kỳ cựu, giáo sư hoặc người đi trước, rồi tiếp tục được kế thừa với chỉ vài chỉnh sửa nhỏ

Vấn đề thiết kế công cụ mà việc sao chép lặp lại bộc lộ

  • Ở thời điểm cần giải quyết vấn đề ngay, tái sử dụng ví dụ đang chạy được có thể là một lựa chọn gọn gàng
    • Vì phần lớn tác vụ không thay đổi, về lý thuyết điều này có thể tạo ra ít bug mới hơn
    • Hiệu ứng Makefile về bản chất không phải lúc nào cũng là hiện tượng xấu hay kém hiệu quả
  • Nhưng ở thời điểm thiết kế, nó là tín hiệu cho thấy công cụ hoặc cách áp dụng công cụ quá phức tạp hoặc quá phiền toái
    • Người dùng lặp đi lặp lại việc sao chép lời giải có sẵn thay vì giải bài toán từ đầu
    • Nếu hiệu ứng này xuất hiện cả với những trường hợp áp dụng đơn giản, thì công cụ có thể đang quá phức tạp so với mục đích đó
  • Mẫu hình này cũng xuất hiện ở các công cụ thiên về cấu hình ngoài Make
    • Trong cấu hình CI/CD, người ta thường sao chép YAML từ cấu hình gần nhất đã chạy được của GitHub Actions hoặc GitLab CI/CD rồi lặp lại quá trình chỉnh sửa
    • Cấu hình linter và formatter thường sao chép một bộ quy tắc mặc định giữa các dự án, rồi siết chặt hoặc nới lỏng theo điều kiện cục bộ
    • Những cấu hình không hề đơn giản của hệ thống build rất dễ trở nên giống với hệ thống build trước đó

Chi phí phát sinh cho học tập, debug và bảo mật

  • Những công cụ có hiệu ứng Makefile mạnh có thể cản trở việc học sâu trên diện rộng
    • Một số ít người thành thạo sẽ cấu hình công cụ, còn những người khác chỉ hiểu phần cần thiết rồi sao chép và chỉnh sửa
    • Đồ thị phụ thuộc của hệ thống build là độ phức tạp mang tính bản chất, nhưng việc phải nhớ sự khác nhau giữa $<$^ trong Make thì không phải vậy
  • Nếu thiếu hỗ trợ chẩn đoán và debug, người dùng sẽ phải dựa vào cách chạy công cụ nhiều lần để nhặt từng manh mối nhỏ
    • Trong CI/CD, việc debug kiểu print thường phải đi qua mạng và các lớp điều phối VM trung gian
  • Xét về bảo mật, rủi ro cũng có thể tăng lên
    • Các biện pháp bảo mật thường đòi hỏi phải hiểu sâu “vì sao” của hành vi hệ thống
    • Những hệ thống nơi hiệu ứng Makefile xuất hiện thường cho phép nhầm lẫn giữa code và data, hoặc kiểu nhầm lẫn in-band signaling nói chung
    • Template injection trong GitHub Actions là ví dụ tiêu biểu

Những câu hỏi người thiết kế công cụ nên tự kiểm tra

  • Khi tạo công cụ mới, cần xem liệu người dùng có thể viết từ đầu hay không, hay họ buộc phải đi tìm một “ví dụ đang chạy được” để sao chép
  • Các câu hỏi nên rà soát gồm
    • Khả năng cấu hình có thực sự cần thiết không
    • Cú pháp riêng có thực sự bắt buộc không
    • Có thể tái sử dụng cú pháp và thành ngữ quen thuộc từ công cụ khác hoặc CLI hay không
    • Ngay cả người tạo ra công cụ cũng phải copy-paste cách dùng hay không, và nếu có thì người dùng khác cũng rất có thể sẽ như vậy
  • Về thuật ngữ “cargo cult”, bài viết của Ken Shirriff bàn về vấn đề đây là một thuật ngữ chuyên môn không phù hợp

1 bình luận

 
GN⁺ 2025-01-12
Các ý kiến trên Hacker News
  • “Một hệ thống phức tạp hoạt động được luôn luôn được phát hiện là đã tiến hóa từ một hệ thống đơn giản từng hoạt động. Một hệ thống phức tạp được thiết kế từ đầu sẽ không bao giờ hoạt động, và cũng không thể vá sửa để khiến nó hoạt động. Bạn phải bắt đầu lại với một hệ thống đơn giản hoạt động được”
    — John Gall (1975), Systemantics: How Systems Really Work and How They Fail
    https://en.wikipedia.org/wiki/John_Gall_(author)#Gall's_law

    • Vì vậy tôi luôn hoài nghi với ngôn ngữ và framework mới. Chúng có thể trông rất hay trên slide PowerPoint, nhưng sẽ ra sao trong các hệ thống phức tạp cần được duy trì lâu dài thì không rõ
      Thường thì các tính năng như những vết xước bắt đầu được gắn thêm để xử lý các trường hợp đặc biệt, và điều đó trông như tín hiệu rằng những ngoại lệ như vậy sẽ tiếp tục tăng vô tận
      Có một khác biệt tinh tế nhưng quan trọng giữa “áp dụng kinh nghiệm” và “thiết kế một hệ thống hoàn toàn mới xoay quanh một điều cá nhân thấy khó chịu”
  • Tôi có một giả thuyết khác. Khoảng 10% lập trình viên thực sự hiểu nguyên lý nên có thể bắt đầu thứ gì đó từ con số không, và khoảng 40% nữa có thể xử lý công việc hằng ngày bằng cách copy-paste từ code local, Stack Overflow, GitHub, LLM, đồng thời đại khái biết chuyện gì đang diễn ra
    50% còn lại thì không biết nhiều ngoài vài câu đố LeetCode, và cũng thiếu hiểu biết thực sự về những thứ họ copy-paste
    Với phân bố như vậy, rất có khả năng hơn một nửa Makefile chỉ là các mảnh copy-paste chạy tạm được. Nếu lấy từ nơi vốn đã chạy, thì trước mắt coi như xong việc và chuyển sang ticket tiếp theo
    Tôi không đổ lỗi cho bản thân công cụ. Makefile đã rất quen thuộc và cũng không dài dòng trong các dự án nhỏ. Nó có thể là lựa chọn tệ cho một con quái vật 10.000 file, nhưng tôi từng thấy Makefile gọn gàng ngay cả trong các dự án khổng lồ. Cá nhân tôi có lẽ sẽ không chọn nó đầu tiên, nhưng tôi thích Makefile và đã dùng lẻ tẻ hơn 30 năm

    • Tôi nghĩ nhiều khi người ta không biết là vì không có thời gian để tìm hiểu. Số trận có thể chiến đấu trong một ngày là có hạn
      Ví dụ, khi một lập trình viên C++ xử lý ticket thì cần biết đến bao nhiêu tầng của stack? Có cần biết cả tên thanh ghi CPU không? Một nhà nghiên cứu AI chỉ dùng Jupyter thì cần biết đến đâu? Việc học tối đa về công cụ và stack là đáng khuyến khích, nhưng thời gian thì có hạn
    • Dùng một Makefile rất đơn giản cho dự án 10.000 file thực ra là chuyện nhỏ. Phần lớn Makefile tôi thấy trong các dự án mã nguồn mở phức tạp hơn rất nhiều so với một Makefile tốt
      Nếu thấy trong Makefile có các rule riêng lẻ để tạo một file đơn lẻ, tôi hầu như luôn coi đó là sai lầm
      Thông thường chỉ nên có rule build tổng quát dùng để build tất cả file thuộc một kiểu nhất định
      Makefile hầu như không nên chứa danh sách file nguồn hay danh sách phụ thuộc, mà chỉ cần danh sách các thư mục chứa file nguồn
      Make nên tìm file bằng cách quét các thư mục nguồn, phân loại theo từng kiểu, tạo danh sách phụ thuộc và gọi rule build phù hợp. Ít nhất với GNU make thì việc này rất đơn giản và cũng có trong hướng dẫn sử dụng
      Nếu viết theo cách này, dù dự án có 1 file hay 10.000 file thì công sức tạo hoặc sửa Makefile đều nhỏ đến mức có thể bỏ qua. Cũng không cần cập nhật Makefile mỗi khi file nguồn được tạo, đổi tên, di chuyển hay xóa
    • Tôi thích Makefile nhưng chỉ dùng cho việc cá nhân. Mỗi khi tạo dự án cá nhân mới, tôi đều thêm Makefile ở thư mục gốc, dù target chỉ là một build cơ bản nhất của ngôn ngữ đó
      Vì mỗi ngôn ngữ và framework có “trình tự” build khác nhau nên tôi không thể nhớ hết. Nhưng $ make thì dễ
    • Tôi nghĩ có thể thiết lập một thứ và thực sự hiểu nó hoạt động như thế nào là hai chuyện khá khác nhau
      Tôi đồng ý rằng nhiều lập trình viên ứng dụng năng suất cao có thể không thiết lập được một dự án mới từ đầu, nhưng điều đó thường là vấn đề biết đúng các quy tắc ma thuật và câu thần chú để nhiều công cụ khớp với nhau, hơn là vấn đề hiểu biết sâu sắc
  • Một yếu tố khác tôi thấy ở nơi làm việc là các công cụ và hệ thống mà lập trình viên rồi cũng sẽ phải đụng đến lúc nào đó, nhưng thường cảm thấy không đáng để học
    Ví dụ như hệ thống build và cấu hình CI. Chúng là cần thiết, nhưng lập trình viên không nghĩ mình phải xử lý chúng hằng ngày. CI bị xem như một hệ thống “thiết lập rồi quên”, và phản ứng thường là liệu có cần học hết những thứ này chỉ để build ứng dụng không
    Lập trình viên kỳ vọng nó “cứ thế chạy”, và nếu có độ phức tạp thì cho rằng một đội khác, tức những người có vai trò như tôi, sẽ xử lý. Vì vậy mỗi lần lập trình viên phải chạm vào hệ thống này, họ có động lực rất mạnh để sao chép cấu hình lần cuối còn chạy được, chuyển nó sang, rồi quay lại với công việc “thực sự”
    Cách giải quyết tốt nhất là gặp lập trình viên ở khoảng giữa. Cần cung cấp công cụ đơn giản hoặc phức tạp phù hợp với công việc, có tài liệu đầy đủ, và giảm tối đa niềm tin rằng đó là “ma thuật”. Những công cụ như Make thường thất bại ở điểm này vì bị cảm nhận là quá phức tạp và giống hộp đen

    • Tôi nghĩ vấn đề lớn của cấu hình CI thường là thế này: chậm, độc quyền, xử lý các giá trị bí mật nên số người có thể làm việc với nó bị giới hạn, và nhìn chung không thể chạy cục bộ
      Vì thế vòng phản hồi trở nên cực kỳ dài, và bản thân công việc trở thành một nỗi khổ lớn
    • Luồng tốt nhất tôi từng thấy là dùng CI/CD như một lớp bọc thật mỏng quanh các script hoặc Makefile trong repository
      Nếu lập trình viên có thể chạy cục bộ một phần hoặc toàn bộ tác vụ “CI/CD”, họ có thể quan sát, kiểm soát và hiểu nó. Điều này giúp rất nhiều trong việc tạo cảm giác sở hữu và yên tâm, thay vì cảm giác “CI/CD là chuyện ở thế giới khác”
      Không phải lúc nào cũng hiệu quả. Tôi từng thấy một nhóm hai người có CI/CD dạng lớp bọc mỏng mà vẫn giả vờ đó là một quy trình ngoài hành tinh và từ chối động vào
    • Máy pha cà phê trong văn phòng cũng không phải thứ “thiết lập rồi quên”, nhưng ta không kỳ vọng mọi người dùng nó đều phải chia đều trách nhiệm bảo trì
      Tương tự, CI cần có quyền sở hữu, và cách để trách nhiệm rơi vào lập trình viên cuối cùng định dùng CI không phải là một cách làm việc hiệu quả
    • Make là một trong những công cụ build đơn giản nhất. So với những thứ như Grunt, Webpack, nó giống cái búa hơn là máy khoan khai thác
      Giải pháp là đừng mang công cụ mà các tập đoàn lớn dùng về chỉ vì các tập đoàn lớn dùng nó. Có thể là ý kiến không được ưa chuộng, nhưng tôi cho rằng CI/CD không cần thiết ở phần lớn nơi nó đang được dùng
      Ngay cả khi số bước tăng lên đôi chút, nên tìm cách build và triển khai với số bộ phận chuyển động ít nhất tuyệt đối. Sau đó hãy cân nhắc cẩn thận chi phí của việc tự động hóa phần nào. Đưa một hệ thống lớn vào chỉ để làm việc đơn giản thường không đáng về dài hạn
      Nếu thật sự cần CI/CD, bạn sẽ biết vì có điểm đau. Nếu hệ thống đó gây đau cho lập trình viên thì nó không phải công cụ phù hợp
    • Nếu thấy make “quá phức tạp và giống hộp đen”, thì tức là bạn chưa thấy cmake
  • Make và Makefile cực kỳ đơn giản nếu không phải do autoconf tự động tạo ra. Nếu là thứ autoconf tạo thì không nên sửa, vì đó là sản phẩm build. Nếu có thể thì tốt nhất cũng nên bỏ luôn autoconf
    Nhìn rộng hơn, hiệu ứng này thực sự tồn tại. Bạn có thể là nạn nhân của nó, cũng có thể tận dụng nó. Cách tận dụng là như sau: viết một ít mã hoặc copy-paste từ đâu đó, dùng thử trong dự án, rồi tinh chỉnh theo nhu cầu. Khi bắt đầu dự án tiếp theo, lại chép đoạn mã đó vào và chỉnh cho phù hợp với dự án thứ hai. Xem liệu có thể áp ngược các thay đổi về dự án ban đầu không. Khi cả hai đều chạy và được đồng bộ, hãy tách mã đó ra thành thư viện. Đôi khi cần thêm nhiều dự án nữa để tinh luyện nó thành hình hài giống một thư viện. Trường hợp tốt nhất là công bố mã nguồn mở để người khác cũng dùng được

    • Makefile cũng cực kỳ hạn chế. Cơ chế xác định độ mới dựa trên timestamp thường hỏng trong các hệ thống quản lý phiên bản hiện đại
      Vì Git không ghi timestamp nội bộ, mtime của file có thể được cập nhật dù nội dung giống hệt, và thực tế chuyện này xảy ra thường xuyên, gây ra các lần rebuild không cần thiết
      Nó cũng hoàn toàn không xử lý tốt các công cụ hiện đại có input hoặc output là cả thư mục, hoặc các công cụ mà trước khi chạy chưa thể biết tên output
      Tôi thích make, đã dùng tốt bất chấp các nhược điểm, và biết cả các cách lách lẫn cách lách của các cách lách đó. Nhưng một khi công cụ bắt đầu không khớp hoàn hảo với kỳ vọng của make, độ khó và độ phức tạp để tạo Makefile đúng sẽ tăng vọt rất nhanh
    • Makefile đơn giản nhưng rất thường bị viết sai. Viết một Makefile hoạt động đúng trong những tình huống không phải “build từ đầu” khó đến đáng ngạc nhiên
      Không đùa đâu. Việc tồn tại khái niệm make clean tự nó đã là bằng chứng quyết định
  • Makefile có lẽ là một phép ví dụ sai. Vấn đề mà phần lớn mọi người gặp với Makefile là họ viết nó quá hiếm. Họ có cảm giác chung về việc make làm gì, nhưng không có trí nhớ cơ bắp để viết từ đầu
    Dù vậy ý chính vẫn đúng. Tôi đã thấy rất nhiều mã copy từ web còn sót đầy mã chết không thực sự được dùng. Thói quen tốt là cứ xóa tiếp cho đến khi hỏng, rồi chỉ hoàn nguyên đúng phần bị hỏng đó. Nên xóa nhiều nhất có thể, và chắc chắn xóa hết những gì hiện không dùng

    • Tôi gặp cùng một vấn đề với rất nhiều công cụ như Makefile, cấu hình KVM, cấu hình Docker, pipeline CI/CD, v.v.
      Giải pháp từ trước đến nay là tạo một repository riêng chứa ghi chú và các chương trình ví dụ bằng shell script cho những công cụ, thư viện, framework này
      Mỗi khi phải dùng lại công cụ, tôi tham khảo ghi chú để gợi lại trí nhớ, và nếu học được điều mới thì cập nhật ghi chú. Giờ cũng có thể trỏ LLM vào repository đó rồi đặt câu hỏi
      Repository đó là dùng cá nhân và chứa thông tin về các công cụ có sẵn công khai. Kiến thức đặc thù của tổ chức thì tương tự nhưng được lưu trong repository riêng, và bị hủy khi hợp đồng với khách hàng hoặc nhà tuyển dụng kết thúc
  • Cách gọi đúng nhất cho chuyện này là phát triển kiểu sùng bái hàng viện trợ. “Cargo cult” xuất hiện ở Thái Bình Dương trong Thế chiến II: những cư dân bản địa trên đảo nhìn thấy các máy bay kỳ diệu chở thức ăn, rượu và vật tư đến; họ bắt chước hành vi của binh lính, làm máy bay bằng tre và thiết bị bằng dừa, rồi cầu xin các vị thần cảm động để hàng hóa lại đến
    Vấn đề là người dân trên đảo không hiểu khoa học đằng sau những thứ như máy bay, máy vô tuyến, súng
    Tương tự, lập trình viên kiểu sùng bái hàng viện trợ nhìn thấy kết quả có thể đạt được nhưng không hiểu các nguyên lý thứ nhất, nên bắt chước hành vi của các “tư tế cấp cao” trong công nghệ, hy vọng có thể sao chép thành công
    Vì vậy họ cứ lặp đi lặp lại việc sao chép, dán, thử, mày mò, tìm kiếm, kéo, đẩy, điều chỉnh, với hy vọng lần này nó sẽ tạm chạy được, ít nhất là trên một tập dữ liệu cụ thể vào tối thứ Ba

    • Tôi không xem đây là phát triển kiểu sùng bái hàng viện trợ. Cargo cult gần với việc bối cảnh rộng hơn đã biến mất, nhưng người ta vẫn bắt chước mà không hiểu những thực hành vốn chỉ hoạt động trong bối cảnh đó
      Thực tế là họ lặp lại những hành động hay nghi thức tự thân không có hiệu quả, trong khi mong nhận được kết quả mà một công ty khác từng đạt được khi thực hiện cùng nghi thức
      Điều bài gốc nói thì khác. Thứ được sao chép là , và bản thân nó có tác dụng. Ta có thể kiểm thử và phán đoán nó có chạy hay không
      Sự phân biệt này quan trọng. Vì triệu chứng của hiệu ứng Makefile trong bài gốc và cargo cult là khác nhau, nếu coi chúng là một thì sẽ khó chẩn đoán. Trong cargo cult, người ta lãng phí thời gian vào những việc thực sự không hoạt động vì mê tín. Trong hiệu ứng Makefile, thứ đó được chứng minh là hoạt động, nhưng các mảnh giống như cơ quan thoái hóa bị sao chép theo, khiến việc bảo trì ngày càng khó hơn
    • Tôi là tác giả bài viết. Nội dung này nằm trong chú thích 1
      Cụ thể, tôi không nghĩ nó hoàn toàn giống cargo cult. Cargo cult hàm ý thiếu hiểu biết. Nhưng bạn vẫn có thể hiểu rất rõ một hệ thống, song vì độ phức tạp nội tại của hệ thống đó thúc đẩy việc sao chép-dán, nên phần lớn thời gian bạn vẫn sống theo cách ấy. Đó là ý chính của bài
    • Tôi thường sao chép-dán những thứ chính mình đã viết trước đây. Đó là khi một công cụ quá phiền phức và chi phí chuyển đổi ngữ cảnh nhận thức quá khó gánh
      Thường thì tôi hiểu bên trong đang xảy ra gì, nhưng bản thân việc chuyển sang “chế độ” đó đã nặng về mặt nhận thức, nên nếu có thể thì tôi tránh
      Những công cụ thuộc loại này thường là công cụ vận hành như CI/CD, k8s, Docker: độ phức tạp rất lớn nhưng không phải vấn đề cốt lõi tôi đang giải. Make đặc biệt khó tránh chuyển ngữ cảnh, nên dạo này tôi thường né luôn
      Nó không liên quan đến thần chú kỳ diệu; tôi biết mình đang đánh đổi gì. Dù vậy vẫn có rủi ro biến thành hiệu ứng Makefile
    • Trong bài cũng có đề cập phần nào ở chú thích 1:
      “Hiệu ứng Makefile giống với các hiện tượng khác như cargo cult, bình thường hóa sai lệch, ‘ngôn ngữ chỉ-ghi’. Trong bài này, tôi sẽ lập luận rằng nó hơi khác từng hiện tượng đó ở chỗ nó không nhất thiết kém hiệu quả hay xấu về bản chất, mà là hệ quả của một thiết kế cụ thể”
    • Tôi cảm thấy mức độ hiểu biết lập trình của mình gần với giai đoạn “mới bắt đầu trong số những người mới bắt đầu”. Vậy có phải để tránh tư duy “cargo cult” thì cần một luồng có cấu trúc như giáo dục → học tập → thực hành → thất bại → lặp lại không?
      Nếu vậy, nếu ai đó thật sự muốn “thoát khỏi hòn đảo và lái máy bay”, rốt cuộc đại học có phải con đường gần với “thật” nhất không?
      Tôi biết khó nói tuyệt đối, có nhiều ngoại lệ, và mỗi người có đủ kiểu biện minh “tôi không làm được việc đó”. Ở đây tôi hỏi từ góc nhìn lý thuyết tối ưu. Con đường tối ưu để tránh hành vi sùng bái là hiểu toàn bộ, và “toàn bộ” đó chẳng phải đến từ giáo dục bậc cao sao?
      Về mặt logic, ngay cả khi chăm chỉ học bằng sách để bắt kịp hoặc vượt qua “tính hoàn chỉnh” của đại học, thì ở một khía cạnh nào đó nó vẫn có vẻ thiếu so với thời gian ở lớp học cùng các nhà giáo có tri thức. Ngay cả giả sử cùng một người nỗ lực như nhau ở cả hai phía
  • Một yếu tố khác là tần suất sử dụng. Tôi viết một tài liệu lớn bằng LaTeX không quá một lần mỗi năm
    LaTeX ở mức tôi dùng không phải công cụ khó, nhưng nếu mỗi năm chỉ dùng vài tuần thì không thể nào nhớ được các chi tiết cách dùng, nên tôi thường bắt đầu tài liệu mới bằng cách sao chép-dán từ tài liệu cũ

    • Với những công nghệ dùng tương đối thường xuyên như Makefile, shell script, tôi cố học để tránh “hiệu ứng Makefile”
      Nhưng với LaTeX, dù trước đây tôi đã dùng rất nhiều, tôi luôn sao chép-dán từ template. Bài trình bày beamer và hình TikZ còn tệ hơn: tôi sao chép từ bài trình bày hoặc hình trước đó thay vì từ template
      TikZ thì tôi nghĩ bản thân công cụ vốn phức tạp và tôi chưa học đủ
      LaTeX thì tôi nghĩ mình đã học đủ, nên có thể có lý do khác
      Theo tôi, đó có thể là vấn đề giá trị mặc định hợp lý. Một công cụ tốt nên cung cấp các mặc định tốt. Nhưng LaTeX không phải công cụ tốt theo tiêu chí này. Tài liệu của tôi thường bắt đầu kiểu như sau
      \documentclass[paper=a4, DIV9, 12pt, abstracton, headings=normal,  
      captions=tableheading]{scrartcl}  
      \usepackage[T1]{fontenc}  
      \usepackage[utf8]{inputenc}  
      \usepackage[english,german,ngerman]{babel}  
      \usepackage[english,german]{fancyref}  
      % ...  
      \usepackage{microtype}  
      \usepackage{hyperref}  
      
      Phần lớn là để có hỗ trợ mặc định hợp lý cho ký tự không phải ASCII cần cho tiếng mẹ đẻ của tôi, hoặc bật các mặc định bình thường như giấy A4, microtype. Với các công cụ hiện đại như pandoc/Markdown thì có thể không cần
      Vì vậy mục đích của việc sao chép-dán những thứ như vậy thường là để có được các mặc định tốt mà một công cụ tốt hơn lẽ ra đã cung cấp ngay từ đầu
    • Tôi dùng LaTeX thường xuyên hơn, nhưng tôi cũng bắt đầu bằng phần header sao chép-dán. Trong đó có các gói cần cho ngôn ngữ của tôi (fontenc, babel, gói dàn trang cục bộ), các gói gần như luôn cần như graphicx/fancyhdr/hyperref/geometry, cùng các định nghĩa ký hiệu và tên hữu ích trong lĩnh vực của tôi
      Nếu không viết toán hoặc không chỉ viết văn bản thuần tiếng Anh, thì LaTeX gần như là “không kèm pin”
  • Đây là phát triển dẫn dắt bởi copy-paste [0], và cũng không phải câu chuyện chỉ liên quan đến Makefile. Nó liên quan đến việc cả ngành sao chép code khắp nơi mà không hề biết mình đang sao chép cái gì
    Thành thật mà nói, tôi nghĩ Copilot đã làm chuyện này tệ hơn. Vì mọi người đang nhắm mắt chấp nhận những khối code vào codebase
    [0] https://andrew.grahamyooll.com/blog/copy-pasta-driven-develo...

    • Nên trách những người phía kinh doanh. Tôi đã cố gắng liên tiếp ít nhất 7 lần để trở thành chuyên gia về make, nhưng chưa bao giờ được dành thời gian xử lý nó hằng ngày cho đến khi thuộc nằm lòng hoàn toàn
      Đến một lúc nào đó tôi chỉ bỏ cuộc. Nó trở thành thứ tri thức bí truyền khó hiểu, không thể tạo được trí nhớ cơ bắp, và mỗi khi cần lại phải học lại từ đầu. Vì vậy tôi chuyển sang công cụ đơn giản hơn
      Sự mất mát của deep work không phải lỗi của những lập trình viên giỏi, mà là lỗi của những người phía kinh doanh
  • Tôi đã thấy quá nhiều trường hợp sao chép nguyên Makefile từ dự án khác rồi chỉnh cho “chạy được”, trong khi vẫn để nguyên các bước build và target thừa, hoàn toàn không liên quan
    Cá nhân tôi thấy điều này rất khó chịu

    • Nếu hoàn toàn không có tài liệu, làm sao biết cái gì liên quan và cái gì không?
      Bằng thử-sai à? Vậy thì chúc vui nhé :p
  • Đúng là có nhiều công cụ phức tạp hơn mức cần thiết, nhưng tôi không nghĩ bản thân Make là ví dụ phù hợp cho điều đó
    Với các công cụ hiện đại, vấn đề độ phức tạp thường bị làm trầm trọng hơn bởi tài liệu thiếu sót, tài liệu kiểu cookbook, tài liệu không giải thích mô hình khái niệm cần thiết để suy luận công cụ hoạt động ra sao, và tài liệu không có đặc tả đủ chi tiết và chính xác
    Make thì không như vậy. Tài liệu của nó tốt, và nếu thật sự dành thời gian đọc tài liệu thì không khó hiểu
    Cách tiếp cận kiểu cookbook ở trên dẫn đến một văn hóa xem nhẹ tầm quan trọng của việc học và hiểu công cụ mình dùng, cũng như tầm quan trọng của tài liệu kỹ lưỡng để làm được điều đó. Hoặc cũng có thể quan hệ nhân quả là ngược lại
    Dù sao thì tôi nghĩ vấn đề nằm ở chỗ chúng ta dành quá ít thời gian để tạo tài liệu công cụ toàn diện và cập nhật, cũng như chưa đủ chú ý thiết kế công cụ sao cho việc viết tài liệu như vậy là khả thi ngay từ đầu, và phân bổ quá ít nguồn lực cho việc dạy và học các công cụ cần thiết