Tin tức mới

Thợ lành nghề #17: Gọi bảo kê (SMCRemote – phần 7)

Dự kiến chuyện tệ hại nhất sau khi “đụng” với Jasmine, Alphonse học được cách dùng mới cho điều kiện cách if – và khám phá bên trong ngoại diện bình thường của người hướng dẫn mới hàm chứa một cái đầu tỉ mỉ –

Tác giả: Robert C. Martin

Người dịch: Hoàng Ngọc Diêu | Biên tập: Phạm Anh Đới

Nhật ký thân mến: Tuần học việc đầu tiên của tôi với ông C đã hoàn tất. Tôi học được thật nhiều nhưng tôi cũng đã làm rối lung tung cả lên. Hôm thứ Hai, Jerry yêu cầu tôi viết một chương trình để tạo số nguyên. Đến thứ Ba, gã lại yêu cầu tôi viết chương trình tạo số nguyên tố. Trọn ngày thứ Tư dành cho việc làm SocketServer có thể chạy được. Thứ Năm chúng tôi bắt đầu làm việc với SMCRemoteClient và tôi đã Micahed -1- Jerry. Tôi gặp Jasmine chiều hôm ấy trong phòng khách của các tay du mục -2-. Nhưng đến thứ Sáu lại là một ngày tôi xấu hổ nhất trong đời. Tôi không gặp lại Jasmine (Ms. J) từ khi chúng tôi hoàn tất công việc chiều thứ Sáu. Quả là một tuần “lên voi xuống ngựa” -3-

Tôi trải qua mấy ngày cuối tuần bệ rạc, chắc mẩm thế nào cũng bị chuyển sang bộ phận vệ sinh và tái dụng, dọn rửa lò phản ứng hoặc kỳ cọ mớ rêu mốc. Tôi chẳng màng mặc quần áo hay ăn uống.

Dù gì đi chăng nữa, bây giờ là tối thứ Hai và tôi đang viết để kể cậu nghe sự thể của ngày đầu trong tuần thứ nhì. Nó cũng không quá tệ. Thật ra tôi bắt đầu cảm thấy phấn chấn trở lại.

Sáng hôm nay, tôi thức dậy trong lòng nặng trĩu. Sau khi dùng xong điểm tâm, tôi lết thếch lê đến phòng làm việc, phỏng chừng cô J đang đợi tôi ở bàn máy nhưng thay vào đó là một phụ nữ trung tuần đẫy đà với mớ tóc điểm sương ngang vai và nụ cười hiền từ, nụ cười ít nhiều còn phảng phất dấu ấn của những năm tươi trẻ ngày trước. Lúc nhìn tôi, mắt bà nhấp nháy và bà cười khẽ. “Cậu hẳn là Alphonse,” bà nói, đưa tay ra. “Tôi tên là Jean. Tôi nghe khá nhiều về cậu. Cậu đói bụng không? Tôi có một ít bánh mì sandwich ngon lắm trong giỏ nếu cậu muốn, hay cậu thích một quả táo hay một trái chuối.”

Quả thật có chiếc giỏ to trên sàn cạnh nơi bà ngồi. Trông chừng như nó không chỉ chứa sandwich và chuối. Bối rối, tôi bắt tay bà và nói, “dạ vâng, thưa bà – ý tôi, không thưa bà – ý tôi – vâng, tôi đúng là Alphonse, và không, cám ơn bà đã mời tôi sandwich và tôi – ườm… ờ…. rất vui khi được gặp bà.”

Bà nhìn tôi một cách nghiêm khắc nhưng cái nhếch mép phảng phất nét hiền từ của một người mẹ. “Này, chúng ta không lần khân với cái mớ “Bà” ngớ ngẩn đó nghe chưa. Tôi nhất định không phải là “Bà” của ai cả. Cậu gọi tôi là Jean thôi, cậu bé thân mến.”

Ườm, cám ơn Jean,” tôi trả lời. “Vậy cô J đâu nhỉ?”

“Ai thế cậu bé?”

“Èm… Jasmine đó,” Tôi trả lời một cách miễn cưỡng. “Lẽ ra cô ta và tôi làm việc chung với nhau.”

“Ôi giời, trước giờ tôi chưa hề nghe ai gọi cô ta là cô J cả. Chắc cô nàng buộc cậu gọi như thế phải không? Tôi không nghĩ có ai gọi cô ta gì khác ngoài cái tên Jasmine. Con bé thật đáng yêu, phải không nhỉ? Mà thôi, cậu bé thân mến, hiện tại ông C muốn cô ta lo công việc khác, cho nên từ rày về sau tôi sẽ làm việc với cậu.”

“Bà?” tôi đớ người ra. “Ô,” tôi lặp bặp. “Ôi…”

“Nào, cậu ngồi đây đi cậu bé thân mến và để tôi nói cho cậu nghe tôi đang nghĩ gì,” Jean nói, trong khi khi vỗ nhẹ trên chiếc ghế cạnh bà.

“Đang nghĩ gì?”

“Tôi xem xét chương trình này trong suốt nửa giờ qua – tôi thích làm việc sớm, cậu biết không — nhưng chẳng phải sớm hơn thường lệ gì đâu — tôi biết một cậu con trai đang lớn thì cần ngủ và điểm tâm. Mà thôi, tôi rất hài lòng với chương trình này. Cậu có một chuỗi kiểm thử rất lý thú và phần mã nguồn rất dễ đọc, cấu trúc lại gọn gàng. Nhưng có một điều làm tôi thắc mắc, cậu bé thân mến.”

“Ùm — thắc mắc?”

“Đúng thế cậu bé! Tôi xem xét khắp nơi trong chương trình này và không hề thấy hàm main. Khi nào cậu sẽ viết phần này vậy hở cậu?”

“Ùm, à, Jerry nói là -” tôi lập bặp.

“Ồ, để tôi đoán thử Jerry nói gì. Jerry là một thằng bé đáng yêu,” Jean ngắt ngang, đôi mắt bà nhấp nháy. “Nhưng tôi nghĩ đôi khi cậu ta nên cần thêm manh mối để lý giải vấn đề. Nhưng thôi, tôi không nên có ý kiến không tốt về người khác. Jerry là một lập trình viên giỏi, cậu bé thân mến, cậu đừng để ý đến những điều tôi nói nhá. Nào, hãy viết hàm main. Cậu muốn bắt đầu không? Sáng nay mấy ngón tay tôi hơi bị cứng. Hãy nghe tôi khuyên này,” bà cười khúc khích “đừng bị lão hoá.”

Đớ người ra từ một chuỗi ngôn từ thằng tuồn tuột của bà, tôi nhón lấy bàn phím và bắt đầu gõ:

public void main(

“Ô, nào nào, cậu bé thân mến!” Jean ngưng tôi lại. “Cậu làm việc ở đây được bao lâu rồi nhỉ? cậu phải viết một cái kiểm thử trước – cậu không thể cắm đầu vào viết hàm main ngay như vậy được! Chúng ta sẽ đi về đâu nếu ai cũng viết mấy cái hàm mà không viết kiểm thử trước? Tôi có thể cho cậu biết: (chúng ta sẽ ở) trong một quả dưa chua! -4- Không, cậu bé, xoá nó đi và viết cái test trước.”

Bà lấy ra từ trong giỏ một đôi que đan và bắt đầu làm việc với một mảnh y phục nhiều màu có hình dáng na ná như một mảnh khăn choàng -5-, khe khẽ ngâm nga một giai điệu đơn tẻ trong khi tôi xoá mớ chữ vừa viết xong và bắt đầu lại.

Làm cách nào để kiểm thử hàm main? cách tốt nhất là gọi nó và bảo đảm nó làm những gì nó nên làm. Hàm main giải dịch các thông số trên dòng lệnh, bởi thế, gọi nó chỉ đơn thuần là việc chuyển các thông số cho đúng. Thế nên tôi bắt đầu gõ lại:

public void testMain() throws Exception {

SMCRemoteClient.main(new String[]{“myFile.sm”});

Jean ghé mắt nhìn và bảo, “tốt đó, nhưng ở đâu ra cái myFile.sm vậy? Mình không thể để nó nằm ngổn ngang như thế được, phải không nào? Không, mình sẽ tạo nó ở ngay đây, phải không? và đừng quên xoá nó khi mình đã xong nhá cậu bé thân mến. Không gì tệ hại bằng một mớ tệp tin cũ nằm chổng chơ, lúc nào tôi cũng bảo thế.”

Thế rồi tôi tiếp tục gõ:

public void testMain() throws Exception {

    File f = createTestFile(“myFile.sm”, “the content”);

    SMCRemoteClient.main(new String[]{“myFile.sm”});

    f.delete();

    File resultFile = new File(“resultFile.java”);

    assertTrue(resultFile.exists());

    resultFile.delete();

}

Jean hoàn tất thêm một dòng (đan) trên mảnh khăn choàng trong khi tôi gõ mã. Bà ngước lên nhìn khi tôi hoàn tất và nói: “Nào, cậu bé, êm rồi đó, nhưng thật tình tôi nghĩ main có thể không đủ thời gian để hoàn thành trách nhiệm trước khi phân đoạn xoá đó có tác dụng. Nên nhớ cậu bé, cậu có hàng lô các socket threads đang chạy và dễ thấy trong mớ thread này có một thread vẫn đang chạy ngay khi main trả về. Không, cậu bé, khoan hẵn làm gì cả ngay lúc này; chỉ ghi nhớ trong đầu thôi. Bây giờ cậu nên viết main, phải không?”

Tôi tự nhủ bà già này khá sắc sảo và bắt đầu viết phần hàm main.

public static void main(String[] args) {

    SMCRemoteClient client = new SMCRemoteClient();

    client.setFilename(args[0]);

    if (client.prepareFile())

        if (client.connect())

            if (client.compileFile())

                client.close();

            else { // compileFile

                System.out.println(“failed to compile”);

            }

        else { // connect

            System.out.println(“failed to connect”);

        }

    else { // prepareFile

        System.out.println(“failed to prepare”);

    }

}

“Ôi chao ơi, xem có thật sướng mắt không! Tôi nghĩ cách cậu chú thích những đoạn điều kiện cách else rất mẫn đạt. Dẫu vậy, tôi không biết nếu cậu thử đảo ngược ý của các đoạn điều kiện cách và dùng chúng như những phần bảo kê thì có dễ đọc hơn không. Đừng, cậu bé thân mến, hẵng khoan đổi nó. Hãy xem nó có chạy được hay không cái đã. Không đáng để thay đổi quá nhiều thứ cho đến khi mình biết chắc chương trình có làm việc hay không, cậu đồng ý không nào? Đầu tiên làm cho nó chạy trước, rồi mới làm cho nó chỉnh sau.”

Thế rồi tôi chạy thử cái kiểm thử, và nó làm việc ngon lành ngay lần đầu.

“Ồ, đúng là ngoạn mục!” Bà ta nói trong khi ghé mắt nhìn. “Bây giờ chúng ta thử thay đổi phần điều kiện cách if.”

Thế rồi tôi đổi hàm cho phần điều kiện cách if được bảo vệ.

public static void main(String[] args) {

    SMCRemoteClient client = new SMCRemoteClient();

    client.setFilename(args[0]);

    if (!client.prepareFile()) {

        System.out.println(“failed to prepare”);

        return;

    }

    if (!client.connect()) {

        System.out.println(“failed to connect”);

        return;

    }

    if (!client.compileFile()) {

        System.out.println(“failed to compile”);

        client.close();

        return;

    }

    client.close();

}

Jean đặt mớ đồ đan vào giỏ và xem xét kỹ lưỡng đoạn mã. “Rồi, tôi xem nó được hơn một chút rồi đó, tôi không có ý càm ràm phần lặp ở đoạn close. Và tính chất vi phạm trong lối nhập đơn, xuất đơn, mấy cái này hơi bị vướng víu một chút. Dẫu vậy, nó còn bảnh hơn mớ dòng mã nguồn được đẩy vào (từ lề bên trái) -6-, cậu đồng ý không nào? Tất nhiên chúng ta có thể thay đổi ba hàm đó cho phép chúng throw exceptions -7-, nhưng rồi chúng ta phải catch -7- chúng, và thế cũng khá phiền. Thôi, bây giờ cứ để yên như vậy. Nào, tôi nghĩ đã đến lúc giải lao, phải không cậu bé? Cậu thích mang dùm tôi chiếc giỏ xách này vào phòng ăn không? Tôi luôn có thói nhồi nhét vào giỏ nhiều hơn cần thiết và sau ít lâu cái của khỉ này trở nên nặng trình trịch.”

-1-    Từ này đã được giải thích một lần trong phần 13 – “Một giải pháp tốt hơn”. “Micah” ở đây, trong bài này, có lẽ là một loại đặc quyền hoặc một vinh dự lớn lao. Theo tự điển Merriam-Webster thì Micah là tên của một nhà tiên tri người Do Thái ở thế kỷ thứ 8 sau Công nguyên. “Micah” phát triển từ nguyên thủy MIkhAyAh (tiếng Hebrew).

-2-    journeymen đã được chú thích ở bài 14 – Transaction Actions. Journeymen có nghĩa bóng chỉ cho những tay lão luyện trong nghề và thích “lang thang” đi tìm những chân trời mới.

-3-    “roller-coaster week”: roller-coaster là một loại xe trược chạy vòng vèo theo cấu trúc dựng sẵn của một giàn giáo. Xe lướt trên roller-coaster với vận tốc nhanh và lên xuống theo cấu trúc dựng sẵn. Ở đây, tác giả hình tượng hoá một tuần làm việc của Alphonse như đi roller-coaster chỉ cho một tuần đi qua rất nhanh và ở trạng thái “khi lên, khi xuống”. Tôi tạm dịch là một tuần lên voi, xuống ngựa cho gần với tiếng Việt.

-4-    in a pickle, một ngạn ngữ chỉ cho tình trạng hoặc môi trường không hay và không dễ thoát ra. “Pickle” là một loại dưa chua trong dấm ví dụ như trái dưa leo ủ chua (người châu Âu, châu Mỹ và châu Úc rất thích ăn loại này). Ăn thì thích nhưng thử tưởng tượng bị ủ trong một trái dưa chua thì sao?

-5-    shawl, một loại khăn choàng đầu và vai dành cho mùa lạnh. Có lẽ từ “khăn sô” đi từ chữ shawl này chăng? Từ đồng nghĩa tiếng Pháp là “châle”, cũng đọc nôm na là “sô”. Chữ shawl tiếng Anh có nguồn gốc từ chữ “shAl” tiếng Persian (người Iran cổ đại). Tôi chưa tìm ra được chính xác nguồn gốc chữ “khăn sô” của tiếng Việt. Có nguồn cho rằng “khăn sô” đi từ gốc vải sô chuyên dùng làm khăn choàng, cũng có nguồn cho rằng “khăn sô” là một dạng từ vay mượn từ tiếng nước ngoài. Ai có hứng thú (và thời gian) khảo cứu (về ngôn ngữ học), xin đóng góp kết quả và ý kiến.

-6-    indentation, lối đẩy dòng chữ thụt vào từ lề trang giấy (từ bên trái hoặc bên phải).

-7-    throw exceptions và catch exceptions, có lẽ dân lập trình nhón nhén chút đỉnh đến Java hẳn biết các thuật ngữ này. Tôi để nguyên thuật ngữ này mà không cố gắng dịch vì có thể làm sai lạc khi cố gắng chuyển ngữ.

Nguồn

Tác giả: Robert C. Martin

Người dịch: Hoàng Ngọc Diêu | Biên tập: Phạm Anh Đới


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

One thought on “Thợ lành nghề #17: Gọi bảo kê (SMCRemote – phần 7)”

Leave a Reply

Your email address will not be published. Required fields are marked *

TÀI LIỆU DEVWORLD
Cẩm nang phát triển nghề nghiệp cho lập trình viên!