4 điểm bởi GN⁺ 2023-10-07 | 1 bình luận | Chia sẻ qua WhatsApp
  • Bài keynote của Julia Evans tại Strange Loop bàn về vì sao những kỹ năng trông có vẻ “cơ bản” như DNS, Bash, HTTP, SQL lại khó và cách hạ thấp rào cản học tập
  • Cái khó của Bash nằm ở chỗ có rất nhiều ngoại lệ và cạm bẫy nhỏ, chẳng hạn set -e bị vô hiệu hóa trong lời gọi hàm bên trong điều kiện ||, và nhiều người chỉ thỉnh thoảng mới dùng Bash nên khó nhớ chính xác
  • HTTP và SQL có độ phức tạp ẩn sau bề mặt đơn giản, như trình duyệt được triển khai với quy mô 20 triệu dòng mã, rất nhiều header và flag, hay sự khác nhau giữa thứ tự viết SQL và thứ tự thực thi, khiến gánh nặng học tập tăng lên
  • Với DNS, thư viện, bộ nhớ đệm và việc giao tiếp với authoritative nameserver không dễ thấy đối với người dùng, còn đầu ra của dig cũng phức tạp, nên các công cụ và phần trình diễn giúp lộ rõ hành vi bị ẩn là rất quan trọng
  • Hỗ trợ học tốt gồm việc chia sẻ công cụ và tài liệu tham khảo, rút các danh sách lớn thành những danh sách nhỏ thực sự dùng tới, giải thích những gì máy tính làm theo trình tự thời gian, và cùng chia sẻ cả các câu chuyện thất bại lẫn bản ghi lỗi

Vì sao những công nghệ trông như “cơ bản” lại mất nhiều thời gian để học

  • Keynote tại Strange Loop Making Hard Things Easy nói về cách khiến những công nghệ khó học trở nên dễ hơn
  • Điểm khởi đầu là DNS
    • Việc tìm địa chỉ IP của một tên miền trông có vẻ đơn giản, nhưng diễn giả nói rằng ngay cả sau 7 năm học DNS, cô vẫn gặp rắc rối khi cấu hình website, và tính tổng thể thì mất khoảng 10 năm
    • Bạn bè cô cũng lặp đi lặp lại cùng những vấn đề đó, và nhiều người tiếp nhận nó như một vấn đề cá nhân kiểu “lẽ ra mình phải hiểu rồi”
  • Để viết dễ hiểu hơn về những chủ đề như vậy, diễn giả đã bắt đầu một nhà xuất bản nhỏ tên là Wizard Zines, lấy Bash, HTTP, SQL và DNS làm ví dụ

Bash: những ngoại lệ khó nhớ nên để công cụ lo

  • Bash là một ngôn ngữ lập trình, nhưng trong số các ngôn ngữ mà diễn giả dùng thì nó có khá nhiều hành vi kỳ quặc
  • Trong ví dụ script, dù mv ./*.txt /tmmpp thất bại, Bash mặc định vẫn không dừng lại mà chạy echo "success!"
    • Có thể dùng set -e để khiến nó dừng khi gặp lỗi
    • Nhưng nếu gọi hàm bên trong điều kiện || như f || echo "failed!" thì set -e sẽ bị vô hiệu hóa trên toàn cục bên trong hàm, nên lại in ra success
    • Hành vi này không phải bug của Bash mà là hành vi đã được tài liệu hóa
  • Một lý do Bash khó là nhiều người chỉ viết Bash script 6 tháng một lần rồi lại không động tới nữa
    • Nếu một hệ thống ít dùng lại đầy kiến thức vặt và cạm bẫy thì rất khó dùng cho đúng
  • Phản ứng kiểu “không ai dùng được Bash đâu” không đúng với thực tế
    • Rất nhiều người vẫn dùng Bash, và dù không hoàn hảo, nó vẫn thường giải quyết được công việc
    • Mục tiêu là đưa người đang đứng trước cả một đống cạm bẫy choáng ngợp sang trạng thái “dùng tương đối đúng được”
  • ShellCheck là công cụ ghi nhớ thay con người những cạm bẫy Bash khó thuộc và đưa ra cảnh báo
    • shellcheck -o all bad-again.sh sẽ hiện cảnh báo SC2310, cho biết set -e bị vô hiệu hóa trong hàm được gọi từ điều kiện ||
    • Kiểm tra này chỉ hiện ra khi chạy với -o all
    • Những công cụ như vậy giúp máy tính gánh phần kiến thức vặt, giảm tải nhận thức

Chuyện thất bại giúp ra quyết định hơn là “best practice”

  • Kể cả khi không tự tạo công cụ, việc giới thiệu các công cụ hữu ích mình đang dùng cho bạn bè hay đồng nghiệp vẫn rất quan trọng
    • Diễn giả cũng biết đến ShellCheck khá muộn, và nói rằng cô đã bực vì hóa ra bấy lâu nay không cần phải nhớ mọi thứ trong đầu
  • Chia sẻ cạm bẫy và các câu chuyện thất bại gần như là một dịch vụ cộng đồng
    • Ví dụ set -e bị vô hiệu hóa trong Bash là điều cô học được từ trải nghiệm mà người bạn Jesse kể vài tuần trước
    • Biết về thất bại của người khác giúp tránh cùng vấn đề mà không cần tự mình vấp phải
  • So với những ý kiến mạnh kiểu “không ai nên dùng Bash”, các câu chuyện về việc Bash thực sự đã gây ra vấn đề gì hữu ích hơn
    • Nghe cùng một câu chuyện, có người sẽ quyết định dùng ShellCheck và tiếp tục duy trì những Bash script đơn giản
    • Người khác có thể quyết định không muốn dùng Bash nữa
    • Phản ứng khác nhau trước cùng một ví dụ là điều hoàn toàn ổn

HTTP: phải hiểu với tiền đề là một trình duyệt 20 triệu dòng mã

  • HTTP response có thể trông như một cấu trúc đơn giản gồm status code, header và body
  • Nhưng câu hỏi “vì sao phải đặt header này?” sẽ nhanh chóng dẫn tới hành vi của trình duyệt
    • Firefox có khoảng 20 triệu dòng mã
    • Trình duyệt đã tiến hóa từ thập niên 1990, và mô hình bảo mật cũng liên tục thay đổi theo các cuộc tấn công và biến chuyển của web
  • Muốn hiểu vì sao một chủ đề khó, cần xem phía sau nó có một codebase khổng lồ hay không
    • Không chỉ riêng HTTP mà còn có cả CSS, JS..., nhưng độ phức tạp của trình duyệt hiện đại giúp giải thích rào cản học HTTP
  • Các danh sách lớn cần được rút xuống thành danh sách nhỏ để dễ hiểu hơn
    • Danh sách HTTP request header có hơn 43 mục, chưa kể cả các header không chính thức
    • Trong truyện tranh về HTTP request headers, diễn giả nói về 15 header mà cô biết và dùng
    • “Các header quan trọng nhất” không phải danh sách khách quan, mà là danh sách chủ quan dựa trên những gì bản thân biết và sử dụng
    • Ví dụ, chỉ cần biết rằng đặt Accept-Encoding thành gzip thì có thể nhận response nén là thường đã đủ
  • Có thể tiếp cận các công cụ dòng lệnh theo cách tương tự
    • Man page của grep có rất nhiều flag, nhưng ngay cả sau 20 năm dùng grep, diễn giả cũng không biết hết
    • Người có kinh nghiệm nói “trong hệ thống này tôi biết 7 cái, và đây là chúng” sẽ rất có ích cho người mới
    • Một người có kinh nghiệm khác có thể biết 7 cái khác nữa

Tài liệu tham khảo nên chia sẻ trung thực những gì thực sự dùng

  • Với những thông tin không thể nhét hết vào đầu, cần có tài liệu tham khảo tốt
  • Diễn giả nói rằng dù học CSS ngắt quãng suốt 20 năm, mãi khoảng 2 năm gần đây cô mới biết đến CSS-Tricks, và giá mà biết sớm hơn thì đã hữu ích hơn nhiều
    • Có vẻ như sau khi được mua lại, CSS-Tricks đã ngừng đăng bài mới từ tháng 4, nhưng các bài cũ vẫn còn hữu ích
  • Với HTTP, cô dùng Mozilla Developer Network rất nhiều
  • Tài liệu tham khảo chính thức cho HTTP là RFC 9110, 9111, 9112, 9113, 9114, được viết năm 2022
    • Có thể tra các chi tiết như hành vi chính xác của header Connection
    • Tài liệu tham khảo chính của diễn giả thường là MDN, nhưng cô đánh giá cao việc các RFC chính thức được tổ chức khá tốt
  • Khi chia sẻ tài liệu tham khảo, cần phân biệt giữa việc chia sẻ vì nó trông “ngầu” và việc chia sẻ thứ mình thực sự dùng trong công việc
    • Trên thực tế, kể cả khi dùng những tài liệu “trông kém ngầu” hơn như w3schools, điều quan trọng là nói trung thực về việc mình có thực sự dùng hay không

SQL: nói theo trình tự thời gian về những gì máy tính làm

  • SQL có thể gây rối cho người mới vì thứ tự viết query khác với thứ tự thực thi theo khái niệm
  • Mô hình tinh thần về SQL mà diễn giả dùng là theo thứ tự sau
    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • SELECT
    • ORDER BY
    • LIMIT
  • Database thực tế còn phức tạp hơn do có tối ưu hóa, nhưng mô hình theo trình tự thời gian này vẫn hữu ích trong phần lớn trường hợp
    • Nó gần giống thứ tự viết trong query, chỉ khác là SELECT đứng thứ năm
  • Cách hỏi “máy tính thực sự làm gì trước tiên?” có thể áp dụng cho nhiều chủ đề khác
    • Với CORS, có thể viết ra mọi giao tiếp giữa trình duyệt và server theo thứ tự thời gian để hiểu
    • Diễn giả lấy truyện tranh về CORS làm ví dụ cho cách này
  • Giải thích theo trình tự thời gian nghe thì đơn giản nhưng thực ra khá khó, nên rất hữu ích cho cộng tác
    • Behind Hello World on Linux nói về những gì xảy ra khi chạy “hello world” trên Linux
    • Diễn giả cũng từng viết một bài tương tự cách đây 10 năm, nhưng bài năm 2023 dài hơn khoảng 6 lần
    • Không phải vì Linux trở nên phức tạp hơn, mà vì vào năm 2013 cô còn hiểu ít hơn về chuyện gì đang xảy ra theo trình tự thời gian
  • Trong team cũng vậy, nếu cùng nhau lập timeline theo thứ tự thời gian về điều gì xảy ra khi một request đến API endpoint, mọi người có thể nối ghép phần hiểu biết của mình với nhau

DNS: phải làm lộ hệ thống bị ẩn thì mới hình thành trực giác

  • DNS là một cấu trúc nơi trình duyệt, hàm thư viện gửi DNS request, bộ nhớ đệm và authoritative nameserver cùng hoạt động
  • Vấn đề là nhiều phần trong số đó bị ẩn khỏi người dùng
    • Không dễ tìm ra đoạn mã thư viện nào đang gửi DNS request
    • Dữ liệu trong cache khó kiểm tra và người dùng cũng không kiểm soát được
    • Giao tiếp giữa cache và authoritative nameserver cũng không nhìn thấy được
  • Diễn giả cùng người bạn Marie đã tạo một DNS server nhỏ tên là Mess With DNS
    • Người dùng có thể tạo DNS record cho domain của mình
    • Mỗi khi có request từ resolver đến, nó sẽ hiển thị message nào đã đi vào
    • Trong demo ở Strange Loop, họ tạo một CNAME record cho tên strangeloop trỏ đến orange.jvns.ca, và xác nhận rằng DNS resolver ở Canada mà trình duyệt dùng đã request cả bản ghi A lẫn AAAA
  • Một ví dụ khác về việc cho thấy thứ bị ẩn là float.exposed
    • Có thể thay đổi significand và exponent trong số thực dấu phẩy động 32-bit để thấy số thực kế tiếp và khoảng cách giữa chúng thay đổi thế nào
  • Một lý do khác khiến DNS khó là vì nó là một hệ thống phân tán khổng lồ
    • Diễn giả nói kiểu như “có thể liên quan đến hơn 5 triệu máy tính”, phần lớn trong số đó người dùng không kiểm soát được, và một số có thể hoạt động khác với kỳ vọng

Khi đầu ra của công cụ như dig trở thành rào cản học tập

  • Đầu ra của các công cụ DNS cũng có thể làm tăng sự rối rắm
  • dig có flag +norecurse
    • Có thể yêu cầu resolver chỉ trả về kết quả đã có sẵn trong cache
    • dig +norecurse jvns.ca có thể được dùng theo kiểu kiểm tra xem resolver đó có cache domain này trong 5 phút gần đây hay không
  • Đầu ra của dig có thể khiến người mới có cảm giác bản thân DNS còn phức tạp hơn nữa
    • Diễn giả cho rằng điều này gần giống hệ quả của một định dạng đầu ra tương đối tùy tiện được quyết định từ thập niên 1990 rồi giữ nguyên rất lâu
  • “eraser eyes” là cách nhìn vào đầu ra phức tạp mà chỉ giữ lại phần mình thực sự cần xem, còn lại thì bỏ qua như thể đã xóa đi
    • Trong ví dụ, chỉ tập trung vào response code SERVFAIL
    • Theo cách hiểu của diễn giả, trong ngữ cảnh này SERVFAIL gần với nghĩa “không có trong cache”
  • Khi demo công cụ, việc nói rõ nên nhìn phần nào của đầu ra hay UI và nên bỏ qua phần nào sẽ giúp việc học dễ hơn
    • dig có đầu ra khá thô, nhưng ưu điểm là nhiều tính năng, hỗ trợ +norecurse, có mặt ở khắp nơi, và ổn định vì ít thay đổi trong thời gian dài

Những vai trò cùng nhau làm mọi thứ dễ hơn

  • Việc khiến công nghệ trở nên dễ hơn vẫn có thể được chia sẻ với người xung quanh, kể cả khi không có blog
  • Các cách mà diễn giả tổng kết gồm
    • Chia sẻ công cụ hữu ích
    • Chia sẻ tài liệu tham khảo mình thực sự dùng
    • Nói về những gì xảy ra trong máy tính theo trình tự thời gian
    • Rút danh sách lớn thành danh sách nhỏ mà bản thân thực sự dùng
    • Cho thấy các hành vi bị ẩn
    • Demo các công cụ gây rối và chỉ ra mình nhìn phần nào
  • Các kiểu người giúp đỡ cũng rất đa dạng
    • “Người dùng cũ hay càm ràm” kể lại trước đây đã có gì sai, giúp người khác bớt khổ
    • “Người mới ồn ào” hỏi “cái này hoạt động thế nào?”, khiến người khác cũng thấy nhẹ nhõm hơn
    • Khi senior developer công khai hỏi về điều mình chưa biết, những người sợ bị đánh giá là không biết cũng có thể học cùng
    • “Người ghi chép bug” tổng hợp lại chuyện gì đã xảy ra để cùng một bug không lặp lại
    • “Người làm công cụ” viết code để biến vấn đề thành dễ lâu dài thay vì phải giải thích lặp đi lặp lại
    • “Người chia sẻ điều học được hôm nay” lan tỏa công cụ mới, bug đã gặp, hay tính năng thư viện vừa biết
    • “Người mở 700 tab” có thể đã biết tìm thông tin ở đâu
    • Cũng cần cả “người trả lời câu hỏi” lẫn “người ghi lại để sau này tìm được”
  • Việc thấy khó với những thứ trông có vẻ cơ bản không phải là vấn đề cá nhân của riêng ai
    • Rất nhiều người gặp khó ở cùng những điểm đó vì cùng những lý do giống nhau
    • Nếu xác định được nguyên nhân của cái khó, ta có thể sửa nó tốt hơn, giống như sửa bug trong chương trình máy tính
  • Những yếu tố tạo ra độ khó gồm lượng lớn kiến thức vặt và cạm bẫy, 20 triệu dòng mã, các hệ thống bị ẩn, và đầu ra công cụ rối rắm chưa được cải thiện
  • Diễn giả nói rằng cô vẫn chưa thực sự hiểu vì sao Git lại khó, nhưng vẫn muốn tiếp tục suy nghĩ và tìm hiểu về chủ đề đó

1 bình luận

 
GN⁺ 2023-10-07
Các ý kiến trên Hacker News
  • Phần gây ấn tượng nhất với tôi là câu hãy cho thấy những gì thường bị ẩn đi
    Những công cụ như vậy gần như lập tức làm tình hình trở nên rõ ràng hơn. Hãy nghĩ đến developer tools của trình duyệt web: trong “thời kỳ đen tối” khi chưa có chúng, thật kinh khủng vì ta không nhìn thấy chuyện gì đang xảy ra mà phải đoán mò
    Những công cụ như Wireshark, hiển thị các byte của gói mạng có thể truy cập và còn phân tích cả cấu trúc, rất hữu ích không chỉ để debug mạng mà còn để dạy các khái niệm mạng, vì chúng không che giấu gì cả
    Tôi cũng thích phần mềm mã nguồn mở vì lý do đó. Không có gì bị che giấu: ta có thể xem source để hiểu nguyên nhân bug, lấp những khoảng trống kiến thức mà tài liệu để lại, hoặc học thêm các khái niệm lập trình

    • Trong lĩnh vực phát triển game, công cụ tương ứng là renderDoc. Khi lần đầu biết nó tồn tại, tôi thật sự rất kinh ngạc
    • Wireshark rất tuyệt, nhưng nó không hiển thị mọi byte mà mạng đã mang đi
      Ví dụ, nó không bao giờ hiển thị Ethernet preamble, chỉ thỉnh thoảng hiển thị Ethernet frame checksum, và cũng không bao giờ hiển thị inter-frame gap, vốn là thành phần thiết yếu của giao thức Ethernet
      Dù đã rất gần rồi, điều đó vẫn cho thấy ở đâu đó luôn còn nhiều chi tiết hơn đang bị ẩn
    • Ước mơ là làm cho mọi thứ đều có thể trực quan hóa lúc runtime. Nếu làm được như vậy, tôi nghĩ toàn bộ lĩnh vực điện toán sẽ trở nên rất đơn giản và bớt phức tạp hơn nhiều
      Trong đầu chúng ta vốn đã trực quan hóa rồi, và bất kỳ lời giải thích nào về điện toán cuối cùng cũng được biểu diễn bằng sơ đồ. Nhưng khi coding thì lại hoàn toàn không có sơ đồ
      Chỉ cần instrument toàn bộ code một cách động và gửi message tới GUI là được
    • Trái với những câu như “hãy cho thấy những gì thường bị ẩn đi” và “những công cụ như vậy gần như lập tức làm tình hình rõ ràng hơn”, các công cụ DevOps ngày nay dường như lại đang che giấu ngày càng nhiều thứ
      Những chuyên gia từng có kiến thức đó và có thể truyền dạy nó giờ cũng tập trung ở các công ty làm những công cụ ấy, chứ không còn ở trong tổ chức nữa
    • Điều tôi thích ở Magit cho Emacs chính là điểm này. UI thật sự thông minh và mượt mà, có lẽ là Git frontend tốt nhất tôi từng dùng, nhưng cách tương tác với UI lại là bật/tắt các flag và option ánh xạ tới các đối số dòng lệnh Git thật sự bên trong
      Vì vậy khi chuyển tự nhiên sang dòng lệnh, bạn có thể dùng trực tiếp ngay một cách quen thuộc
  • Julia có vẻ là một trong những người dễ mến nhất trong giới công nghệ
    Mỗi lần đọc bài của cô ấy, tôi lại cảm thấy sự háo hức phấn khích như hồi nhỏ, khi bắt đầu mở khóa những bí mật của thực tại bằng các thí nghiệm nho nhỏ. Thật sự rất đáng yêu

    • Hiếm có người vừa có kiến thức kỹ thuật sâu, vừa có khả năng giáo dục và giao tiếp xuất sắc. Một người khác tôi nghĩ đến là Andrej Karpathy
      May mắn là gần đây tôi đang phát hiện thêm nhiều người phù hợp với kiểu này
    • Trong khoảnh khắc tôi tưởng đang nói về ngôn ngữ Julia :)
    • Rất đồng cảm. Bình thường tôi không thích lắm những bài blog hay tutorial phấn khích quá mức kiểu “omg awesomesauce”, và thích văn phong kiểu Landau&Lifschitz hơn nhiều: khô, tỉ lệ tín hiệu trên nhiễu cao, súc tích và đẹp
      Nhưng tất cả bài viết của Julia đều khiến tôi cảm nhận được sự phấn khích đã nói ở trên
    • Gặp ngoài đời cũng thật sự đáng yêu. Tôi đã xin cô ấy ký vào cuốn How DNS Works của tôi
  • Tôi nghĩ câu “khi người mới nói ‘cái này khó’, người có kinh nghiệm nói ‘đúng, bash không dùng được đâu. Chẳng ai thật sự hiểu nó cả’” không phải là điều nên hiểu theo nghĩa đen
    Ý của nó gần hơn với “chúng ta không có mức độ hiểu biết cao về đoạn bash code mình đã viết, cũng không có niềm tin mạnh rằng nó sẽ hoạt động như mong đợi trong các tình huống chưa được test”
    Nghĩa là hễ có chuyện gì hơi khác thường xảy ra, ta phần nào dự đoán rằng thứ gì đó sẽ hỏng, và một sự thật mới học được về bash sẽ khiến ta rùng mình hoặc đập mạnh đến mức làm hỏng đồ vật gần đó
    Bash là một ngôn ngữ phức tạp, và với đa số lập trình viên, nó hoàn toàn khác với các ngôn ngữ khác mà họ thường dùng. Phần lớn công ty đều có đâu đó một ít bash trong production, nhưng thường không có ai dùng nó đủ nhiều để thật sự rành
    Tôi không nghĩ việc các build tool, CI tool và cloud orchestration tool tiến hóa theo hướng giảm nhu cầu shell scripting là chuyện ngẫu nhiên

    • Tôi nghĩ độ phức tạp của các công cụ như bash đến từ thiếu tiến hóa
      Thử một thí nghiệm tư duy: chẳng lẽ không thể thêm một câu lệnh gán tốt hơn vào bash sao? Ví dụ, nếu trong một chế độ kiểu set --goodass có thể viết a = string1 + '.' + string2, ta có thể cắt bỏ phần lớn xử lý quoting của shell
      Các công cụ như make cũng sẽ được lợi. Nếu dành 6 tháng để tạo ra biến dùng được, cách rõ ràng để thao tác đường dẫn và tên file, và target hữu dụng hơn cho make, có khi còn tốt hơn là mất 6 tháng tạo các Makefile phức tạp
    • Vấn đề là người mới có hiểu được ý ngầm đó không, hay sẽ hiểu theo nghĩa đen hơn mức người nói định truyền đạt
      Đặc biệt, cảm giác rằng “với đa số lập trình viên, bash khác với bất kỳ ngôn ngữ nào họ thường dùng” không phải là thứ người mới nhất thiết có thể suy luận ra. Vì cần có đủ kinh nghiệm để biết khác biệt giữa “không phổ biến” và “cực kỳ khó hiểu”
  • Liên quan đến chuyện này, phần lớn phần mềm đều bị thiết kế quá mức
    Tôi nghĩ một phần cũng là do sự tập trung hóa trong ngành. Tất cả bị đẩy vào một số ít công cụ để mang lại lợi ích cho một số ít người kiểm soát chúng, và kết quả là nhiều công cụ trở thành “công cụ cho mọi thứ”, bao phủ nhiều hơn rất nhiều so với các use case mà chúng phải xử lý
    Các công ty muốn developer đều biết cùng một bộ công cụ. Như vậy họ dễ thay thế giữa các dự án và công ty, đồng thời sức thương lượng của họ trong ngành yếu đi
    Vì thế phần mềm chỉ còn một nhánh chủ lưu, còn các cách tiếp cận thay thế thì bị gạt ra ngoài và không có việc làm. Dù ngành này vốn tự nhiên muốn phân tán, nó lại không thể trở thành như vậy
    Nhìn tích cực thì một ngày nào đó, các cách tiếp cận phi chủ lưu vượt trội hơn nhiều sẽ xuất hiện và ăn dần cách tiếp cận chủ lưu. Công nghệ không phải toán học và cũng khác khoa học; nó hoàn toàn có thể chống đỡ nhiều nhánh giải quyết cùng một vấn đề theo nhiều cách khác nhau

    • Đồng ý. Ở một khía cạnh nào đó, web development thậm chí còn có cảm giác thụt lùi so với thời kỳ ASP.NET hay Rails ban đầu
      Khi đó browser wars khiến chúng ta bận rộn, nhưng giờ các trình duyệt nhìn chung đã tương thích, vậy mà chúng ta lại tạo ra cả đống độ phức tạp frontend cho web app vốn đa phần là không cần thiết
      Những thứ như DNS, IP, HTTPS thì là công nghệ nền tảng có liên quan đến tương thích ngược và yếu tố chính trị nên không tránh được
      Dù vậy, tôi vẫn cảm thấy học kỹ những thứ đó là khoản đầu tư tốt hơn so với học framework. Nói thêm nữa chắc sẽ dẫn tới chuyện innovation tokens
  • Muốn biến điều khó thành dễ, cần tìm được sự trừu tượng hóa phù hợp. Tức là chỉ giữ trong đầu một phần nội dung khó và những chi tiết thường dùng, phần còn lại thì khi cần mới tra cứu
    Vấn đề là con người thường không chủ động tạo ra một dạng nén nhận thức cho một chủ đề lớn cho đến khi thật sự cần. Vì họ vốn đã gánh những tải nhận thức lớn khác, nên họ kháng cự việc thêm một gánh nặng mới
    Nếu có thể dựa vào người khác hiểu rõ một chủ đề X nào đó thì cứ làm vậy, và có thể không cần cố gắng để biết đủ về X. Cách tốt nhất để người hiểu rõ X giảm bớt các yêu cầu nhờ giúp đỡ là giúp người khác hiểu mức tối thiểu về X
    set -e bị hỏng, nhu cầu phải đặt mọi thứ trong dấu nháy cũng hỏng, và globbing lẽ ra phải là một tính năng chỉ hoạt động khi được yêu cầu rõ ràng. Trên dòng lệnh thì có thể phiền, nhưng trong script lại là chuyện khác; hiện nay nếu tắt globbing toàn cục thì rất khó glob ở những chỗ mình muốn
    Những mặc định tệ như vậy không chỉ có ở Bash, mà có trong Ksh và các shell thuộc dòng Bourne shell nói chung
    Với SQL cũng có nhiều người muốn đổi thứ tự các mệnh đề. Không có lý do gì không làm được, và có vẻ chỉ là một thay đổi tương đối nhỏ để các parser SQL hiện có cho phép mệnh đề theo thứ tự khác
    Tuy nhiên cá nhân tôi không gặp vấn đề nhận thức này, có lẽ vì tôi biết phải nhìn nguồn bảng trước

    • Ba cái bẫy: set -e bị hỏng, phải đặt mọi thứ trong dấu nháy, và globbing nên là tường minh, đều được OSH sửa trong khi vẫn chạy được các shell script hiện có
      Chỉ cần thêm shopt --set ysh:upgrade vào đầu script là ba vấn đề đó biến mất
      Nếu muốn giúp dự án, hãy tải tarball xuống, kiểm chứng các tuyên bố đó và viết một bài blog
      Chi tiết có tại https://www.oilshell.org/release/latest/doc/error-handling.h...https://www.oilshell.org/release/latest/doc/simple-word-eval...
      Tài liệu khá toàn diện, nhưng đa số người dùng không muốn mức chi tiết như vậy, nên nếu có ai đó thử nghiệm và viết ngắn gọn lại thì sẽ rất hữu ích
      Lý do tôi đã không tích cực thúc đẩy Oils trong một thời gian là vì nó có phụ thuộc Python; nhưng giờ đây nó là C++ thuần, và tính đến tuần này đã vượt bash trong một số benchmark thiên về tính toán
      Các script thiên về nhập/xuất thì luôn có tốc độ tương đương, như hầu hết shell script. Trong tài liệu vẫn cần đổi Oil thành YSH nên có thể sẽ còn gây nhầm lẫn một thời gian: https://www.oilshell.org/blog/2023/03/rename.html
    • Vấn đề là dù đã có shell tốt hơn, chúng ta vẫn tiếp tục dùng những shell cổ lỗ này. Người dùng không nên lãng phí thời gian ghi nhớ các kiến thức truyền miệng như set -e. Dù sao thì giờ cũng đã có công cụ tìm kiếm
    • Một cách hơi cấp tiến để sửa thứ tự mệnh đề SQL có thể là đưa vào project, hoạt động giống select nhưng có thể đặt ở đúng vị trí
    • Khi phần giải thích chứa những chi tiết không cần thiết thì cực kỳ dễ gây rối. Giống như khẩu súng của Chekhov, ta cứ cố nhét nó vào mạch truyện, nhưng nó không khớp
      Siêu năng lực của tôi là trí nhớ tệ hại. Vì vậy, muốn nhớ thì tôi nhất thiết phải hiểu, tức là cần nén nhận thức. Tôi không thể cứ học theo cách của người bình thường
    • Cần có khả năng bóc bỏ SQL và truy cập vào lớp bên dưới
  • Hôm nay học được: trong danh sách && hoặc ||, ngoại trừ lệnh sau && hoặc || cuối cùng, shell sẽ không thoát ngay cả khi có lệnh thất bại
    Tham khảo: https://www.gnu.org/software/bash/manual/bash.html#index-set

    • “Thất bại” là một khái niệm ở tầng cao hơn những gì shell quan tâm. Điều kiện thất bại và phản ứng hoàn toàn do lập trình viên quyết định, không được tích hợp sẵn như một giả định trong shell
      Việc /bin/false làm chỉ là trả về 1. Đó có phải thất bại không? Không. Nó được thiết kế để hoạt động như vậy và đúng nghĩa là một công cụ có mục đích đó
      Tôi đã viết hàng trăm shell script, và trong số đó nhiều lệnh trả về giá trị khác 0 một cách rất bình thường để làm việc của chúng, chẳng hạn kiểm tra xem một chuỗi có khớp một mẫu nhất định hay không
      Chương trình có thể trả về bất kỳ mã thoát nào nó muốn trong mọi tình huống; theo quy ước, thành công là 0, thất bại là khác 0. Nhưng điều shell language quan tâm chỉ là 0 được đánh giá là “đúng”, còn giá trị khác 0 là “sai”
      Nếu shell thoát mỗi khi bất kỳ chương trình nào trả về giá trị khác 0, thì câu lệnh if và vòng lặp sẽ trở nên bất khả thi, rất bất tiện
      Nếu một script coi trọng mã trả về của một chương trình cụ thể, thì phải kiểm tra và xử lý nó một cách tường minh. Như trong liên kết, có các tùy chọn khiến shell thoát khi một lệnh bên trong trả về giá trị khác 0, và nhiều người viết shell script trình độ sơ-trung cấp thường giáo điều khẳng định rằng mọi script đều nên dùng chúng
      Nhưng trong các script phức tạp, tôi cảm thấy có nhiều edge case hơi hacky và khó xử lý. Nếu lần nào cũng cần các tùy chọn như vậy, có lẽ dùng Makefile còn tốt hơn
    • Đó là vì &&|| thường được dùng như câu điều kiện
      [ -e README ] && cat README tránh lỗi khi không có file README, còn [ -e README ] || echo "You should write a README!" thì hoạt động theo hướng ngược lại
      Vấn đề tinh vi hơn là ngay cả khi giả định có set -e, trong pipeline shell cũng sẽ không thoát nếu lệnh cuối cùng không thất bại
      grep foo README | sort sẽ không thất bại ngay cả khi README không tồn tại, trừ khi cũng dùng set -o pipefail
    • Tôi xem đây là một trong những khiếm khuyết lớn nhất trong thiết kế shell language. Vì một hàm, không phụ thuộc vào đối số, có thể dẫn tới kết quả khác nhau tùy theo ngữ cảnh mà nó được gọi
      Ngay cả khi bên trong hàm đặt set -e một cách tường minh, điều này cũng bị ghi đè
      Trước đây tôi từng nêu ví dụ: https://news.ycombinator.com/item?id=22213830
    • Shell còn có rất nhiều kiến thức bí truyền phải học. Đến một lúc nào đó, ta phải nhún vai và chấp nhận rằng đây là công cụ ổn để có kết quả nhanh, nhưng không phù hợp để viết chương trình vững chắc
  • Bài viết mô tả tốt những thứ trông như không nên khó, nhưng thực tế lại có nhiều độ phức tạp
    Tuy nhiên phần SQL có vẻ như đẩy sâu thêm một thất bại về mặt khái niệm hơn là giải ảo cho nó
    Logic của truy vấn là khai báo và định nghĩa đầu ra. Thứ có thứ tự thực thi hay tính chất thủ tục là query plan. Cần học điều này trước
    Sau đó mới có thể học các vùng mập mờ như dependent subquery. Nếu có thể thấy not exists và anti join là tương đương, bạn có thể hiểu và suy luận được
    Ẩn dụ kiểu hãy hiểu truy vấn đã viết theo cách thủ tục chỉ trì hoãn vấn đề; khi mắc kẹt ở thứ phức tạp hơn, bạn sẽ không có cách nào gỡ bỏ lời nói dối thiện ý đó

    • Phần SQL nói về mô hình tinh thần giúp hiểu truy vấn, và cũng có nhắc rằng cơ sở dữ liệu thực tế có lẽ không xử lý theo cách đó
    • Một tập gần đây liên quan đến Postgres, nhưng trong nhiều trường hợp cũng có thể mở rộng cách nghĩ sang các cơ sở dữ liệu khác: https://www.se-radio.net/2023/09/se-radio-583-lukas-fittl-on...
  • Đây là một bài thuyết trình tuyệt vời. Nói rằng Bash đầy “cạm bẫy” và kiến thức vụn vặt, khó mà nhớ hết, là đúng; nhưng tôi nghĩ cũng nên học thuộc một số kiến thức vụn vặt đó
    Ví dụ, tôi thường quên thứ tự đối số của lệnh find, nên từng mất thời gian cố nhớ cú pháp khi đứng trước một máy không có kết nối Internet ngay lập tức
    Vì vậy tôi quyết định học và ghi nhớ các công cụ dòng lệnh phổ biến nhất cùng một số cạm bẫy của chúng, dùng Anki và vài kỹ thuật ghi nhớ. Tôi nghĩ lợi tức trên khoản đầu tư này hoàn toàn xứng đáng

    • Anki là phao cứu sinh của tôi trong việc hiểu những thứ khó như DNS
      Thực ra, sau khi xem gợi ý sách trên jvns.ca, tôi đã đọc Networking for System Administrators của Michael W. Lucas, rồi rút ra các thẻ Anki từ kiến thức kỹ thuật và không ít sự khôn ngoan của quản trị viên hệ thống trong đó
      Giờ khi debug các vấn đề ở tầng vận chuyển, tôi nhớ ngay cách dùng các công cụ như netcat và tcpdump, nên đây có thể là một trong những cuốn sách có lợi tức đầu tư cao nhất trong số những gì tôi từng đọc
    • Tôi duy trì một file tập hợp các lệnh không dùng thường xuyên. Ví dụ như lệnh tăng âm lượng bằng ffmpeg, hoặc thêm viền cho ảnh bằng convert
      Tôi cũng tạo phím tắt để thêm lệnh vừa chạy vào file này, và phím tắt để tìm kiếm trong file đó
    • man page có thể dùng ngay
      man page của bash rất lớn và phức tạp, nhưng toàn diện. Nếu đã quen với các mục chính và hình dạng trực quan của văn bản, bạn có thể lướt nhanh và tìm đúng thông tin cần thiết, khá hữu ích
      Cách này nhiều khi còn nhanh hơn dùng công cụ tìm kiếm Internet
    • Có lẽ nên đầu tư vào các tài liệu/cheat sheet tổng quát hơn để không phải phụ thuộc vào Internet mà cũng không phải ghi nhớ thiết kế tệ
      Chẳng hạn chuyển đổi các man page cũ sang định dạng thân thiện với trình soạn thảo văn bản, hoặc dùng các công cụ tốt hơn như tldr, Dash. Vì đâu phải chỉ riêng find mới như vậy
    • Nên ngừng dùng Bash và dùng TypeScript thay thế. Bash thật kinh khủng
  • Không hiểu vì sao nhưng tôi đã muốn ghét bài này. Có lẽ vì jvns xuất hiện quá thường xuyên trên HN, hoặc chỉ là tôi đang không vui
    Nhưng đây thật sự là một bài rất hay, và với tư cách một người có 20 năm kinh nghiệm phát triển, tôi thấy nó khá gần với sự thật trong các thảo luận ở cấp độ meta về lập trình
    Chuyện tầm nhìn có chọn lọc thực sự đúng với cả dig lẫn các trang man. Không biết bao nhiêu lần tôi mở man ra rồi bị choáng ngợp bởi vô tận tùy chọn cấu hình và cờ dòng lệnh
    Mẹo tôi dùng trong man là dùng chức năng tìm kiếm kiểu Vim, tức /. Ví dụ nếu muốn tìm cách để grep in số dòng của từng kết quả khớp mà không nhớ, tôi mở man grep, rồi nhập /line và nhấn Enter để tìm các lần xuất hiện của “line” trong trang man. Kết quả khớp tiếp theo thì chỉ cần /
    Cũng hơi buồn khi nghe tin Strange Loop đã kết thúc. Tôi chỉ mới biết đến nó khoảng năm ngoái, nhưng nhiều bài nói có vẻ có chất lượng đặc biệt cao

  • Tôi rất không đồng ý với quan điểm về bash. Giải pháp tốt nhất không phải là chồng thêm công cụ lên bash hay ghi nhớ các điểm kỳ quặc của nó, mà là không dùng bash
    Đó là cách duy nhất để tránh các cạm bẫy

    • Tôi vẫn chưa tìm được phương án thay thế bash thật sự tốt, đặc biệt là trong script
      Các lựa chọn thay thế phổ biến nhất là 1) dùng một shell mới như Oil shell [0], hoặc 2) dùng ngôn ngữ lập trình như Python, JavaScript, PHP
      Vấn đề với shell mới là bạn phải cài shell đó ở mọi nơi muốn chạy script. Trong khi bash thì có ở khắp nơi. Nếu đó không phải là script chỉ một mình bạn bảo trì, bạn sẽ yêu cầu người khác cũng học shell đó để bảo trì
      Vấn đề với các ngôn ngữ lập trình khác là bash lại có mức độ tiện dụng hiếm thấy ở những việc nó làm tốt: nối các lệnh với nhau, xử lý input/output của lệnh và file
      Khi thử làm bằng ngôn ngữ khác, mọi thứ đột nhiên phức tạp hơn nhiều, hoặc ít nhất là dài dòng hơn
      Vì vậy tôi vẫn dùng bash, nhưng thừa nhận rằng thế mạnh của nó nằm ở việc chạy các lệnh khác và xử lý I/O. Nếu là logic phức tạp không liên quan đến những việc đó thì tôi chuyển sang ngôn ngữ khác. Đôi khi không phải là tránh bash hoàn toàn, mà chỉ là gọi một script Python từ bash
      Nếu có cách tiếp cận khác phù hợp hơn, rất mong được chia sẻ
      [0] https://www.oilshell.org
    • Đây là một điểm hợp lý. bash là một công cụ quá phức tạp, nên việc viết thêm một công cụ khác bên trên để làm bash bớt phức tạp nghe thật kỳ lạ
      Công cụ mới đó cũng sẽ không có hàng chục năm được debug như chính bash. Vấn đề nằm ở bản thân bash
      Chúng ta có xu hướng đánh giá thấp tính dễ dùng và đánh giá quá cao sự “thông minh”
      Ví dụ tiêu biểu là Git. Đó là một công cụ rất thông minh, nhưng tính dễ dùng thì khủng khiếp. Dù vậy, vì Linus tạo ra nó và Linus thì thông minh, nên có vẻ như vấn đề là ở chúng ta
      Chúng ta nhận được thứ mà mình coi trọng. Chúng ta nên coi trọng tính dễ dùng hơn
    • Tôi là fan nhiệt thành của shellcheck và đã thực sự dùng bash khá sâu, nhưng không linter nào hay công cụ nào bên trên bash có thể sửa được chuyện này
      Cách tốt nhất là cứ tránh xa nó. Thật sự nên dừng lại. Đừng cố tỏ ra cứng rắn
      Toàn bộ mô hình của ngôn ngữ này đã hỏng từ gốc. Kiểu dữ liệu xoay quanh chuỗi, các công tắc chế độ toàn cục, cờ một ký tự cho các toán tử so sánh cơ bản, hành vi mặc định bỏ qua lỗi ở khắp nơi, và đặc biệt là cả hàm nữa
      Chỉ một điểm kỳ quặc như vậy cũng đủ để loại một ngôn ngữ, nhưng bash có tất cả những thứ đó và còn hơn thế nữa
    • Lý do bash kỳ quặc là vì nó không phải là ngôn ngữ đa dụng. Những điều được nhắc trong bài cũng có lý do chính đáng riêng. Ví dụ như việc set -x có thể phá vỡ hành vi mong đợi của ||&&
      Ngay từ đầu, có ngôn ngữ nào lại xung đột chỉ vì một hàm trả về false? Có ngôn ngữ ném ngoại lệ, nhưng “false” chẳng phải là một giá trị hợp lệ có thể trả về sao
      Điều tương tự cũng thấy trong Makefile. Mọi người không hiểu mình đang làm gì, cũng chưa từng suy nghĩ sâu về hệ thống build, nên kỳ vọng nó hoạt động theo một cách nhất định
      Ví dụ, gán đệ quy của Make khiến hầu như ai cũng vấp
      FLAGS=-b, COMPILE=compile $(FLAGS), $(info compile command=$(COMPILE)), FLAGS=-a, myfile:, echo $(COMPILE) $? -o $@ sẽ in thông tin ban đầu là compile -b, nhưng khi thực thi thật thì thành compile -a -o myfile
      Nhưng nếu vì muốn khớp với các ngôn ngữ lập trình khác mà biến mọi phép gán thành đánh giá tức thì, ta sẽ tước đi một công cụ rất hữu ích. Càng hiểu những công cụ như vậy, ta càng biết rõ nên dùng chúng ở đâu và nên bỏ bao nhiêu công sức
    • Nói thì dễ hơn làm, và việc loại bỏ hoàn toàn bash không phải lúc nào cũng đáng so với thời gian và công sức bỏ ra
      Dù vậy nhìn chung tôi đồng ý. Tôi cố chuyển bất cứ thứ gì hơi phức tạp sang script viết bằng một ngôn ngữ ít kỳ quặc hơn
      Khi đó, những công cụ giúp tránh sai lầm trong 5% cuối cùng vẫn còn nằm trong bash là cực kỳ hữu ích