RESTful API'ler, anemik alan modellerini teşvik etme eğiliminde midir?


34

Alan odaklı tasarım ve REST'i hizmet odaklı bir mimariye uygulamaya çalıştığımız bir proje üzerinde çalışıyorum. % 100 REST uyumluluğundan endişe etmiyoruz; muhtemelen kaynak odaklı HTTP API'leri oluşturmaya çalıştığımızı söylemek daha iyi olurdu (Richardson'un REST olgunluk modelinin 2. Seviyesi ). Yine de, HTTP isteklerinin RPC stili kullanımından uzak durmaya çalışıyoruz, yani biz uygulamak girişiminde bizim HTTP fiilleri göre RFC2616 kullanmak yerine POSTyapılacak IsPostalAddressValid(...)örneğin.

Ancak, bunun üzerinde durulması, etki alanına dayalı tasarım uygulama girişiminin pahasına görünüyor. Sadece GET, POSTve PUT, DELETEnadiren kullanılan diğer birkaç yöntemle, CRUDdy hizmetlerini oluşturma eğilimindeyiz ve CRUDdy hizmetlerinin anemik etki alanı modelleri olma eğilimindedir.

POST: Veriyi alın, doğrulayın, veriye atın. GET: Verileri alın, geri gönderin. Orada gerçek bir iş mantığı yok. Ayrıca hizmetler arasında mesajlar (olaylar) kullanıyoruz ve bana öyle geliyor ki, iş mantığının büyük kısmı bunun etrafında inşa ediliyor.

REST ve DDD gerginlik düzeyinde mi? (Veya burada bir şeyi yanlış mı anlıyorum? Belki başka bir şeyi yanlış mı yapıyoruz?) RPC tarzı HTTP çağrılarını engellerken hizmet odaklı bir mimaride güçlü bir etki alanı modeli oluşturmak mümkün mü?


1
POST kasten “kasıtlı olarak belirsiz” olacak şekilde tasarlandı ; Bir POST sonucu uygulamaya özeldir. Twitter ve diğer API tasarımcılarının yaptıklarını yapmanıza engel olan ve her bir POST yöntemini API'nizin CRUD olmayan kısmında kendi özel gereksinimlerinize göre tanımlayan nedir?
Robert Harvey,

@RobertHarvey POST'u bir yaratık olarak gördük. Standarda tekrar bakıldığında belki de fazlasıyla basittir. Örneğin, POST'un IsPostalAddressValid(...)"Bir form gönderme sonucu gibi bir veri bloğu veri işleme sürecine sunulması" na uygun olacağını düşünüyor musunuz?
Kazark,

Çünkü CREATE fiili yok (ve bunun için UPDATE fiili yok). Bu fiillerin standarttan (her ne sebeple olursa olsun) eksik olduğunu ve bu nedenle POST'u "her şey" için birlikte seçmeniz gerektiğini düşünüyorum. Bu durumda, "veri işleme süreci", posta adresini inceleyen ve bu analizin sonucuna karşılık gelen bir değer döndüren işlemdir.
Robert Harvey,

1
@RobertHarvey: POST ve PUT / PATCH’nin sadece istediğiniz CREATE ve UPDATE fiili olduğuna inanıyorum. Sadece farklı olarak adlandırılmıştır, böylece fiil RESTful olmayan tasarımda bile bir anlam ifade eder.
Yalan Ryan

@LieRyan: Sana bunu vereceğim. Ben sadece CRUD'un tanımsal olarak anemik veri modellerini ima ettiğini düşünüyorum. MVC'nin M'sindeyseniz, ancak kesinlikle heterojen sistemler arasında değilseniz, bazı davranışları devam ettirebilirsiniz. CRUD dışındaki her şey için POST'a ihtiyacınız var.
Robert Harvey,

Yanıtlar:


38

Martin Fowler'in ilk dağıtılmış sistemler yasası: "Nesnelerinizi dağıtmayın!" Uzak arayüzler kaba taneli ve ince arayüzlü iç arayüzler olmalıdır. Genellikle zengin etki alanı modeli yalnızca sınırlı bir bağlamda uygulanır .

REST API, her ikisi de kendi dahili modellerine sahip iki farklı bağlamı ayırır. Bağlamlar "anemik" nesneler (DTO) kullanarak kaba taneli arabirim (REST API) aracılığıyla iletişim kurar.

Sizin durumunuzda, bir bağlamı REST API olan bir sınırın üzerine yaymaya çalışıyorsunuz gibi geliyor. Bu, ince taneli uzak arabirime veya anemik modele yol açabilir. Projenize bağlı olarak bir problem olabilir veya olmayabilir.


1
Fowler'ın birçok iyi düşüncesi var ancak orijinal EJB spesifikasyonunun ve uygulamalarının ne kadar felaket olduğunu unutmayalım. Sadece düşük seviyeli yöntemin getName () gibi her küçük işlem için bir ağ / yük kabusu olduğunu anladıklarını anladılar. İri taneli arayüzler, tüm varlık-grafiklerin / mesajların fiil + isim bağlamında gönderildiği ve alındığı kavramı haline geldi.
Darrell Teague

9

POST kasten “kasıtlı olarak belirsiz” olacak şekilde tasarlandı ; Bir POST sonucu uygulamaya özeldir. Twitter ve diğer API tasarımcılarının yaptıklarını yapmanıza engel olan ve her bir POST yöntemini API'nizin CRUD olmayan kısmında kendi özel gereksinimlerinize göre tanımlayan nedir? POST, catchall fiilidir. Yapmak istediğiniz işlem için diğer fiillerden hiçbiri uygun olmadığında kullanın.

Başka bir deyişle, sorunuz aynı şekilde "akıllı" nesneler RPC tarzı tasarımı teşvik ediyor mu? " Martin Fowler ("Anemic Domain Model" terimini kullanan) bile, çıplak DTO'ların bazı faydaları olduğunu kabul ediyor:

Etki alanını nesnelere yerleştirmek, etki alanı mantığını kalıcılık ve sunum sorumlulukları gibi şeylerden ayırmak için katman kullanmanın sağlam yaklaşımına aykırı olmamalıdır. Bir etki alanı nesnesinde olması gereken mantık , etki alanı mantığıdır - doğrulamalar, hesaplamalar, iş kuralları - ne demek istersen.

İlgili Richardson Olgunluk Modeli , hiç hakkında kendinizi ilgilendiren olmadan seviyeye 3'e alabilirsiniz "Anemik Alan Modelleri." Unutmayın, davranışları tarayıcıya asla aktaramazsınız (bazı Javascript’leri modellerinizden enjekte etmeyi planlamıyorsanız).

REST çoğunlukla makine bağımsızlığı ile ilgilidir; REST modelini, uç noktalarınızın kaynakları temsil etmesini istediğiniz ölçüde uygulayın ve API'nizin tüketicilerinin bu kaynaklara standart bir şekilde kolayca erişebilmelerini ve bakımlarını yapmalarını sağlayın. Bu anemik görünüyorsa, öyle olsun.

Ayrıca
Daha Fazla Fiile İhtiyacım Var


Bunun kesinlikle sorunun RFC2616'ya yönelik olduğunu düşünüyorum. Kaynak odaklı olmaya çalıştığımız, yani en azından REST için Richardson olgunluk modelinde 2. Seviyeye ulaşmaya çalıştığımıza ne dersiniz?
Kazark,

1
Martinfowler.com/articles/richardsonMaturityModel.html sayfasını okudum . "Anemik Alan Modelleri" ile ilgili kendinizle hiç ilgilenmeden 3. seviyeye geçebilirsiniz. Unutmayın, davranışları tarayıcıya asla aktaramazsınız (bazı Javascript’leri modellerinizden enjekte etmeyi planlamıyorsanız).
Robert Harvey,

4

REST API, yalnızca bir tür sunum katmanıdır. Etki alanı modeli ile ilgisi yoktur.

Gönderdiğiniz soru, bir şekilde diğerine uyum sağlamanız gerektiği konusundaki kafa karışıklığınızdan geliyor. Sen değil.

Etki alanı modelinizi, bir ORM aracılığıyla etki alanı modelinizi bir RDBMS'ye eşlediğiniz gibi REST API'nize eşlersiniz - bu eşleme katmanı olmalı.

Domain ← ORM → RDBMS
Domain ← REST Eşleme → REST API


3

IMHO Anemik alan modellerini (ADM'leri) teşvik etme eğiliminde olduklarını sanmıyorum, ancak biraz zaman ayırmanızı ve bir şeyleri düşünmenizi gerektiriyorlar.

Öncelikle, ADM'lerin temel karakteristiğinin, davranışlarında çok az veya hiç davranış bulunmadığıdır. Bu, sistemin bir davranışının olmadığını, sadece bir tür Servis sınıfında olduğunu söylemez (bkz. Http://vimeo.com/43598193 ).

Tabii ki davranış ADM'de mevcut değilse, o zaman ne olur? Elbette cevap veridir. Peki bu nasıl REST API ile eşleşiyor? Muhtemelen veri, kaynağın içeriğiyle eşleşir ve davranış, HTTP fiilleriyle eşlenir.

Böylece zengin bir etki alanı modeli oluşturmak için ihtiyacınız olan her şeye sahipsiniz, yalnızca HTTP fiillerinin verilerdeki etki alanı işlemleriyle nasıl eşleştiğini görmeniz ve ardından bu işlemleri verilerinizi içine alan aynı sınıflara koymanız yeterli.

İnsanların sorunlarla karşılaştığı yerlerde, davranışların basit CRUD'nin ötesinde olduğu zaman, yani etki alanının diğer bölümlerinde yan etkiler olduğunda HTTP fiillerinin etki alanı davranışlarıyla nasıl eşleştiğini görme konusunda zor zamanları olduğunu düşünüyorum. HTTP isteği tarafından değiştirilen kaynak. Bu sorunu çözmenin bir yolu etki alanı olaylarıdır ( http://www.udidahan.com/2009/06/14/domain-events-salvation/ ).


3

Bu makale konuyla oldukça ilgili ve sanırım sorunuzu cevaplıyor.

Sorunuzu çok iyi cevapladığını düşündüğüm bir çekirdek konsept, bu makalenin aşağıdaki paragrafında özetlenmiştir:

"REST API'sindeki kaynaklar ile etki alanı odaklı bir tasarımdaki etki alanı varlıkları arasındaki farkı ayırt etmek çok önemlidir. Etki alanına dayalı tasarım, REST API'deki kaynaklar API tasarımını ve sözleşmesini yönetirken, şeylerin uygulama tarafına uygulanır (API uygulaması dahil). API kaynağı seçim, temel etki alanı uygulama ayrıntılarına bağlı olmamalıdır. "


1

Gördüğüm / inşa ettiğim birçok makul uygulama, fiil + isim metaforunu, varlıklara etki eden kaba tanınmış “iş dostu” yöntemler kullanarak nasıl karıştırdıklarına dair bir soruyu cevaplıyor.

Böylece (doomed) getName()yöntem / hizmet yerine, getPerson()tanımlayıcı tipi / ID gibi şeyleri geçirip tüm Personöğeyi döndürerek ortaya çıkarın.

Kişi varlığının bu tür bir bağlamdaki davranışları yeterince aktarılamadığından (ve belki de bunun veri merkezli bir bağlamda olması gerekmiyorsa), talep / cevap çiftleri için bir veri (Nesne'ye göre) modelini tanımlamak tamamen mantıklıdır. hizmetler.

Servisler ve tanımlanmış fiiller, varlıklar için etki alanı tarafından izin verilen davranışlar, kontroller ve hatta devlet geçişi kuralları ekleyecektir. Örneğin, transferPerson()servis çağrısında ne olduğuna dair etki alanına özgü bir mantık olacaktır, ancak arabirimin kendisi yalnızca THEIR iç davranışlarını tanımlamaksızın girişleri / çıkış varlıklarını / verilerini tanımlayacaktır.

Örneğin, Şahıs sınıfına ait bir transfer fiili uygulaması veya Şahıs merkezli bir hizmetle ilişkili olduğunu söyleyen yazarlara katılmıyorum . Gerçekten de, bir yöntem transferi bir için Person(bu, basit bir örnekte) ve isteğe bağlı bunların daha iyi bir ile tanımlanacaktır Carrier, burada Personhiçbir bilgiye sahip olabilir aktarma yöntemleri kullanılabilir olsa bile, ne veya aktarım bile ne kadar jet motorlarının çalışma bilir yer (ne kadar Neyse).

Bu, Personvarlığı anemik kılıyor mu? Sanmıyorum

Harici bir sınıf tarafından tanımlanmaması gereken, sağlık durumları gibi, Kişinin içindeki Kişiye özgü şeyler hakkında mantık olabilir / olmalıdır.

Bununla birlikte, kullanım durumlarına bağlı olarak, bir varlık sınıfının bir taşıma sisteminde koltuk atama servisi gibi bazı sistemlerde önemli / ilgili davranışların olmaması tamamen kabul edilebilir. Böyle bir sistem, Kişi örnekleri ve ilişkili tanımlayıcılarla ilgilenen, ancak iç davranışlarını asla tanımlayamayan / uygulayamayan REST tabanlı hizmetleri iyi uygulayabilir.


İyi noktalar --- bu, diğer cevapların henüz sahip olmadığı yeni bir bakış açısı getiriyor.
Kazark

0

POST'u olabildiğince kullanarak, modelini temel fiillere sıkıştırmaya çalışıyor musun?

Gerekli değil - çoğu insan için REST'in POST, GET, PUT ve DELETE anlamına geldiğini biliyorum, ancak http rfc diyor ki:

HTTP / 1.1 için ortak yöntem kümesi aşağıda tanımlanmıştır. Bu kümenin genişletilebilmesine rağmen, ayrı olarak genişletilmiş istemciler ve sunucular için aynı semantiği paylaşmak için ek yöntemler kullanılamaz.

SMTP gibi sistemler aynı fiil tabanlı yöntemleri kullanır ancak tamamen farklı bir set kullanırlar.

Yani, bunları kullanmak zorunda olmanızın bir nedeni yok, istediğiniz fiil grubunu kullanabilirsiniz (gerçekte, temel 4'te ihtiyacınız olan her şeyi biraz düşünerek yapabileceğinizi göreceksiniz). REST'i diğer mekanizmalardan ayırt edici kılan şey, vatansız ve bu fiilleri uygulamadaki tutarlı tarzıdır. Temelde REST yapmadığınız için ana hatlar arasında mesaj geçiş sistemini uygulamaya çalışmamalısınız, o zaman bir mesaj geçişi, RPC veya mesaj sırası mekanizması yapıyorsunuz, bunun yerine hiç şüphesiz REST'in faydalarını kaybedeceksiniz (ör. basitliği onu bir http bağlantısı üzerinden gerçekten iyi çalışmasını sağlar).

Tam özellikli, karmaşık bir mesajlaşma protokolü istiyorsanız, bunu yapın (web üzerinden yapabiliyorsanız, REST'in bu kadar popüler olmasının bir nedeni vardır), ancak aksi takdirde REST'in mimari tasarımına uymaya çalışın.

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.