Thứ Ba, 22 tháng 3, 2011

OOP - một số lưu ý khi tạo class

Class bao gồm các đặc tả & hành vi nhằm mô tả thuộc tính của object. Dưới đây là một số lưu ý nhỏ nhưng hữu ích mà chúng ta có thể cân nhắc khi tạo mới một class nào đó.

1. dữ liệu nên là private.
2. dữ liệu nên được khởi tạo trong (các) hàm constructor.
3. tránh sử dụng quá nhiều kiểu dữ liệu cơ bản để mô tả, nên tách thành các class khác trong trường hợp này.
4. tên của class nên phản ánh chính xác nhất trách nhiệm & vai trò của nó.
5. một class không nên gánh vác quá nhiều việc.
6. nên sắp xếp việc khai báo các fields một cách có trật tự (theo tứ tự chữ cái, hoặc gom nhóm thành từng kiểu logic, kiểu dữ liệu ...).
7. có thể không phải tất cả các field đều có thể truy cấp (cần có hàm get/set)




    Phần thưởng:

    • ai trả lời được "tại sao?" cho các ý 1, 2, 5, 7 sẽ có quà :D

    • ai trả lời được câu trên và cho ví dụ được các ý 3, 4, 6 sẽ có quà to hơn :D--- mại dô!

    8 nhận xét:

    1. Theo thiển ý của em thì em thấy các lưu ý trên mang tính chất kinh nghiệm là chính. Đơn giản là nếu làm theo các trên thì code sẽ sáng hơn. Người sử dụng các code đấy đỡ nhức đầu hơn. Theo em đơn giản là như vậy.

      Cũng tùy mục đích cho mỗi quy tắc, ví dụ 1) dữ liệu nên là private. Chú ý là nếu dữ liệu là private trong PHP thì hình như không được sửa đổi ở lớp kế thừa (không return, không assign lại được luôn). Nên private chỉ dành cho các dữ liệu mà mình chắc chắn rằng sẽ không được phép thao tác trên ngay cả lớp kế thừa nó. Ngược lại nên dùng protected.

      Các quy tắc của OOP như private, protected, public ... và ... cũng ra đời với mục đích là để cho code của bạn sáng sủa hơn. Tránh các lỗi tiềm ẩn do bất cẩn, tùy tiện vân vân và vân vân...

      Trả lờiXóa
    2. nếu không dùng protected mà dùng private với vài dòng getter/setter thì cái nào hay hơn nhey? :D

      ngoài ra, nếu sử dụng lại code thì chỉ cần nó chạy ngon thôi chứ đâu cần hiểu chi cho nhức đầu :D

      Trả lờiXóa
    3. Cho em hỏi : quà to hơn sẽ là nhân vật nào trong bức hình ạ.... cô gái hay con chó hả anh :D

      Trả lờiXóa
    4. Đúng là mình không cần hiểu nhưng nếu mình cần phát triển lên thì đó là chuyện khác. Code mà đẹp thì chỉ cần nhìn các khóa public, protected & private cũng ra được một số vấn đề rùi.

      Với setter/getter áp dụng cho private & protected thì ý nghĩa như nhau. Họa chăng private có thời gian truy xuất nhanh hơn một tí tí tí tí tí xíu xíu xíu xíu xíu do không gian tìm kiếm được thu hẹp lại.

      Trả lờiXóa
    5. updated:
      nên lựa chọn việc kế thừa các thiết kế class hay cố gắng thiết kế sao cho class đó flexible nhất có thể? :)

      Trả lờiXóa
    6. @hoangnd: cho câu hỏi của bạn "nên lựa chọn việc kế thừa các thiết kế class hay cố gắng thiết kế sao cho class đó flexible nhất có thể?"

      Linh hoạt sẽ đồng nghĩa với việc khó sử dụng. Mọi tính năng đều nên được đơn giản hóa. Có lẽ đây cũng là một tiêu chí của code "Đẹp" của mình. Làm sao cho tính năng đơn giản và rõ ràng.

      Kế thừa hay linh hoạt với các hỗ trợ nhiều mức? Theo mình kế thừa vẫn là hay hơn. Nhìn vào kế thừa, người ta sẽ biết bạn muốn cài đặt, mở rộng tính năng nào. Còn nhìn vào một class "linh hoạt", người ta hầu như chẳng muốn tìm hiểu về các mức tính năng mà class đó hỗ trợ.

      Quan trọng là, mình xin được nhấn mạnh lại, sử dụng đúng Design Pattern cho vấn đề bạn đang giải quyết mang lại vô cùng nhiều lợi ích cho các dòng code của bạn và cho cả những người cùng làm việc với bạn nữa.

      Trả lờiXóa
    7. Em cũng mới học qua về OOP, không biết hiểu có đúng ko :) nếu có j` sai mong mọi người sửa giùm :D
      1. dữ liệu nên là private + 7. có thể không phải tất cả các field đều có thể truy cấp (cần có hàm get/set) => em nghĩ cái này nằm trong tính chất Encapsulation của OOP, dữ liệu của 1 class thường chỉ để các hàm thành viên của class được phép truy xuất, các hàm ngoài (thậm chí lớp kế thừa) ko nên cấp quyền truy xuất để tránh tình trạng dữ liệu bị thay đổi ngoài ý muốn (nên truy cập dữ liệu thông qua các hàm thành viên như set(), get(),...). Cũng nên hạn chế sử dụng hàm friend
      2. dữ liệu nên được khởi tạo trong (các) hàm constructor => Với cá nhân em dùng các constructor như 1 kiểu tạo an toàn ý, các hàm constructor tạo ra Safe Empty State, như vậy sẽ tránh bị báo lỗi khi khởi tạo (hay bị nhất là thiếu constructor không tham số), thứ 2 là constructor tạo các dữ liệu mặc định theo ý mình, từ đó sẽ dễ dàng thao tác điều khiển theo ý.
      5. một class không nên gánh vác quá nhiều việc + 4. tên của class nên phản ánh chính xác nhất trách nhiệm & vai trò của nó => Em này em nghĩ quá đúng rùi :P nó cũng là 1 phần tròn tính Encapsulation, mỗi class nên đảm nhiệm 1 nhiệm vụ chính như vậy sẽ dẽ dàng định hướng hơn (mà lúc trừu tượng mọi thứ thành class em nghĩ đã xác định được vấn đề này khá rõ ràng rùi :D)
      6. nên sắp xếp việc khai báo các fields một cách có trật tự (theo tứ tự chữ cái, hoặc gom nhóm thành từng kiểu logic, kiểu dữ liệu …) => Cái này em nghĩ có lẽ làm code dễ hiểu và quản lí hơn (hi vọng đúng :P)

      Trả lờiXóa
    8. @Phan Quảng
      Bạn nói như sách :-)

      Trong số các yếu tố trên (1 - 7), hoặc là tất cả cùng thỏa mãn hoặc là ... sai. :D

      Ví dụ như nếu (1) mà thiết kế của (5) không hoàn hảo thì cũng chịu, rất dễ dẫn đến việc trùng lặp dữ liệu hoặc chồng chéo gọi hàm về sau (kinh nghiệm thôi).

      Thử trường hợp này xem, nếu ta có 1 class là Employee, tên class có vẻ như là khá súc tích roài. Ngoài các trường tên, tuổi, nghề nghiệp ... thì có nên đưa các hàm update/insert vào trong class đó không? Cái này đơn giản nhưng có nhiều cách xử lý, mại zô kiếm quà :D

      Trả lờiXóa