Object Oriented Trick: Luật Của Demeter

OOT (viết tắt của Object Oriented Trick) là một số thủ thuật để các bạn developer viết code theo kiểu hướng đối tượng (hay OOP) tốt hơn, cụ thể có thể dễ dàng quản lý hơn. Law of Demeter hay dịch sang tiếng Việt là luật của Demeter là một trong số những trick (hay nói đúng hơn là nguyên lý lập trình) mà chúng ta sẽ tìm hiểu trong bài viết này.

Khi lập trình việc gọi method liên tiếp bắt đầu bởi một object là một trong những trường hợp khá phổ biến. Ví dụ một đoạn code xử lý việc thanh toán của khác hàng như sau:

// thanh toán tiền
customer.getWallet().subtractMoney(amount);

Trong đó class Customer như sau:

class Customer {
    private Wallet wallet;

   public Wallet getWallet() {
        return this.wallet;
    }
}

Trong đó class Walllet như sau:

class Wallet {
    public int substractMoney(int ammount) {
        // ...
    }
}

Với các bạn mới lập trình thì thẩy rằng cách làm này không có vấn đề gì vì trong method getWallet() chúng ta trả về một đối tượng kiểuWallet và có thể gọi method substractMoney().

Tuy nhiên, logic của cách triển khai trên khi áp dụng vào trường hợp thực tế sẽ tương ứng với quá trình sau: Khi bạn hỏi khách hàng thanh toán tiền hàng, khách hàng đưa cho bạn ví của anh ta và bạn lấy một số tiền nhất định từ ví của anh ta.

Có bao giờ bạn đưa ví cho nhân viên thu ngân khi người đó yêu cầu bạn tính tiền cho ly cà phê bạn đã đặt? Nếu là tôi thì tôi chỉ dám đưa cho nhân viên đó tiền và nhận tiền thừa (nếu có) thay vì đưa cả chiếc ví của mình cho nhân viên này.

Hãy nhớ rằng trong lập trình việc method của một class có thể gọi tới method của một object khác là vi phạm nguyên tắc Law of Demeter.

Law of Demeter Là gì

Law of Demeter là một nguyên lý được sử dụng trong lập trình với mục đích giới hạn mối liên quan phụ thuộc của các class (hay object tạo bởi class) khác nhau qua đó hạn chế tối đa rủi ro trong việc sự thay đổi của một class sẽ phá vỡ hoạt động của object khác.

Nội dung của luật này được áp dụng trong lập trình hướng đối tượng bằng cách quy định cách triển khai code bên trong một method của class như sau:

  • Bạn có thể gọi các method khác của cùng một class với method hiện tại.
  • Nếu trong class có các thuộc tính (property) thì bạn có thể gọi các method của các thuộc tính này.
  • Nếu bên trong method có các biến local được tạo và các biến này là object thì bạn cũng có thể gọi method của các biến object này.
  • Nếu method chấp nhận đối số truyền vào và object thì bạn có thể gọi method của đối số truyền vào này.

Áp dụng nguyên lý này trong ví dụ về thanh toán tiền cho khách hàng ở trên chúng ta có thể viết lại đoạn code như sau:

Chúng ta thay đổi quá trình xử lý việc chuyển tiền về cho Customer:

class Customer {
    private Wallet wallet;

    public Wallet getWallet() {
        return this.wallet;
    }
    public int payMoney(amount) {
        return this.wallet->subtractMoney(amount);
    }
}

Ở trên do Customer có một thuộc tính là $wallet (thuộc kiểu Wallet) đại diện cho ví của anh ta. Việc gọi method subtracMoney() trong thuộc tính này là tuân thủ nội dung của nguyên lý Law of Demeter như đã đề cập ở trên. Qua đó việc thanh toán lúc này được phản ánh qua việc trừ tiền từ ví và do đó sẽ lại được chuyển về method subtractMoney() của class Wallet (class này giữ nguyên và không thay đổi so với ban đầu):

class Wallet {
    public int substractMoney(int ammount) {
        // ...
    }
}

Cuối cùng quy trình thanh toán sẽ diễn ra như sau:

// thanh toán tiền
customer.payMoney(amount);

Và như bạn thấy ở câu lệnh trên chúng ta hạn chế việc gọi liên tiếp các method từ một object customer.

Loosely Couple

Bạn còn nhớ câu nói nổi tiếng mà các anh em lập trình trình viên hay dặn nhau thay đổi là hằng số duy nhất trong phát triển phần mềm?

Change is only constant in software development

Thử tưởng tượng nếu bạn tham gia một dự án và sau khi họp với sếp và khách hàng bạn ước tính cần 1 tuần để hoàn thành xong các yêu cầu cơ bản đã thống nhất trong buổi meeting. Bạn bắt đầu code và đã xong sớm hơn 2 ngày so với deadline. Tuy nhiên ở buối họp thứ 2 diễn ra sau đó không lâu, khách hàng yêu cầu thay đổi một số tính năng cũ và đồng thời cũng thêm nhẹ vài tính năng mới. Lúc này bạn phát hiện ra rằng mình phải cần tới nửa tháng để hoàn thành do phải xử lý quá nhiều thay đổi trong code cũ.

Khi lập trình thì một trong những điều quan trọng bạn cần lưu ý đó là đảm bảo việc một object thay đổi không ảnh hưởng tới một object khác. Nguyên tắc có tên tiếng Anh là loosely couple. Sử dụng nguyên lý Law of Demeter sẽ giúp code của bạn dễ quản lý hơn và đáp ứng dễ dàng được các thay đổi từ yêu cầu người dùng.

Liên quan tới loosely couple bạn có thể tham khảo thêm bài viết về nguyên lý Composition over Inheritance.

Content must not be empty

Related Blog