[Code sao cho chuẩn] Bài 4 – Đôi khi code tốt nhất là không code gì cả.

         Lúc còn trẻ, khi chúng ta mới bắt đầu làm một việc gì đó, chúng ta thường có tâm trạng rất háo hức, bản thân tràn đầy nhiệt huyết. Chúng ta muốn tự mình làm hết tất cả mọi thứ, từ những việc nhỏ nhất cho tới việc lớn nhất, chúng ta muốn làm trọn vẹn quy trình từ phân tích thiết kế đến triển khai sản phẩm, chúng ta muốn tự tay mình code hết tất cả các chức năng, như thể sợ ai đó code thay là sẽ lấy hết phần thưởng của ta vậy. Có thể không phải vì sợ mất phần, nhưng vì niềm đam mê học hỏi thôi thúc chúng ta làm như thế. Có lẽ chúng ta chỉ muốn cải thiện khả năng của mình mà thôi, vậy điều đó có nên khuyến khích hay không?

               Lúc còn đi học, một số thầy cô cũng thường khuyên sinh viên không nên sử dụng các thư viện có sẵn mà nên tự mình code chức năng cho quen. Sinh viên cũng hay được khuyên rằng nên tham gia học hỏi và làm thử ở tất cả các quá trình phát triển sản phẩm để nắm rõ các nguyên tắc đã học. Thật ra thì điều này cũng đúng thôi, chúng ta nên phát triển kĩ năng của mình ở nhiều khía cạnh hơn là việc bó hẹp vào chỉ một vài khía cạnh, tuy nhiên là điều này chỉ đúng nếu thời gian của bạn cho phép và bạn đang cần học hỏi một công đoạn cụ thể nào đó. Nếu không, tốt nhất là bạn nên làm quen với việc sử dụng sự trợ giúp từ một thư viện hoặc framework nào đó, hay tốt hơn phối hợp hoạt động với những người khác, bởi vì việc phát triển phần mềm không phải là công việc của cá nhân, mà nó mang tính kế thừa và đòi hỏi cả tập thể cùng phải hợp sức. Mình sẽ nói rõ 2 vấn đề này ngay sau đây

Thứ nhất: Hãy tận dụng những sự trợ giúp xung quanh

         Trước đây khi còn đang học đại học, ngôn ngữ chủ yếu mà mình code là C++, mặc dù cũng là một ngôn ngữ lập trình bậc cao nhưng sự hỗ trợ của nó về mặt tiện dụng kém hơn nhiều so với những ngôn ngữ hiện đại hơn như C#, Python hay PHP. Khi mình tự học thêm về PHP, mình có gặp phải một bài toán sau đây:

           Từ một mảng gồm n phần tử là n tên sinh viên, xuất ra file log chuỗi có định dạng sau: “Students in class: name[0], name[1], name[3], …, name[n-1]”

        Do đã quá quen với ngôn ngữ C++, mà C++ lại không có hỗ trợ các hàm thao tác với mảng, nên mình ngay lập tức tự viết đoạn code để xử lí nó như sau:

$names = array("name1", "name2", "name3", "name4", "name5");
$str_log = "Names in class: ";

for($i = 0; $i < count($names); $i++)
{
    $str_log = $str_log . $names[$i];
    if( $i < count($names) - 1)
    {
        $str_log .= ", ";
    }
}
writeLog($str_log);

           Mình cứ nghĩ đoạn code trên là đã quá chuẩn rồi, cho tới khi có một anh bạn nhìn vào nó và nói rằng “rảnh hơi vai~~”, anh đó sửa lại đoạn code đó như sau:

$names = array("name1", "name2", "name3", "name4", "name5");
$str_log = "Names in class: " . implode($names, ", ");
writeLog($str_log);

          Wow! Mình như bị thông não. Một công việc đơn giản mà mình lại code ra quá phức tạp, trông có vẻ cồng kềnh và lại tốn nhiều thời gian cho người khác (nếu phải maintain sau này), PHP đã hỗ trợ sẵn hàm implode() để hỗ trợ chúng ta việc này rồi. Sẽ là hợp lí nếu bạn đang tìm hiểu C++ và học cách thao tác với mảng sao cho thuần thục, nhưng mục đích chính ở đây là chuyển data từ dạng mảng sang dạng chuỗi nhanh nhất và chính xác nhất có thể để ghi log, vậy nên không có lí do gì để phải tự viết các thao tác chi tiết cả.

           Một ví dụ khác, khi mình xử lí chức năng hiển thị những người nào đã mua hàng trong ngày hôm nay, mình phải xử lí những công đoạn sau: lấy danh sách các hoá đơn trong ngày, đọc trong đó ra thông tin người mua hàng và lưu vào mảng (có thể lưu biến “`user_id“`), xử lí mảng để không có các giá trị “`user_id“` trùng nhau và xuất ra màn hình. Khi mình phải xử lí mảng để chắc chắn không có giá trị nào trong đó bị trùng lặp, mình đã code như sau:

function removeDuplicatedValue( $input_arr )
{
    $result_arr = array();
    foreach ( $input_arr as $item )
    {
        $result_arr[$item] = true;
    }
    return array_key( $result_arr );
}

//...

//Sử dụng hàm trên để loại bỏ các giá trị dư thừa
$user_ids = getUsersInDay($time);
$user_ids = removeDuplicatedValue($user_ids);

           Đoạn code trên xử lí được vấn đề của mình, nhưng dường như cách xử lí này quá rườm rà và mất thời gian người đọc code. PHP đã hỗ trợ sẵn hàm xử lí các giá trị trùng lặp của mảng bằng hàm “`array_unique“` như sau:

//Sử dụng hàm trên để loại bỏ các giá trị dư thừa
$user_ids = getUsersInDay($time);
$user_ids = array_unique($user_ids);

            Code của ta trở nên ngắn và tường minh hơn nhiều phải không nào!

            Có thể nguyên nhân sâu xa của vấn đề là do mình chưa quen và chưa nắm rõ được ngôn ngữ PHP, nhưng không thể vì việc đó mà phủ nhận mình vừa viết ra một đoạn code tồi. Trước khi bắt đầu làm một việc gì hay code chức năng nào đó, chúng ta nên nhìn quanh một vòng liệu xung quanh mình đã có sẵn công cụ nào hay chưa, nếu có hãy tận dụng chúng. Chúng ta đều biết code càng dài thì lại càng tiềm ẩn nguy cơ xảy ra lỗi, vậy nên hãy code sao cho đơn giản, dễ hiểu và ngắn nhất có thể. Một developer chuyên nghiệp phải có trách nhiệm với những dòng code mình viết ra, và để đảm bảo nó chạy đúng thì chúng ta phải chắc chắn rằng code viết ra phải được test một cách đầy đủ. Các hàm built-in hoặc các thư viện hỗ trợ chắc chắn là đã được test rất kĩ càng rồi, hãy tận dụng chúng nếu có thể, chẳng có gì là sai trái hay kém chuyên nghiệp khi sử dụng sự trợ giúp từ thư viện cả.

quote-if-i-have-seen-further-than-others-it-is-by-standing-upon-the-shoulders-of-giants-isaac-newton-135288.jpg

Thứ hai: Thời gian không có nhiều, hãy nghĩ đơn giản

           Một trong các công đoạn có thời gian xử lí lâu nhất chính là công đoạn đọc dữ liệu từ ổ đĩa lên, để nâng cao năng suất chương trình bạn sẽ nghĩ ngay đến kĩ thuật lưu cache. Ý tưởng thì đơn giản, nhưng cache sao cho tốt lại là vấn đề không hề đơn giản một chút nào. Xét một bài toán cụ thể sau đây: bạn cần xử lí để nâng cao hiệu suất của chương trình có thao tác như sau

readFromDisk(fileA);
…
… //process something
…
readFromDisk(fileA);
…
readFromDisk(fileA);
...
readFromDisk(fileB);
…
readFromDisk(fileB);
…
readFromDisk(fileC);
…
readFromDisk(fileC);

          Một cách rất tự nhiên, bạn nghĩ ngay tới một lớp đối tượng Cache hoành tráng, gồm các kĩ thuật design pattern như Singleton, tự động lưu cache các dữ liệu đã load vào SESSION để dành sử dụng sau này, thiết kế cấu trúc dữ liệu để lưu cache, ..v.v. và hàng tá các thứ khác để chắc chắn rằng bạn xây dựng được một kĩ thuật cache hoàn chỉnh và hiệu quả. Bạn nghĩ rằng sẽ phải viết hàng trăm dòng code và sẽ phải mất vài giờ thậm chí cả ngày để có thể đảm bảo mọi thứ vận hành ổn định. Nhưng nếu thế nào khi bạn chỉ có vỏn vẹn 30 phút để triển khai ý tưởng của mình? Bạn có nghĩ điều này là khả thi không? Nếu bạn còn đang nghĩ tới các kĩ thuật hoành tráng khác thì hãy thử xem xét một cách xử lí vô cùng đơn giản như sau:

              Nhận xét rằng việc đọc dữ liệu từ đĩa chỉ thực hiện tuần tự với các filename, cụ thể là nó sẽ gọi fileA nhiều lần liên tiếp nhau, và nếu có chuyển sang fileB thì nó sẽ không còn cần tới fileA nữa, và cứ liên tục như thế. Với nhận định này, ta sẽ sử dụng một kĩ thuật cache cực kì đơn giản là: cache lại duy nhất file vừa sử dụng. Ta triển khai nó liền như sau:

DiskObject lastUsed;          // class member

DiskObject lookUp(String key)
{
    if (lastUsed == null || !lastUsed.key().equals(key))
    {
         lastUsed = loadDiskObject(key);
    }
    return lastUsed;
}

            Có thể đoạn cách giải quyết trên không phải là kĩ thuật cache hoàn hảo nhất, không chứa một cấu trúc dữ liệu chuẩn mực nhất, … nhưng nó giải quyết được vấn đề là đã tăng được đáng kể hiệu suất chương trình, đây chính là thứ chúng ta cần.

            Đối với một hệ thống lớn hơn, hay với một nhu cầu phức tạp hơn, thì kĩ thuật cache ở trên sẽ trở nên vô dụng, và bạn sẽ cần xây dựng một hệ thống cache hiệu quả hơn, nhưng đó là với những hệ thống lớn, nơi bạn cũng sẽ cần nhiều thời gian hơn để có thể thiết kế tốt. Như đã nói từ đầu, một developer chuyên nghiệp phải có trách nhiệm đối với code mình viết ra, và nếu bạn không thể test hoặc không có thời gian để test nó một cách cẩn thận, thì hãy nghĩ đến những cách đơn giản hơn nhưng không kém hiệu quả hơn quá nhiều.

Đừng tham lam, hãy tập trung vào vấn đề bạn quan tâm nhất

            Khi bắt đầu ý định sẽ phát triển blog cá nhân, mình cũng có những suy nghĩ kiểu tham lam như rất nhiều bạn khác: mình muốn tự code nên giao diện và hệ thống xử lí backend để học thêm kĩ năng phát triển web, rồi mình cũng muốn tự thuê một Host hay một VPN để host trang blog của mình nhằm học thêm kĩ thuật triển khai hệ thống, … và còn rất nhiều mong muốn khác nữa. Tuy nhiên, cuối cùng lựa chọn của mình là nền tảng blog được cung cấp sẵn: WordPress.

                Nếu mình chọn cách xây dựng hết từ đầu đến cuối thì có lẽ đến giờ này cũng chưa có bài viết nào được ra đời, lí do là … hệ thống chưa được xây dựng xong ^_^ Khi xây dựng một hệ thống mới từ đầu thì bạn phải có thiết kế đủ tốt để có thể mở rộng sau này, một hệ thống với đầy đủ chức năng để có thể post bài và quản lí bài viết, một hệ thống để thống kê số lượng truy cập, … một hệ thống đầy đủ như vậy cần rất nhiều thời gian để phát triển và chạy thử nghiệm. Sẽ là phù hợp nếu như mình có đủ thời gian để làm tất cả những điều đó, nhưng với thời gian có hạn khi vừa phải đi làm kiếm ăn qua ngày tới 40-50h mỗi tuần, rồi thời gian để học các kĩ năng và công nghệ khác, thì việc tự phát triển hệ thống để viết blog là điều rất khó để thực hiện. Mình chọn cách tự tìm hiểu các kĩ thuật riêng, và rồi sẽ viết chia sẻ lại dựa trên nền tảng WordPress đã được hỗ trợ sẵn, công việc trở nên dễ dàng và hiệu quả hơn nhiều.

imageedit_2_3290832787
Mọi thứ vốn dĩ đơn giản, đừng làm nó trở nên phức tạp.

               Công nghệ và kiến thức là vô hạn, nhưng thời gian của bạn và các developer khác là có hạn, vậy nên hãy biết bạn đang cần tập trung vào điều gì, code bạn cần phải xử lí điều gì, và bạn chỉ cần tập trung và xử lí việc đó mà thôi. Bạn không cần phải làm điều gì đó khó khăn hay code một thứ gì đó rất hoành tráng và phức tạp để có thể trở thành một pro-developer, bạn chỉ cần giải quyết mọi vấn đề theo cách đơn giản nhất, code một chức năng với ít code nhất để người khác dễ hiểu nhất là cũng đủ để trở thành một pro-developer rồi. Đời vốn dĩ đơn giản mà, và code cũng như thế, đừng làm nó trở nên phức tạp, phải không nào!

Vcttai

2 thoughts on “[Code sao cho chuẩn] Bài 4 – Đôi khi code tốt nhất là không code gì cả.

  1. Pingback: [Giới thiệu sách] The art of readable code – Cái tên đã nói lên tất cả – Webbynat

  2. Pingback: [ Giới thiệu sách ] The pragmatic programmer – Lập trình viên … tiêu biểu. (P1) – Những dòng code vui

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s