Published on

Clean Coder __ Chương 1 -- Sự chuyên nghiệp

Authors
  • avatar
    Name
    Harvey Bui
    Twitter

1-cover Nụ cười ư, Curtin, ông bạn già. Đó là một trò đùa với chúng ta của chúa trời, hoặc của số phận, hoặc của thiên nhiên, hoặc bất cứ điều gì bạn thích. Nhưng bất cứ ai hay điều gì làm nên nó thì chắc chắn phải có khiếu hài hước! Ha!

-- Howard, Kho báu của Sierra Madre

Bạn muốn trở thành một lập trình viên phần mềm chuyên nghiệp? Bạn muốn ngẩng cao đầu và nói với thế giới rằng: "Tôi là một người chuyên nghiệp!" Bạn muốn mọi người nhìn bạn và đối xử với bạn một cách tôn trọng. Bạn muốn các vị phụ huynh lấy bạn ra làm gương và định hướng con cái họ trở thành người như vậy. Bạn muốn tất cả những thứ trên. Đúng chứ?

Cẩn thận với những gì bạn muốn

Chuyên nghiệp là một thuật ngữ nặng nề. Đó chắc chắn là huy hiệu của vinh dự và tự hào, nhưng cũng đồng nghĩa với nhiệm vụ và trách nhiệm. Chúng gắn liền với nhau, tất nhiên rồi. Bạn không thể có được vinh dự và tự hào từ những việc bạn không thể chịu trách nhiệm.

Trở thành người không chuyên nghiệp lại dễ dàng hơn rất nhiều. Những người không chuyên không phải chịu trách nhiệm về công việc họ làm - họ để việc đó lại cho quản lý của mình. Nếu người không chuyên mắc lỗi, những quản lý sẽ là người dọn dẹp mớ hỗn độn đó. Nhưng khi một người chuyên nghiệp gây ra lỗi, anh ta sẽ người xử lý.

Điều gì sẽ xảy ra nếu bạn để lọt lỗi của một chức năng và khiến công ty thiệt hại 10.000$ ? Người không chuyên nghiệp sẽ nhún vai, nói "sự đã rồi" và tiếp tục làm một chức năng khác. Người chuyên nghiệp sẽ viết cho công ty một tấm séc trị giá 10.000$.

Vâng, cảm giác rất khác nếu đó là tiền của chính bạn phải không? Nhưng đó là cảm giác mà một người chuyên nghiệp luôn có. Cảm giác đó là bản chất của sự chuyên nghiệp. Bởi vì, như bạn thấy, chịu trách nhiệm là tất cả những gì cần cho sự chuyên nghiệp.

Chịu trách nhiệm

Bạn đã đọc phần giới thiệu chưa? Nếu chưa, hãy quay lại và đọc ngay bây giờ; Nó đưa ra bối cảnh cho mọi thứ tiếp theo trong cuốn sách này.

Tôi đã học được cách chịu trách nhiệm qua việc gánh chịu hậu quả của việc chối bỏ trách nhiệm.

Năm 1979, khi tôi đang làm việc cho Teradyne. Tôi là "kỹ sư chịu trách nhiệm" cho phần mềm điều khiển hệ thống máy tính nhỏ và siêu nhỏ dùng để đánh giá chất lượng đường truyền điện thoại. Máy tính mini trung tâm được kết nối qua đường dây điện thoại, quay số hoặc chuyên dụng, 300-baud với hàng chục máy tính vệ tinh điều khiển phần cứng đó lường. Tất cả mã đều được viết bằng Assembler.

Khách hàng của chúng tôi là những giám đốc dịch vụ của các công ty điện thoại lớn. Mỗi người chịu trách nhiệm khoảng hơn 100,000 đường dây điện thoại. Hệ thống của tôi hỗ trợ họ tìm cũng như sửa chữa các trục trặc và sự cố trong đường dây điện thoại trước khi khách hàng của họ nhận ra. Điều này giảm tỉ lệ phàn nàn của khách hàng do các tổ chức công ích đo lường, và được sử dụng để điều chỉnh mức giá điện thoại công ty điện thoại đưa ra. Tóm lại, hệ thống này cực kỳ quan trọng.

Mỗi đêm hệ thống sẽ chạy một "quy trình ban đêm" cố định, máy tính mini trung tâm sẽ ra lệnh cho từng máy tính vệ tinh kiểm tra mọi đường dây điện thoại chúng kiểm soát. Vào sáng hôm sau, máy tính trung tâm sẽ thu về danh sách những đường dây bị lỗi cùng với thông tin chi tiết lỗi. Các quản lý khu vục sẽ sử dụng báo cáo này để lên lịch sửa chữa, khắc phục lỗi trước khi khách hàng phàn nàn.

Có một lần, tôi "gửi" bản cập nhật mới cho hàng loạt khách hàng. "Gửi" là một từ chính xác. Tôi viết phần mềm lên những cuộn băng và gửi chúng cho khách hàng. Họ cho đoạn băng đó vào hệ thống và khởi động lại.

Bản cập nhật mới sửa vài lỗi nhỏ và thêm một tính năng mới mà khách hàng yêu cầu. Chúng tôi nói với họ rằng chúng tôi sẽ cung cấp tính năng mới vào một ngày xác định. Tôi đã xoay sở với những cuộn băng suốt đêm để chúng được giao đúng vào ngày hẹn.

Hai ngày sau, tôi nhận được cuộc gọi từ người quản lý dịch vụ của chúng tôi, Tom. Anh ấy nói một số khách hàng phản nàn rằng "quy trình ban đêm" chưa hoàn thành, và họ không nhận được báo cáo nào. Tim tôi như chùng xuống, vì để bàn giao phần mềm đúng hạn, tôi đã bỏ qua việc kiểm thử "quy trình". Tôi đã kiểm thử nhiều chức năng khác của hệ thống, nhưng việc kiểm thử "quy trình" có thể mất hàng giờ đồng hồ, và tôi thì lại cần "gửi" chúng đi. Trong code của "quy trình" không có lỗi nào cần sửa, vì thế nên tôi cảm thấy khá tự tin.

Mất một phiên báo cáo hàng đêm là một vấn đề lớn. Điều đó có nghĩa là vào lúc này những thợ sửa sẽ có ít việc hơn nhưng về sau sẽ bị quá tải. Đồng nghĩa với việc một số khách hàng có thể nhận thấy lỗi và khiếu nại. Mất một phiên dữ liệu đáng giá đủ để Tom bị khiến trách gay gắt từ những quản lý khu vực.

Tôi khởi động hệ thống, tải phần mềm mới, và chạy thử một "quy trình". Nó mất vài giờ nhưng sau đó bị hủy. Quy trình thất bại. Nếu tôi chạy thử nghiệm trước khi gửi đi, các quản lý khu vực sẽ không bị mất dữ liệu và Tom cũng không bị quay như bây giờ.

Tôi gọi cho Tom và thông báo tôi đã phát hiện được vấn đề. Tom nói hầu hết những khách hàng khác đều đã gọi cho anh ấy và phàn nàn về cùng một vấn đề. Sau đó hỏi tôi khi nào có thể sửa xong. Tôi trả lời tôi cũng không biết, nhưng tôi đang sửa nó rồi. Trong khi chờ đợi, tôi đề xuất khách hàng nên quay lại sử dụng phiên bản cũ của phần mềm. Tom rất tức giận nói với tôi rằng đây là "cú đấm kép" tới khách hàng vì họ đã mất dữ liệu cả đêm cũng như không thể sử dụng tính năng mới mà họ được hứa.

Lỗi rất khó tìm, và việc kiểm thử mất nhiều giờ. Bản sửa lỗi đầu tiên không hoạt động. Lần thứ 2 cũng thế. Tôi đã mất vài lần thử, cũng là vài ngày, để tìm hiểu chuyện gì đang xảy ra. Trong suốt thời gian này, cứ vài giờ Tom lại gọi cho tôi và hỏi khi nào tôi sẽ sửa xong. Anh ta cũng đảm bảo rằng tôi biết về những lời khiển trách nhận được từ những quản lý khu vực, và thật xấu hổ khi anh ta hướng dẫn họ sử dụng lại phiên bản cũ.

Cuối cùng, tôi sửa được lỗi, gửi cho khách hàng những cuộn băng mới, và mọi thứ quay trở về bình thường. Tom, người không phải sếp của tôi, đã bình tĩnh lại và chúng tôi bỏ mọi thứ lại phía sau. Sếp của tôi đến gặp tôi khi mọi thứ kết thúc và nói "Tôi cá rằng anh sẽ không để điều đó lặp lại." Tôi đồng ý.

Nghĩ lại thì, tôi thấy rằng việc gửi bản cập nhật đi mà không kiểm thử lại "quy trình" là hoàn toàn vô trách nhiệm. Lý do tôi đưa ra là để bàn giao công việc đúng thời hạn. Đó chỉ là lý do để giữ thể diện cho bản thân tôi. Không quan tâm đến khách hàng cũng như công ty của mình. Tôi chỉ quan tâm đến danh tiếng của chính mình. Lẽ ra tôi nên nhận trách nhiệm sớm hơn và nói với Tom việc kiểm thử chưa hoàn thành và tôi không thể bàn giao đúng hạn. Đó là một việc khó, và Tom có thể sẽ phiền lòng. Nhưng không khách hàng nào bị mất dữ liệu, và không có lời phàn nàn nào từ phía quản lý khu vực.

Việc đầu tiên, không gây hại

Vậy thì chúng ta nhận trách nhiệm bằng cách nào? Có một số nguyên tắc được rút ra từ lời thề Hippocrate, nghe khá xa lạ nhưng khó tìm được nguồn nào tốt hơn? Và thực sự thì, chẳng phải trách nhiệm và mục tiêu hàng đầu của người có tham vọng trở thành chuyên gia là sử dụng năng lực của mình cho những mục đích tốt?

Một lập trình viên phần mềm thì có thể gây hại gì? Từ quan điểm thuần túy của phần mềm, họ có thể gây hại cho cả chức năng và cấu trúc phần mềm. Chúng ta sẽ khám phá cách tránh những việc đó.

Không gây hại đến hàm (function)

Rõ ràng là, chúng ta muốn phần mềm của mình hoạt động. Trên thực tế, phần lớn chúng ta trở thành lập trình viên vì chúng ta đã từng khiến chương trình nào đó hoạt động một lần và chúng ta lại muốn cảm giác đó thêm nữa. Nhưng chúng ta không phải là những người duy nhất muốn chương trình hoạt động. Khách hàng và công ty cũng muốn thế. Và họ trả tiền để chúng ta tạo ra những phần mềm hoạt động theo cách họ muốn.

Chúng ta gây hại đến hàm của phần mềm khi chúng ta tạo ra lỗi. Vì vậy, để trở nên chuyên nghiệp, chúng ta không được tạo ra lỗi.

"Nhưng đợi đã" Tôi chắc bạn sẽ nói "Điều đó không hợp lý. Phần mềm quá phức tạp để tạo ra mà không có lỗi".

Tất nhiên bạn cũng đúng. Phần mềm quá phức tạp để tạo ra mà không có lỗi. Nhưng không may là điều đó không giúp bạn chối bỏ trách nhiệm. Cơ thể con người quá phức tạo để có thể hiểu được toàn bộ, nhưng các bác sỹ vẫn tuyên thệ không làm tổn hại đến chúng. Nếu họ không chối bỏ trách nhiệm, sao chúng ta có thể?

"Anh đang nói rằng chúng tôi cần phải hoàn hảo?" Bạn đang phản đối đúng không?

Không, tôi đang nói với bạn rằng bạn phải chịu trách nhiệm cho sự không hoàn hảo của mình. Các lỗi chắc chắn sẽ xảy ra trong code của bạn không có nghĩa là bạn không có trách nhiệm với chúng. Nhiệm vụ viết phần mềm hoàn hảo gần như là không thể không có nghĩa là bạn không phải chịu trách nhiệm cho sự không hoàn hảo đó.

Rất nhiều chuyên gia phải chịu trách nhiệm cho các sai sót mặc dù chúng hầu như chắc chắn xảy ra. Vì vậy, những chuyên gia đầy tham vọng của tôi, điều đầu tiên bạn cần thực hành là xin lỗi. Lời xin lỗi là cần thiết những chưa đủ. Bạn không thể tiếp tục mắc lại một lỗi hết lần này đến lần khác. Khi bạn trưởng thành trong công việc, tỷ lệ sai sót của bạn sẽ nhanh chóng giảm dần và tiệm cận 0. Nó sẽ không bao giờ về 0, nhưng bạn phải có trách nhiệm giảm số lỗi xuống ít nhất có thể.

QA sẽ không tìm thấy gì cả

Khi bàn giao chương trình của mình, bạn nên kỳ vọng rằng QA không tìm thấy vấn đề gì. Sẽ là vô cùng thiếu chuyên nghiệp nếu bạn bàn giao chương trình cho QA mà bạn biết thừa là sẽ có lỗi. Và đoạn code nào bạn biết sẽ có lỗi? Tất cả những phần bạn không hiểu rõ.

Vài người coi QA như là công cụ giúp tìm lỗi. Họ bàn giao chương trình chưa được họ kiểm thử kỹ lưỡng. Họ dựa vào QA để tìm lỗi và báo lại. Trên thực tế, nhiều công ty còn thưởng cho QA dựa trên số lỗi mà họ tìm được. Càng nhiều lỗi, phần thưởng càng lớn.

Tạm bỏ qua việc hành vi này có hậu quả cực kỳ tốn kém, gây thiệt hại cho công ty và chương trình. Bỏ qua việc hành vi này làm hỏng lịch trình và suy giảm niềm tin của công ty với đội ngũ phát triển. Bỏ qua việc hành vi này thể hiện sự lười biếng và vô trách nhiệm. Xét cho cùng, bàn giao cho QA chương trình mà bạn không biết có hoạt động không là rất thiếu chuyên nghiệp. Nó vi phạm nguyên tắc "không gây hại".

Vậy QA có thể tìm được lỗi không? Có thể, nên hãy sẵn sàng để xin lỗi - và sau đó tìm hiểu những tại sao những lỗi đó lại thoát được và ngăn chặn điều đó diễn ra lần sau.

Mỗi khi QA, hoặc tệ hơn là người dùng, tìm thấy vấn đề, bạn nên ngạc nhiên, lo lắng và quyết tâm ngăn chặn nó xảy ra một lần nữa.

Bạn phải biết nó hoạt động

Làm sao để biết code hoạt động? Dễ thôi. Kiểm thử nó, kiểm thử đi kiểm thử lại, kiểm thử lên kiểm thử xuống. Kiểm thử với 7 cách đến chủ nhật!

Có thể bạn lo việc kiểm thử quá nhiều sẽ mất quá nhiều thời gian. Trong khi bạn cần giữ đúng lịch trình và hạn chót. Nếu bạn dành tất cả thời gian để kiểm thử, bạn sẽ không viết được gì khác. Rất tốt! Giải pháp là, hãy tự động hóa nó. Viết những kiểm thử đơn vị (Unit test) có thể chạy ngay lập tức, và chạy chúng thường xuyên nhất có thể.

Bao nhiêu code nên được kiểm thử với những kiểm thử đơn vị tự động này? Tôi có thực sự cần trả lời câu hỏi này không? Tất cả! Tất. Cả.

Tôi đang đề xuất kiểm thử sẽ bao phủ 100% code? Không, tôi không đề xuất. Tôi đang yêu cầu điều đó. Mọi dòng code bạn viết ra đều phải được kiểm thử. Chấm hết.

Nghe khá thiếu thực tế? Dĩ nhiên là không. Bạn viết code vì bạn mong đợi nó được sử dụng. Nếu bạn muốn nó được sử dụng, bạn phải biết rằng nó hoạt động. Cách duy nhất để biết điều đó là kiểm thử nó.

Tôi là một thành viên chính của dự án mã nguồn mở có tên FitNesse. Tính đến thời điểm viết những dòng này, FitNesse có khoảng 60 ksloc ((1000)K Source Lines of Code). Trong đó có 26 ksloc được tạo nên bởi hơn 2000 kiểm thử đơn vị. EMMA (công cụ miễn phí bằng Java đo lường độ bao phủ) thống kê độ bao phủ của hơn 2000 kiểm thử đơn vị đó là khoảng 90%.

Tại sao phạm vi bao phủ không nhiều hơn? EMMA không thể nhìn thấy được tất cả các dòng code đang được thực thi! Tôi tin rằng độ phủ còn cao hơn thế nhiều. Liệu có đến 100%? Không, nhưng sẽ tiệm cận 100%.

Nhưng sẽ có một vài đoạn code rất khó kiểm thử? Có, nhưng chỉ khi đoạn code đó được thiết kế để khó kiểm thử. Giải pháp cho điều đó là thiết kế code của bạn để dễ kiểm thử. Và cách tốt nhất để làm điều đó là viết kiểm thử trước khi viết code vượt qua chúng.

Đây là một quy chuẩn được biết đến với cái tên Phát triển Định hướng Kiểm thử (Test Driven Development - TDD), sẽ được nói rõ hơn ở chương sau.

Tự động hóa QA

Toàn bộ quy trình QA cho FitNesse bao gồm việc chạy kiểm thử đơn vị và kiểm thử chấp nhận (Acceptance Tests). Khi vượt qua quy trình này, tôi bàn giao chương trình. Điều đó có nghĩa là quy trình QA của tôi mất khoảng 3 phút và tôi có thể thực hiện nó tùy ý.

Thực tế thì, không có ai chết nếu có FitNesse có lỗi, cũng chẳng có ai mất hàng triệu đô la. Nhưng FitNesse có hàng nghìn người dùng với số lỗi rất nhỏ.

Chắc chắn là một số hệ thống có những nhiệm vụ quan trọng đến mức những kiểm thử tự động không thể xác định mức độ sẵn sàng đưa vào sử dụng. Tuy nhiên, bạn - với cương vị là một lập trình viên - cần một cơ chế tương đối nhanh chóng và tin cậy để biết rằng code của bạn hoạt động và không ảnh hưởng đến phần còn lại của hệ thống. Vì vậy, ít nhất, những kiểm thử tự động của bạn sẽ cho bạn biết hệ thống có khả năng cao vượt qua QA.

Không hại đến cấu trúc

Người thực sự chuyên nghiệp biết rằng cung cấp một chức năng làm ảnh hưởng tới cấu trúc là một lỗi ngớ ngẩn. Cấu trúc code của bạn cần phải linh hoạt. Nếu bạn làm tổn hại đến cấu trúc, sẽ là hậu quả xấu trong tương lai.

Tiền đề căn bản cho tất cả các dự án phần mềm là chúng phải dễ dàng thay đổi. Nếu bạn vi phạm tiền đề khi tạo ra các cấu trúc không linh hoạt, thì bạn đã cắt xén mô hình kinh tế mà toàn bộ ngành công nghiệp này dựa vào.

Tóm lại: Bạn phải thực hiện những thay đổi với ảnh hưởng nhỏ nhất đến cấu trúc

Không may là, có quá nhiều dự án sa lầy với một cấu trúc kém. Công việc bình thường mất vài ngày, sẽ mất vài tuần, sau đó là vài tháng. Ban quản lý, muốn lấy lại năng suất vốn có trong tuyệt vọng, tuyển thêm nhiều lập trình viên để đẩy nhanh tiến độ. Nhưng những người mới chỉ thêm vào một mớ hỗn độn, ảnh hưởng đến cấu trúc nhiều hơn và khó khăn càng lớn hơn.

Hầu hết những bài viết về nguyên tắc và nguyên mẫu thiết kế phần mềm đều hỗ trợ cho tính linh hoạt và dễ bảo trì của cấu trúc. Những lập trình viên chuyên nghiệp ghi nhớ điều này và cố gắng tuân thủ chúng. Nhưng có một mẹo nhỏ mà rất ít người làm theo: Nếu bạn muốn phần mềm của mình linh hoạt, chính bạn phải làm nó linh hoạt.

Cách duy nhất để chứng minh chương trình của bạn dễ thay đổi là thực hiện những thay đổi dễ dàng với nó. Và khi bạn thấy có sự thay đổi không dễ như bạn nghĩ, tinh chỉnh lại thiết kế để dễ thay đổi hơn về sau.

Khi nào bạn thực hiện những tinh chỉnh này? Mọi lúc! Bất kỳ khi nào bạn nhìn vào một module, bạn thực hiện những thay đổi nhỏ, nhẹ để cải thiện cấu trúc của nó. Mỗi khi mà bạn đọc code, bạn lại điều chỉnh cấu trúc.

Triết lý này đôi khi được gọi là tái cấu trúc không thương tiếc (merciless refactoring). Tôi gọi nó là "quy tắc Hướng đạo sinh". Luôn luôn làm cho một module sạch hơn sau khi bạn kiểm tra nó. Luôn thực hiện một số hành động tử tế ngẫu nhiên với bất kỳ đoạn code nào bạn nhìn thấy.

Điều này hoàn toàn trái ngược với cách mà hầu hết mọi người nghĩ về phần mềm. Họ nghĩ rằng việc thực hiện những thay đổi liên tục đói với phần mềm đang hoạt động là rất nguy hiểm. Không! Điều nguy hiểm là để cho phần mềm ở trạng thái tĩnh. Nếu bạn không uốn nắn nó, khi đến thời điểm bạn cần thay đổi, bạn sẽ thấy rất cứng ngắc.

Tại sao phần lớn lập trình viên đều sợ những thay đổi liên tục trong code của họ? Họ lo sợ họ sẽ phá vỡ nó! Và tại sao họ lại lo sợ sẽ phá vỡ nó? Bởi vì họ không có những kiểm thử.

Tất cả quay trở lại với những kiểm thử. Nếu bạn có một bộ kiểm thử tự động bao phủ gần như 100% code, và nếu nó được thực thi nhanh chóng tùy theo ý bạn, khi đó bạn đơn giản là sẽ không ngại thay đổi code nữa. Làm thế nào dể bạn chứng minh rằng bạn không sợ thay đổi code? Bạn thay đổi nó mọi lúc.

Những lập trình viên chuyên nghiệp nắm rõ về code và kiểm thử của họ đến mức họ cảm thấy bình thường kinh khủng khi thực hiện những thay đổi ngẫu nhiên và cơ hội. Họ sẽ thay đổi tên một class, theo ý thích. Họ sẽ thấy một phương thức dài khi đọc một module và phân chia lại nó như một việc tất nhiên. Họ sẽ thay đổi một câu lệnh switch thành triển khai đa hình, hoặc thu gọn hệ thống phân cấp kế thừa thành một chuỗi các câu lệnh. Tóm lại, họ xử lý phần mềm như cách một nhà điêu khắc xử lý đất sét - liên tục tạo hình và nhào nặn sản phẩm của mình.

Đạo đức nghề nghiệp

Sự nghiệp của bạn là trách nhiệm của bạn. Quản lý không phải là người có trách nhiệm đảm bảo bạn được đánh giá cao. Họ cũng không có trách nhiệm đào tạo bạn, hoặc đưa bạn đến hội thảo, hay mua sách cho bạn. Tất cả là trách nhiệm của bạn. Thật tội nghiệp cho những lập trình viên phần mềm giao phó sự nghiệp cho quản lý của mình.

Một vài quản lý sẵn lòng mua sách cho bạn, cho bạn tham gia các lớp đào tạo và đi dự hội thảo. Tốt thôi, họ đang giúp đỡ bạn. Nhưng đừng bao giờ rơi vào bẫy khi nghĩ rằng đó là trách nhiệm của quản lý. Nếu họ không làm điều đó cho bạn, bạn phải tìm cách tự thực hiện những việc này.

Quản lý cũng không có trách nhiệm cho bạn thời gian bạn cần để học tập. Một vài người có thể cho bạn thời gian. Thậm chí có người còn yêu cầu bạn dành thời gian cho học tập. Nhưng một lần nữa, họ đang giúp đỡ bạn, và bạn nên thấy cảm ơn vì điều đó. Những ưu ái như vậy không phải là điều bạn nên mong đợi.

Bạn nợ quản lý của mình một khoảng thời gian và nỗ lực nhất định. Ví dụ như tiêu chuẩn của Mỹ là 40 giờ mỗi tuần. Bạn nên dành 40 giờ này để giải quyết vấn đề của quản lý, chứ không phải vấn đề của bạn.

Bạn nên lên kế hoạch làm việc 60 giờ một tuần. 40 giờ đầu tiên cho quản lý, 20h còn lại dành cho bạn. Với 20h này, bạn nên đọc, luyện tập, học hỏi, hoặc là nâng tầm sự nghiệp của mình.

Bạn đang thắc mắc: "Nhưng còn gia đình tôi? Cuộc sống của tôi? Tôi phải hi sinh chúng cho quản lý của mình?

Tôi không nói đến toàn bộ thời gian rảnh của bạn. Mỗi tuần bạn chỉ cần dành thêm 20 giờ. Như vậy mỗi ngày chỉ khoảng 3 giờ. Nếu bạn dành thời gian ăn trưa để đọc, nghe podcast lúc đi làm, và dành 90 phút mỗi ngày để học một ngôn ngữ mới, bạn sẽ có tất cả.

Thử tính xem. Một tuần có 168 giờ. 40 giờ dành cho công việc, và 20 giờ nữa dành cho sự nghiệp. Còn lại 108 giờ. 56 giờ nữa dành cho giấc ngủ, bạn còn lại 52 giờ cho mọi việc khác.

Có thể bạn sẽ không muốn cam kết như vậy. Cũng chả sao, nhưng bạn không nên nghĩ mình là một người chuyên nghiệp. Tất cả các chuyên gia đều dành thời gian để phát triển sự nghiệp của mình.

Có thể bạn nghĩ rằng công việc nên ở lại văn phòng, bạn không nên mang công việc về nhà. Tôi đồng ý! Bạn không nên làm việc cho quản lý của bạn trong 20 giờ đó. Thay vào đó, bạn nên phát triển sự nghiệp của mình.

Đôi khi 2 việc này xen kẽ nhau. Đôi khi việc bạn làm cho quản lý có lợi rất nhiều cho sự nghiệp của bạn. Trong trường hợp này, dành 20 giờ đó cho công việc rất hợp lý. Nhưng hãy nhớ rằng, 20 giờ này là dành cho bạn. Chúng phải được sử dụng để làm bạn có giá trị hơn, như một người chuyên nghiệp.

Có thể bạn nghĩ rằng đây là công thức cho sự kiệt sức. Thực ra là ngược lại, đây là công thức để tránh kiệt sức. Khi bạn là muốn mình trở thành một lập trình viên phần mềm vì bạn đam mê lập trình và bạn muốn trở thành một chuyên gia bởi niềm đam mê đó. Trong 20 giờ đó, bạn có thể làm những việc để củng cố đam mê đó. Bạn sẽ có 20 giờ vui vẻ!

Nắm rõ lĩnh vực của mình

Bạn có biết biểu đồ Nassi-Schneiderman là gì không? Nếu không thì tại sao? Bạn có biết sự khác nhau giữa máy Mealy và máy Moore không? Bạn nên biết. Bạn có thể viết một đoạn code sắp xếp nhanh (quick sort) mà không cần tra cứu không? Bạn có biết thuật ngữ "Transform Analysis" nghĩa là gì không? Bạn có thể thực hiện phân tích chức năng với sơ đồ luồng dữ liệu (Data Flow Diagrams) không? Thuật ngữ "Tramp Data" có nghĩa là gì? Bạn đã bao giờ nghe thuật ngữ "Conascense" chưa? Bảng Parnas là gì?

Có vô số ý tưởng, khuôn phép, kỹ thuật, công cụ và thuật ngữ được tạo ra trong lĩnh vực của chúng ta suốt 50 năm qua. Bạn biết được bao nhiêu trong số đó? Nếu bạn muốn trở nên chuyên nghiệp, bạn phải biết được một phần khá lớn và không ngừng tăng hiểu biết của mình lên.

Tại sao bạn cần biết những thứ này? Xét cho cùng, chẳng phải lĩnh vực của chúng ta đang phát triển quá nhanh đến mức mọi ý tưởng cũ này đã trở nên không phù hợp nữa sao? Phần đầu tiên của câu hỏi có vẻ rất rõ ràng. Chắc chắn là lĩnh vực của chúng ta đang phát triển với tốc độ chóng mặt. Tuy nhiên, thật thú vị là sự tiến bộ phần lớn đều nằm ở phần ngoại vi. Đúng là bây giờ chúng ta không cần đợi 24h để quay vòng biên dịch nữa. Đúng là chúng ta có thể viết các hệ thống với kích thước hàng GB. Đúng là chúng ta đang làm việc giữa một mạng lưới rộng khắp toàn cầu cung cấp khả năng truy cập thông tin tức thì. Mặt khác, chúng ta đang viết những câu lệnh ifwhile giống như chúng ta đã viết cách đây 50 năm. Nhiều thứ đã thay đổi, nhiều thứ thì không.

Phần thứ 2 của câu hỏi thì hoàn toàn không đúng. Rất ít ý tưởng trong 50 năm qua trở nên không phù hợp. Một số đã bị loại bỏ, điều đó đúng. Khái nhiệm phát triển theo mô hình thác nước đã rơi vào quên lãng. Nhưng không có nghĩa là chúng ta không biết nó là gì, và có những điểm nào tốt cũng như chưa tốt.

Tuy nhiên, nhìn chung thì phần lớn những ý tưởng xương máu trong 50 năm qua vẫn còn giá trị tới ngày nay. Thậm chí đến bây giờ còn có giá trị hơn.

Hãy nhớ lời nguyền Santayana: "Những người không nhớ đến lịch sử, thì chắc chắn sẽ lặp lại nó"

Dưới đây là một danh sách tối thiếu những thứ mà mọi chuyên gia phần mềm nên thông thạo:

  • Các khuôn mẫu thiết kế (Design patterns). Bạn phải mô tả được tất cả 24 mẫu trong sách GOF (Gang of Four) và có kiến thức về nhiều mẫu trong sách POSA (Pattern-Oriented Software Architecture)
  • Các nguyên tắc thiết kế. Bạn nên biết về nguyên tắc SOLID và hiểu rõ các thành phần của nó.
  • Các mô hình phát triển. Bạn nên hiểu về XP, Scrum, Lean, Kanban, Waterfall, Structured Analysis (Phân tích cấu trúc), và Structured Design (Thiết kế cấu trúc).
  • Các nguyên tắc phát triển. Bạn nên thực hành TDD, thiết kế Object-Oriented, Structured Programming, Continuous Integration, và Pair Programming
  • Các ứng dụng. Bạn nên biết cách sử dụng UML, DFDs, sơ đồ cấu trúc (Structure Charts), Petri Nets, sơ đồ và bảng chuyển đổi trạng thái (State Transition Diagrams and Tables), biểu đồ luồng (flow charts), và bảng quyết định (decision tables).

Không ngừng học hỏi

Tốt độ thay đổi điên cuồng trong ngành CNTT đồng nghĩa với việc các lập trình viên phần mềm phải liên tục học hỏi nhiều thứ chỉ để theo kịp sự thay đổi. Thật buồn cho những kỹ sư ngừng viết code - họ sẽ sớm thấy mình không không còn phù hợp. Buồn cho những lập trình viên ngừng học ngôn ngữ mới - họ sẽ sớm nhìn thấy mọi thứ lướt qua họ. Buồn cho những lập trình viên không học những nguyên tắc phát triển và kỹ thuật mới - đồng nghiệp của họ sẽ nổi trội hơn trong khi họ bị sa sút.

Bạn có đến khám một vị bác sỹ không cập nhật các tạp chí y khoa không? Bạn có thuê một luật sư thuế không cập nhật luật thuế và các tiền lệ thuế hiện hành không? Vậy tại sao chủ doanh nghiệp lại đi thuê những lập trình viên không theo kịp thời đại?

Đọc sách, tham khảo các bài viết, blog, tweet. Tham gia các buổi thảo luận. Tham gia những nhóm người dùng. Tham gia đọc và học nhóm. Học những thứ ngoài vùng an toàn của bạn. Nếu bạn đã là một lập trình viên .NET, học Java. Nếu bạn lập trình Java, học Ruby. Nếu bạn lập trình C, học Lisp. Nếu bạn thực sự muốn thử thách bộ não của mình, học Prolog và Forth!

Luyện tập

Người chuyên nghiệp luôn luyện tập. Người thực sự chuyên nghiệp làm việc chăm chỉ để giữ cho các kỹ năng của họ luôn sắc bén và sẵn sàng. Sẽ là chưa đủ nếu chỉ làm những công việc đơn giản hàng ngày và gọi đó là luyện tập. Làm công việc hàng ngày là nhiệm vụ, không phải luyện tập. Luyện tập là khi cụ thể hóa các kỹ năng của mình ngoài việc thực hiện nhiệm vụ trong công việc của bạn, với mục đích duy nhất là hoàn thiện và nâng cao các kỹ năng đó.

Điều này có ý nghĩa là gì với việc luyện tập của lập trình viên phần mềm? Thoạt nghe khái niệm này có vẻ vô lý. Nhưng hãy dừng lại suy nghĩ một chút. Hãy xem cách các nhạc sỹ làm chủ kỹ năng của họ. Không phải qua biểu diễn. Mà qua luyện tập. Và họ luyện tập như thế nào? Trong rất nhiều thứ, họ có các bài tập đặc biệt mà họ thực hiện. Âm giai (scale), khúc luyện (etudes) và chạy (runs). Họ làm đi làm lại những việc này để rèn luyện các ngón tay và tâm trí, cũng như sự thành thạo các kỹ năng của họ.

Vậy các lập trình viên phần mềm làm gì để luyện tập? Có riêng một chương trong cuốn sách này dành riêng cho các kỹ thuật luyện tập khác nhau, vì vậy tôi sẽ không đi sâu vào chi tiết ở đây. Một kỹ thuật tôi thường sử dụng là lặp đi lặp lại các bài tập đơn giản như Bowling Game hoặc Số nguyên tố. Tôi gọi chúng là kata. Có rất nhiều kata để lựa chọn.

Một kata thường bắt nguồn từ việc giải quyết một bài toàn lập trình đơn giản, chẳng hạn như viết hàm tính các thừa só nguyên tố của một số nguyên. Quan điểm của việc thực hiện kata không phải là tìm ra cách giải quyết bài toán, bạn chắc đã biết điều đó rồi. Mục đích của kata là rèn luyện các ngón tay và trí não của bạn.

Tôi thực hiện 1 đến 2 kata mỗi ngày, thường là một phần để ổn định công việc. Tôi có thể làm điều này bằng Java, Ruby, Clojure, hoặc bằng một số ngôn ngữ khác tôi muốn duy trì kỹ năng của mình. Tôi sử dụng kata để mài dũa một kỹ năng cụ thể, chẳng hạn như giữ các ngón tay của tôi quen với các phím tắt, hoặc sử dụng những tái cấu trúc xác định.

Hãy coi kata như một bài tập khởi động 10 phút buổi sáng và 10 phút hạ nhiệt vào buổi tối.

Cộng tác

Cách tốt nhất thứ 2 để học là cộng tác với người khác. Những lập trình viên phần mềm chuyên nghiệp dành nỗ lực đặc biệt để lập trình cùng nhau, luyện tập cùng nhau, thiết kế và lập kế hoạch cùng nhau. Bằng cách đó, họ có thể học hỏi được nhiều điều từ nhau và hoàn thành công việc nhanh hơn, ít lỗi hơn.

Điều đó không có nghĩa là bạn phải dành 100% thời gian làm việc với những người khác. Thời gian một mình cũng rất quan trọng. Tôi rất thích làm việc với người khác, nhưng tôi sẽ phát điên lên nếu thỉnh thoảng không thể làm việc một mình.

Cố vấn

Cách tốt nhất để học là dạy. Không gì có thể nhồi vào đầu bạn những dữ kiện và giá trị nhanh hơn và khó hơn việc phải truyền đạt chúng cho những người mà bạn có trách nhiệm hướng dẫn. Vì vậy, lợi ích của việc giảng dạy là một đặc ân của giáo viên.

Tương tự, để giúp những người mới gia nhập tổ chức, không có cách nào tốt hơn là ngồi xuống và chỉ cho họ cách mọi thứ hoạt động. Các chuyên gia chịu trách nhiệm cá nhân trong việc kèm cặp đàn em. Họ sẽ không để cho một đàn em than vãn về việc không được giám sát.

Hiểu được lĩnh vực của bạn

Mọi chuyên gia phần mềm phải có trách nhiệm hiểu rõ lĩnh vực của các giải pháp mà họ đang lập trình. Nếu bạn xây dựng một hệ thống kế toán, bạn nên biết về lĩnh vực kế toán. Nếu bạn đang xây dựng một ứng dụng du lịch, bạn nên biết về ngành du lịch. Bạn không cần trở thành chuyên gia trong lĩnh vực đó, nhưng cũng đòi hỏi bạn phải biết một lượng kiến thức hợp lý.

Khi bắt đầu một dự án trong một lĩnh vực mới, đọc một hoặc hai cuốn sách về chủ đề này. Phỏng vấn khách hàng và người dùng về nền tảng và những khái niệm cơ bản của lĩnh vực. Dành một chút thời gian với các chuyên gia, và cố gắng nắm bắt được những nguyên tắc và giá trị của họ.

Loại hành vi thiếu chuyên nghiệp tồi tệ nhất là chỉ viết code dựa trên đặc điểm kỹ thuật mà không hiểu tại sao đặc điểm kỹ thuật đó có ý nghĩa với doanh nghiệp như thế nào. Thay vào đó, bạn nên hiểu đủ về lĩnh vực để có thể nhận ra và xử lý các lỗi đặc thù.

Xác định chủ doanh nghiệp/khách hàng của bạn

Vấn đề của chủ doanh nghiệp là vấn đề của bạn. Bạn cần phải hiểu những vấn đề đó là gì và hướng đến những cách giải quyết tốt nhất. Là một lập trình viên hệ thống, bạn cần đặt mình vào vị trí chủ doanh nghiệp và chắc chắn rằng những tính năng mà bạn tạo ra thực sự khớp với mong muốn của chủ doanh nghiệp.

Các lập trình viên rất dễ dàng tách biệt 2 vấn đề này. Càng dễ dàng rơi vào thái độ tôi và họ với chủ doanh nghiệp. Các chuyên gia tránh điều này bằng mọi giá.

Khiêm tốn

Lập trình là một công việc sáng tạo. Khi chúng ta viết code, chúng ta tạo ra một thứ gì đó từ con số 0. Chúng ta mạnh mẽ áp đặt trật tự lên sự hỗn loạn. Chúng ta tự tin chỉ huy, chính xác từng chi tiết, các hành vi của một cỗ máy có thể gây ra những thiệt hại không lường. Vì thế nên, lập trình là một công việc rất đáng kiêu ngạo.

Các chuyên gia biết họ kiêu ngạo và không khiêm tốn vô lý. Một chuyên gia biết công việc của mình và tự hào về nó. Một chuyên gia tự tin vào khả năng của mình, chấp nhận rủi ro một cách táo bạo và có tính toán dựa trên sự tự tin đó. Một chuyên gia không được rụt rè.

Tuy nhiên, họ cũng biết rằng sẽ có lúc mình thất bại, tính toán rủi ro của anh ta sẽ sai, các kỹ năng không đủ đáp ứng. Anh ta sẽ nhìn vào gương và nhìn thấy một kẻ ngốc kiêu ngạo đang nhìn lại.

Vì vậy, khi một chuyên gia thấy mình như một trò đùa, anh ta sẽ là người đầu tiên cười. Anh ta sẽ không bao giờ chế giễu người khác, nhưng sẽ chấp nhận chế giễu khi nó xứng đáng và cười nhạo khi điều đó không xứng đáng. Anh ta sẽ không hạ thấp người khác khi họ mắc sai lầm vì anh ta biết mình có thể là người tiếp theo.

Một chuyên gia hiểu rõ sự kiêu ngạo của mình. và số phận cuối cùng cũng sẽ nhận thấy và cân bằng chúng. Và khi mục tiêu đó liên kết lại, điều tốt nhất bạn có thể làm theo là nghe theo lời khuyên của Howard: Cười.