Buổi tối đầu tiên với một ngôn ngữ mới thường khiến mình bớt tự tin đi một chút. Trình soạn thảo đã mở, tài liệu trông cũng thân thiện, vậy mà một ví dụ bé xíu vẫn ngốn nhiều chú ý hơn dự tính. Thiếu một import, vướng một lỗi kiểu dữ liệu lạ, hoặc gặp một câu không chịu đi theo ngữ pháp quen thuộc. Chỉ vài phút là cảm giác của người mới học quay lại nguyên vẹn.
Học một ngôn ngữ mỗi năm không có nghĩa năm nào cũng phải đạt tới mức thành thạo. Với tôi, đó là chọn một cách nghĩ chưa quen rồi ở lại đủ lâu để thấy nó làm việc gì dễ, việc gì khó, và nó phơi ra điều gì trong những công cụ mình vẫn dùng hằng ngày. Có năm đó là một ngôn ngữ lập trình. Có năm lại là một ngôn ngữ con người nói với nhau. Cả hai đều rèn cách chú ý.
Mỗi ngôn ngữ lập trình mang theo một quan niệm riêng về cách viết phần mềm. Go nghiêng về sự đơn giản và xử lý lỗi tường minh. Rust bắt người viết nghĩ kỹ về ownership và lifetime. Python giúp phác ý tưởng rất nhanh. TypeScript đặt contract sát hơn với công việc JavaScript thường ngày. Elixir khiến cách nhìn về concurrency thay đổi. Dù sau đó không dùng ngôn ngữ ấy trong hệ thống thực tế, mình vẫn đã luyện được một nhóm cơ tư duy khác.
Giá trị vì thế không chỉ nằm ở cú pháp. Cú pháp là phần nổi, giống như từ vựng. Phần sâu hơn là những gì ngôn ngữ coi là chuyện bình thường: dữ liệu có nên bất biến, null dễ hay khó xuất hiện, code được ghép bằng composition, message passing, pattern matching hay object, lỗi được ngăn từ đầu, buộc phải xử lý hay có thể lờ đi. Những lựa chọn ấy dần đổi cách người viết phần mềm nhìn ra vấn đề.
Ngôn ngữ con người cũng dạy một bài học khiêm tốn tương tự. Một câu được xem là thẳng thắn ở ngôn ngữ này có thể nghe quá sắc ở ngôn ngữ khác. Có những từ mang theo cả một lớp bối cảnh mà bản dịch khó chuyển trọn. Chỉ cần học một ít cũng đủ thấy giao tiếp không phải phép chuyển dữ liệu từ người này sang người kia. Trong đó còn có giọng điệu, sự tôn trọng, nhịp điệu và những điều hai bên ngầm hiểu.
Việc chấp nhận mình chậm còn đem lại một lợi ích nghề nghiệp ít được nhắc tới. Nhiều kỹ sư chỉ thấy thoải mái trong bộ công cụ quen, rồi vô tình xem cái quen là cái đúng. Ngôn ngữ mới cắt ngang sự chắc chắn ấy. Nó làm lộ những thói quen trước giờ mình không nhìn thấy: cách đặt tên, cách tổ chức lỗi, cách diễn đạt một ý, hay việc chọn một cách làm chỉ vì tay đã quen chứ không phải vì bài toán cần.
Nhịp một năm vừa đủ dài mà vẫn thực tế. Không cần xây một sản phẩm lớn bằng mọi ngôn ngữ. Vài bài tập có chủ đích đã đủ: viết một CLI, đọc và phân tích một file, gọi API, mô hình hóa một domain nhỏ, viết test, đọc code của một dự án thật rồi ghi lại điều gì khiến mình thấy khác. Phần ghi chép rất đáng làm. Không dừng lại để nghĩ, kiến thức mới dễ rơi rụng thành vài mẩu kiến thức vụn.
So sánh là lúc bài học bám lại. Sau khi dùng Rust, mình nhìn hệ thống kiểu dữ liệu của TypeScript khác đi. Sau Elixir, kiến trúc dựa trên hàng đợi bớt xa lạ. Sau khi học một ngôn ngữ nói khác, một thông báo sản phẩm bằng tiếng Anh có thể được viết cẩn thận hơn vì mình nhớ không phải người đọc nào cũng hiểu cùng một thành ngữ. Ngôn ngữ mới không thay chỗ ngôn ngữ cũ; nó làm đường nét của cái cũ rõ hơn.
Dĩ nhiên cũng có một cái bẫy: cứ học thứ mới để né việc đào sâu. Bắt đầu lại mỗi vài tháng tạo cảm giác mình đang tiến lên, trong khi chẳng có việc khó nào được làm đến nơi đến chốn. Cách giữ mình trung thực là thu hẹp phạm vi: một ngôn ngữ, một năm, một sản phẩm nhỏ, một bài tổng kết. Đủ lạ để kéo giãn tư duy, nhưng không lạ đến mức trở thành chỗ trốn.
Điều còn lại lâu nhất thường là cảm giác làm người mới. Nó không dễ chịu, nhưng làm tôi mềm hơn khi đọc và góp ý code của người đang học, đồng thời cẩn thận hơn khi giải thích. Chuyên môn không phải một danh tính cố định; nó là chỗ đứng tạm thời được bồi lên bằng luyện tập. Một ngôn ngữ đáng học không chỉ cho ta thêm cách nói hoặc cách viết code. Nó làm hiện ra những thói quen mà trước đó ta đã quá quen để nhận thấy.