REST API - DTO atau tidak? [Tutup]

154

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?

benbjo
sumber
9
Jangan heran jika pertanyaan ini ditutup. Ini lebih merupakan pertanyaan berbasis diskusi yang berarti tidak ada jawaban yang benar dan jelas. Tanyakan orang yang berbeda dan Anda akan mendapatkan jawaban yang berbeda.
Ben Thurley
2
Tautan artikel itu ( ibm.com/developerworks/community/blogs/barcia/entry/… ) rusak.
pinkpanther
7
@pinkpanther Itu artikel yang bagus dan sayang sekali tidak lagi tersedia. Ini adalah versi cache Web Archive .
cassiomolin

Jawaban:

251

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 @XmlTransientdan @JsonIgnoreuntuk 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 @ApiModeldan @ApiModelPropertyanotasi 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 sebagai ResourceSupport) atau membungkusnya dengan EntityModel(sebelumnya dikenal sebagai Resource<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()dan toString()metode untuk Anda.


Terkait: Untuk memberikan nama yang lebih baik ke kelas DTO Anda, lihat jawaban ini .

cassiomolin
sumber
2
Jika saya memang menggunakan cara DTO, apakah Anda akan memetakan semua objek domain ke DTO atau hanya yang tidak identik? Juga, bagaimana Anda memecahkan masalah mengekspos data berdasarkan skenario / konteks yang berbeda? Beberapa DTO per objek domain?
benbjo
6
@benbjo Terserah Anda. Saya biasanya memetakan hanya entitas yang paling kompleks untuk DTO, entitas yang saya tidak ingin semua atributnya terbuka dan entitas dengan banyak hubungan. DTO memberi saya fleksibilitas untuk memiliki daftar tautan yang akan digunakan di HATEOAS. Itu adalah hal yang saya tidak akan tambahkan ke objek kegigihan saya.
cassiomolin
2
@molin terima kasih banyak atas informasi dan sarannya. Saya pasti akan memeriksa MapStruct. Sepintas tampaknya sesuai dengan kebutuhan saya dengan sangat baik.
benbjo
6
Dear downvoter, bisakah Anda setidaknya menjelaskan alasan downvote Anda?
cassiomolin
8
Ada juga alasan arsitektur untuk menggunakan DTO alih-alih entitas domain di REST API. API REST tidak boleh berubah untuk menghindari kerusakan klien yang ada. Jika Anda menggunakan model domain langsung di API, Anda membuat sambungan yang tidak diinginkan antara API dan model domain. Menurut prinsip desain Loose Coupling, kontrak layanan tidak boleh digabungkan dengan logika layanan atau detail implementasi.
Paulo Merson
25

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.

David Siro
sumber
Saya setuju dengan Anda pada bagian terakhir dan biasanya saya lakukan, tetapi ini adalah API publik pertama saya. Saya akan mempertimbangkan apa yang Anda katakan tentang menggunakan DTO untuk bagian publik. Mungkin bagian pribadi dan publik dari API memang harus terpisah, bahkan jika "makan makanan anjing Anda sendiri" adalah prinsip yang baik.
benbjo
11

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.

Argb32
sumber
9

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.

Martin Frey
sumber
2
Saya setuju bahwa pertanyaan saya agak terkait dengan opini (dan tidak disarankan), namun saya juga mencari tips tentang bagaimana menyelesaikan masalah saya. Saya akan mengambil banyak di addon Jackson Anda, tetapi apakah Anda berpikir bahwa menggunakan mixin untuk mengontrol data apa yang harus diekspos dalam berbagai skenario adalah baik apa yang harus pergi?
benbjo