The Law of Demeter Principle

The Law of Demeter Principle

(Tạm dịch là luật cho người thứ 3 – đùa đó)

Một đoạn hội thoại

“Giờ anh tính giải quyết thế nào về chuyện này?”
“Ah… anh…”
“Tôi không biết, chuyện của anh và cô ấy, tốt nhất là anh nên tự giải quyết riêng với cô ấy. Đừng để đến lúc em phải đi nói chuyện với cô ấy thì mọi chuyện đã quá muộn..”
Rốt cuộc thì anh chàng đó vẫn lén lút qua lại với cô nàng thứ 3. Cho đến 1 ngày, cô người yêu bắt gặp.. Everything is broken..

OK, một câu chuyện vui, nếu anh chàng đó có thể giải quyết riêng với cô kia thì mọi chuyện đã không đến nỗi.

Định nghĩa

Hôm nay tôi sẽ nói thêm một nguyên lý nữa về thiết kế hướng đối tượng. Đó là Law of Demeter (LoD). Nguyên lý này chỉ ra rằng các đối tượng chỉ nên biết những đối tượng nó cần biết phải biết.

Đây là loạt bài về các nguyên lý thiết kế hướng đối tượng. Chúng ta đã trải qua 5 nguyên lý SOLID. Sau đây sẽ là một nguyên lý cũng khá hay để giúp chúng ta giải quyết những vấn đề Ở ĐÂY

Một câu chuyện về quản lý dự án

Nghe phức tạp nhỉ. Ví dụ, trong một dự án, phía phát triển dự án gồm có Project Manager, Team leader, một vài Developer và Tester. OK, bây giờ khách hàng bên kia yêu cầu đội dự án phát triển một phần mềm quản lý ABC. Theo lẽ thường thì họ chỉ cần liên hệ với PM để trao đổi yêu cầu và tiến độ dự án, khách hàng không quan tâm đến các Leader hay Developer bên bạn. Điều này có ý nghĩa gì? Thực tế là như vậy, nên chắc chắn nó là đúng (~99.99%). Vậy là 2 bên cũng đã áp dụng LoD vào việc phát triển dự án, khách hàng chỉ biết đến Developer. Giả sử bây giờ khách hàng muốn control tất cả các các member khác, họ sẽ giao yêu cầu cho các Developer và kiểm tra tiến độ của họ. Điều đó cũng không sai, nhưng giả sử phía phát triển dự án có một số sự thay đổi về nhân sự, một số Developer nghỉ và có một số người khác vào thay. Chẳng cần phải tưởng tượng quá nhiều, chúng ta cũng thấy rõ được là sự thay đổi đó sẽ ảnh hưởng đến toàn bộ 2 phía, khách hàng và bộ phận phát triển, cả 2 đều phải cập nhật lại thông tin của sự thay đổi. Điều này là không cần thiết nếu họ áp dụng nguyên lý Law of Demeter.

Demo

/**
 *    	OO Design Principle Tutorial
 *		View more at: https://edwardthienhoang.wordpress.com/
 */
package edward.tutorial.designprinciple.lawofdemeter;

public class Main {

    public static void main(String[] args) {
        Address address = new Address();
        address.setName("01");
        address.setZipCode("000001");

        House house = new House();
        house.setAddress(address);

        Person person = new Person();
        person.setHouse(house);

        // Print the person zip code
        System.out.println(person.getHouse().getAddress().getZipCode());
    }
}

Đoạn code trên nhìn không có vấn đề gì. Hãy nhìn lại nguyên lý Law of Demeter. Lớp Main muốn in ra ZipCode của 1 người nào đó nhưng nó lại phải “quan tâm” đến nhiều lớp khác như: House, Address. Có thể nó có 1 sự “tight coupling” không nhẹ ở đây. Để in ra ZipCode, Main phải get House của người đó, sau đó lại get ra địa chỉ của House và cuối cùng là get ra ZipCode từ địa chỉ.

Bây giờ là phần của “The Change”. Không lâu sau đó, Boss của bạn muốn bỏ đi lớp Address, thay vào đó lớp House sẽ giữ ZipCode. Với đoạn chương trình hiện tại của chúng ta thì điều đó chẳng có nghĩa lý gì. Nhưng hãy nghĩ đến những cái hố đen hơn nếu như đoạn in ra ZipCode ở trên xuất hiện ở hàng trăm nơi trong chương trình thực sự của bạn, bạn có đủ can đảm để thay đổi hết chúng, và sau đó… test lại..

Resolve problem with Law of Demeter

Person.java

/**
 *    	OO Design Principle Tutorial
 *		View more at: https://edwardthienhoang.wordpress.com/
 */
package edward.tutorial.designprinciple.lawofdemeter;

public class Person {
	private House house;

    public void setHouse(House house) {
        this.house = house;
    }

    public House getHouse() {
        return house;
    }

    public String getZipCode() {
        return house.getZipCode();
    }
}

House.java

/**
 *    	OO Design Principle Tutorial
 *		View more at: https://edwardthienhoang.wordpress.com/
 */
package edward.tutorial.designprinciple.lawofdemeter;

public class House {
	private Address address;

    public void setAddress(Address address) {
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }

    public String getZipCode() {
        return address.getZipCode();
    }
}

Address.java

/**
 *    	OO Design Principle Tutorial
 *		View more at: https://edwardthienhoang.wordpress.com/
 */
package edward.tutorial.designprinciple.lawofdemeter;

public class Address {
	private String name;
    private String zipCode;

    public void setName(String name) {
        this.name = name;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    public String getName() {
        return name;
    }

    public String getZipCode() {
        return zipCode;
    }
}

Main.java

/**
 *    	OO Design Principle Tutorial
 *		View more at: https://edwardthienhoang.wordpress.com/
 */
package edward.tutorial.designprinciple.lawofdemeter;

public class Main {

	public static void main(String[] args) {
		Address address = new Address();
	    address.setName("01");
	    address.setZipCode("000001");

	    House house = new House();
	    house.setAddress(address);

	    Person person = new Person();
	    person.setHouse(house);

	    // Print the person zip code
	    System.out.println(person.getZipCode());
	}

}

Bây giờ, khi sếp muốn remove lớp Address ra khỏi hệ thống, việc đơn giản là move ZipCode qua House và delete lớp Address, những phần khác đều không phải “lo”.

Class Diagram:

Vi phạm Law of Demeter

ViolateLoD

Áp dụng Law of Demeter

LoD

Đó là lợi điểm của LoD, nó giúp hệ thống của chúng ta đứng vững trước những thay đổi bằng cách giảm coupling hay còn gọi là cách design loose coupling, mọi sự thay đổi sẽ là nhỏ nhất nếu có thể.

Nhìn thì có vẻ mọi thứ rất đơn giản. Nhưng nếu chúng ta vi phạm những điều rất đơn giản này, nó sẽ kéo theo việc vi phạm những thứ phức tạp hơn. Vì những điều phức tạp đều được xây dựng từ những điều đơn giản nhất như ở trên.

Mình kết thúc bài Law of Demeter ở đây.

NGUỒN: HTTP://EDWARDTHIENHOANG.WORDPRESS.COM/

5 thoughts on “The Law of Demeter Principle

  1. Cảm ơn anh vì bài viết nhưng nếu em không nhầm thì 2 class Main.java ở Demo và Resolve giống nhau anh ạ 😀

    1. Haha, cám ơn em. Anh đã sửa rồi.
      Thật ra tinh thần của bài này nằm ở chỗ là: đừng có gọi abc.def.ghi.jkl.. Quá nhiều dấu . (lời gọi hàm) là 1 code smell và sẽ dẫn đến việc code rất dễ “vỡ” khi có thay đổi.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.