Durum
Bu akşamın erken saatlerinde StackOverflow ile ilgili bir soruya cevap verdim .
Soru:
Mevcut bir nesnenin düzenlenmesi havuz katında mı yoksa hizmette mi yapılmalı?
Örneğin, borcu olan bir kullanıcı varsa. Borcunu değiştirmek istiyorum. Bunu UserRepository'de veya serviste yapmalı mıyım, örneğin BuyingService'i bir nesne alarak, düzenleyerek ve kaydederek mi yapmalıyım?
Cevabım:
Bir nesneyi aynı nesneye döndürme sorumluluğunu bırakmalı ve bu nesneyi almak için depoyu kullanmalısınız.
Örnek durum:
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
}
}
Aldığım bir yorum:
İş mantığı gerçekten bir hizmette olmalıdır. Manken değil.
İnternet ne diyor?
Bu yüzden beni aramaya soktu çünkü gerçekten (bilinçli olarak) bir servis katmanı kullanmadım. Servis Katmanı deseni ve Çalışma Birimi desenini okumaya başladım, ancak şu ana kadar bir servis katının kullanılması gerektiğine ikna olduğumu söyleyemem.
Örneğin , Anemic Domain Modelinin anti-paterni hakkındaki Martin Fowler'ın bu makalesini ele alalım :
Etki alanı alanındaki isimlerden sonra adlandırılan nesneler var ve bu nesneler, gerçek etki alanı modellerinin sahip olduğu zengin ilişkiler ve yapıyla bağlantılı. Davranış, davranışa baktığınız zaman gelir ve bu nesneler üzerinde neredeyse hiçbir davranış olmadığını fark edersiniz, bu da onları alıcıların ve ayarlayıcıların çantalarından daha az yapar. Gerçekten de bu modeller, etki alanı nesnelerine herhangi bir etki alanı mantığı koymadığınızı söyleyen tasarım kuralları ile birlikte gelir. Bunun yerine, tüm etki alanı mantığını yakalayan bir dizi hizmet nesnesi vardır. Bu hizmetler etki alanı modelinin tepesinde yaşar ve etki alanı modelini veriler için kullanır.
(...) Bir etki alanı nesnesinde olması gereken mantık, etki alanı mantığıdır - doğrulamalar, hesaplamalar, iş kuralları - ne şekilde istersen.
Bana göre durum tam olarak bununla ilgili gibiydi: Bir nesnenin verilerinin manipülasyonunu, o sınıfın içine tam da bunu yapan yöntemler getirerek savundum. Bununla birlikte, bunun her iki şekilde de verilmesi gerektiğinin farkındayım ve muhtemelen bu yöntemlerin nasıl çağrıldığını (bir havuz kullanarak) yapması gerekiyor.
Ayrıca, bu makalede (aşağıya bakınız) Hizmet Katmanının, çalışmayı asıl iş yoğun bir katmandan ziyade, temeldeki modele delege eden bir cephe olarak kabul edildiğini de hissettim .
Uygulama Katmanı [Servis Katmanı için adı]: Yazılımın yapması gereken işleri tanımlar ve etkileyici etki alanı nesnelerini sorunları çözmeleri için yönlendirir. Bu katmanın sorumlu olduğu işler, iş için anlamlıdır veya diğer sistemlerin uygulama katmanlarıyla etkileşim için gereklidir. Bu katman ince tutulur. İş kurallarını veya bilgisini içermez, ancak yalnızca görevleri koordine eder ve çalışmaları bir sonraki katmandaki etki alanı nesnelerinin işbirliğine aktarır. İşletmenin durumunu yansıtan bir durumu yoktur, ancak kullanıcı veya program için bir görevin ilerlemesini yansıtan bir durumu olabilir.
Hangisi burada güçlendirilmiş :
Servis arayüzleri Servisler, gelen tüm mesajların gönderildiği bir servis arayüzü sunar. Hizmet arayüzünü, uygulamada uygulanan iş mantığını (tipik olarak iş katmanındaki mantığı) potansiyel tüketicilere maruz bırakan bir cephe olarak düşünebilirsiniz.
Ve burada :
Hizmet katmanı herhangi bir uygulamadan veya iş mantığından yoksun olmalı ve öncelikle birkaç kaygıya odaklanmalıdır. İş Katmanı çağrılarını kapsamalı, Etki Alanınızı müşterilerinizin anlayabileceği ortak bir dile çevirin ve sunucu ile istemci arasında iletişim ortamını idare etmelidir.
Bu, Hizmet Katmanı hakkında konuşan diğer kaynaklara ciddi bir karşıtlıktır :
Hizmet katmanı, aynı işleme ait işlemlerin yapıldığı iş birimleri olan yöntemlerden oluşan sınıflardan oluşmalıdır.
Veya daha önce bağladığım bir sorunun ikinci cevabı :
Bir noktada, uygulamanız biraz iş mantığı isteyecektir. Ayrıca, kötü ya da uygun olmayan bir şeyin talep edilmediğinden emin olmak için girişi doğrulamak isteyebilirsiniz. Bu mantık servis katmanınıza aittir.
"Çözüm"?
Bu cevaptaki yönergelere uyarak, Servis Katmanı kullanan aşağıdaki yaklaşımı gördüm:
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;
}
}
Sonuç
Hep birlikte burada pek bir şey değişmedi: kontrol cihazından gelen kod servis katmanına taşındı (bu iyi bir şey, bu yüzden bu yaklaşıma bir terslik var). Ancak bu benim orijinal cevabım ile ilgisi var gibi görünmüyor.
Tasarım desenlerinin, mümkün olduğunda uygulanacak taşa konulmuş kurallar değil, kurallar olduğunu fark ediyorum. Yine de, servis katmanının ve nasıl dikkate alınması gerektiğine dair kesin bir açıklama bulamadım.
Kontrol cihazından mantığı çıkarmak ve bunun yerine bir hizmetin içine koymak için bir araç mı?
Denetleyici ile etki alanı arasında bir sözleşme mi yapılması gerekiyor?
Etki alanı ve hizmet katmanı arasında bir katman olmalı mı?
Ve, son fakat en az değil: orijinal yorumu takip ederek
İş mantığı gerçekten bir hizmette olmalıdır. Manken değil.
Bu doğru mu?
- İş mantığımı model yerine bir serviste nasıl tanıtırım?