REST API - DTO'lar mı, değil mi? [kapalı]


154

Şu anda bir proje için bir REST-API oluşturuyorum ve en iyi uygulamalar hakkında makale üzerine makale okuyorum. Birçoğu DTO'lara karşı gibi görünüyor ve sadece etki alanı modelini ortaya çıkarırken, diğerleri DTO'ların (veya Kullanıcı Modellerinin veya ne demek istersen) kötü uygulama olduğunu düşünüyor. Şahsen, bu makalenin çok anlamlı olduğunu düşündüm .

Ancak, DTO'ların dezavantajlarını tüm ekstra eşleme kodlarıyla, DTO muadillerine% 100 özdeş olabilecek etki alanı modellerini ve benzerlerini anlıyorum.

API'mız çoğunlukla diğer müşterilerin veri tüketebilmesi için oluşturulur, ancak doğru yaparsak mümkünse kendi web GUI'miz için de kullanmak isteriz.

Mesele şu ki, tüm alan adı verilerini diğer istemci kullanıcılarına göstermek istemeyebiliriz. Verilerin çoğu sadece kendi web uygulamamızda anlamlı olacaktır. Ayrıca, tüm senaryolarda, özellikle diğer nesnelerle olan ilişkilerde vb. Bir nesneyle ilgili tüm verileri göstermek istemeyebiliriz. Örneğin, belirli bir nesnenin listesini ortaya koyarsak, tüm nesne hiyerarşisini ortaya çıkarmak istemeyiz; böylece nesnenin çocukları açığa çıkmaz, ancak bağlantılar (hateoas) aracılığıyla keşfedilebilir.

Bu sorunu nasıl çözebilirim? Farklı senaryolar verildiğinde hangi verilerin gösterileceğini kontrol etmek için alan adı modellerimizde Jackson karışımlarını kullanmayı düşünüyordum. Ya da DTO'ları sonuna kadar kullanmalıyız - dezavantajları ve tartışmaları olsa bile?


9
Bu soru kapanırsa şaşırmayın. Daha çok tartışmaya dayalı bir sorudur, bu da doğru bir doğru cevabın olmadığı anlamına gelir. Farklı kişilere sorun, farklı bir cevap alırsınız.
Ben Thurley


7
@pinkpanther Bu harika bir makale ve artık kullanılamaması üzücü. İşte Web Arşivi önbelleğe alınmış sürümü .
cassiomolin

Yanıtlar:


252

REST API'nizde neden DTO'lar kullanmalısınız?

DTO , D ata T ransfer O bject anlamına gelir .

Bu model çok iyi tanımlanmış bir amaç için oluşturulmuştur: tıpkı web hizmetleri gibi verileri uzak arabirimlere aktarın . Bu model bir REST API'sine çok iyi uyuyor ve DTO'lar uzun vadede size daha fazla esneklik sağlayacak .

Temsil modelleri domain temsil Başvurunuzun ve modelleri API'nızdan tarafından ele verileri (veya en azından olmalıdır) farklı kaygılar ve gerektiği ayrılmış birbirinden. Uygulama etki alanı modeline bir alan eklediğinizde, kaldırdığınızda veya yeniden adlandırdığınızda API istemcilerinizi kırmak istemezsiniz.

Hizmet katmanınız etki alanı / kalıcılık modelleri üzerinde çalışırken, API denetleyicileriniz farklı modellerde çalışmalıdır. Alan adı / kalıcılık modelleriniz yeni işletme gereksinimlerini desteklemek için geliştikçe, bu değişiklikleri desteklemek için API modellerinin yeni sürümlerini oluşturmak isteyebilirsiniz. Ayrıca, yeni sürümler yayınlandıkça API'nızın eski sürümlerini kullanımdan kaldırmak isteyebilirsiniz. Ve işler ayrıştırıldığında başarmak mükemmel bir şekilde mümkündür.


Kalıcılık modelleri yerine DTO'ları ortaya çıkarmanın birkaç faydasından bahsetmek gerekirse:

  • Kalıcılık modellerini API modellerinden ayırın .

  • DTO'lar ihtiyaçlarınıza göre uyarlanabilir ve kalıcılık varlıklarınızın yalnızca bir dizi niteliğini ortaya koyarken harikadır. Bazı özelliklerin serileştirilmesini önlemek için @XmlTransientve gibi ek açıklamalara ihtiyacınız yoktur @JsonIgnore.

  • DTO'ları kullanarak, kalıcılık varlıklarınızdaki cehennem ek açıklamalarından kaçınacaksınız , yani kalıcılık varlıklarınız kalıcılık ile ilgili olmayan ek açıklamalarla şişirilmez.

  • Sen sahip olacak tam kontrol oluşturma veya kaynak güncellerken aldığınız nitelikleri üzerinde.

  • Swagger kullanıyorsanız , kalıcılık varlıklarınızı bozmadan API modellerinizi belgelemek için @ApiModelve @ApiModelPropertyek açıklamaları kullanabilirsiniz .

  • API'nizin her sürümü için farklı DTO'larınız olabilir.

  • İlişkileri eşlerken daha fazla esnekliğe sahip olacaksınız.

  • Farklı ortam türleri için farklı DTO'larınız olabilir.

  • DTO'larınız HATEOAS için bir bağlantı listesine sahip olabilir . Bu, kalıcılık nesnelerine eklenmemesi gereken bir şey. Spring HATEOAS kullanırken , DTO sınıflarınızı genişletebilir RepresentationModel(eski adıyla bilinir ResourceSupport) veya bunları EntityModel(daha önce bilinen adıyla ) sarabilirsiniz Resource<T>.

Isıtıcı kod ile başa çıkmak

Kalıcı varlıklarınızı DTO'larla eşlemenize gerek yoktur veya tam tersi de mannely . Bunu yapmak için kullanabileceğiniz birçok harita çerçevesi vardır . Örneğin , ek açıklama tabanlı ve Maven Ek Açıklama İşlemcisi olarak çalışan MapStruct'a bir göz atın . Hem CDI hem de Spring tabanlı uygulamalarda iyi çalışır.

Ayrıca düşünebilirsiniz Lombok getters, ayarlayıcılar, üretmek için equals(), hashcode()ve toString()sizin için yöntemler.


İlgili: DTO sınıflarınıza daha iyi adlar vermek için bu cevaba bakın .


2
DTO yoluna gitmiş olsaydım, tüm etki alanı nesnelerini bir DTO'ya mı yoksa sadece özdeş olmayanlara mı eşlerdiniz? Ayrıca, farklı senaryolara / bağlamlara göre veri gösterme sorununu nasıl çözersiniz? Etki alanı nesnesi başına birden fazla DTO mu?
benbjo

6
@benbjo Size kalmış. Genellikle yalnızca en karmaşık varlıkları DTO'lara, tüm özniteliklere maruz kalmak istemediğim varlıkları ve çok fazla ilişkisi olan varlıkları eşlerim. DTO'lar bana HATEOAS'ta kullanılacak bağlantıların bir listesine sahip olma esnekliğini veriyor. Kalıcılık nesnelerime eklemeyeceğim türden bir şey.
cassiomolin

2
@molin bilgi ve öneriler için çok teşekkürler. MapStruct'ı kesinlikle kontrol edeceğim. Bir bakışta ihtiyaçlarımı çok iyi karşılıyor.
benbjo

6
Sevgili downvoter, en azından downvote nedeninizi açıklayabilir misiniz?
cassiomolin

8
Ayrıca REST API'sındaki etki alanı varlıkları yerine DTO'ları kullanmanın mimari bir nedeni de vardır. REST API, mevcut istemcileri bozmamak için değişmemelidir. Etki alanı modelini doğrudan API'da kullanırsanız, API ile etki alanı modeli arasında istenmeyen bağlantı oluşturursunuz. Servis Gevşek Kavrama tasarım ilkesine göre, servis sözleşmesi servis mantığına veya uygulama ayrıntılarına sıkıca bağlanmamalıdır.
Paulo Merson

25

API'nız herkese açık olduğunda ve birden çok sürümü desteklemeniz gerektiğinde, DTO'larla gitmeniz gerekir.

Öte yandan, özel API ise ve hem istemci hem de sunucuyu kontrol ediyorsanız, DTO'ları atlayıp doğrudan etki alanı modelini ortaya çıkarma eğilimindeyim.


Son bölümde size katılıyorum ve genellikle bunu yapıyorum, ancak bu benim ilk herkese açık API'm. Herkese açık olarak DTO'ları kullanma hakkında söylediklerinizi ele alacağım. Belki de "kendi yiyeceklerinizi yiyin" iyi bir prensip olsa bile, API'nın özel ve genel bölümleri gerçekten ayrı olmalıdır.
benbjo

11

DTO'lar kullanma eğilimindeyim.

Dezavantajları sevmiyorum ama diğer seçenekler daha da kötü görünüyor:

Etki alanı nesnelerinin açıklanması güvenlik sorunlarına ve veri sızıntısına neden olabilir. Jackson ek açıklamaları sorunu çözüyor gibi görünebilir, ancak bir hata yapmak ve açıklanmaması gereken verileri ortaya çıkarmak çok kolaydır. Bir DTO sınıfı tasarlarken böyle bir hata yapmak çok daha zordur.

Öte yandan, DTO yaklaşımının dezavantajları, nesneden nesneye eşleme ve daha az kaynatma plakası için Lombok gibi şeylerle azaltılabilir .


9

Kendinizi daha önce belirttiğiniz gibi, bu açıkça bir görüşle ilgili soru. Ben daha çok No-DTOs yaklaşımına, sadece ihtiyaç duyduğunuz ortak plaka kodundan dolayı çekiliyor.

Bu esas olarak bir json / rest api'nin yanıt tarafı için geçerlidir. Hatta bu durumlar için birçok json görüntüleme / filtre yazmamak için bir jackson addon yazdım: https://github.com/Antibrumm/jackson-antpathfilter

Öte yandan DTO'lar, bu tür API'lerin istek giriş tarafında iyi bir şeydir. Varlıklar üzerinde doğrudan çalışmak, örneğin çift yönlü ilişkileri dikkate alarak oldukça zor olabilir. Ayrıca bir arayanın örneğin "yaratıcı" özelliğini değiştirmesine izin vermek istemezsiniz. Bu nedenle, bu tür isteklerin eşlenmesi sırasında belirli alanlara izin vermemeniz gerekir.


2
Sorumun fikirle ilgili (ve cesareti kırılmış) bir fikir olduğunu kabul ediyorum, ancak aynı zamanda sorunumu nasıl çözeceğime dair ipuçları da arıyordum. Jackson addon'unuzda çok şey alacağım, ancak farklı senaryolarda hangi verilerin ortaya çıkması gerektiğini kontrol etmek için mixins kullanmanın iyi bir şey olduğunu düşünüyor musunuz?
benbjo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.