Diễn Đàn Tin Học
 Trang chủ      Tutorial Room      Diễn đàn      Liên hệ - Góp ý
Diễn Đàn Tin Học
Thông tin
Download
Tutorial Room
Sản phẩm
Thống kê
Hiện có 12 người đang trực tuyến.
Google


Diễn Đàn Tin Học » Tutorial Room » Lập trình » Software Engineering » Craftsman-Truyện dài nhiều tập

Craftsman 14 - Transaction Actions
Làm việc với một tay du mục mới là một kinh nghiệm nặng nề cho Alphonse. Liệu chàng chịu nổi tia nhìn sắc bén của Jasmine và xứng đáng với cái tên lóng mới của mình? 

  Thông tin      
  Chuyên đề   Lập trình - Software Engineering  
  Dịch giả   hnd  
  Bài gốc   http://www.vninformatics.com/forum/?action=msg&msg=1023492790#1023492790  
  Tựa gốc   Craftsman 14 - Transaction Actions  
 

Xin được thay mặt diễn đàn cảm ơn bạn về bài viết này.

 

 

Chương 14 Hành động chuyển tải

Làm việc với một tay du mục -1- mới là một kinh nghiệm nặng nề cho Alphonse. Liệu chàng chịu nổi tia nhìn sắc bén của Jasmine và xứng đáng với cái tên lóng mới của mình? 

Robert C. Martin

"OK, cao thủ -2- xem thử cậu thế nào." Độ căng thẳng trong cái nhìn của Jasmine làm tôi dán chặt vào ghế. "Ý... ý cô thế nào?" tôi lắp bắp. "Thôi đi cao thủ, bộ cậu định không làm tôi quê như cậu đã làm Jerry quê sao," nàng nói. "Tôi chẳng cố tình làm cho ai quê cả," tôi chống chế một cách yếu ớt. "Tôi chỉ...." "Ừa, hẳn nhiên rồi," nàng bất chợt ngắt ngang câu nói của tôi, tỏ vẻ cháng chường. "Thôi, hãy bắt tay vào công việc cho rồi. Cậu định sẽ thay đổi những gì tiếp theo đây?"

Chúng tôi ngồi trong phòng làm việc, xem xét đoạn mã Jerry và tôi vừa viết xong. Tôi chỉ cho Jasmine cách tôi thay đổi đoạn code của Jerry dùng để gởi strings thay vì objects xuyên qua socket.

"Tôi... ùm... ờ không biết. Tôi chỉ nghĩ là gởi objects chắc tốt hơn strings." Nàng làm tôi hết sức bối rối. Mức căng thẳng cứ đổ dồn từ ánh mắt và thái độ của nàng. "Suy nghĩ đi cao thủ, suy nghĩ! Cậu không chỉ thuần tuý gói vài cái strings và integers vào trong một object, phải thế không? Gói như vậy ngầm định vấn đề gì? Cậu có thể làm gì với nó?"

"Tôi, ùm...." giá như đôi mắt nàng ngưng đè nặng lên tôi, có lẽ tôi có thể suy gẫm. Tôi nhắm nghiền đôi mắt và thầm tụng một đoạn kinh -3-. Trong vòng vài giây, tôi đã có thể xem xét câu hỏi của nàng.

Cái test case chúng tôi đã làm dùng để xác thực chúng tôi có thể gởi hồ sơ có xuyên qua socket. Đoạn mã dùng để gởi hồ sơ như thế này:
 

   private void writeSendFileCommand() throws IOException {
        os.writeObject("Sending");
        os.writeObject(itsFilename);
        os.writeLong(itsFileLength);
        char buffer[] = new char[(
int) itsFileLength];
        fileReader.read(buffer);
        os.writeObject(buffer);
        os.flush(); }
 


Nhưng tại sao chúng tôi lại gởi hồ sơ đi? Chúng tôi gởi nó đến SMCRemoteServer để được biên dịch. Sau đó server sẽ trả về hồ sơ đã được biên dịch. Tại sao Jerry lại gởi "Sending" string trước? Gã nói rằng mục đích là để báo server có hồ sơ đang được gởi đến - nhưng chúng tôi lại không muốn thông báo cho server là có hồ sơ đang được gởi đến; chúng tôi muốn ra lệnh cho server biên dịch một hồ sơ và gởi ngược lại kết quả.

Tôi suy nghĩ rất kỹ lưỡng, nhưng một phần nào đó trong não bộ của tôi vẫn đang tiếp tục tụng kinh. Hầu như trong trạng thái nửa tỉnh, nửa mê, tôi đi thẳng đến bức tường và vẽ ra sơ đồ "kết quả biên dịch". Tôi nhác thấy khuôn mặt nghiêm trọng của Jasmine thoáng một nụ cười. "Tôi khoái cái lối suy nghĩ của cậu đó cao thủ. Đừng dừng lại ở đó."

Bốn mẩu dữ liệu được gởi đến server: tên hồ sơ, độ dài hồ sơ, nội dung hồ sơ và chuỗi "Sending". Tại sao những mẩu này được gởi riêng biệt? Chúng đều thuộc vào một gói tin của một xuất chuyển tải! Đúng rồi! Tôi tự lắc đầu với chính mình và thay đổi đoạn test như sau:
 

   public void testCompileFile() throws Exception {
    File f = createTestFile("testSendFile", "I am sending
     this file."
);
    c.setFilename("testSendFile");
    assertTrue(c.connect());
    assertTrue(c.prepareFile());
    assertTrue(c.compileFile());
    Thread.sleep(50);
    assertTrue(server.fileReceived);
    assertEquals("testSendFile", server.filename);
    assertEquals(23, server.fileLength);
    assertEquals("I am sending this file.",
      new String(server.content));
    f.delete();\ }
 


Thế rồi tôi đổi hàm sendFile cũ như sau:
 

   public boolean compileFile() {
    boolean fileSent = false;
    char buffer[] = new char[(int) itsFileLength];
    try {
      fileReader.read(buffer);
      CompileFileTransaction cft =
        new CompileFileTransaction(itsFilename, buffer);
      os.writeObject(cft);
      os.flush();

      fileSent = true;
    } catch (Exception e) {
      fileSent = false; }
    return fileSent; }
 


Jasmine theo dõi rất sát sao. Tôi không thể dò nổi cảm giác của nàng nhưng tôi biết chắc là mình đang đi đúng hướng. Kế tiếp tôi viết CompileFileTransaction class:
 

   public class CompileFileTransaction implements Serializable {
   private String filename;
   private char contents[];
   public CompileFileTransaction(String filename,
    char buffer[]) {
     this.filename = filename;
     this.contents=buffer;
   }
   public String getFilename() {
     return filename; }
   public char[] getContents() {
     return contents; }
}
 


Đoạn này cho phép chương trình được biên dịch. Tất nhiên là mấy cái test bị hỏng, bởi thế tôi lại thay đổi phần server giả như sau:
 

   public void serve(Socket socket) {
    try {
      os = new PrintStream(socket.getOutputStream());
      is = new ObjectInputStream(socket.getInputStream());
      os.println("SMCR Test Server");
      os.flush();
      parse(is.readObject());
    } catch (Exception e) { }
  }
  private void parse(Object cmd) throws Exception {
    if (cmd != null ) {
      if (cmd instanceof CompileFileTransaction) {
        CompileFileTransaction cft = (CompileFileTransaction) cmd;
        filename = cft.getFilename();
        content = cft.getContents();
        fileLength = content.length;

        fileReceived = true; }
    }
}
 


Những thay đổi này giúp cho các phần test đều đạt. "Phải ý cô giống như thế này không?" Tôi hỏi. "Ừa, chỉ là khởi điểm thôi," nàng xác nhận một cách dè chừng. "Chắc chắn là nó hay hơn lối chuyển mỗi phần dữ liệu thành strings của Jerry - và nó cũng hay hơn lối chuyển gởi mỗi phần dữ liệu riêng biệt." "Vậy cô làm thế nào cho hay hơn nữa vậy?" Tôi hỏi. "Hẵn đã," nàng nói một cách thiếu kiên nhẫn. "Ngay lúc này hãy hoàn tất phần chuyển tải. Cậu phải làm cho client tiếp nhận hồi đáp từ server." "Cái đó chắc không khó lắm," tôi đáp, cảm thấy phấn chấn hơn một chút, và thêm vào ba dòng như sau vào đoạn testCompileFile như sau:
 

   File resultFile = new File("resultFile.java");
    assertTrue("Result file does not exist", resultFile.exists());
        resultFile.delete();
 


Tôi chạy đoạn test và xác thật nó bị hỏng. "Sau khi mình gọi compileFile, kết quả hẳn phải được viết vào một hồ sơ," tôi giải thích cho Jasmine, rồi nói thêm, "ngay lúc này tôi không quan tâm đến chuyện có gì trong hồ sơ; tôi chỉ muốn chắc là hồ sơ đó được tạo ra." "Vậy cậu làm cách nào để tạo ra nó?" nàng thách thức. "Tôi sẽ cho cô thấy," tôi nói, thay đổi đoạn server giả như sau:
 

   private void parse(Object cmd) throws Exception {
    if (cmd != null) {
      if (cmd instanceof CompileFileTransaction) {
        CompileFileTransaction cft = (CompileFileTransaction) cmd;
        filename = cft.getFilename();
        content = cft.getContents();
        fileLength = content.length;
        fileReceived = true;
        CompilerResultsTransaction crt =
          new CompilerResultsTransaction("resultFile.java");
        os.writeObject(crt);
        os.flush();
 }
    }
  }
 


Thế rồi tôi tạo phần biên dịch này bằng cách thêm một cái sườn của CompileResultsTransaction class
 

   public class CompilerResultsTransaction implements
  Serializable {
   public CompilerResultsTransaction(String filename) {
   }
   public void write() {
   }
}
 


Tất nhiên phần test vẫn hỏng, bởi thế tôi thay đổi compileFile như sau:
 

   public boolean compileFile() {
    boolean fileCompiled = false;
    char buffer[] = new char[(int) itsFileLength];
    try {
      fileReader.read(buffer);
      CompileFileTransaction cft =
        new CompileFileTransaction(itsFilename, buffer);
      os.writeObject(cft);
      os.flush();
      Object response = is.readObject();
      CompilerResultsTransaction crt =
        (CompilerResultsTransaction)response;
      crt.write();
      fileCompiled
 = true;
    } catch (Exception e) {
      fileCompiled = false; }
    return fileCompiled; }
 


Cuối cùng, tôi thực hiện chi tiết phần chuyển tải:
 

   public class CompilerResultsTransaction implements
  Serializable {
   private String filename;
   public CompilerResultsTransaction(String filename) {
     this.filename = filename; }

  public void write() throws Exception {
      File resultFile = new File(filename);
       resultFile.createNewFile();
  }
}
 


DDTHCode::Image


Kết quả biên dịch
Tại sao tên, độ dài, nội dung của hồ sơ và "Sending" string đều được gởi đến server riêng biệt nếu chúng đều thuộc về một chặng chuyển tải?

"Ở giai đoạn này được vậy là tốt rồi," Jasmine nói. "Tôi đi giải lao một chốc trong khi cậu thực hiện xong quy trình CompileResultsTransaction thực sự viết thành hồ sơ thay vì chỉ tạo ra nó. Cũng nên dọn dẹp chút đỉnh nữa. Có khá nhiều mảnh vụn vặt còn sót lại trong lúc cậu và Jerry khuấy vọc chuyện gởi strings và integers. Nhưng trước khi tôi đi, tôi muốn biết ý kiến của cậu trong phần instanceof cậu dùng trong đoạn server giả."

Đó là giải pháp đơn giản nhất mà thôi có thể nghĩ ra dùng để kiểm tra xem object sắp trả lại có thật sự là CompileFileTransaction hay không." Tôi nói, bắt đầu cảm thấy bối rối. "Có gì sai với phần này sao?"

Nàng đứng lên, nhìn về phía tôi và trả lời, "không có gì sai trầm trọng, nhưng cậu có nghĩ rằng server thật sẽ làm thế sao? Liệu server thật sẽ có chuỗi if/else dài ngoằng cho instanceof để mà biến xuất các chuyển tải đi vào?"

"Tôi chưa nghĩ xa đến như thế," tôi thú nhận. "Không," nàng nói một cách thẳng thừng, "Tôi không hình dung cậu nghĩ xa như vậy." Và rồi nàng rảo bước ra khỏi phòng.

Căn phòng trống rỗng khi không có nàng, như thể sự hiện diện của tôi chẳng có giá trị gì. Tôi thở dài và ngúc ngoắc cái đầu. Làm việc với Jasmine sắp tới sẽ đầy mệt mỏi và đầy sự giáo huấn đủ mọi kiểu. Một điều tôi biết chắc - tôi ghét bị gọi là cao thủ. Tôi lại thở dài và bắt đầu giải quyết công tác nàng giao cho.


-1- Dựa trên góp ý của cl trong bài thứ 13 , journeyman có thể được xem như những kẻ du mục, đi tìm những vùng "đất mới". Nghĩa bóng cho journeyman cũng hết sức thích hợp cho những lập trình viên có cái nhìn khai phá. Tôi tạm dịch journeyman là du mục theo tinh thần này.[Back]

-2- Hotshot: tiếng lóng chỉ cho một cá nhân kinh nghiệm và nổi bật. Hotshot cũng có thể dùng với tính cách châm biếm, bỡn cợt hoặc thân thiện. Trong bài này, có lẽ Jasmine gọi Alphonse với tính cách bỡn cợt.[Back]

-3- Mantra: có nghĩa chung là đoạn kinh kệ. Theo đạo Hindu và đạo Phật, mantra có khả năng hoá giải những trắc trở.[Back]
 

Các bài viết mới nhất
Bạn không được phép truy cập vào địa chỉ này!
[Download] - NT Password Recovery Bootdisk
Craftsman 18 - Slow and Steady
Quản lý MySQL Server sử dụng lệnh trên console
Memory-RAM - Một số thuật ngữ và kỹ thuật
Đưa chương trình vào đường dẫn hệ thống
Thay thế BIND với djbdns - phần 1
Phương pháp khôi phục lại password trong hệ thống Win2k/XP/2K3 (Support NTFS)
Cài đặt ActivePython 2.4 trên IIS
Sử Dụng Tiếng Việt Với LaTeX
Cài đặt 1 SMTP server tại nhà với Microsoft IIS
Linux - Vì sao sáng trên bầu trời CNTT
Biên dịch Linux kernel - phần 4
Tự học lập trình Borland Delphi
Thiết kế và Lập trình Web bằng ASP
Cài đặt PHP 4 trên IIS
Giới thiệu về XML-RPC
Sử dụng CSDL MySQL
Một chương trình download manager đơn giản
Giới thiệu - Sơ lược về ngôn ngữ PHP
Các bài viết liên quan
Craftsman 18 - Slow and Steady
Craftsman 17 - Call the Guards
Craftsman 16 - Excess Politesse
Craftsman 15 - Ess Are Pee
Craftsman 14 - Transaction Actions
Craftsman 13 - A Better Solution
Craftsman 12 - Three Ugly Lines
Craftsman 11 - Forget the Main()
Craftsman 10 - Iterations Unbound
Craftsman 9 - Dangerous Threads
Craftsman - 8 : Testing in Synch
Craftsman 7 - Socket Service2
Craftsman 6 - Socket Service
Craftsman 05 - Baby Steps
Craftsman 04 - A Test of Patience
Craftsman 03 - Clarity and Collaboration
Craftsman 02 - Crash Diet
Craftsman 01 - Opening Disaster
Quảng cáo
HOME | TUTORIAL ROOM | FORUM | CONTACT