Saat ini saya sedang membuat REST-API untuk sebuah proyek dan telah membaca artikel demi artikel tentang praktik terbaik. Banyak yang tampaknya menentang DTO dan hanya mengekspos model domain, sementara yang lain tampaknya berpikir DTO (atau Model Pengguna atau apa pun yang Anda ingin menyebutnya) adalah praktik yang buruk. Secara pribadi, saya pikir artikel ini masuk akal.
Namun, saya juga memahami kelemahan DTO dengan semua kode pemetaan tambahan, model domain yang mungkin 100% identik dengan mitra DTO mereka dan seterusnya.
API kami sebagian besar dibuat sehingga klien lain dapat mengkonsumsi data, namun jika kami melakukannya dengan benar, kami juga ingin menggunakannya untuk GUI web kami sendiri jika memungkinkan.
Masalahnya adalah kita mungkin tidak ingin mengekspos semua data domain ke pengguna klien lain. Sebagian besar data hanya akan masuk akal di aplikasi web kita sendiri. Selain itu, kami mungkin tidak ingin memaparkan semua data tentang suatu objek di semua skenario, terutama hubungan dengan objek lain dan seterusnya. Sebagai contoh, jika kita mengekspos daftar objek tertentu, kita tidak perlu ingin mengekspos seluruh hirarki objek; sehingga objek anak-anak tidak akan terekspos, tetapi dapat ditemukan melalui tautan (hateoas).
Bagaimana saya harus menyelesaikan masalah ini? Saya sedang berpikir tentang menggunakan Jackson mixin pada model domain kami untuk mengontrol data apa yang akan diekspos dengan skenario yang berbeda. Atau haruskah kita menggunakan DTO sepenuhnya - bahkan mengingat kekurangan dan kontroversi?
Jawaban:
Mengapa Anda harus menggunakan DTO di REST API Anda
DTO adalah singkatan dari D ata T ransfer O bject .
Pola ini dibuat dengan tujuan yang sangat jelas: mentransfer data ke antarmuka jarak jauh , seperti halnya layanan web . Pola ini sangat cocok di API REST dan DTO akan memberi Anda lebih banyak fleksibilitas dalam jangka panjang.
Model-model yang mewakili domain aplikasi Anda dan model-model yang mewakili data yang ditangani oleh API Anda adalah (atau setidaknya seharusnya) keprihatinan yang berbeda dan harus dipisahkan satu sama lain. Anda tidak ingin memecah klien API Anda ketika Anda menambah, menghapus, atau mengganti nama bidang dari model domain aplikasi.
Sementara lapisan layanan Anda beroperasi di atas model domain / kegigihan, pengontrol API Anda harus beroperasi di atas serangkaian model yang berbeda. Sebagai model domain / ketekunan Anda berkembang untuk mendukung persyaratan bisnis baru, misalnya, Anda mungkin ingin membuat versi baru dari model API untuk mendukung perubahan ini. Anda juga mungkin ingin mencela API versi lama saat versi baru dirilis. Dan sangat mungkin untuk mencapai ketika hal-hal dipisahkan.
Untuk menyebutkan beberapa manfaat dari mengekspos DTO daripada model ketekunan:
Pisahkan model-model persistensi dari model-model API.
DTO dapat disesuaikan dengan kebutuhan Anda dan sangat bagus ketika mengekspos hanya seperangkat atribut entitas kegigihan Anda. Anda tidak akan memerlukan anotasi seperti
@XmlTransient
dan@JsonIgnore
untuk menghindari serialisasi beberapa atribut.Dengan menggunakan DTO, Anda akan menghindari banyak anotasi dalam entitas kegigihan Anda, yaitu, entitas kegigihan Anda tidak akan membengkak dengan anotasi yang tidak terkait dengan kegigihan.
Anda akan memiliki kontrol penuh atas atribut yang Anda terima saat membuat atau memperbarui sumber daya.
Jika Anda menggunakan Swagger , Anda dapat menggunakan
@ApiModel
dan@ApiModelProperty
anotasi untuk mendokumentasikan model API Anda tanpa mengacaukan entitas kegigihan Anda.Anda dapat memiliki DTO berbeda untuk setiap versi API Anda.
Anda akan memiliki lebih banyak fleksibilitas saat memetakan hubungan.
Anda dapat memiliki DTO berbeda untuk berbagai jenis media.
DTO Anda dapat memiliki daftar tautan untuk HATEOAS . Itu adalah hal yang tidak seharusnya ditambahkan ke objek kegigihan. Saat menggunakan Spring HATEOAS , Anda dapat membuat kelas DTO Anda diperluas
RepresentationModel
(sebelumnya dikenal sebagaiResourceSupport
) atau membungkusnya denganEntityModel
(sebelumnya dikenal sebagaiResource<T>
).Berurusan dengan kode boilerplate
Anda tidak perlu memetakan entitas kegigihan Anda ke DTO dan sebaliknya secara manual . Ada banyak kerangka pemetaan yang bisa Anda gunakan untuk melakukannya. Misalnya, lihat MapStruct , yang berbasis pada anotasi dan berfungsi sebagai Maven Annotation Processor. Ini berfungsi baik di aplikasi berbasis CDI dan Spring.
Anda juga mungkin ingin mempertimbangkan Lombok untuk menghasilkan getter, setter
equals()
,hashcode()
dantoString()
metode untuk Anda.Terkait: Untuk memberikan nama yang lebih baik ke kelas DTO Anda, lihat jawaban ini .
sumber
Ketika API Anda bersifat publik dan Anda harus mendukung banyak versi, Anda harus menggunakan DTO.
Di sisi lain, jika itu API pribadi dan Anda mengontrol klien dan server, saya cenderung mengabaikan DTO dan mengekspos secara langsung model domain.
sumber
Saya cenderung menggunakan DTO.
Saya tidak suka kekurangannya tapi sepertinya pilihan lain lebih buruk lagi:
Eksposisi objek domain dapat menyebabkan masalah keamanan dan kebocoran data. Anotasi Jackson tampaknya bisa menyelesaikan masalah, tetapi terlalu mudah untuk membuat kesalahan dan memaparkan data yang seharusnya tidak diekspos. Saat merancang kelas DTO, akan jauh lebih sulit untuk membuat kesalahan seperti itu.
Di sisi lain kelemahan dari pendekatan DTO dapat dikurangi dengan hal-hal seperti pemetaan objek ke objek dan Lombok untuk pelat kurang boiler.
sumber
Seperti yang sudah Anda nyatakan sendiri, ini jelas pertanyaan terkait opini. Saya sendiri lebih tertarik pada pendekatan No-DTO, hanya karena semua kode boilerplate yang Anda butuhkan.
Hal ini terutama berlaku untuk sisi respons api json / sisanya. Saya bahkan menulis addon jackson untuk menghindari penulisan banyak json view / filter untuk kasus ini: https://github.com/Antibrumm/jackson-antpathfilter
Di sisi lain DTO adalah hal yang baik di sisi input permintaan API tersebut. Misalnya, bekerja langsung pada entitas bisa sangat sulit dengan mempertimbangkan hubungan dua arah akun. Anda juga tidak benar-benar ingin membiarkan penelepon memodifikasi atribut "pencipta" misalnya. Jadi, Anda perlu melarang bidang tertentu selama pemetaan permintaan tersebut.
sumber