Các cách sử dụng get/set propert

Hôm nay, mình muốn thảo luận với các bạn về một chủ đề rất gần gũi với chúng ta khi lập trình đó là về hàm get/set property ý nghĩa và cách chúng ta có thể sử dụng chúng như thế nào.

Lúc đầu mới tiếp cận get/ set method mình chỉ hiểu một cách đơn giản nó phục vụ cho mục đích Encapsulation của OOP, tức là để phù hợp với lập trình hướng đối tượng, chúng ta cần giấu tất cả các fields đi, không để user có thể trực tiếp thao tác với chúng được (concealed) còn properties là cái mà class đưa ra (exposed) thông qua method get/set(accessor method).

Ngay cái tên gọi ban đầu của get/set method là accessor method, chúng ta cũng có thể cơ bản hình dung được ý nghĩa cơ bản và tổng quát nhất của 2 hàm get và set này rồi nhỉ. Về cơ bản nó đóng vai trò là cổng vào và cổng ra cho data. Ví dụ chút:

public class People{
private String name;

public String Name
{
        Get
            { return name; }
        Set
            { name= value; }
}

}

Như ví dụ trên về cơ bản thì do biến name là kiểu private -> get và set là phương thức giúp chúng ta có thể truy cập và thao tác với name được.

  1. Vì get và set đóng vai trò là "cổng" vào và cổng ra cho data -> chức năng đầu tiên của nó là cho phép truy cập và sửa đổi data.

  2. Thông qua "cổng" này chúng ta cũng tiến hành kiểm soát (control) và ngăn chặn (validation) dữ liệu một cách hiệu quả.

Kiểm soát dữ liệu là gì, với get set method chúng ta có thể quy định chỉ có thể đọc, hoặc chỉ có thể ghi dữ liệu (giống với keyword readOnly nhưng linh hoạt hơn nhiều) từ bên ngoài class. Ví du:

public class People{

private string name;

public string Name
{
        get
            { return name; }
        set
            { name= value; }
}

private string id;

public string Id
        get
                { return id; }
}

}

hay chỉ ghi vào được như

class User
{
    public void SetPassword(string password)
    {
        /* password encryption here */
    }
}

Một khía cạnh khác của control kiểm soát data đó là thực hiện một chuỗi các hành động liên quan đến sử lý khi truy cập vào data đó hoặc thay đổi giá trị của data đó. Ta có các trường hợp thường gặp sau: Thao tác với set:

  • Thay đổi năm sinh -> cần tính lại tuổi ( tương tác với trigger data)
private int age;
public int Age{
    get{ return age;}
}

private int birthYear;
public int BirthYear{
    set {
        birthYear = value;
        calculateAge();
   }
}

private void calculateAge(){
    .....
}
  • Thay đổi data -> raise event thông báo cho tiến trình khác xử lý tiếp công việc.
private int birthYear;
public int BirthYear{
    set {
        birthYear = value;
        onChangeData(value, "BirthYear");
   }
}
  • Validate data, ngăn chặn data không mong muốn, cần thiết có thể throw exception
private int myProperty;
public int MyProperty
{
   get
   {
       return this.myProperty;
   }
   set
   {
       if(this.myProperty <=5)
          throw new ArgumentOutOfRangeException("bad user");
       this.myProperty = value;
   }
}
  • Sử dụng set để bảo mật dữ liệu tốt hơn.
class User
{
    public void SetPassword(string password)
    {
        /* password encryption here */
       md5(password);
    }
}

Giá trị password tồn tại rất ngắn trong chương trình sẽ giảm thiểu nguy cơ truy cập xấu.

Thao tác với get:

  • Check quyền truy cập dữ liệu của user hoặc customize hiểu thị chương trình theo loại user. ( Get giá trị theo điều kiện)
    public List<Category> getCategories(User user)
    {
        /* Check user type = v..v... and return v.v... */
    }
  • Trace log chương trình. Ghi lại history acccess vào biến
  • Sử dụng cho các biến kiển tính toán động như count, total v.v... public double getTotalSale(User user) { return sale1 + sale2 + ....; } Các mục đich sử dụng chung khác của get và set:
  • Sử dụng get set trên interface hoặc abtract method -> giúp linh hoạt code hơn. Ngoài ra còn hỗ trợ unit test, design code tốt hơn.
  • Sử dụng get/set method giúp clone giá trị khi chúng ta chỉ muốn nhận hoặc set vào giá trị clone, chứ không muốn thao tác trực tiếp với object gốc.
  • Biến được thực hiện trong lazy-loaded. Chúng ta không biết rõ được khi nào thì data được set vào hết và khi nào thì data được đọc ra hết.
  • Với get/set method chúng ta cũng có thể tiến hành locking object giúp ngăn chặn deadlock khi biến được sử dụng trong multi-thread. Mình đã trình bày hết các ý tưởng mình gặp được về cách sử dụng get/ set property. Còn rất nhiều case khác nữa mình chưa biết hết hoặc đề cập đến còn thiếu xót. Rất mong các bạn cùng thảo luận để làm rõ hơn về đề tài trên nhé.