Gỡ Lỗi: Nền Tảng Thực Sự Của Kỹ Năng Lập Trình Trong Thời Đại AI – Mọi Thứ Khác Chỉ Là Sao Chép-Dán?

Trong thế giới công nghệ hiện đại, đặc biệt là với sự trỗi dậy của Trí tuệ Nhân tạo (AI) và các công cụ hỗ trợ lập trình thông minh, định nghĩa về “kỹ năng lập trình thực sự” đang dần thay đổi. Nhiều người tin rằng, nếu gạt bỏ lớp vỏ hào nhoáng bên ngoài, thì nghệ thuật gỡ lỗi (debugging) mới chính là đỉnh cao của năng lực kỹ sư phần mềm. Liệu những công việc còn lại, từ viết code đến thiết kế kiến trúc, có thực sự chỉ là một phiên bản nâng cấp của hành động “sao chép-dán” (copy-paste)?

Khi nhắc đến lập trình viên, hình ảnh phổ biến thường khá ấn tượng, thậm chí mang hơi hướng điện ảnh. Đó có thể là một hacker tài ba, ngồi giữa phòng server tối tăm, đột nhập vào các hệ thống ngân hàng phức tạp hay các cơ sở dữ liệu tối mật. Một hình ảnh khác ít lãng mạn hơn nhưng vẫn không kém phần kịch tính là một nhà phát triển gõ phím thoăn thoắt như vũ bão, với những dòng code cuồn cuộn đổ xuống màn hình như trong phim Ma Trận.

Thực tế, khi bạn mới bắt đầu học lập trình, hình dung đó không hoàn toàn sai lệch (trừ phần “người hùng màn bạc” bên cạnh). Bạn thực sự sẽ viết rất nhiều code. Các chuyên gia trong ngành thường nhận định rằng, biểu đồ đóng góp xanh lè trên GitHub, thường thuộc về những lập trình viên trẻ, đang học hỏi và thử nghiệm. Việc họ dành hàng giờ mỗi ngày để viết code, thử nghiệm và khám phá là hoàn toàn tự nhiên và cần thiết.

Đối với nhiều lập trình viên ở cấp độ Junior và Mid-level, công việc thường được định nghĩa là “cung cấp tính năng” hay “đưa sản phẩm ra thị trường.” Thành thật mà nói, không có gì sai khi suy nghĩ như vậy. Đây là giai đoạn quan trọng để tích lũy kinh nghiệm, hiểu biết về quy trình phát triển và làm quen với các công nghệ.

Sự Chuyển Mình Của Kỹ Năng Khi Thăng Tiến Trong Sự Nghiệp

Tuy nhiên, một điều thú vị sẽ xảy ra khi bạn tiến xa hơn trong sự nghiệp. Càng trở nên thâm niên – và càng chịu nhiều trách nhiệm hơn đối với hệ thống – bạn sẽ càng dành ít thời gian hơn cho việc viết code mới. Thay vào đó, phần lớn thời gian của bạn sẽ được đổ vào:

  • Gỡ lỗi chuyên sâu: Tìm kiếm và khắc phục các lỗi phức tạp mà không ai khác có thể giải quyết.
  • Điều tra sự cố lạ: Nghiên cứu những hành vi bất thường của hệ thống, đôi khi xuất hiện ngẫu nhiên.
  • Giải quyết vấn đề cốt lõi: Tìm ra nguyên nhân gốc rễ của những trục trặc “bí ẩn” nhất.

Bạn có thể nghĩ: “Nhưng nhiều Senior vẫn viết code rất nhiều mà!” Điều đó đúng ở một mức độ nào đó. Nếu bạn là một nhà phát triển kinh nghiệm làm việc trong một startup nhỏ, nơi mọi người đều phải đa năng, bạn vẫn sẽ dành nhiều thời gian để viết code. Đặc biệt là khi các công cụ AI hiện nay có thể tăng tốc độ phát triển đáng kể.

Nhưng khi các dự án phát triển và thành công hơn, độ phức tạp của chúng cũng tăng theo cấp số nhân. Và với sự phức tạp đó, một loại công việc khác sẽ nổi lên. Thay vì chỉ viết code, bạn cần tập trung vào việc hiểu sâu sắc toàn bộ hệ thống. Bởi vì, khi một vấn đề phát sinh trên môi trường production, sẽ luôn có người phải chịu trách nhiệm điều tra nó.

Đột nhiên, đội ngũ hỗ trợ cần câu trả lời. Ngay lập tức! Và bạn có thể sẽ dành cả ngày để phân tích các tập tin log:

[ERROR] 2023-10-27 10:35:12,123 - com.example.service.UserService - UserNotFoundException: User with ID 123 not found.
[WARN] 2023-10-27 10:35:15,456 - com.example.api.OrderController - Payment failed for order 789. Retrying...

Ồ, có một “race condition” (điều kiện tranh chấp) ở đâu đó! Bạn là Senior, bạn phải điều tra nó. Có điều gì đó không ổn với cấu hình của chúng ta? Bạn cần phải tìm ra nó!

// configuration snippet
const appConfig = {
    databaseUrl: process.env.DB_URL || 'mongodb://localhost:27017/devdb',
    // ...
    maxConnections: 10 // Is this too low for production?
};

Và tất nhiên, các Junior sẽ luôn đến với câu hỏi quen thuộc nhất trong giới lập trình:

“Tại sao cái này lại là null?”

function processUserData(user) {
    // What if 'user' is null here?
    const userName = user.name; // Throws TypeError: Cannot read property 'name' of null
    // ...
}

Kiến Trúc Phần Mềm: Có Phải Cũng Chỉ Là Sao Chép-Dán Ở Cấp Độ Cao Hơn?

Bạn có thể lập luận: lập trình không chỉ là gỡ lỗi. Các nhà phát triển cũng cần chọn kiến trúc, framework và các ngăn xếp công nghệ phù hợp. Điều đó hoàn toàn đúng.

Nhưng càng làm việc lâu trong ngành này, tôi càng nhận ra rằng trong nhiều lĩnh vực, hầu hết mọi thứ đã được phát minh. Có các mẫu thiết kế (design patterns), các phương pháp kiến trúc nổi tiếng, và các giải pháp đã được chứng minh cho nhiều lớp vấn đề. Khi bạn thiết kế một hệ thống, bạn hiếm khi tạo ra mọi thứ từ con số 0. Thay vào đó, bạn tái sử dụng các mẫu đã hoạt động, điều chỉnh các kiến trúc mà người khác đã thử nghiệm, và xây dựng dựa trên kho tri thức chung của cộng đồng nhà phát triển.

Theo nghĩa đó, bản thân kiến trúc thường là một dạng sao chép-dán – chỉ ở một cấp độ cao hơn rất nhiều. Việc phớt lờ tất cả những kiến thức tích lũy đó sẽ là một hành động hoặc là thiên tài… hoặc là ngu ngốc.

Hãy xem xét một số ví dụ:

  • Kiến trúc Microservices: Một mô hình đã được kiểm chứng cho các hệ thống phân tán, ít khi bạn “phát minh” lại mà thường áp dụng và tùy chỉnh.
  • Thiết kế API RESTful: Các nguyên tắc và chuẩn mực đã có sẵn, giúp việc thiết kế API trở nên nhất quán và dễ hiểu.
  • Sử dụng các thư viện và framework: React, Angular, Spring Boot, Laravel… đều là những “khối xây dựng” khổng lồ mà chúng ta “sao chép” (sử dụng) thay vì viết lại từ đầu.

Hồi Ức Về Thời Junior

Khi tôi còn là một lập trình viên Junior, tôi đã liên tục cung cấp các tính năng mới. Tôi chắc chắn đã viết hàng km code vào thời điểm đó. Nếu có gì đó không hoạt động, tôi sẽ dành một chút thời gian nghiên cứu, thử nghiệm, tìm kiếm lỗi trên Google và các diễn đàn như Stack Overflow. Nếu vẫn không thể tự khắc phục, tôi đơn giản là tìm đến một lập trình viên Senior.

Và thế là xong. Bất kể vấn đề khó chịu và tốn thời gian đến mức nào, Senior phải giải quyết nó. Đó đúng nghĩa là công việc của họ.

Tôi nhớ một tình huống từ thời đó khi dự án trên máy cục bộ của tôi đột nhiên không thể build được. Tôi đã mất hàng giờ để cố gắng tìm hiểu, cho đến khi một Senior kiểm tra vài thứ và bình tĩnh nói: “Phiên bản Node của bạn bị sai.” Đó là toàn bộ bí ẩn.

// My Node.js version: 16.x
// Project required Node.js version: 18.x
// Error: node_modules/some-package/index.js: SyntaxError: Unexpected token '.'
// This could be easily fixed by running 'nvm use 18' or similar.

Khi đó, tôi cũng cảm thấy hơi tội nghiệp cho các Senior. Họ luôn bận rộn với các cuộc gọi, liên tục bị gián đoạn, hiếm khi thực sự viết code mới. Trong khi đó, tôi hạnh phúc triển khai hết tính năng này đến tính năng khác. Cơ sở hạ tầng? Các pipeline CI/CD? AWS? Tôi gần như không hề nghĩ đến những điều đó.

Thực Tại Của Một Senior Developer Ngày Nay

Giờ đây, tôi cũng là một Senior developer, và thậm chí tôi phải điều phối công việc giữa nhiều nhóm khác nhau. Tôi có còn viết code không? Tất nhiên là có. Nhưng tôi có cung cấp một số lượng lớn các tính năng mới như khi tôi còn là Junior không?

Không hẳn.

Thay vào đó, rất nhiều công việc của tôi trông như thế này: nâng cấp một framework và cố gắng hiểu tại sao mọi thứ đột nhiên bị hỏng. Kiểm tra xem một bản cập nhật dependency có gây ra lỗi hồi quy (regression) nào không. Điều tra những lỗi kỳ lạ chỉ xuất hiện trong một số môi trường nhất định.

Hãy nhớ những lỗ hổng bảo mật (CVE) nổi tiếng về frontend mà chúng ta đã có gần đây? Loại lỗi đột nhiên xuất hiện ở khắp mọi nơi và gây ra một làn sóng hoảng loạn nhỏ. Ví dụ như những vấn đề liên quan đến chuỗi cung ứng phần mềm hay các lỗ hổng zero-day trong các thư viện phổ biến. Việc kiểm tra và xác định tác động của chúng là một nhiệm vụ cấp bách.

Liệu nó có ảnh hưởng đến dự án của chúng ta không? May mắn là không. Bây giờ, nhiệm vụ còn lại duy nhất là dành cả tuần để trả lời email giải thích rằng chúng ta thậm chí còn không sử dụng React 😉.

Kỹ Năng Thực Sự: Gỡ Lỗi

Viết code có thể giống như sao chép-dán. Kiến trúc chỉ là một dạng sao chép-dán ở cấp độ cao. Nhưng gỡ lỗi là giải quyết vấn đề thuần túy.

Nó buộc bạn phải hiểu sâu sắc hệ thống, theo dõi luồng dữ liệu, phân tích nhật ký (logs), và kiểm tra các giả thuyết. Đôi khi không có câu trả lời nào trên Stack Overflow giúp được. Đôi khi các công cụ AI cũng không giúp được. Bạn đơn giản cần phải tư duy, suy luận, và phân tích.

Và sau nhiều giờ điều tra, nguyên nhân gốc rễ thường hóa ra lại là một điều gì đó nhỏ đến ngạc nhiên: một thuộc tính bị thiếu, một cấu hình không chính xác, hoặc chỉ một dòng code duy nhất.

// The culprit might be as simple as this:
// Old: const TIMEOUT = 5000;
// New: const TIMEOUT = '5s'; // String instead of number, causing unexpected behavior in some libraries.

Gỡ lỗi đôi khi mang lại cảm giác rất giống công việc của một thám tử. Bạn thu thập bằng chứng, kết nối các manh mối, và từng bước tiến gần hơn đến sự thật ẩn giấu.

Trách Nhiệm Của Một “Thám Tử Phần Mềm”

Điều này gợi nhớ cho tôi một câu chuyện. Nhớ người Senior đã phải giúp tôi bất kể điều gì không? Giờ đây, tôi chính là người Senior đó đối với các đồng đội của mình.

Một thời gian trước, một lập trình viên Junior đã đến gặp tôi vì, khi triển khai một biểu mẫu phức tạp, cậu ấy đã không nhận thấy rằng chức năng xác thực (validation) không hoạt động ở một chỗ. Cậu ấy không biết cách khắc phục và đã bị mắc kẹt khá lâu. Hạn chót đang đến gần.

Tôi đã cố gắng hướng dẫn cậu ấy, chỉ ra một vài nơi trong code có thể hữu ích, nhưng không thành công. Cuối cùng, tôi phải tự mình ngồi xuống và đào sâu vào đoạn code đó.

// The Junior's validation logic might look like this:
// const isValid = validateInput(value);
// if (!isValid) {
//     displayErrorMessage('Invalid input');
// }
// Problem: 'displayErrorMessage' was called, but the form submission was not prevented.

Và tôi đã hoàn thành công việc vào lúc 1 giờ sáng, một ngày trước hạn chót. Có căng thẳng không? Có lẽ. Lẽ ra cậu ấy nên thông báo cho tôi về vấn đề này sớm hơn? Chắc chắn rồi. Nhưng đôi khi đó là thực tế của công việc.

Vậy… Tôi Có Không Hài Lòng Về Điều Đó Không?

Tôi có cảm thấy không hài lòng vì không cung cấp nhiều tính năng như khi tôi còn là Junior không?

Hoàn toàn không.

Suy cho cùng – ai lại không muốn trở thành một thám tử khi còn nhỏ? Các lập trình viên Senior về cơ bản là những thám tử phần mềm. 🕵️‍♀️ Họ không chỉ viết code; họ giải mã các bí ẩn, khôi phục trật tự cho hệ thống, và đảm bảo mọi thứ vận hành trơn tru. Đây là một vai trò đòi hỏi sự kiên nhẫn, tư duy phản biện và khả năng nhìn thấy bức tranh toàn cảnh, những kỹ năng mà không một công cụ AI nào có thể thay thế hoàn toàn.

Chỉ mục