Situasi
Sebelumnya malam ini saya memberikan jawaban atas pertanyaan di StackOverflow.
Pertanyaan:
Mengedit objek yang ada harus dilakukan di lapisan repositori atau dalam layanan?
Misalnya jika saya memiliki Pengguna yang memiliki hutang. Saya ingin mengubah utangnya. Haruskah saya melakukannya di UserRepository atau dalam layanan misalnya BuyingService dengan mendapatkan objek, mengedit dan menyimpannya?
Jawabanku:
Anda harus meninggalkan tanggung jawab untuk memutasikan suatu objek ke objek yang sama dan menggunakan repositori untuk mengambil objek ini.
Contoh situasi:
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
}
}
Komentar yang saya terima:
Logika bisnis harus benar-benar dalam layanan. Tidak dalam model.
Apa kata internet?
Jadi, ini membuat saya mencari karena saya tidak pernah (secara sadar) menggunakan lapisan layanan. Saya mulai membaca tentang pola Lapisan Layanan dan pola Unit Kerja tetapi sejauh ini saya tidak bisa mengatakan saya yakin lapisan layanan harus digunakan.
Ambil contoh artikel ini oleh Martin Fowler tentang anti-pola Model Domain Anemik:
Ada objek, banyak yang dinamai dengan kata benda di ruang domain, dan objek ini terhubung dengan hubungan dan struktur kaya yang dimiliki oleh model domain yang sebenarnya. Tangkapan datang ketika Anda melihat perilaku, dan Anda menyadari bahwa hampir tidak ada perilaku pada benda-benda ini, membuat mereka sedikit lebih dari sekantong getter dan setter. Memang sering model-model ini datang dengan aturan desain yang mengatakan bahwa Anda tidak boleh menempatkan logika domain di objek domain. Sebaliknya ada satu set objek layanan yang menangkap semua logika domain. Layanan ini hidup di atas model domain dan menggunakan model domain untuk data.
(...) Logika yang harus ada dalam objek domain adalah logika domain - validasi, perhitungan, aturan bisnis - apa pun yang Anda suka menyebutnya.
Bagi saya, ini persis seperti apa situasinya: Saya menganjurkan manipulasi data objek dengan memperkenalkan metode di dalam kelas yang melakukan hal itu. Namun saya menyadari bahwa ini harus diberikan dengan cara apa pun, dan mungkin lebih berkaitan dengan bagaimana metode ini dipanggil (menggunakan repositori).
Saya juga merasa bahwa dalam artikel itu (lihat di bawah), Layer Layanan lebih dianggap sebagai façade yang mendelegasikan pekerjaan ke model yang mendasarinya, daripada lapisan padat karya yang sebenarnya.
Application Layer [namanya untuk Service Layer]: Menentukan pekerjaan yang seharusnya dilakukan oleh perangkat lunak dan mengarahkan objek domain ekspresif untuk menyelesaikan masalah. Tugas-tugas yang bertanggung jawab atas lapisan ini bermakna bagi bisnis atau diperlukan untuk interaksi dengan lapisan aplikasi sistem lain. Lapisan ini dijaga tetap tipis. Itu tidak mengandung aturan atau pengetahuan bisnis, tetapi hanya mengoordinasikan tugas dan delegasi yang bekerja untuk kolaborasi objek domain di lapisan berikutnya ke bawah. Itu tidak memiliki keadaan yang mencerminkan situasi bisnis, tetapi bisa memiliki keadaan yang mencerminkan kemajuan tugas bagi pengguna atau program.
Yang diperkuat di sini :
Antarmuka layanan. Layanan memperlihatkan antarmuka layanan tempat semua pesan masuk dikirim. Anda dapat menganggap antarmuka layanan sebagai fasad yang memaparkan logika bisnis yang diterapkan dalam aplikasi (biasanya, logika di lapisan bisnis) kepada konsumen potensial.
Dan di sini :
Lapisan layanan harus tanpa aplikasi atau logika bisnis apa pun dan harus berfokus terutama pada beberapa masalah. Seharusnya membungkus panggilan Layer Bisnis, menerjemahkan Domain Anda dalam bahasa umum yang dapat dipahami klien Anda, dan menangani media komunikasi antara server dan klien yang meminta.
Ini sangat berbeda dengan sumber daya lain yang berbicara tentang Lapisan Layanan:
Lapisan layanan harus terdiri dari kelas dengan metode yang merupakan unit kerja dengan tindakan yang termasuk dalam transaksi yang sama.
Atau jawaban kedua untuk pertanyaan yang sudah saya tautkan:
Pada titik tertentu, aplikasi Anda akan menginginkan beberapa logika bisnis. Selain itu, Anda mungkin ingin memvalidasi input untuk memastikan bahwa tidak ada sesuatu yang jahat atau tidak diminta yang diminta. Logika ini termasuk dalam lapisan layanan Anda.
"Larutan"?
Mengikuti pedoman dalam jawaban ini , saya datang dengan pendekatan berikut yang menggunakan Lapisan Layanan:
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;
}
}
Kesimpulan
Semua bersama-sama tidak banyak yang berubah di sini: kode dari controller telah pindah ke lapisan layanan (yang merupakan hal yang baik, jadi ada sisi positif dari pendekatan ini). Namun ini sepertinya tidak ada hubungannya dengan jawaban asli saya.
Saya menyadari bahwa pola desain adalah pedoman, bukan aturan yang ditetapkan untuk diterapkan bila memungkinkan. Namun saya belum menemukan penjelasan yang pasti tentang lapisan layanan dan bagaimana seharusnya dianggap.
Apakah ini sarana untuk mengekstrak logika dari controller dan memasukkannya ke dalam layanan?
Apakah ini seharusnya membentuk kontrak antara pengontrol dan domain?
Haruskah ada lapisan antara domain dan lapisan layanan?
Dan, yang tak kalah pentingnya: mengikuti komentar asli
Logika bisnis harus benar-benar dalam layanan. Tidak dalam model.
Apakah ini benar?
- Bagaimana saya memperkenalkan logika bisnis saya dalam layanan, bukan model?
sumber
Jawaban:
Untuk menentukan apa tanggung jawab suatu layanan , Anda harus terlebih dahulu menentukan apa layanan itu.
Layanan bukan istilah perangkat lunak kanonik atau generik. Bahkan, akhiran
Service
pada nama kelas adalah banyak seperti banyak difitnah Manajer : Ini memberitahu Anda hampir tidak ada tentang apa benda itu sebenarnya tidak .Pada kenyataannya, apa yang harus dilakukan oleh suatu layanan sangat spesifik untuk arsitektur:
Dalam arsitektur berlapis tradisional, layanan secara harfiah identik dengan lapisan logika bisnis . Ini lapisan antara UI dan Data. Karena itu, semua aturan bisnis masuk ke layanan. Lapisan data seharusnya hanya memahami operasi CRUD dasar, dan lapisan UI hanya harus berurusan dengan pemetaan presentasi DTO ke dan dari objek bisnis.
Dalam arsitektur terdistribusi gaya RPC (SOAP, UDDI, BPEL, dll.), Layanan ini adalah versi logis dari titik akhir fisik . Ini pada dasarnya adalah kumpulan operasi yang ingin disediakan oleh pengelola sebagai API publik. Berbagai panduan praktik terbaik menjelaskan bahwa operasi layanan seharusnya menjadi operasi tingkat bisnis dan bukan CRUD, dan saya cenderung setuju.
Namun, karena merutekan segala sesuatu melalui layanan jarak jauh yang sebenarnya dapat sangat merusak kinerja, biasanya yang terbaik adalah tidak membiarkan layanan ini benar-benar mengimplementasikan logika bisnis itu sendiri; alih-alih, mereka harus membungkus satu set objek bisnis "internal". Layanan tunggal mungkin melibatkan satu atau beberapa objek bisnis.
Dalam arsitektur MVP / MVC / MVVM / MV *, layanan tidak ada sama sekali. Atau jika mereka melakukannya, istilah ini digunakan untuk merujuk ke objek generik yang dapat disuntikkan ke model controller atau view. Logika bisnis ada dalam model Anda . Jika Anda ingin membuat "objek layanan" untuk mengatur operasi yang rumit, itu terlihat sebagai detail implementasi. Banyak orang, sayangnya, menerapkan MVC seperti ini, tetapi itu dianggap sebagai anti-pola ( Anemic Domain Model ) karena model itu sendiri tidak melakukan apa-apa, itu hanya sekumpulan properti untuk UI.
Beberapa orang keliru berpikir bahwa mengambil metode 100-line controller dan mendorong semuanya ke dalam layanan entah bagaimana membuat arsitektur yang lebih baik. Sebenarnya tidak; yang dilakukannya hanyalah menambahkan lapisan tipuan yang mungkin tidak perlu. Secara praktis , controller masih melakukan pekerjaan, itu hanya melakukannya melalui objek "pembantu" yang tidak disebutkan namanya. Saya sangat merekomendasikan presentasi Wicked Domain Model Jimmy Bogard untuk contoh yang jelas tentang cara mengubah model domain anemia menjadi yang bermanfaat. Ini melibatkan pemeriksaan yang teliti terhadap model yang Anda ungkap dan operasi mana yang benar-benar valid dalam konteks bisnis .
Misalnya, jika database Anda berisi Pesanan, dan Anda memiliki kolom untuk Jumlah Total, aplikasi Anda mungkin tidak boleh benar-benar mengubah bidang itu ke nilai arbitrer, karena (a) riwayatnya dan (b) seharusnya ditentukan oleh apa yang ada dalam urutan serta mungkin beberapa data / aturan sensitif waktu lainnya. Membuat layanan untuk mengelola Pesanan tidak serta merta menyelesaikan masalah ini, karena kode pengguna masih dapat mengambil objek Pesanan yang sebenarnya dan mengubah jumlahnya. Sebaliknya, pesanan itu sendiri harus bertanggung jawab untuk memastikan bahwa pesanan itu hanya dapat diubah dengan cara yang aman dan konsisten.
Dalam DDD, layanan dimaksudkan secara khusus untuk situasi ketika Anda memiliki operasi yang tidak semestinya menjadi milik agregat root . Anda harus berhati-hati di sini, karena seringkali kebutuhan akan layanan dapat menyiratkan bahwa Anda tidak menggunakan akar yang benar. Tetapi dengan asumsi Anda melakukannya, suatu layanan digunakan untuk mengoordinasikan operasi lintas banyak akar, atau terkadang untuk menangani masalah yang sama sekali tidak melibatkan model domain (seperti, mungkin, menulis informasi ke basis data BI / OLAP).
Salah satu aspek penting dari layanan DDD adalah bahwa ia diizinkan untuk menggunakan skrip transaksi . Ketika bekerja pada aplikasi besar, Anda sangat mungkin pada akhirnya akan mengalami contoh di mana itu hanya cara yang lebih mudah untuk mencapai sesuatu dengan prosedur T-SQL atau PL / SQL daripada harus repot dengan model domain. Ini tidak masalah, dan itu termasuk dalam Layanan.
Ini adalah perubahan radikal dari definisi layanan arsitektur berlapis. Lapisan layanan merangkum objek domain; layanan DDD merangkum apa pun yang tidak ada dalam objek domain dan tidak masuk akal.
Dalam Arsitektur Berorientasi Layanan, layanan dianggap sebagai otoritas teknis untuk kemampuan bisnis. Itu berarti bahwa itu adalah pemilik eksklusif dari bagian tertentu dari data bisnis dan tidak ada yang diizinkan untuk menyentuh data itu - bahkan tidak hanya untuk membacanya .
Dengan kebutuhan, layanan sebenarnya merupakan proposisi ujung ke ujung dalam SOA. Artinya, layanan bukanlah komponen spesifik seperti seluruh tumpukan , dan seluruh aplikasi Anda (atau seluruh bisnis Anda) adalah seperangkat layanan ini yang berjalan berdampingan tanpa persimpangan kecuali pada lapisan pesan dan UI. Setiap layanan memiliki data sendiri, aturan bisnisnya sendiri, dan UI sendiri. Mereka tidak perlu mengatur satu sama lain karena mereka diharapkan memiliki bisnis yang selaras - dan, seperti bisnis itu sendiri, setiap layanan memiliki serangkaian tanggung jawab masing-masing dan beroperasi kurang lebih secara independen dari yang lain.
Jadi, menurut definisi SOA, setiap bagian dari logika bisnis di mana saja terkandung dalam layanan, tetapi sekali lagi, demikian pula seluruh sistem . Layanan dalam SOA dapat memiliki komponen , dan mereka dapat memiliki titik akhir , tetapi cukup berbahaya untuk menyebut setiap bagian dari kode layanan karena bertentangan dengan apa yang seharusnya "S" maksudnya.
Karena SOA umumnya cukup tertarik pada olahpesan, operasi yang mungkin telah Anda bungkus dalam layanan sebelumnya umumnya dienkapsulasi dalam penangan , tetapi multiplisitasnya berbeda. Setiap pawang menangani satu jenis pesan, satu operasi. Ini adalah interpretasi ketat dari Prinsip Tanggung Jawab Tunggal , tetapi membuat pemeliharaan yang luar biasa karena setiap operasi yang mungkin dilakukan berada di kelasnya sendiri. Jadi Anda tidak benar-benar membutuhkan logika bisnis terpusat, karena perintah mewakili operasi bisnis daripada yang teknis.
Pada akhirnya, dalam arsitektur apa pun yang Anda pilih, akan ada beberapa komponen atau lapisan yang memiliki sebagian besar logika bisnis. Lagi pula, jika logika bisnis tersebar di semua tempat maka Anda hanya memiliki kode spageti. Tetapi apakah Anda menyebut komponen itu suatu layanan , dan bagaimana komponen itu dirancang dalam hal-hal seperti jumlah atau ukuran operasi, tergantung pada tujuan arsitektur Anda.
Tidak ada jawaban benar atau salah, hanya yang berlaku untuk situasi Anda.
sumber
Adapun judul Anda , saya pikir pertanyaan itu tidak masuk akal. Model MVC terdiri dari data dan logika bisnis. Mengatakan logika harus dalam Layanan dan bukan Model itu seperti mengatakan, "Penumpang harus duduk di kursi, bukan di dalam mobil".
Kemudian lagi, istilah "Model" adalah istilah yang kelebihan beban. Mungkin Anda tidak bermaksud Model MVC tetapi Anda berarti model dalam arti Data Transfer Object (DTO). AKA dan Entitas. Inilah yang dibicarakan Martin Fowler.
Cara saya melihatnya, Martin Fowler berbicara tentang hal-hal di dunia yang ideal. Dalam dunia nyata Hibernate dan JPA (di tanah Jawa) DTO adalah abstraksi super bocor. Saya ingin menempatkan logika bisnis saya di entitas saya. Itu akan membuat segalanya lebih bersih. Masalahnya adalah entitas ini dapat eksis dalam kondisi terkelola / cache yang sangat sulit untuk dipahami dan terus-menerus mencegah upaya Anda. Untuk meringkas pendapat saya: Martin Fowler merekomendasikan cara yang benar, tetapi ORM mencegah Anda melakukannya.
Saya pikir Bob Martin memiliki saran yang lebih realistis dan dia memberikannya di video ini yang tidak gratis . Dia berbicara tentang menjaga DTO Anda bebas dari logika. Mereka hanya memegang data dan mentransfernya ke lapisan lain yang jauh lebih berorientasi objek dan tidak menggunakan DTO secara langsung. Ini menghindari abstraksi bocor dari menggigit Anda. Lapisan dengan DTO dan DTO sendiri bukan OO. Tapi begitu Anda keluar dari lapisan itu, Anda bisa menjadi sama seperti OO seperti pendukung Martin Fowler.
Manfaat dari pemisahan ini adalah mengabstraksi lapisan ketekunan. Anda bisa beralih dari JPA ke JDBC (atau sebaliknya) dan tidak ada logika bisnis yang harus berubah. Itu hanya tergantung pada DTO, tidak peduli bagaimana DTO tersebut dihuni.
Untuk sedikit mengubah topik, Anda perlu mempertimbangkan fakta bahwa database SQL tidak berorientasi objek. Tapi ORM biasanya memiliki entitas - yang merupakan objek - per tabel. Jadi sejak awal Anda sudah kalah dalam pertempuran. Dalam pengalaman saya, Anda tidak pernah bisa mewakili Entitas dengan cara yang persis Anda inginkan dengan cara yang berorientasi objek.
Adapun " sebuah layanan", Bob Martin akan melawan memiliki kelas bernama
FooBarService
. Itu tidak berorientasi objek. Apa yang dilakukan layanan? Apa pun yang terkait denganFooBars
. Mungkin juga diberi labelFooBarUtils
. Saya pikir dia menganjurkan lapisan layanan (nama yang lebih baik akan menjadi lapisan logika bisnis) tetapi setiap kelas di lapisan itu akan memiliki nama yang bermakna.sumber
Saya sedang mengerjakan proyek greenfield sekarang dan kami harus membuat beberapa keputusan arsitektur baru kemarin. Lucunya, saya harus meninjau kembali beberapa bab 'Pola Arsitektur Aplikasi Perusahaan'.
Inilah yang kami temukan:
Kami berakhir dengan yang berikut:
Klien -> Layanan -> Domain -> Data
Kami dapat mengganti klien, layanan atau lapisan data dengan jumlah pekerjaan yang wajar. Jika logika domain Anda tinggal di layanan dan Anda telah memutuskan bahwa Anda ingin mengganti atau bahkan menghapus lapisan layanan Anda, maka Anda harus memindahkan semua logika bisnis di tempat lain. Persyaratan seperti itu jarang terjadi, tetapi itu mungkin terjadi.
Setelah mengatakan semua ini, saya pikir ini cukup dekat dengan apa yang dikatakan Martin Fowler
Diagram di bawah menggambarkan ini dengan cukup baik:
http://martinfowler.com/eaaCatalog/serviceLayer.html
sumber
Ini adalah salah satu hal yang sangat tergantung pada use case. Titik keseluruhan dari lapisan layanan adalah untuk menggabungkan logika bisnis bersama. Ini berarti bahwa beberapa pengontrol dapat memanggil UserService.MakeHimPay () yang sama tanpa benar-benar peduli tentang bagaimana pembayaran dilakukan. Apa yang terjadi dalam layanan mungkin sesederhana memodifikasi properti objek atau mungkin melakukan logika kompleks berurusan dengan layanan lain (yaitu, memanggil layanan pihak ketiga, memanggil logika validasi, atau bahkan hanya menyimpan sesuatu ke database. )
Ini tidak berarti Anda harus menghapus SEMUA logika dari objek domain. Kadang-kadang lebih masuk akal untuk memiliki metode pada objek domain melakukan beberapa perhitungan pada dirinya sendiri. Dalam contoh terakhir Anda, layanan ini adalah lapisan yang berlebihan di atas objek repositori / domain. Ini memberikan penyangga yang bagus terhadap perubahan persyaratan, tetapi sebenarnya tidak perlu. Jika Anda merasa Anda membutuhkan layanan, cobalah yang melakukan logika "modifikasi properti X pada objek Y" sederhana alih-alih objek domain. Logika pada kelas domain cenderung masuk ke "hitung nilai ini dari bidang" daripada mengekspos semua bidang melalui pengambil / setter.
sumber
Cara termudah untuk mengilustrasikan mengapa programmer menghindari menempatkan logika domain dalam objek domain adalah bahwa mereka biasanya dihadapkan pada situasi "di mana saya meletakkan logika validasi?" Ambil objek domain ini misalnya:
Jadi kami memiliki beberapa logika validasi dasar di setter (tidak boleh negatif). Masalahnya adalah Anda tidak dapat benar-benar menggunakan kembali logika ini. Di suatu tempat ada layar atau ViewModel atau Pengendali yang perlu melakukan validasi sebelum benar-benar melakukan perubahan pada objek domain, karena itu perlu memberi tahu pengguna baik sebelum atau ketika mereka mengklik tombol Simpan bahwa mereka tidak bisa melakukan itu, dan mengapa . Menguji pengecualian ketika Anda memanggil setter adalah hack yang jelek karena Anda benar-benar harus melakukan semua validasi bahkan sebelum Anda memulai transaksi.
Itu sebabnya orang-orang memindahkan logika validasi semacam layanan, seperti
MyEntityValidator
. Kemudian entitas dan logika panggilan bisa mendapatkan referensi ke layanan validasi dan menggunakannya kembali.Jika Anda tidak melakukan itu dan Anda masih ingin menggunakan kembali logika validasi, Anda akhirnya meletakkannya dalam metode statis kelas entitas:
Ini akan membuat model domain Anda kurang "anemia", dan menjaga logika validasi di sebelah properti, yang bagus, tapi saya rasa tidak ada orang yang benar-benar menyukai metode statis.
sumber
Saya pikir jawabannya jelas jika Anda membaca artikel Model Domain Anemik Martin Fowler .
Menghapus logika bisnis, yang merupakan domain, dari model domain pada dasarnya melanggar desain berorientasi objek.
Mari kita tinjau konsep berorientasi objek paling dasar: Objek merangkum data dan operasi. Misalnya, menutup akun adalah operasi yang harus dilakukan objek objek dengan sendirinya; Oleh karena itu, memiliki lapisan layanan melakukan operasi itu bukan solusi berorientasi objek. Ini prosedural, dan itulah yang dimaksud Martin Fowler ketika dia berbicara tentang model domain anemia.
Jika Anda memiliki lapisan layanan menutup akun, daripada menutup objek akun, Anda tidak memiliki objek akun nyata. "Objek" akun Anda hanyalah struktur data. Apa yang akhirnya Anda dapatkan, seperti yang disarankan Martin Fowler, adalah banyak tas berisi getter dan setter.
sumber
Bagaimana Anda menerapkan logika bisnis Anda di lapisan layanan? Ketika Anda melakukan pembayaran dari pengguna, Anda membuat pembayaran, bukan hanya mengurangi nilai dari properti.
Metode pembayaran make Anda perlu membuat catatan pembayaran, menambah hutang pengguna itu dan bertahan semua ini di repositori Anda. Melakukan ini dalam metode layanan sangat mudah, dan Anda juga dapat membungkus seluruh operasi dalam transaksi. Melakukan hal yang sama dalam model domain gabungan jauh lebih bermasalah.
sumber
Versi tl; dr:
Pengalaman dan pendapat saya mengatakan bahwa objek apa pun yang memiliki logika bisnis harus menjadi bagian dari model domain. Model data seharusnya tidak memiliki logika apa pun. Layanan mungkin harus menyatukan keduanya, dan menangani masalah lintas sektoral (database, logging, dll.). Namun, jawaban yang diterima adalah yang paling praktis.
Versi yang lebih panjang, yang telah disinggung oleh orang lain, adalah bahwa ada kata penyimpangan pada kata "model". Posting beralih antara model data dan model domain seolah-olah mereka sama, yang merupakan kesalahan yang sangat umum. Mungkin juga ada sedikit penyangkalan pada kata "service".
Secara praktis, Anda seharusnya tidak memiliki layanan yang membuat perubahan pada objek domain apa pun; alasan untuk ini adalah bahwa layanan Anda kemungkinan akan memiliki beberapa metode untuk setiap properti pada objek Anda untuk mengubah nilai properti itu. Ini merupakan masalah karena dengan demikian, jika Anda memiliki antarmuka untuk objek Anda (atau bahkan jika tidak), layanan tidak lagi mengikuti Prinsip Terbuka-Tertutup; sebaliknya, setiap kali Anda menambahkan lebih banyak data ke model Anda (terlepas dari domain vs data), Anda akhirnya harus menambahkan lebih banyak fungsi ke layanan Anda. Ada cara-cara tertentu di sekitarnya, tetapi ini adalah alasan paling umum saya melihat aplikasi "perusahaan" gagal, terutama ketika organisasi-organisasi itu berpikir bahwa "perusahaan" berarti "memiliki antarmuka untuk setiap objek dalam sistem". Bisakah Anda bayangkan menambahkan metode baru ke antarmuka, kemudian ke dua atau tiga implementasi yang berbeda (yang dalam aplikasi, implementasi tiruan, dan debug satu, yang dalam memori?), hanya untuk satu properti pada model Anda? Kedengarannya seperti ide yang buruk bagi saya.
Ada masalah yang lebih lama di sini yang tidak akan saya bahas, tetapi intinya adalah ini: Pemrograman berorientasi objek hardcore mengatakan bahwa tidak ada seorang pun di luar objek yang relevan yang dapat mengubah nilai properti di dalam objek, atau bahkan " lihat "nilai properti di dalam objek. Ini dapat dikurangi dengan membuat data hanya-baca. Anda masih dapat mengalami masalah seperti ketika banyak orang menggunakan data bahkan sebagai hanya baca dan Anda harus mengubah jenis data itu. Mungkin saja semua konsumen harus berubah untuk mengakomodasi itu. Inilah sebabnya, ketika Anda membuat API untuk dikonsumsi oleh siapa saja dan semua orang, Anda disarankan untuk tidak memiliki properti / data publik atau yang dilindungi; itulah alasan utama OOP diciptakan, pada akhirnya.
Saya pikir sebagian besar jawaban di sini, selain dari yang ditandai diterima, semuanya mengaburkan masalah ini. Yang ditandai diterima baik, tetapi saya masih merasa perlu untuk menjawab dan setuju bahwa peluru 4 adalah cara untuk pergi, secara umum.
sumber
Jawabannya adalah itu tergantung pada use case. Tetapi dalam sebagian besar skenario umum, saya akan mematuhi logika bisnis yang diletakkan di lapisan layanan. Contoh yang Anda berikan adalah yang sangat sederhana. Namun begitu Anda mulai memikirkan sistem atau layanan yang dipisahkan dan menambahkan perilaku transaksional di atasnya, Anda benar-benar ingin itu terjadi sebagai bagian dari lapisan layanan.
Sumber-sumber yang Anda kutip untuk lapisan layanan tanpa adanya logika bisnis memperkenalkan lapisan lain yang merupakan lapisan bisnis. Dalam banyak skenario lapisan layanan dan lapisan bisnis dikompresi menjadi satu. Itu sangat tergantung pada bagaimana Anda ingin merancang sistem Anda. Anda bisa menyelesaikan pekerjaan dalam tiga lapisan dan terus mendekorasi dan menambahkan kebisingan.
Apa yang Anda idealnya dapat lakukan adalah memodelkan layanan yang mencakup logika bisnis untuk bekerja pada model domain untuk mempertahankan status . Anda harus mencoba memisahkan layanan sebanyak mungkin.
sumber
Dalam MVC Model didefinisikan sebagai logika bisnis. Mengklaim bahwa itu harus di tempat lain tidak benar kecuali dia tidak menggunakan MVC. Saya melihat lapisan layanan mirip dengan sistem modul. Ini memungkinkan Anda untuk menggabungkan satu set fungsionalitas terkait ke dalam paket yang bagus. Internal lapisan layanan itu akan memiliki model melakukan pekerjaan yang sama seperti milik Anda.
sumber
Konsep lapisan Layanan dapat dilihat dari perspektif DDD. Aaronaught menyebutkannya dalam jawabannya, saya hanya sedikit menguraikannya.
Pendekatan umum ada untuk memiliki pengontrol yang spesifik untuk jenis klien. Katakanlah, ini bisa berupa browser web, bisa juga beberapa aplikasi lain, bisa juga tes fungsional. Format permintaan dan respons mungkin beragam. Jadi saya menggunakan layanan aplikasi sebagai alat untuk memanfaatkan arsitektur Hexagonal . Saya menyuntikkan kelas infrastruktur di sana khusus untuk permintaan konkret. Misalnya, begitulah tampilan pengontrol saya yang melayani permintaan browser web:
Jika saya menulis tes fungsional, saya ingin menggunakan klien pembayaran palsu dan mungkin saya tidak akan memerlukan respons html. Jadi pengontrol saya bisa terlihat seperti itu:
Jadi layanan aplikasi adalah lingkungan yang saya atur untuk menjalankan logika bisnis. Di situlah kelas model disebut - agnostik dari implementasi infrastruktur.
Jadi, jawablah pertanyaan Anda dari perspektif ini:
Tidak.
Yah, orang bisa menyebutnya begitu.
Nggak.
Namun ada pendekatan yang sangat berbeda yang sama sekali menyangkal penggunaan segala jenis layanan. Misalnya, David West dalam bukunya Object Thinking mengklaim bahwa objek apa pun harus memiliki semua sumber daya yang diperlukan untuk melakukan tugasnya. Pendekatan ini menghasilkan, misalnya, membuang ORM .
sumber
Untuk catatan.
SRP:
Dalam hal ini, boleh-boleh saja melakukan langkah-langkah selanjutnya:
Jika hutang tidak membutuhkan perhitungan:
Namun, jika memerlukan beberapa perhitungan maka:
atau juga
Tetapi juga, jika perhitungan dilakukan dalam lapisan persistensi, prosedur penyimpanan seperti itu
Dalam hal ini, saya ingin mengambil pengguna dari basis data dan memperbarui utangnya kemudian, kita harus melakukannya dalam beberapa langkah (sebenarnya, dua) dan tidak perlu membungkus / merangkumnya dalam fungsi layanan.
Dan jika perlu menyimpannya, kita bisa menambahkan langkah ketiga
Tentang solusi yang diajukan
a) Kita tidak perlu takut meninggalkan pengembang akhir untuk menulis beberapa alih-alih merangkumnya dalam suatu fungsi.
b) Dan tentang Antarmuka, beberapa pengembang menyukai antarmuka dan mereka baik-baik saja tetapi dalam beberapa kasus, mereka tidak perlu sama sekali.
c) Tujuan dari suatu layanan adalah untuk membuat satu tanpa atribut, terutama karena kita dapat menggunakan fungsi Shared / Static. Ini juga mudah untuk unit test.
sumber
"We shouldn't be afraid to left the end-developer to write a couple of instead of encapsulate it in a function.
"? Saya hanya bisa mengutip Lewis Black" jika bukan karena kuda saya, saya tidak akan menghabiskan tahun itu di perguruan tinggi ".