Hỏi về MVC hướng đối tượng: phân biệt Model và Controller


Mình có đọc một bài viết. Họ viết model lấy dữ liệu rồi chuyển thành đối tượng.

Còn trên trường mình, model thầy cô chỉ làm một lớp có phương thức kết nối, query,…Ví dụ

$db = new ThuVienKNCSDL();
$chuoiTruyVan = "select * from user";
$data = $db->query($chuoiTruyVan);
//ThuVienKNCSDL là model
//Còn 3 dòng code trên là ở Controller

Vậy, giả sử hệ thống cho thuê xe, có phương thức tính toán tiền thuê trong 1 tuần của cửa hàng. Thì

  1. Model lấy dữ liệu => Tính toán vào 1 hàm. Controller chỉ lấy giá trị trả về từ Model thôi không đụng đến dữ liệu

hay

  1. Model lấy dữ liệu trả về cho Controller. Controller lấy dữ liệu trả về tính toán tiền thuê chuyển về cho view ạ

Thắc mắc thứ 2: Mình thấy sơ đồ cơ sở dữ liệu và sơ đồ lớp, cả hai có các thuộc tính giống nhau, chỉ là csdl thì là các trường của bảng để lưu dữ liệu, còn lớp thì có thêm các phương thức tính toán.
Vậy, class mình đặt trong Model, Controller tạo đối tượng đó lấy dữ liệu và chuyển về View hay class được đặt ở Controller, Model trả kết quả về, Controller mới đem dữ liệu đó tạo đối tượng từ class của mình rồi chuyển sang View ạ.

Vì Controller thì làm các xử lý, còn những gì liên quan đến dữ liệu thì ở Model nên mình thấy nó chéo chéo nhau ạ.
Hiểu biết nông cạn, các bác giải thích giúp mình với. Xin cảm ơn!

Welcome to Dạy nhau học,

Cho phép tớ trả lời các thắc mắc của cậu về MVC :smiley:
Disclaim: đây là quan điểm cá nhân của tớ, vì vậy, feel free to disagree and any contribution is welcome.

Trong 2 cách cài đặt mà cậu đề cập ở trên, điểm khác biệt của 2 cách đó là logic tính toán được đặt ở đâu.
Cách cài đặt thứ 1 mà cậu đề cập, logic tính toán sẽ được đẩy vào model, nằm ở trung tâm của toàn bộ kiến trúc.
Cách cài đặt thứ 2 mà cậu đề cập, thực ra là 3-tire architechture. Controller ở đây sẽ chứa toàn bộ các logic tính toán.
Theo quan điểm cá nhân tớ, cách thứ 2 sẽ ổn hơn, vì những lý do dưới đây:

  • Ở cách 1, cậu đã để chung phần logic của application với phần mô hình dữ liệu hệ thống + các thành phần liên lạc với external components (ví dụ: thành phần gọi external API, thành phần gọi tới DB… Tớ sẽ gọi chung nó là infrastructure). Sự phức tạp đó sẽ khiến cho hệ thống của cậu vô cùng khó để có thể test và bảo trì, và cậu sẽ end up với 1 đống spagetti code ở trong model.
  • Ở cách 2, logic của application được tách ra khỏi mô hình dữ liệu hệ thống + infrastructure trong model. Ít nhất nó sẽ làm giảm độ phức tạp của model, và khiến cho ít nhất phần application logic của cậu dễ bảo trì hơn.
    Tuy nhiên, cách này cậu vẫn có sự phụ thuộc chặt chẽ giữa mô hình dữ liệu hệ thống và các thành phần liên lạc với infrastructure, vậy nên cậu có thể cân nhắc giới thiệu thêm 1 tầng infrastructure nữa làm giảm độ phức tạp của model, nếu cậu nhận thấy ứng dụng của cậu không còn nhỏ nữa.

Trước tiên, cho phép tớ đề cập điều này, tớ nghĩ có lẽ có “design smell” ở mô tả đầu tiên của cậu.

  • Sơ đồ cơ sở dữ liệu của cậu là cách cậu tổ chức dữ liệu vật lý.
  • Khi cậu lấy dữ liệu lên trên application, cậu sẽ chuyển nó thành object tương ứng 1 - 1 với tổ chức dữ liệu vật lý của cậu. Các object này chỉ chứa dữ liệu, không có bất cứ hành vi nào, và nó thường được gọi là DTO (data transfer object).
  • Việc cậu gán thêm các phương thức tính toán vào object này như trong mô tả của cậu, đồng thời sử dụng nó trong toàn bộ application như các thực thể dữ liệu dùng để mô hình hóa business data của cậu là 1 sai lầm. Nó sẽ khiến cậu gặp khó khăn lớn khi có bất cứ yêu cầu thay đổi gì, hoặc xảy ra ở trên giao diện/business logic layer, hoặc xảy ra ở dưới DB hay external API, khi cậu phải cập nhật toàn bộ dữ liệu ở tất cả mọi nơi trong hệ thống.
  • Design thường gặp là cậu sẽ có các thực thể dữ liệu riêng của cậu (entity), thứ mà cậu sẽ sử dụng trong application logic. Hiển nhiên, sau khi lấy dữ liệu về DTO, cậu sẽ cần convert DTO sang entity và xử lý. Nó sẽ khiến cho tầng infra của cậu độc lập hoàn toàn với tầng business logic layer, mọi thay đổi ở 1 trong 2 nơi sẽ chỉ cần sửa ở conversion logic.

Về câu hỏi của cậu:

Tớ nghĩ cậu đang đề cập tới DTO và DAO (data access object - các object được dùng để lấy dữ liệu từ DB) được đặt ở đâu.
Trong MVC, thường cậu đặt nó ở model, vì sau khi cậu lấy dữ liệu vật lý về, cậu phải convert nó thành dữ liệu thực sự sử dụng trong business của cậu.
Nhưng tốt nhất, nó nên được giới thiệu như 1 tầng nhỏ trong model, và gọi nó là Infrastructure/DAO layer, nếu như hệ thống của cậu trở nên phức tạp hơn.

Tớ hi vọng câu trả lời hơi dài dòng của tớ sẽ giúp giải đáp phần nào thắc mắc của cậu.

5 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?