Mã sạch
ạn đang đọc cuốn sách này bởi hai lý do. Đầu tiên, bạn là một lập trình viên. Thứ hai, bạn muốn trở thành một lập trình viên tốt hơn. Tốt rồi. Chúng ta cần lập trình tốt hơn. Cuốn sách này viết về điều đó – lập trình tốt – và đầy những mã lệnh. Chúng ta sẽ soi xét mã lệnh theo nhiều ...
ạn đang đọc cuốn sách này bởi hai lý do. Đầu tiên, bạn là một lập trình viên. Thứ hai, bạn muốn trở thành một lập trình viên tốt hơn. Tốt rồi. Chúng ta cần lập trình tốt hơn.
Cuốn sách này viết về điều đó – lập trình tốt – và đầy những mã lệnh. Chúng ta sẽ soi xét mã lệnh theo nhiều hướng khác nhau. Ta sẽ nhìn mã từ đầu đến cuối, ngước lên nhìn mã từ dưới lên trên và lần theo các khối lệnh từ trong ra ngoài. Khi làm được điều đó thì ta sẽ hiểu rất nhiều điều về mã. Thêm vào đó, ta có thể kể ra sự khác biệt giữa mã tốt và mã tồi. Chúng ta sẽ biết cách viết mã tốt. Và chúng ta sẽ biết cách biến mã lệnh xấu thành mã lệnh tốt.
Tương lai sẽ có lập trình
Ai đó có thể cho rằng sách toàn nói về mã đã là thứ gì đó lỗi thời – rằng bây giờ mã đã không còn là vấn đề nữa, rằng ta nên quan tâm tới những mô hình và yêu cầu thì hơn. Thực tế thì một số người cho rằng thời đại chúng ta bây giờ đang tiến gần tới sự kết thúc của việc viết mã. Sẽ sớm tới ngày tất cả các mã lệnh sẽ được tự động tạo ra thay vì phải viết. Rồi thì đơn giản là sẽ không còn cần tới lập trình viên nữa – bởi vì những người kinh doanh sẽ tạo ra chương trình từ những chi tiết kỹ thuật.
Vớ vẩn! Chúng ta sẽ không bao giờ thoát khỏi mã lệnh. Bởi vì mã lệnh đại diện cho các chi tiết của yêu cầu. Có những chi tiết ở một vài mức độ thậm chí không thể bỏ qua hay trừu tượng hóa được mà phải được đặc tả rõ ràng. Và quá trình đặc tả những yêu cầu thành những chỉ thị mà máy tính có thể thực thi được thì chính là sự lập trình. Một đặc tả như vậy chính là mã lệnh.
Tôi mong rằng mức độ trừu tượng của các ngôn ngữ lập trình sẽ tiếp tục tăng. Tôi cũng hi vọng rằng sẽ có thêm nhiều ngôn ngữ miền cụ thể (Domain-specific language*) hơn nữa. Đó là một điều tốt. Nhưng chúng sẽ không loại bỏ việc viết mã. Thực tế là tất cả những đặc tả được viết bằng những ngôn ngữ miền cụ thể cấp cao hiện nay vẫn là mã. Nó vẫn cần chặt chẽ, chính xác và đủ formal và chi tiết để máy móc có thể hiểu và thực thi nó.
Những người tin rằng mã lệnh sẽ tuyệt chủng thật sự giống như là những nhà toán học hi vọng có một ngày họ có thể nghiên cứu toán học mà không cần dùng tới các công thức. Họ cũng có một ước mơ, rằng một ngày sẽ tìm ra cách để tạo ra các cỗ máy có thể làm những gì chúng ta muốn thay vì những gì chúng ta nói. Những cỗ máy này sẽ phải hiểu chúng ta tốt tới nỗi chúng có thể dịch những yêu cầu mơ hồ thành một chương trình đáp ứng những yêu cầu đó một cách tuyệt vời.
Điều đó sẽ không bao giờ xảy ra. Thậm chỉ cả loài người với tất cả trực giác và khả năng sáng tạo của mình cũng không thể tạo ra những hệ thống thành công từ những cảm giác mơ hồ của khách hàng. Trên thực tế, nếu việc đặc tả các yêu cầu có thể dạy chúng ta điều gì, thì đó là một đặc tả tốt bao giờ trông cũng giống như mã và có thể đóng vai trò như những kiểm thử chạy được luôn của mã đó.
Nhớ rằng mã lệnh suy cho cùng thật ra là ngôn ngữ để chúng ta diễn đạt các yêu cầu. Chúng ta có thể tạo ra những ngôn ngữ lập trình gần với yêu cầu hơn. Ta cũng có thể tạo ra các công cụ giúp ta phân tích và ráp những yêu cầu thành các cấu trúc chuẩn. Nhưng ta sẽ không bao giờ được loại bỏ sự chính xác thiết yếu – và thế là, mã sẽ mãi luôn tồn tại.
Mã xấu
Gần đây tôi được đọc lời nói đầu trong một cuốn sách của Kent Beck – cuốn Implementation Patterns (Cài đặt Mẫu thiết kế). Trong đó có câu “cuốn sách này được dựa trên một giả thuyết khá mong manh: mã tốt là một vấn đề quan trọng”. Một giả thuyết mong manh? Tôi không đồng ý. Tôi nghĩ rằng tiền đề đó là một trong những cơ sở mạnh mẽ nhất, được khuyến khích nhất, và nan giải nhất trong nghề của chúng ta (và tôi nghĩ là Kent biết điều đó). Còn chúng tôi thì hiểu rõ, vì đã phải đương đầu với sự hiếm hoi của mã nguồn tốt quá lâu rồi.
Tôi biết một công ty vào cuối những năm 1980 đã viết một ứng dụng sát thủ (killer application). Nó đã rất phổ biến, và rất nhiều chuyên gia đã mua và sử dụng nó. Nhưng rồi các chu kỳ phát hành phiên bản mới ngày càng thưa dần. Các lỗi không được sửa sau mỗi bản phát hành. Ứng dụng càng lúc càng “nặng” và hay bị “treo”. Tôi nhớ một ngày tôi đã tắt chương trình đó đi trong sự thất vọng và không bao giờ sử dụng nó nữa. Còn công ty thì đã chấm dứt kinh doanh một thời gian ngắn sau.
Hai thập kỷ sau, tôi gặp một trong những nhân viên đầu tiên của công ty đó và hỏi anh ta những gì đã xảy ra. Câu trả lời đã xác nhận những e ngại của tôi. Họ đã vội vã tung sản phẩm ra thị trường và tạo ra một mớ lộn xộn khổng lồ trong mã. Khi họ thêm ngày càng nhiều các tính năng thì mã nguồn ngày càng tệ hại hơn nữa. Cho đến khi họ thực sự không thể quản lý nổi mã nguồn nữa. Vậy chính mã nguồn xấu đã làm công ty phải đóng cửa.
Đã bao giờ bạn gặp trở ngại to lớn do mã nguồn xấu? Nếu bạn là một lập trình viên từng trải, bạn hẳn đã nhận ra sự trở ngại này nhiều lần. Trên thực tế, chúng tôi đã đặt cho nó một cái tên. Chúng tôi gọi đó là “lội”. Chúng tôi lội qua mã xấu, một cách ì ạch qua những bãi lầy đầy gai rối và cạm bẫy. Chúng tôi nỗ lực tìm đường, loay hoay để tìm ra một vài gợi ý, một ít đầu mối, về những gì đang xảy ra; nhưng tất cả những gì chúng tôi thấy là nhiều và nhiều hơn nữa những dòng mã vô nghĩa.
Tất nhiên bạn đã từng gặp trở ngại với mã xấu. Vậy thì – tại sao bạn lại viết ra chúng?
Có phải bạn đã cố đi nhanh? Lúc đó bạn đang vội? Có lẽ vậy. Có lẽ bạn cảm thấy bạn không có thời gian để làm một việc tốt; rằng sếp có thể sẽ bực mình nếu bạn dành thời gian để làm sạch mã của bạn. Có lẽ bạn thật ra rất mệt mỏi với dự án này và chỉ mong cho nó xong sớm. Hoặc cũng có thể bạn nhìn vào backlog và thấy còn rất nhiều hạng mục khác mà mình đã hứa sẽ hoàn thành, và bạn nhận ra rằng phải nhanh chóng “làm cho xong” mô-đun này để có thể chuyển sang việc tiếp theo.
Chúng ta cũng từng làm như vậy. Chúng ta cũng từng nhìn vào mớ bừa bộn mình vừa tạo ra và ngao ngán quyết định sẽ dọn sau. Chúng ta cảm thấy nhẹ nhõm khi chương trình lộn xộn của chúng ta hoạt động được và quyết định rằng “lộn xộn còn hơn là không có gì”. Chúng ta thống nhất rằng sẽ quay lại làm sạch nó sau. Dĩ nhiên là trong những ngày đó chúng ta chưa biết đến “định luật LeBlanc”: để sau nghĩa là không bao giờ.
Tổng chi phí của sự lộn xộn
Nếu bạn làm lập trình viên được khoảng hai đến ba năm, có lẽ bạn đã bị mã rối của ai đó làm chậm lại một cách kinh khủng. Nếu bạn làm lập trình viên lâu hơn ba năm, có lẽ bạn cũng đã bị mã rối làm chậm lại. Mức độ làm chậm có thể khác biệt đáng kể. Qua một hoặc hai năm, những đội đang triển khai giai đoạn đầu dự án ở tốc độ rất nhanh có thể thấy rằng tốc độ của họ trở nên chậm như sên. Mỗi sự thay đổi mã nguồn làm hỏng hai hay ba phần khác trong mã nguồn. Không sự thay đổi nào là dễ dàng. Mỗi việc thêm mới hay sửa đổi hệ thống đòi hỏi bạn phải hiểu hết những mớ bòng bong và những nút thắt của mã để bạn có thể thêm vào những mớ bòng bong và những nút thắt khác. Càng ngày đống lộn xộn càng to ra, sâu hơn và cao hơn, họ không thể dọn sạch nó được. Không thể nào làm nổi.
Mã nguồn càng lộn xộn càng làm năng suất làm việc của nhóm liên tục giảm đi, gần như xuống tới không. Và vì năng suất giảm, người quản lý làm việc duy nhất họ có thể làm đó là: bổ sung nhân lực cho dự án hòng cải thiện năng suất. Nhưng nhân viên mới lại không thông thạo về thiết kế hệ thống. Họ không hiểu rằng có những thay đổi phù hợp với định hướng thiết kế trong khi một số khác thì không. Hơn nữa, họ cùng những người khác trong nhóm đều phải chịu áp lực khủng khiếp để tăng năng suất. Và tất cả họ càng ngày càng làm ra nhiều lộn xộn hơn, làm năng suất giảm gần về không hơn.
Cuộc tái thiết vĩ đại giữa lưng chừng trời
Cuối cùng thì nhóm quyết định làm điều gì đó. Họ thông báo cho quản lý rằng họ không thể tiếp tục phát triển mớ mã nguồn kinh khủng này. Họ yêu cầu được thiết kế lại. Quản lý không muốn phải dùng cạn kinh phí của dự án cho việc tái thiết, nhưng cũng không thể phủ nhận rằng năng suất đang thật khủng khiếp. Cuối cùng họ nhượng bộ yêu cầu của đội ngũ phát triển và cho phép bắt đầu cuộc tái thiết kế vĩ đại giữa lưng chừng dự án.
Một nhóm gồm những tay cứng cựa được chọn ra. Ai cũng muốn được vào nhóm này bởi vì đây là một dự án mới toanh. Họ sẽ được làm lại từ đầu và sẽ tạo ra một thứ thật sự đẹp đẽ. Nhưng chỉ những cá nhân xuất sắc và triển vọng nhất được lựa chọn để gia nhập “biệt đội hổ”. Những người khác phải tiếp tục bảo trì hệ thống hiện tại.
Bây giờ thì hai đội đang ở trong một cuộc đua. Đội hổ cần phải xây dựng một hệ thống mới có thể làm mọi thứ thay cho hệ thống cũ. Không những thế, họ còn phải theo kịp với những thay đổi liên tục được thực hiện trên hệ thống cũ. Quản lý sẽ không thay thế hệ thống cũ cho tới khi hệ thống mới đã hoàn toàn đáp ứng được công việc của hệ thống cũ.
Cuộc đua này có thể tiếp diễn qua một thời gian rất dài. Tôi đã thấy nó mất tới mười năm. Qua thời gian, những thành viên cũ của đội hổ đã rời đi, và những thành viên hiện tại đang yêu cầu được tái thiết kế hệ thống mới bởi vì hệ thống mới đã lại là một mớ mã nguồn lộn xộn.
Nếu bạn đã từng trải qua chỉ cần một phần nhỏ câu chuyện tôi vừa kể, bạn đã biết rất rõ rằng bỏ thời gian để giữ cho mã sạch không chỉ là vấn đề giảm chi phí, mà nó là chuyện sống còn của lập trình viên chuyên nghiệp.
Thái độ
Bạn đã bao giờ lội qua những vũng bùn của mã nguồn khó khăn đến nỗi phải mất một tuần để làm những thứ lẽ ra nên xong trong một giờ? Đã bao giờ nhận thấy lẽ ra chỉ cần thay đổi một dòng mã thay vì phải sửa trong hàng trăm mô-đun khác nhau. Những triệu chứng này đã quá phổ biến rồi.
Tại sao những điều đó xảy ra với mã? Tại sao mã tốt nhanh chóng biến thành mã xấu. Chúng ta đưa ra rất nhiều lời giải thích. Chúng ta phàn nàn rằng những yêu cầu ban đầu bị thay đổi đã phá vỡ thiết kế ban đầu. Chúng ta than vãn rằng lịch công việc quá chặt chẽ để làm mọi thứ một cách đúng đắn.
Chúng tôi đổ lỗi cho quản lý ngu ngốc, những khách hàng cứng cổ, các thể loại tiếp thị vô dụng và cả “những người dọn toa lét”. Nhưng lỗi, Dilbert thân mến, không phải tại những ngôi sao của chúng tôi, mà thuộc về bản thân chúng tôi.
Sự thật đó như một viên thuốc đắng khó nuốt trôi. Làm thế nào mà đống lộn xộn này lại là lỗi của chúng tôi? Thế còn những yêu cầu? Còn lịch công việc thì sao? Quản lý đần độn và tiếp thị vớ vẩn thì sao? Chẳng lẽ họ không lãnh phần trách nhiệm nào?
Không hề! Các quản lý và bộ phận tiếp thị tìm tới chúng ta cho thông tin họ cần để soạn ra những lời hứa và cam kết; và ngay cả khi họ không tới tìm, chúng ta vẫn không nên ngần ngại nói với họ quan điểm của mình. Người dùng thì tìm tới chúng ta để xác nhận liệu những yêu cầu có thích hợp với hệ thống hay không. Quản lý dự án thì nhờ chúng ta hỗ trợ trong việc quyết định lịch trình. Chúng ta can dự sâu sắc vào viện lên kế hoạch cho dự án và chia sẻ phần không nhỏ trách nhiệm với bất kỳ một sự thất bại nào; đặc biệt nếu những thất bại đó một phần là do mã xấu.
Bạn có thể nói “Từ từ đã! Nếu tôi không làm những gì quản lý yêu cầu, tôi sẽ bị sa thải mất.” Không hẳn. Hầu hết quản lý muốn được biết sự thật, ngay cả khi họ không hành động như vậy. Hầu hết các quản lý muốn có mã tốt, ngay cả khi họ bị ám ảnh về lịch trình. Họ có thể bảo vệ lịch trình và yêu cầu với sự đam mê; nhưng đó là công việc của họ. Công việc của bạn là bảo vệ mã nguồn với một đam mê tương đương họ.
Để làm rõ chuyện này, hãy giả sử bạn là một bác sỹ và có một bệnh nhân yêu cầu bạn bỏ qua mấy công việc rửa tay vớ vẩn trong khi chuẩn bị cho ca phẫu thuật vì chúng mất quá nhiều thời gian. Rõ ràng bệnh nhân là ông chủ, nhưng bác sỹ hoàn toàn nên từ chối làm theo yêu cầu trên. Tại sao? Bởi vì chắc chắn là bác sỹ biết rõ hơn bệnh nhân về nguy cơ lây bệnh và nhiễm trùng. Sẽ là không chuyên nghiệp (thậm chí vi phạm pháp luật) nếu bác sĩ làm theo yêu cầu của bệnh nhân. Vì vậy cũng sẽ là không chuyên nghiệp nếu như lập trình viên nhất nhất tuân theo ý muốn của nhà quản lý – những người không am hiểu rủi ro của việc tạo ra mã nguồn lộn xộn.
Bài toán căn bản
Lập trình viên phải đối mặt với một bài toán hóc búa của các giá trị cơ bản. Tất cả các nhà phát triển có vài năm kinh nghiệm đều hiểu rằng những đoạn mã lộn xộn rồi sẽ làm họ bị chậm lại. Và những người đó luôn cảm thấy áp lực buộc phải tạo ra mã lộn xộn, để đáp ứng thời hạn. Tóm lại, họ bỏ đi phần thời gian dành cho việc gỡ rối mã nguồn để đáp ứng tiến độ.
Chuyên gia thực thụ biết rằng phần thứ hai của bài toán là không đúng. Bạn sẽ không đáp ứng được tiến độ bằng cách tạo ra những đoạn mã lộn xộn. Thật vậy, mã lộn xộn sẽ làm bạn chậm lại ngay lập tức, và sẽ khiến bạn phải trễ thời hạn. Cách duy nhất để đáp ứng tiến độ – cách duy nhất để đi nhanh – đó là giữ cho mã nguồn của bạn luôn luôn sạch nhất có thể.
Nghệ thuật của mã sạch
Hãy coi như bạn tin rằng mã lộn xộn là một tay ngáng đường kinh khủng. Và bạn chấp nhận rằng cách duy nhất để đi nhanh là giữ sạch mã của bạn. Vậy bạn sẽ tự hỏi: “Làm thế nào để viết mã sạch?” Sẽ là không ổn chút nào nếu bạn cố gắng thử viết mã sạch mà không được biết thật ra như thế nào mới được gọi là mã sạch.
Tin xấu là viết mã sạch có rất nhiều điểm giống như vẽ một bức tranh. Phần lớn chúng ta biết như thế nào là tranh được vẽ đẹp hay xấu. Nhưng có thể nhận thức được cái đẹp và cái xấu không có nghĩa là chúng ta biết làm thế nào để vẽ. Thế nên việc nhìn ra mã sạch hay mã xấu không có nghĩa là ta biết làm thế nào để viết ra mã sạch.
Việc viết mã nguồn sạch yêu cầu sử dụng một cách kỷ luật vô số kỹ thuật nhỏ được ứng dụng thông qua việc dày công luyện tập cảm giác về sự “sạch”. Cảm-giác-mã này là chìa khóa. Một vài trong chúng ta sinh ra đã có được cảm-giác-mã. Một số thì phải chiến đấu để có được nó. Nó không chỉ quan trọng trong việc làm cho chúng ta nhận thấy được mã tốt hay mã xấu, mà còn giúp ta nhìn ra chiến lược để áp dụng kỷ luật mà chúng tôi đề ra cho việc chuyển đổi mã xấu thành mã sạch.
Một lập trình viên thiếu cảm-giác-mã có thể nhìn vào một mô-đun lộn xộn và nhận ra sự lộn xộn trong đó nhưng sẽ không biết sẽ phải làm gì với nó. Lập trình viên có cảm-giác-mã tốt thì khác, anh ta sẽ thấy được những hướng phát triển khác. Cảm-giác-mã sẽ giúp lập trình viên chọn được hướng biến đổi tốt nhất, đưa anh (cô) ta qua một chuỗi biến đổi mà không làm thay đổi hành vi để đi đến đích.
Tóm lại, một “lập trình viên viết mã sạch” là một nghệ sĩ người mà có thể biến một màn hình trống rỗng thành một hệ thống mã thanh lịch thông qua một chuỗi biến đổi
Mã sạch là gì?
Mỗi lập trình viên thì lại có một định nghĩa về mã sạch khác nhau. Vậy nên tôi đã đi hỏi một vài người rất nổi tiếng và dày dạn kinh nghiệm xem họ nghĩ gì về mã sạch.
Bjarne Stroustup, người phát minh ra C++ và là tác giả của cuốn The C++ Programming Language
“Tôi thích mã của tôi thanh lịch và hiệu quả. Lô-gic nên đơn giản để làm cho nó khó gặp những lỗi ẩn, có tối thiểu những sự phụ thuộc để dễ dàng bảo trì, xử lý lỗi hoàn chỉnh theo những chiến lược thống nhất, và hiệu suất gần như tối ưu để không cám dỗ người ta làm mã lộn xộn với những trò tối ưu hóa lố lăng. Mã sạch là mã làm tốt một việc”.
Bjarne dùng từ “thanh lịch”. Một từ hết xẩy. Từ điển trong MacBook® của tôi cung cấp các định nghĩa sau: “diện mạo tinh tế và dễ chịu ; tài tình dễ chịu và đơn giản.” Bất cứ định nghĩa nào cũng nhấn mạnh sự “dễ chịu”. Rõ ràng Bjarne cho rằng mã sạch phải là mã khiến người đọc dễ chịu. Đọc nó phải làm bạn mỉm cười vui sướng giống hệt như trải nghiệm mà một hộp nhạc được chế tác tinh xảo hoặc chiếc xe hơi được thiết kế tinh tế mang lại.
Bjarne cũng đề cập đến “hiệu suất” – hai lần. Có lẽ điều này không làm chúng ta ngạc nhiên vì nó tới từ người sáng tạo ra C++; nhưng tôi nghĩ có nhiều điều để nói về hiệu suất ngoài chuyện tốc độ. Những chu kỳ lãng phí không thanh lịch, chúng không dễ chịu. Và hãy lưu ý từ mà Bjarne dùng để mô tả hệ quả của việc không thanh lịch. Ông dùng từ “cám dỗ”. Có một sự thật sâu sắc ở đây. Mã xấu “cám dỗ” sự lộn xộn phát triển. Khi những người khác thay đổi mã xấu, họ thường có xu hướng làm cho nó tồi tệ hơn.
Pracmatic Dave Thomas và Andy Hunt (**) đã nói về điều này theo một cách khác. Họ sử dụng câu chuyện ẩn dụ về những cửa sổ bị hỏng. Một tòa nhà có những cửa sổ bị hỏng khiến mọi người tưởng rằng không ai quan tâm đến nó. Vì vậy họ cũng không quan tâm đến nó. Họ cứ để mặc những cửa sổ hỏng (broken windows). Cuối cùng người ta chủ động phá chúng. Họ vẽ đầy những hình graffiti lên mặt trước tòa nhà, để mặc cho rác chất đống. Một ô cửa sổ hỏng sẽ dẫn đến sự đổ nát.
Bjarne cũng đề cập tới việc xử lý lỗi nên được hoàn chỉnh. Điều này tiến tới kỷ luật trong việc chú ý vào các chi tiết. Xử lý lỗi không hoàn chỉnh chỉ là một cách để các lập trình viên trốn tránh các chi tiết. Rò rỉ bộ nhớ là một ví dụ khác, tranh đoạt điều khiển (race condition) cũng thế. Đặt tên không nhất quán là một ví dụ khác nữa. Ta có thể kết luận rằng mã sạch thể hiện sự chú ý tỉ mỉ đến từng chi tiết.
Bjarne kết thúc với sự khẳng định rằng mã sạch là mã làm tốt một thứ. Không phải ngẫu nhiên mà có rất nhiều nguyên tắc thiết kế phần mềm có thể tóm lược lại thành lời khuyên đơn giản này. Hết tác giả này đến tác giả khác đã cố gắng truyền đạt tư tưởng này. Mã xấu cố gắng làm quá nhiều thứ, nó có ý định lộn xộn và mục đích không rõ ràng. Mã sạch là sự hội tụ. Mỗi chức năng, mỗi lớp, mỗi môđun cho thấy sự tập trung vào một mục đích, ý đồ duy nhất mà không bị sao nhãng và làm bẩn bởi những chi tiết ngoài lề.
Grady Booch, tác giả cuốn Object Oriented Analysis and Design with Applications
“Mã sạch là mã đơn giản và trực tiếp. Mã sạch được đọc như đọc văn xuôi được viết trôi chảy. Mã sạch không bao giờ làm lu mờ ý định của người thiết kế mà nó luôn có đầy những sự trừu tượng hóa rõ ràng và những dòng mã điều khiển dễ hiểu.”
Grady đưa ra một vài luận điểm tương tự như Bjarne, nhưng ông ấy nhắc tới khía cạnh “dễ đọc”. Tôi đặc biệt thích quan điểm của ông về “đọc mã sạch như đọc văn xuôi được viết trôi chảy.” Hãy nhớ lại một cuốn sách được viết tốt mà bạn đã đọc. Nhớ lại cách mà từ ngữ đã biến mất và thay vào đó là những hình ảnh hiện ra. Giống như xem một bộ phim phải không? Tốt hơn nữa. Bạn thấy những nhân vật, bạn nghe thấy tiếng động, bạn thấy xúc độc và vui vui.
Đương nhiên đọc mã sạch không thể giống hoàn toàn như đọc Chúa tể chiếc nhẫn. Nhưng ẩn dụ đó cũng không phải là quá tệ. Bởi cũng giống như một cuốn tiểu thuyết hay, mã sạch phải phơi bày rõ ràng những căng thẳng trong vấn đề cần giải quyết. Cần đưa những căng thẳng lên tới đỉnh điểm và rồi làm cho người đọc thốt lên: “À há, tất nhiên rồi!” khi thấy các vấn đề và sự căng thẳng được giải quyết bằng một giải pháp rõ ràng.
Tôi thấy rất thú vị với phép chơi chữ nghịch hợp mà Grady sử dụng khi dùng cụm từ “trừu tượng hóa rõ ràng” (“crisp abstraction”). Dù theo nghĩa nào, từ crisp cũng gần như là một từ đồng nghĩa với từ “concrete” (cụ thể). Từ điển trong máy Macbook của tôi có những nghĩa sau của từ crisp: quyết định dứt khoát và thực-tế-nó-vậy, không ngập ngừng hoặc có chi tiết thừa. Dù cho có những ý nghĩa chẳng liên quan đến nhau lắm, từ này vẫn mang đến một thông điệp mạnh mẽ. Mã của chúng ta phải có tính thực-tế-nó-vậy, không phải có tính suy đoán, không chắc chắn. Nó chỉ gồm những gì thực sự cần thiết. Người đọc phải hiểu rõ điều chúng ta quyết định làm trong từng dòng mã.
“Vĩ đại” Dave Thomas, sáng lập viên của OTI, cha đẻ của chiến lược Eclipse
“Mã sạch là mã có thể được đọc và cải tiếng bởi một nhà phát triển bất kỳ chứ không phải chỉ tác giả của nó mới đọc nổi. Nó phải có cả kiểm thử đơn vị ở phía lập trình viên lẫn kiểm thử chấp chận do khách hàng thực hiện. Mã sạch có những tên có ý nghĩa. Nó chỉ đưa ra một cách để làm một việc chứ không đưa ra nhiều cách. Mã sạch có tối thiểu những sự phụ thuộc luôn được định nghĩa một cách tường minh, và đưa ra một cách dùng rõ ràng và tối thiểu hóa các API. Mã nên dễ đọc bởi vì tùy từng ngôn ngữ, không phải mọi thông tin cần thiết đều có thể được thể hiện rõ ràng chỉ bằng mã.”
Dave có cùng đam mê với Grady về sự dễ đọc, nhưng với một sự bổ sung quan trọng. Ông khẳng định rằng mã sạch giúp người khác dễ dàng cải tiến nó. Điều này có vẻ hiển nhiên, nhưng ta không thể quá coi trọng điều này. Dù sao thì vẫn có sự khác biệt giữa mã dễ đọc và mã dễ cải tiến.
Dave gắn liền tính sạch sẽ với các kiểm thử. Vào thời điểm mười năm trước việc này có thể làm nhiều người nhíu mày. Nhưng kỹ thuật phát triển hướng kiểm thử (Test Driven Development) đã tác động sâu sắc tới toàn nghành công nghiệp phần mềm và trở thành một trong những kỹ thuật cơ bản nhất của chúng ta. Dave nói đúng. Mã không có kiểm thử thì không thể gọi là sạch. Dù cho nó thanh lịch cỡ nào, dễ dọc và dễ tiếp cận ra sao, nếu không có kiểm thử, nó không sạch.
Dave đã hai lần dùng tới từ “tối thiểu”. Rõ ràng ông coi trọng mã nguồn nhỏ gọn hơn là mã nguồn cồng kềnh. Thật vậy, đây là một điệp khúc phổ biến trong tất cả “tàng thư phần mềm” kể từ những tài liệu đầu tiên. Nhỏ hơn thì tốt hơn.
Dave cũng nhắc tới rằng mã nên dễ đọc. Quan điểm này khá gần gũi với thuyết lập trình Literate của Knuth. Nghĩa là mã nên được viết ra với một hình thức dễ đọc cho con người.
Michael Feathers, tác giả của Working Effectively with Legacy Code
Tôi có thể liệt kê tất cả những phẩm chất mà tôi nhận thấy trong mã sạch, nhưng có một phẩm chất bao trùm dẫn đến tất cả chúng. Đó là mã sạch bao giờ cũng trông như được viết bởi những người có tâm. Không có manh mối rõ ràng nào cho bạn biết có thể làm mã này tốt hơn nữa. Tất cả mọi phương án dường như đều đã được tác giả của mã này nghĩ tới, và nếu bạn cố gắng tưởng tượng ra những bước cải tiến, bạn sẽ được dẫn về lại chỗ cũ, nơi bạn đang ngồi cảm kích trước mã nguồn được để lại cho bạn bởi một người hết sức có tâm với nghề.
Một từ: “tâm”. Đó thực sự là chủ đề của cuốn sách này. Còn phụ đề sẽ là “Để tâm đến mã như thế nào”.
Michael nhấn mạnh nó đầu tiên. Mã sạch là mã được để tâm tới. Một ai đó đã phải mất thời gian để giữ cho nó đơn giản và ngăn nắp. Họ đầu tư một sự chú ý thích đáng tới các chi tiết. Họ đã để tâm.
Ron Jeffries, tác giả cuốn “Extreme Programming Installed” và “Extreme Programming Adventures in C#”.
Ron bắt đầu sự nghiệp lập trình của mình bằng ngôn ngữ Fortran tại Bộ tư lệnh Không quân Chiến lược và đã viết mã nguồn trong hầu hết các ngôn ngữ và trên gần như tất cả các loại máy. Chúng ta nên xem xét ý kiến của ông một cách cẩn thận.
Trong những năm gần đây, tôi bắt đầu làm theo, gần như đầy đủ, những quy tắc của Beck về mã nguồn đơn giản. Xếp theo độ quan trọng thì thứ tự là:
• Chạy tất cả các kiểm thử;
• Không có sự trùng lặp;
• Diễn đạt tất cả các ý tưởng thiết kế có trong hệ thống;
• Có tối thiểu số lượng các lớp, phương thức, chức năng, và những thứ tương tự.
Trong số những quy tắc này, tôi quan tâm chủ yếu tới sự trùng lặp. Khi một điều được thực hiện nhiều lần, đó là một dấu hiệu cho thấy có một ý tưởng trong tâm trí chúng ta đã không được triển khai tốt trong mã nguồn. Tôi cố gắng tìm ra nó là gì. Sau đó tôi cố gắng thể hiện ý tưởng đó rõ ràng hơn.
“Với tôi, tính rõ nghĩa bao gồm việc đặt tên có ý nghĩa, và tôi thường phải đổi tên của một thứ gì đó nhiều lần cho tới khi vừa ý. Với các công cụ viết mã hiện đại như là Eclipse, đổi tên không hề phức tạp, vì vậy không phải là vấn đề lớn đổi với tôi trong việc đổi các tên. Tuy nhiên, tính rõ nghĩa cũng không chỉ nằm trong các tên. Tôi cũng xem xét liệu có đối tượng hay phương thức nào làm nhiều hơn một việc hay không. Nếu nó là một đối tượng, có thể sẽ cần phải chia nó thành hai hoặc nhiều đối tượng. Nếu nó là phương thức, tôi thường dùng kỹ thuật tái cấu trúc“Extract Method”, kết quả là tôi có một phương thức diễn đạt rõ ràng hơn về việc nó làm, và một số phương thức con diễn đạt việc đó được làm như thế nào.”
Sự trùng lặp và tính rõ nghĩa đã chiếm rất nhiều thời gian của tôi trong định nghĩa về mã sạch, đổi lại chỉ với hai điều đó thôi cũng có thể làm cho mã xấu trở nên sạch hơn rất nhiều. Tuy nhiên, còn một điều nữa mà tôi vẫn làm để viết mã sạch thì khó diễn đạt hơn một chút.
“Sau nhiều năm làm công việc này, tôi nhận thấy rằng có vẻ mọi chương trình điều được tạo thành từ những yếu tố rất giống nhau. Ví dụ như “tìm thứ gì đó trong một bộ sưu tập (collection)”. Cho dù cái chúng ta có là một cơ sở dữ liệu các hồ sơ nhân viên, hay một bảng băm (hashmap) của khóa và giá trị, hoặc một mảng các phần tử loại gì đó, thì chúng ta cũng đều nảy sinh nhu cầu tìm lấy một món trong chỗ đó. Thế nên khi tôi muốn làm cái việc “tìm thứ gì đó”, tôi thường bao gói việc triển khai cụ thể vào một lớp hoặc phương thức trừu tượng hơn. Việc này cho tôi một vài lợi thế thú vị”.
“Tôi hoàn toàn có thể triển khai chức năng ngay lúc đó một cách đơn giản bằng cách sử dụng một bảng băm (hashmap) chẳng hạn, nhưng do tất cả các tham chiếu đến việc tìm kiếm đó đều được gói lại trong trừu tượng hóa nhỏ bé của tôi(một hàm tìm kiếm), tôi có thể thay đổi cách thức triển khai việc tìm kiếm bất cứ lúc nào tôi muốn. Và tôi có thể đi tiếp nhanh hơn trong khi vẫn có thể thay đổi nó sau.”
“Thêm vào đó, việc trừu tượng hóa bộ sưu tập (collection) lên thường giúp tôi chú ý tới việc gì đang thực sự diễn ra, và giữ cho tôi khỏi sa vào việc triển khai những cách làm phức tạp (arbitrary collection), trong khi tôi thực ra chỉ cần vài cách cực kỳ đơn giản để tìm kiếm điều tôi muốn”.
“Giảm thiểu trùng lặp, cực kỳ rõ nghĩa, và sớm xây dựng những trừu tượng hóa nhỏ.
Với tôi, đó là những thứ làm nên mã sạch”.
Lần này, trong một vài đoạn ngắn, Ron đã tóm tắt nội dung của cuốn sách này. Không trùng lặp, đơn nhiệm (SRP), tính rõ nghĩa, những trừu tượng hóa tí hon. Nội dung cuốn sách này là về tất cả những điều đó.
Ward Cunningham, người tạo ra Wiki, Fit, đồng sáng lập của eXtreme Programing. Động tác giả của cuốn sách Design Patterns (Mẫu thiết kế), lãnh đạo tư tưởng của Smalltalk và Lập trình Hướng Đối tượng. Bố già của bất cứ ai quan tâm đến lập trình.
“Bạn biết bạn đang làm việc với mã sạch khi mỗi đoạn mã bạn đọc đúng như những gì bạn mong đợi. Bạn có thể gọi nó là mã đẹp khi mã đó làm cho ngôn ngữ trông cứ như là ngôn ngữ được tạo ra để giải quyết vấn đề đó.”
Kiểu phát biểu này đúng là kiểu của của Ward. Bạn đọc nó, gật đầu, và sau đó thì chuyển sang chủ đề tiếp theo. Nó có vẻ rất hợp lý, rất rõ ràng cứ như nó là điều tất nhiên vậy. Bạn có thể nghĩ rằng điều đó là hiển nhiên. Nhưng hãy xem xét kĩ hơn một chút.
“…đúng như những gì bạn mong đợi.” Lần cuối bạn thấy một mô-đun đúng như những gì bạn mong đợi là khi nào? Hay bạn toàn thấy các mô-đun thật là phức tạp, loằng ngoằng? Chả phải mã thì luôn gây nhầm lẫn cho người đọc? Chẳng phải bạn đã quen với việc rất khó khăn để hiểu được mô-đun bạn đang đọc thì liên quan quái gì đến toàn bộ hệ thống? Lần cuối mà bạn đọc mã của ai đó và gật đầu như khi bạn gật đầu trước phát biểu của Ward là khi nào?
Ward muốn rằng khi bạn đọc mã sạch bạn sẽ không gặp phải bất cứ sự ngạc nhiên nào. Thật vậy, bạn sẽ không phải tốn nhiều công sức để đọc mã sạch. Bạn đọc nó, và nó sẽ đúng như những gì bạn mong đợi. Nó rõ ràng, đơn giản và thuyết phục. Mỗi mô-đun sẽ chuẩn bị sân khấu cho mô-đun tiếp theo, nó sẽ cho bạn biết điều gì sẽ được viết tiếp. Những chương trình sạch được viết tốt đến nỗi bạn không phải để tâm đến chuyện nó được viết như thế nào. Người thiết kế đã làm cho nó trông cực kỳ đơn giản như những thiết kế tuyệt vời khác.
Thế còn quan điểm của Ward về vẻ đẹp? Chúng ta luôn trách móc cuộc đời rằng ngôn ngữ ta dùng không được thiết kế để giải quyết vấn đề của mình. Nhưng lời của Ward đã đẩy trách nhiệm đó về lại cho chúng ta.
Ông nói rằng mã đẹp làm cho ngôn ngữ trông chứ như là được sinh ra để giải quyết vấn đề đó. Vậy trách nhiệm của chúng ta là phải làm cho ngôn ngữ trông thật đơn giản. Những người hâm mộ cuồng nhiệt của các ngôn ngữ, hãy nhớ rằng! Không phải ngôn ngữ là thứ làm cho chương trình trông đơn giản. Mà chính lập trình viên mới là “thứ” làm cho ngôn ngữ trông đơn giản!
Các trường phái tư tưởng
Còn tôi (Uncle Bob) thì sao? Tôi nghĩ thế nào là mã sạch? Cuốn sách này sẽ nói cho bạn biết, qua những chi tiết rất gớm ghiếc, về những điều mà tôi và những bạn đồng sự nghĩ về mã sạch. Chúng tôi sẽ cho bạn biết suy nghĩ về những gì làm tạo nên một tên biến sạch, một hàm sạch, một lớp sạch, v.v… Chúng tôi sẽ trình bày những ý kiến này như là một sự thật hiển nhiên và chúng tôi sẽ không xin lỗi vì ngôn từ chối tai của mình.
Với chúng tôi, tại thời điểm này của sự nghiệp, chúng là tuyệt đối, hiển nhiên. Chúng là trường phái tư tưởng của chúng tôi về mã sạch.
Các võ sư luôn không đồng ý với nhau về môn phái tốt nhất hay kĩ thuật tốt nhất của một môn phái. Thường thì những võ sư bậc thầy sẽ tạo ra trường phái tư tưởng của riêng họ và chiêu dụ môn sinh đến học. Vì vậy ta có Nhu thuật Gracie được thành lập và giảng dạy bởi nhà Gracie ở Brazil, có Nhu thuật HakkoRyu được thành lập và giảng dạy bởi Okuyama Ryuho ở Tokyo, và có Triệt-quyền-đạo, được Bruce Lee sáng tạo và giảng dạy ở Hoa Kỳ.
Những “môn đệ” của các công phu đó đắm mình trong lời dạy của người lập phái. Họ dồn hết tâm huyết để học theo một người thầy, thường là để xóa đi những điều học được từ những người thầy trước. Sau đó, khi đã phát triển công phu đến một mức nhất định, họ có thể tiếp tục học hỏi từ một bậc thầy khác để mở rộng kiến thức và kỹ năng của họ.
Vài người thậm chí tiếp tục khổ luyện công phu, sáng tạo ra các kỹ thuật mới và lập ra trường phái riêng của họ.
Không trường phái nào trong số đó là đúng tuyệt đối. Nhưng khi học tập tại một ngôi trường cụ thể, chúng ta sẽ mặc nhiên coi tất cả những kỹ năng được dạy là đúng. Đúng là luôn phải có một cách chuẩn mực để luyện tập Nhu thuật Hakkoryu hoặc Triệt quyền đạo. Nhưng chuẩn mực trong một trường phái không làm mất giá trị các lời dạy của một trường phái khác.
Hãy xem cuốn sách này như bản miêu tả của trường (phái) Object mentor về mã sạch. Những kỹ năng và bài học trong đây là cách chúng tôi luyện tập công phu của mình. Chúng tôi sẵn lòng khẳng định rằng nếu bạn làm theo những chỉ dẫn này, bạn sẽ nhận được những lợi ích mà chúng tôi đã đạt được, và bạn sẽ học được cách viết mã sạch và chuyên nghiệp. Nhưng đừng nghĩ rằng chúng tôi đúng tuyệt đối trong mọi trường hợp. Có những trường phái khác và những bậc thầy khác cũng được tuyên bố chuyên nghiệp như chúng tôi. Bạn cũng cần phải học từ họ nữa.
Thật vậy, nhiều điều được khuyến nghị trong cuốn sách này vẫn đang gây tranh cãi. Bạn có thể sẽ không đồng ý với tất cả trong số chúng, và thậm chí có thể dữ dội bác bỏ một số trong đó. Không sao cả. Chúng tôi không thể yêu cầu cho mình quyền thắng cuối cùng. Mặt khác, những khuyến nghị trong này là những thứ mà chúng tôi đã phải suy nghĩ rất kỹ sau một thời gian dài mới nhận ra. Chúng tôi đã học được những điều đó qua nhiều thập kỷ tích lũy kinh nghiệm và thử nghiệm lặp đi lặp lại và sai lầm. Vì vậy cho dù bạn có hay không đồng ý, thật là một sự xấu hổ nếu bạn không nhìn thấy được, và tôn trọng quan điểm của chúng tôi.
Chúng ta là những tác giả
Trường @author của Javadoc nói lên chúng ta là ai. Chúng ta là những tác giả. Và một điều về các tác giả đó là họ có các độc giả. Thật vậy, những tác giả có trách nhiệm là giao tiếp tốt với độc giả của họ. Mỗi khi bạn viết một dòng mã, hãy nhớ bạn là một tác giả, đang viết cho những độc giả người mà sẽ đánh giá thành quả của bạn.
Bạn có thể thắc mắc: “Mã thật sự được đọc nhiều đến mức nào?” “Chẳng phải hầu hết công sức đều dành cho việc viết ra nó sao?” Bạn đã từng chiếu lại một phiên chỉnh sửa? Trong những năm 80 và 90, chúng tôi có những phần mềm editor như là Emacs, chúng có thể lưu giữ tất cả những lần gõ phím. Bạn có thể làm việc trong một giờ và sau đó phát lại toàn bộ phiên làm việc như đang xem một đoạn phim tốc độ cao. Khi tôi thực hiện việc đó, kết quả thực sự thú vị.
Phần lớn của đoạn phim đó là tác vụ cuộn và nhảy tới các mô-đun khác.
“Bob nhảy vào mô-đun.”
“Anh ta cuộn xuống chức năng cần phải sửa đổi.”
“Anh ấy dừng lại, cân nhắc các lựa chọn.”
“Ô, giờ thì hắn cuộn lên đầu mô-đun để kiểm tra việc khởi tạo của 1 biến.”
“Giờ anh ấy cuộn lại chỗ cũ và bắt đầu gõ.”
“Opp, anh xóa câu vừa gõ.”
“Anh lại gõ lại câu đó.”
“Anh lại xóa nó một lần nữa..”
“Anh gõ một nửa của một thứ khác, nhưng rồi lại xóa nó đi.”
“Anh cuộn xuống một hàm khác, chỗ mà có gọi tới hàm anh ta đang sửa đổi, để xem nó được gọi như thế nào.”
“Anh cuộn lại chỗ cũ, gõ lại y hệt những gì vừa xóa.”
“Anh tạm dừng.”
“Anh xóa đoạn code đó một lần nữa!
“Anh ta mở tạm một cửa sổ khác để xem xét một subclass. Liệu chức năng kia có bị ghi đè không?
. . .
Bạn thấy vấn đề rồi chứ. Thực vậy, tỷ lệ giữa thời gian đọc mã so với viết mã nhiều hơn 10:1.
Chúng ta liên tục phải đọc lại mã cũ, việc này chiếm một phần nhất định trong quá trình viết mã mới. Bởi vì tỷ lệ này cao như vậy, chúng ta muốn việc đọc hiểu mã phải thật dễ dàng, ngay cả khi nó làm cho việc viết mã trở nên khó khăn hơn. Tất nhiên ta không thể viết mã mà không cần đọc chính đoạn mã đang viết (trừ khi bạn nhắm mắt trong khi viết mã), thế nên làm cho mã dễ đọc cũng thực sự giúp cho việc viết mã trở nên dễ dàng hơn.
Không có cách nào để thoát khỏi lô-gic này – bạn không thể viết mã nếu bạn không thể đọc được mã xung quanh. Đoạn mã hôm nay sẽ khó hay dễ để viết phụ thuộc vào những đoạn mã liên quan đến nó là khó hay dễ để đọc. Vì vậy nếu bạn muốn công việc của bạn trôi chảy, muốn xong nhanh, muốn viết ra mã dễ dàng hơn – trước hết hãy làm cho nó dễ đọc.
Luật hướng đạo.
Chỉ viết mã tốt thôi là không đủ. Mã còn phải được giữ sạch cùng thời gian. Tất cả chúng ta đều đã chứng kiến mã xấu đi và giảm chất lượng theo thời gian. Do đó chúng ta cần phải chủ động trong việc ngăn ngừa sự suy thoái này.
Những cậu bé hướng đạo sinh của nước Mỹ có một luật đơn giản mà chúng ta cũng có thể áp dụng vào nghề của chúng ta.
“Rời khỏi khu cắm trại sạch hơn lúc bạn đến”
Nếu mỗi lần check-in mã (commit) chúng ta đều làm mã của mình sạch một chút so với khi ta check-out (update) nó về, mã chắc chắn sẽ không bị thối. Việc làm sạch không phải là thứ gì đó quá lớn lao. Đơn giản có thể chỉ là đổi tên một biến nào đó cho tốt hơn, phân tách một chức năng quá lớn, khử một vài đoạn mã lặp, dọn dẹp một câu lệnh if phức tạp v.v..
Bạn có tưởng tượng được việc làm việc trên một dự án mà mã đơn giản là cứ mỗi ngày một trông đẹp hơn? Nếu không phải như vậy thì liệu có phải là chuyên nghiệp nữa hay không? Thực sự, chẳng phải “cải tiến liên tục” là một phần bản chất của tính chuyên nghiệp sao?
Cuốn sách tiền truyện và những nguyên tắc
Về nhiều mặt, cuốn sách này là phần trước (prequel) của một cuốn khác mà tôi đã hoàn thành vào năm 2002 với tựa đề “Phát triển phần mềm linh hoạt: Nguyên tắc, Hình mẫu và Thực hành.” (Agile Software Development: Principles, Patterns, and Practices – (PPP) – ND). Cuốn PPP bản thân nó liên quan tới các nguyên lý của thiết kế hướng đối tượng, và có rất nhiều các bài thực hành được dùng bởi các nhà phát triển chuyên nghiệp. Nếu bạn chưa đọc nó, bạn sẽ thấy rằng nó là phần sau của câu chuyện được kể trong cuốn sách này. Nếu bạn đã đọc PPP, thì giờ đây bạn có cơ hội tìm thấy rất nhiều cảm hứng của nó được lặp lại trong cuốn sách này, nhưng ở cấp độ của mã.
Trong cuốn sách này, bạn sẽ thấy nhắc đến nhiều nguyên tắc thiết kế phần mềm. Trong số đó có thể kể đến Nguyên lý đơn nhiệm (Single Responsibility Principle – SRP), Nguyên lý mở đóng (the Open Closed Principle – OCP), và Nguyên tắc đảo ngược sự phụ thuộc (Dependency Inversion Principle – DIP) ngoài nhiều nguyên tắc khác. Những nguyên tắc đó được miêu tả rất sâu trong cuốn PPP.
Kết luận
Sách về nghệ thuật không bảo đảm giúp bạn trở thành nghệ sĩ. Tất cả những gì nó làm đó là cung cấp cho bạn một số công cụ, kỹ thuật và cách suy nghĩ mà những nghệ sĩ khác đã sử dụng. Vậy nên cuốn sách này không thể đảm bảo sẽ làm bạn trở thành một lập trình viên tốt. Nó không thể đảm bảo sẽ giúp bạn có được cảm-giác-mã. Tất cả nó làm là cho bạn thấy tư duy của những lập trình viên tốt và những thủ thuật, kỹ thuật và công cụ mà họ dùng.
Cũng giống như một cuốn sách về nghệ thuật, bạn sẽ thấy cuốn sách này có rất nhiều những chi tiết. Bạn sẽ thấy rất nhiều mã. Có cả mã tốt và mã xấu. Và bạn sẽ thấy quá trình chuyển mã xấu thành mã tốt. Bạn sẽ thấy hàng loạt các cách giải quyết vấn đề thông qua việc thử nghiệm, những nguyên lý, và những kỹ thuật. Bạn sẽ thấy rất nhiều ví dụ. Kết quả đạt được sẽ phụ thuộc vào chính bản thân bạn.
Bạn có nhớ câu chuyện đùa cũ về người nghệ sĩ hòa tấu violin bị lạc đường khi đang đến buổi biểu diễn (tại Carnegie Hall)? Anh ta hỏi một cụ già xem mình phải làm gì để tới được Carnegie Hall (* “phòng hòa nhạc của những giấc mơ” – ND). Cụ già nhìn chăm chú người nghệ sĩ với cây violin kẹp dưới cánh tay, và nói: “Luyện tập, con trai ạ. Luyện tập!”
(*) Domain-specific language: – trong phát triển phần mềm, là một loại ngôn ngữ lập trình dành riêng cho một vấn đề / kỹ thuật biểu diễn / giải pháp cụ thể. HTML là một ví dụ về DSL. Trái ngược với DSL là General-purpose Programming Language ( những ngôn ngữ lập trình được thiết kế cho lập trình trên diện rộng, điển hình là C, Java, Python ) và General-purpose Modeling Language mà UML là một ví dụ.
(**) Hai người này đã sáng lập Pracmatic programer, và tác giả dùng từ Pracmatic trong tên như biệt danh.
Techtalk via tapchilaptrinh