Tình hình
Đầu buổi tối hôm nay tôi đã đưa ra câu trả lời cho một câu hỏi trên StackOverflow.
Câu hỏi:
Chỉnh sửa một đối tượng hiện có nên được thực hiện trong lớp kho lưu trữ hoặc trong dịch vụ?
Ví dụ: nếu tôi có một Người dùng có nợ. Tôi muốn thay đổi nợ của anh ấy. Tôi nên làm điều đó trong UserRep repository hoặc trong dịch vụ, ví dụ như MuaService bằng cách lấy một đối tượng, chỉnh sửa và lưu nó?
Câu trả lời của tôi:
Bạn nên để lại trách nhiệm biến đổi một đối tượng thành cùng một đối tượng đó và sử dụng kho lưu trữ để truy xuất đối tượng này.
Ví dụ tình huống:
class User {
private int debt; // debt in cents
private string name;
// getters
public void makePayment(int cents){
debt -= cents;
}
}
class UserRepository {
public User GetUserByName(string name){
// Get appropriate user from database
}
}
Một nhận xét tôi nhận được:
Logic kinh doanh nên thực sự trong một dịch vụ. Không phải trong một mô hình.
Internet nói gì?
Vì vậy, điều này khiến tôi tìm kiếm vì tôi chưa bao giờ thực sự sử dụng một lớp dịch vụ. Tôi đã bắt đầu đọc lên mẫu Lớp dịch vụ và mẫu Đơn vị công việc nhưng cho đến nay tôi không thể nói rằng tôi tin rằng một lớp dịch vụ phải được sử dụng.
Lấy ví dụ bài viết này của Martin Fowler về mô hình chống mô hình miền thiếu máu:
Có các đối tượng, nhiều tên được đặt theo danh từ trong không gian miền và các đối tượng này được kết nối với các mối quan hệ và cấu trúc phong phú mà các mô hình miền thực có. Nắm bắt được khi bạn nhìn vào hành vi, và bạn nhận ra rằng hầu như không có bất kỳ hành vi nào trên các đối tượng này, làm cho chúng ít hơn nhiều so với các túi getters và setters. Thật vậy, thường các mô hình này đi kèm với các quy tắc thiết kế nói rằng bạn không được đặt bất kỳ logic miền nào trong các đối tượng miền. Thay vào đó, có một tập hợp các đối tượng dịch vụ nắm bắt tất cả logic miền. Các dịch vụ này nằm trên mô hình miền và sử dụng mô hình miền cho dữ liệu.
(...) Logic nên có trong một đối tượng miền là logic miền - xác thực, tính toán, quy tắc kinh doanh - bất cứ điều gì bạn muốn gọi nó.
Đối với tôi, đây dường như chính xác là tình huống xảy ra: Tôi ủng hộ việc thao túng dữ liệu của một đối tượng bằng cách giới thiệu các phương thức bên trong lớp đó thực hiện điều đó. Tuy nhiên tôi nhận ra rằng đây phải là một trong hai cách nhất định và có lẽ nó liên quan nhiều hơn đến cách các phương thức này được gọi (sử dụng một kho lưu trữ).
Tôi cũng có cảm giác rằng trong bài viết đó (xem bên dưới), Lớp Dịch vụ được coi là mặt tiền mà các đại biểu làm việc cho mô hình bên dưới, hơn là một lớp chuyên sâu thực tế.
Lớp ứng dụng [tên của anh ta cho lớp dịch vụ]: Xác định các công việc mà phần mềm phải làm và chỉ đạo các đối tượng miền biểu cảm để giải quyết các vấn đề. Các tác vụ mà lớp này chịu trách nhiệm có ý nghĩa đối với doanh nghiệp hoặc cần thiết để tương tác với các lớp ứng dụng của các hệ thống khác. Lớp này được giữ mỏng. Nó không chứa các quy tắc hoặc kiến thức kinh doanh, mà chỉ phối hợp các tác vụ và đại biểu làm việc với sự hợp tác của các đối tượng miền trong lớp tiếp theo. Nó không có trạng thái phản ánh tình hình kinh doanh, nhưng nó có thể có trạng thái phản ánh tiến trình của một nhiệm vụ cho người dùng hoặc chương trình.
Được củng cố ở đây :
Giao diện dịch vụ. Các dịch vụ hiển thị giao diện dịch vụ mà tất cả các tin nhắn gửi đến được gửi. Bạn có thể nghĩ về giao diện dịch vụ như một mặt tiền phơi bày logic nghiệp vụ được triển khai trong ứng dụng (thông thường, logic trong lớp nghiệp vụ) cho người tiêu dùng tiềm năng.
Và đây :
Lớp dịch vụ nên không có bất kỳ ứng dụng hoặc logic kinh doanh nào và nên tập trung chủ yếu vào một vài mối quan tâm. Nó sẽ bao bọc các cuộc gọi của Lớp nghiệp vụ, dịch Miền của bạn bằng ngôn ngữ chung mà khách hàng của bạn có thể hiểu và xử lý phương tiện liên lạc giữa máy chủ và yêu cầu máy khách.
Đây là một sự tương phản nghiêm trọng với các tài nguyên khác nói về Lớp dịch vụ:
Lớp dịch vụ nên bao gồm các lớp với các phương thức là các đơn vị công việc với các hành động thuộc cùng một giao dịch.
Hoặc câu trả lời thứ hai cho câu hỏi tôi đã liên kết:
Tại một số điểm, ứng dụng của bạn sẽ muốn một số logic kinh doanh. Ngoài ra, bạn có thể muốn xác thực đầu vào để đảm bảo rằng không có điều gì xấu hoặc không phù hợp được yêu cầu. Logic này thuộc về lớp dịch vụ của bạn.
"Giải pháp"?
Theo hướng dẫn trong câu trả lời này , tôi đã đưa ra cách tiếp cận sau đây sử dụng Lớp dịch vụ:
class UserController : Controller {
private UserService _userService;
public UserController(UserService userService){
_userService = userService;
}
public ActionResult MakeHimPay(string username, int amount) {
_userService.MakeHimPay(username, amount);
return RedirectToAction("ShowUserOverview");
}
public ActionResult ShowUserOverview() {
return View();
}
}
class UserService {
private IUserRepository _userRepository;
public UserService(IUserRepository userRepository) {
_userRepository = userRepository;
}
public void MakeHimPay(username, amount) {
_userRepository.GetUserByName(username).makePayment(amount);
}
}
class UserRepository {
public User GetUserByName(string name){
// Get appropriate user from database
}
}
class User {
private int debt; // debt in cents
private string name;
// getters
public void makePayment(int cents){
debt -= cents;
}
}
Phần kết luận
Tất cả cùng nhau không có nhiều thay đổi ở đây: mã từ bộ điều khiển đã chuyển sang lớp dịch vụ (đây là một điều tốt, vì vậy có một mặt trái của phương pháp này). Tuy nhiên điều này không giống như nó có liên quan đến câu trả lời ban đầu của tôi.
Tôi nhận ra các mẫu thiết kế là hướng dẫn, không phải là các quy tắc được thiết lập để thực hiện bất cứ khi nào có thể. Tuy nhiên, tôi đã không tìm thấy một lời giải thích dứt khoát về lớp dịch vụ và cách nó nên được xem xét.
Nó có phải là một phương tiện đơn giản để trích xuất logic từ bộ điều khiển và đặt nó bên trong một dịch vụ thay thế không?
Có phải hình thành một hợp đồng giữa bộ điều khiển và tên miền?
Có nên có một lớp giữa miền và lớp dịch vụ?
Và, cuối cùng nhưng không kém phần quan trọng: theo nhận xét ban đầu
Logic kinh doanh nên thực sự trong một dịch vụ. Không phải trong một mô hình.
Điều này có đúng không?
- Làm thế nào tôi có thể giới thiệu logic kinh doanh của mình trong một dịch vụ thay vì mô hình?