Nguyên lý KISS trong lập trình
KISS = Keep It Simple Stupid Bài viết này nhằm giới thiệu nguyên lý KISS (Keep It Simple Stupid) trong lập trình ứng dụng. Bài viết được thể hiện theo quan điểm của tác giả, nếu các bạn cảm thấy chưa chính xác, hãy vui lòng góp ý! "Make things as simple as possible, but not simpler" –Einstein ...
KISS = Keep It Simple Stupid
Bài viết này nhằm giới thiệu nguyên lý KISS (Keep It Simple Stupid) trong lập trình ứng dụng. Bài viết được thể hiện theo quan điểm của tác giả, nếu các bạn cảm thấy chưa chính xác, hãy vui lòng góp ý!
"Make things as simple as possible, but not simpler" –Einstein
Câu nói trên của Einstein, khi áp dụng trong tình huống lập trình, có nghĩa là “Hãy giữ cho mọi thứ càng đơn giản càng tốt, nhưng không có nghĩa là bỏ qua sự phức tạp của vấn đề cần giải quyết”. Và điều đó có nghĩa là, hãy giữ cho code của bạn thật đơn giản, đọc vào là hiểu ngay nhưng code của bạn vẫn có thể giải quyết được bài toán khó mà bạn đặt ra ban đầu.
Trong lập trình có một nguyên lý có ý nghĩa tương tự với câu nói của Einstein đó là nguyên lý KISS. KISS là viết tắt của cụm từ “Keep It Simple Stupid”, dịch tạm là “giữ cho mọi thứ đơn giản đi ngốc ạ”.
Vậy nguyên lý KISS trong lập trình là như thế nào, tại sao lại nên áp dụng KISS?
Tôi sẽ nêu một tình huống và bạn sẽ nghĩ xem mình đã mắc phải lần nào không nhé.
Bạn cần viết một ứng dụng web blog, nghĩa là có truy xuất dữ liệu, lưu bài viết..v.v Ứng dụng này bạn viết bằng PHP, và bạn chia ứng dụng ra thành nhiều trang, ví dụ trang hiển thị danh sách bài viết, trang quản lý bài viết, trang tạo bài viết… Với trang tạo bài viết bạn sẽ tạo một trang create_article.php, trong đó bạn để tất cả các mã, HTML, PHP, mã truy xuất CSDL, nội dung câu lệnh SQL, chuỗi kết nối CSDL, quản lý GET & POST dữ liệu, bạn sẽ có luôn cả code để tạo slug cho bài viết (ví dụ tiêu đề của bài là “Nguyên lý KISS” thì slug có thể là “nguyen-ly-kiss”), bạn sẽ có mã để upload hình ảnh, thay đổi kích thước của nó, tạo thumbnail. Tất cả những chức năng đó được bạn chỉ viết trong một file, theo thứ tự từ trên xuống dưới. Các trang còn lại cũng được lập trình theo cách tương tự. Bạn viết xong, và đến mười ngày sau bạn vào xem lại, và bạn vò đầu bứt tóc bởi vì mã rối rắm quá.
Nếu ứng dụng của bạn có vài chục trang, bạn sẽ có hàng chục tập tin php với mã dài đằng đẵn lên tới cả ngàn dòng. Bạn sẽ copy và paste ở mọi nơi. Ở trang nào cũng có chuỗi kết nối. Ở trang nào cũng có resize ảnh. Và tới một lúc nào đó, bạn sẽ nhận ra, toàn bộ các dòng lệnh của bạn không có giá trị sử dụng, bởi nó quá rối rắm, và nó hoàn toàn không phù hợp để làm việc theo nhóm bạn sẽ chán ngán và chả muốn đụng vào nữa.
Đó là một tình huống mà người lập trình quên mất nguyên lý KISS.
Bạn cứ nghĩ theo lối thông thường, khi bạn làm một bài toán, bạn khó có thể giải bài toán nếu chỉ đọc cái đề, bạn sẽ phải phân loại bài toán, chia ra các trường hợp để xử lý, và giải những trường hợp nhỏ, khi số biến được giảm bớt và số hằng số tăng lên. Khi bạn lập trình, bạn sẽ làm điều tương tự, đó là chia nhỏ bài toán thành từng phần đủ nhỏ để giải được. Tuy nhiên bạn lại không cố gắng chia nhỏ bài toán nhỏ đến mức nó đơn giản để có thể đọc và hiểu được ngay. Đôi lúc bạn có gắng giải quyết nhiều vấn đề trong cùng một hàm (như ví dụ ở trên) và điều đó dẫn đến việc bạn tạo ra những giải pháp phức tạp cho những bài toán tưởng như đơn giản nhất.
Vậy thì KISS nghĩa là hãy làm cho mọi thứ (mã lệnh của bạn) trở nên đơn giản và dễ nhìn hơn. Hãy chia nhỏ vấn đề ra những bài toán nhỏ đơn giản hơn, viết mã để xử lý nó, biến nó thành các lớp và các hàm riêng biệt, đừng để một lớp hay một phương thức có hàng trăm dòng lệnh, hãy để nó trở về con số chục thôi. Đừng viết những lớp hay phương thức theo kiểu spaghetti hay all-in-one (tất cả trong một) như dao thụy sĩ, hãy để mọi thứ thật đơn giản để bạn luôn có thể hiểu được, và kết hợp chúng với nhau để giải quyết được các bài toán lớn.
Nói ngang đây thì bạn thấy nó vẻ hao hao một nguyên lý nào đó mà bạn đã được nghe qua, đó là nguyên lý SoC, tức là Seperation of Concerns (tách các mối quan tâm ra khỏi nhau), nghĩa là không viết một phương thức hay một class giải quyết nhiều vấn đề, mà tốt hơn là tách nó ra và xây dựng mã riêng biệt để xử lý từng vấn đề một. Nói cách khác, SoC là quá trình chia nhỏ một ứng dụng máy tính thành các tính năng riêng biệt để đảm bảo các tính năng này càng ít lặp nhau càng tốt.
KISS cũng liên quan tới một nguyên lý mà chúng ta cần áp dụng, đó là Single Responsibility Principle (SPR), nghĩa là mỗi đối tượng chỉ đảm nhiệm một vai trò, và có nghĩa rằng mọi dịch vụ mà đối tượng đó đáp ứng thì cũng chỉ được gói gọn trong vai trò đó.
Và cần phải kể đến nguyên lý DRY (Don’t Repeat Yourself), đối với việc lập trình đó là đừng lặp lại việc code một tác vụ nhiều lần, xây dựng một ứng dụng đa tầng cũng để đáp ứng nguyên lý này. Theo Andy Hunt và Dave Thomas trong cuốn sách The Pragmatic Programmer của họ, thì họ đã định nghĩa DRY là "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system." Tạm dịch là “Bên trong một hệ thống, mọi thành phần của tri thức phải có một đại diện duy nhất, có thẩm quyền và phải rõ ràng”, nghe như vậy thì khó hiểu, nhưng nói một cách đơn giản DRY nghĩa là đừng làm việc gì lặp lại, đừng cài đặt một chức năng hai lần.
Các lợi ích bạn sẽ có được là:
Bạn sẽ có khả năng giải quyết nhiều vấn đề hơn với tốc dộ nhanh hơn Bạn có khả năng xây dựng mã lệnh để xử lý các vấn đề phức tạp với số lượng mã ít hơn Bạn có khả năng nâng cao chất lượng của mã lệnh Bạn có thể xây dựng những hệ thống lớn và dễ dàng bảo trì Mã lệnh của bạn sẽ uyển chuyển hơn, dễ mở rộng, điều chỉnh hoặc cải tiến nếu có thêm các yêu cầu mới. Bạn có khả năng đạt được những điều mà bạn chưa từng nghĩ đến Bạn có khả năng làm việc trong những nhóm phát triển lớn và các dự án lớn khi tất cả mã lệnh bạn viết ra vô cùng đơn giản để hiểu.
Để áp dụng KISS, có vài bước cần thực hiện, nói chung thì các bước này khá đơn giản, nhưng cũng khá thử thách, và bạn cần kiên trì để giữ cho mã lệnh của bạn luôn đơn giản. Luôn khiêm tốn, đừng nghĩ bạn là siêu thiên tài, nếu bạn nghĩ như vậy thì bạn đã phạm phải sai lầm đầu tiên. Và điều đó cũng có nghĩa là, bạn không cần phải viết ra cả mớ code phức tạp, hãy viết những dòng lệnh đơn giản, vô cùng dễ để hiểu, và bạn không cần có thiên tài để xử lý những dòng code đó. Chia nhỏ những tác vụ của bạn thành các tác vụ nhỏ hơn để bạn có thể xử lý nó trong vòng từ 4 đến 12 giờ. Chia nhỏ các bài toán của bạn thành các bài toán nhỏ hơn. Mỗi bài toán có thể giải quyết chỉ với một vài class (lớp). Hãy giữ cho phương thức của bạn thật nhỏ và gọn, mỗi phương thức đừng nên có hơn 30 hoặc 40 dòng. Mỗi phương thức chỉ nên xử lý một bài toán, chứ không để xử lý quá nhiều tính huống. Nếu bạn có quá nhiều mệnh lệnh điều kiện trong phương thức của bạn, hãy chia nhỏ thành các phương thức nhỏ hơn. Như vậy nó không chỉ giúp bạn dễ đọc và quản lý hơn mà bạn còn có thể tìm lỗi nhanh hơn. Giữ cho các lớp của bạn nhỏ, như cách bạn giữ cho các phương thức nhỏ và đơn giản. Tìm cách xử lý bài toán trước khi bắt đầu code. Nhiều lập trình viên tìm cách xử lý bài toán khi code, thực ra như vậy cũng chả có gì sai, nhưng vậy có nghĩa là bạn đang vi phạm nguyên tắc này. Vậy thì hãy kiên trì nâng cấp mã lệnh lần này đến lần khác, để mã lệnh của bạn sau mỗi lần xem lại sẽ tốt hơn, đơn giản hơn. Đừng sợ khi phải bỏ code cũ đi và làm lại từ đầu, đó cũng là một công việc quan trọng nên làm, tại sao không xây dựng một giải pháp tốt hơn cho một bài toán cũ nếu bạn thấy rằng việc cải tiến nó mất nhiều thời gian hơn? Nhìn vào tất cả các tình huống, cố gắng giữ cho chúng càng đơn giản càng tốt, và khi bạn áp dụng được như vậy, bạn sẽ nhìn lại và tự hỏi tại sao bạn lại làm những điều quá tệ trong quá khứ với các dự án của bạn.
Đối với lập trình viên Việt Nam, do thường phải làm các dự án out-source nhỏ, chúng ta cứ làm một dự án này rồi chuyển sang dự án khác mà không đủ thời gian quay lại để xem và học tập những dự án cũ, và viết code theo kiểu viết xong, giao cho khách hàng thế là được, chính vì vậy chúng ta tự dễ dãi với mình và làm ra những sản phẩm kém chất lượng, và chúng ta không nâng cấp được kỹ năng của chính mình. Nếu môi trường công ty không cho phép, hãy tự tạo những dự án của chính mình để luyện tập. Nếu xem lập trình là tình yêu, và ngay cả khi nó chỉ là công cụ kiếm tiền, bạn cũng phải để tâm huyết vào cho nó để trở thành chuyên gia thực sự, chỉ có thế bạn mới có thể tiến xa hơn, làm được nhiều điều hơn, và góp phần vẽ được một nét chấm phá cho bản đồ CNTT thế giới cho Việt Nam.
KISS là một nguyên lý đơn giản để hiểu nhưng rất khó áp dụng và đòi hỏi sự kiên nhẫn lớn lao để áp dụng, bạn hãy từ từ áp dụng chúng, và nhớ đừng quên các mẫu thiết kế (design patterns), vì có chúng bạn sẽ áp dụng đượng KISS, SoC, SRPLời khuyên cuối cùng, chả ăn nhập gì với với bài viết này, đó là hãy luôn nghĩ rằng “Mình có thể làm được điều đó theo cách tốt hơn, và nếu có cơ hội, hãy làm cho nó tốt hơn”.
Chúc các bạn áp dụng KISS thành công!