Büyük arayüzleri ayırın


9

Bir veritabanına erişmek için yaklaşık 50 yöntem ile büyük bir arayüz kullanıyorum. Arayüz bir meslektaşım tarafından yazıldı. Bunu tartıştık:

Ben: 50 yöntem çok fazla. Bu bir kod kokusu.
Meslektaşım: Bu konuda ne yapmalıyım? DB erişimi istiyorsunuz - buna sahipsiniz.
Ben: Evet, ama gelecekte belirsiz ve bakımı zor.
Meslektaşım: Tamam, haklısın, hoş değil. Arayüz o zaman nasıl olmalı?
Me: Her biri 10 yöntemi olan nesneleri döndüren yaklaşık 5 yöntem?

Mmmh, ama bu aynı olmaz mıydı? Bu gerçekten daha fazla netliğe yol açıyor mu? Çabaya değer mi?

Arada bir arayüz istediğim bir durumdayım ve akla ilk gelen şey büyük bir arayüz. Bunun için genel bir tasarım modeli var mı?


Güncelleme (SJuan'ın yorumuna yanıt olarak):

"Bir çeşit yöntem": Veritabanından veri almak için kullanılan bir arayüz. Tüm yöntemlerin formu (sözde kod)

List<Typename> createTablenameList()

Yöntemler ve tablolar tam olarak 1-1 ilişkisinde değildir, vurgu her zaman bir veritabanından gelen bir tür liste almanızdır.


12
Alakalı bilgi eksik (ne tür yöntemleriniz var). Her neyse, tahminim: sadece sayıya bölerseniz meslektaşınız haklı, hiçbir şey geliştirmiyorsunuz. Muhtemel bir bölüm kriteri "varlık" (neredeyse bir tablonun eşdeğeri) tarafından döndürülür (yani, a UserDaove a CustomerDaove a ProductDao)
SJuan76

Gerçekten de bazı tablolar semantik olarak "cliques" oluşturan diğer tablolara yakındır. Yöntemler de öyle.
TobiMcNamobi

Kodu görmek mümkün mü? 4 yaşında olduğunu biliyorum ve muhtemelen şimdiye kadar çözdün: D Ama bu sorun hakkında düşünmek isterim. Daha önce böyle bir şey çözmüştüm.
clankill3r

@ clankill3r Gerçekten yukarıdaki soruyu göndermemi sağlayan belirli arayüze artık erişimim yok. Sorun daha geneldir. Yaklaşık 50 tablo ve her tablo için bir yöntem gibi bir DB düşününList<WeatherDataRecord> createWeatherDataTable() {db.open(); return db.select("*", "tbl_weatherData");}
TobiMcNamobi

Yanıtlar:


16

Evet, 50 yöntem bir kod kokusudur, ancak kod kokusu, ikinci kez bakmak anlamına gelir, otomatik olarak yanlış değildir. Bu sınıfı kullanan her müşteri potansiyel olarak 50 yönteme ihtiyaç duyuyorsa, onu bölmek için bir durum olmayabilir. Ancak, bu olası değildir. Demek istediğim, bir arayüzü keyfi olarak bölmek, onu bölmekten daha kötü olabilir.

Bunu düzeltmek için tek bir desen yoktur, ancak istenen durumu açıklayan ilke , hiçbir istemcinin kullanmadığı yöntemlere bağımlı olmaya zorlanması gerektiğini belirten Arabirim Ayrışma İlkesi'dir ( SOLID'de 'I'). .

ISS açıklaması, nasıl düzeltileceğine dair bir ipucu verir: istemciye bakın . Çoğu zaman, sadece bir sınıfa bakarak her şey birbirine ait gibi görünür, ancak o sınıfı kullanan istemcilere baktığınızda net bölünmeler ortaya çıkar . Bir arayüz tasarlarken her zaman önce müşterileri düşünün.

Bir arabirimin bölünüp bölünmeyeceğini ve nerede bölüneceğini belirlemenin diğer yolu, ikinci bir uygulama yapmaktır. Sıklıkla ortaya çıkan şey, ikinci uygulamanızın çok fazla yönteme ihtiyaç duymamasıdır, bu yüzden bunlar açıkça kendi arayüzlerine ayrılmalıdır.


Bu ve utnapistim'in cevabı gerçekten harika.
TobiMcNamobi

13

Meslektaşım: Tamam, haklısın, hoş değil. Arayüz o zaman nasıl olmalı?

Me: Her biri 10 yöntemi olan nesneleri döndüren yaklaşık 5 yöntem?

Bu iyi ölçütler değil (aslında bu ifadede hiçbir ölçüt yoktur). Bunları gruplandırabilirsiniz (uygulamanızın örneklerim için bir finansal işlemler uygulaması olduğunu varsayarak):

  • işlevsellik (ekler, güncellemeler, seçimler, işlemler, meta veriler, şema vb.)
  • varlık (kullanıcı DAO , depozito DAO, vb.)
  • uygulama alanı (finansal işlemler, kullanıcı yönetimi, toplamlar vb.)
  • soyutlama seviyesi (tüm tablo erişim kodu ayrı bir modüldür; tüm seçili API'ler kendi hiyerarşilerindedir, işlem desteği ayrıdır, bir modüldeki tüm dönüşüm kodu, bir modüldeki tüm doğrulama kodu vb.)

Mmmh, ama bu aynı olmaz mıydı? Bu gerçekten daha fazla netliğe yol açıyor mu? Çabaya değer mi?

Doğru kriterleri seçerseniz, kesinlikle. Eğer yapmazsanız, kesinlikle değil :).

Birkaç örnek:

  • bakmak ADODB nesneleri (DB API muhtemelen zaten bu sunar) OO ilkel bir basit örnek

  • yüksek düzeyde soyutlama içeren bir veri modeli fikri için Django veri modeline ( https://docs.djangoproject.com/en/dev/topics/db/models/ ) bakın (C ++ 'da muhtemelen biraz daha kazan plakasına ihtiyacınız olacak kod, ama güzel bir fikir). Bu uygulama, MVC tasarım modeli dahilinde bir "model" rolü göz önünde bulundurularak tasarlanmıştır.

  • yalnızca işlevsel ilkellerden (C API) oluşan düz bir API fikri ( http://www.sqlite.org/c3ref/funclist.html ) için sqlite API'sine bakın .


3

Arada bir arayüz istediğim bir durumdayım ve akla ilk gelen şey büyük bir arayüz. Bunun için genel bir tasarım modeli var mı?

Monolitik sınıf adı verilen bir tasarım anti örüntüsü . Bir sınıfta veya arabirimde 50 yöntem bulunması SRP'nin olası bir ihlalidir . Monolitik sınıf ortaya çıkar çünkü herkes için her şey olmaya çalışır.

DCI yöntem bloat adresleri. Esasen bir sınıfın birçok sorumluluğu, yalnızca belirli bağlamlarda geçerli olan rollere (diğer sınıflara aktarılmış) dağıtılabilir. Rollerin uygulanması, karışımlar veya dekoratörler dahil olmak üzere çeşitli şekillerde gerçekleştirilebilir . Bu yaklaşım sınıfları odaklanmış ve yalın tutar.

Her biri 10 yöntem olan nesneleri döndüren 5 yöntem nasıl olur?

Bu, nesnenin kendisi başlatıldığında tüm rolleri başlatmayı önerir. Peki neden ihtiyaç duymayabileceğiniz rolleri canlandırın? Bunun yerine, gerçekten ihtiyaç duyduğunuz bağlamda bir rol başlatın.

DCI'ye doğru yeniden düzenlemenin belirgin olmadığını fark ederseniz, daha basit bir ziyaretçi modeliyle gidebilirsiniz . Kullanım durumu bağlamlarının oluşturulmasını vurgulamadan benzer bir yarar sağlar.

EDIT: Bu konuda düşüncelerim biraz değişti. Alternatif bir cevap verdim.


1

Bana öyle geliyor ki diğer cevapların hiçbiri eksik. Mesele şu ki, bir arayüz ideal olarak atomik bir davranış yığını tanımlamalıdır. SOLID'deki I budur .

Bir sınıfın bir sorumluluğu olmalıdır, ancak bu yine de birden fazla davranış içerebilir. Tipik bir veritabanı istemci nesnesine bağlı kalmak, bu tam CRUD işlevselliği sunabilir. Bu dört davranış olacaktır: oluşturma, okuma, güncelleme ve silme. Saf bir SOLID dünyasında veritabanı istemcisi IDatabaseClient değil sabit ICreator, IReader, IUpdater ve IDeleter uygulardı.

Bunun bir takım faydaları olacaktır. Birincisi, sadece sınıf bildirimini okuyarak, sınıf hakkında çok şey öğrenilir, uyguladığı arayüzler tüm hikayeyi anlatır. İkincisi, istemci nesnesi bağımsız değişken olarak iletilecekse, artık birinin farklı kullanışlı seçenekleri vardır. Bir IReader olarak geçirilebilir ve biri callee'nin sadece okuyabileceğinden emin olabilir. Farklı davranışlar ayrı ayrı test edilebilir.

Bununla birlikte, test söz konusu olduğunda, yaygın uygulama, bir sınıfta tam sınıf arayüzünün 1'e 1 kopyası olan bir arayüzü tokatlamaktır. Eğer test etmeniz yeterli ise, bu geçerli bir yaklaşım olabilir. Aptalları oldukça hızlı bir şekilde yapmanızı sağlar. Ama neredeyse hiç SOLID ve gerçekten özel bir amaç için arayüzlerin kötüye kullanılması.

Yani evet, 50 yöntem bir koku ama kötü ya da kötü olup olmadığına bağlı. Kesinlikle ideal değil.


0

Veri Erişim Katmanları, bir sınıfa birçok yöntem iliştirme eğilimindedir. Entity Framework veya diğer ORM araçlarıyla daha önce çalıştıysanız, bunların 100'lü yöntemler oluşturduğunu göreceksiniz. Siz ve meslektaşınızın el ile uyguladığınızı varsayıyorum. Kod kokusu gerekli değildir, ama bakmak güzel değildir. Alan adınızı bilmeden söylemek zor.


Yöntemler veya özellikler?
JeffO

0

FP ve OOP ile tüm apisler için neredeyse evrensel olarak protokolleri (isterseniz arayüz olarak adlandırın) kullanıyorum. (Matrisi hatırlayın? Beton yoktur!) Elbette somut türler vardır, ancak bir program kapsamında her tür, bir bağlamda rol oynayan bir şey olarak düşünülür.

Bu, programlar boyunca, işlevlere vb. Aktarılan nesnelerin, adlandırılmış davranış kümelerine sahip soyut varlıklar olarak düşünülebileceği anlamına gelir. Nesne, bazı protokoller kümesi olan bir rol oynamak olarak düşünülebilir. Bir kişi (somut tip) bir adam, bir baba, bir koca, bir arkadaş ve bir çalışan olabilir, ancak varlığı bunlardan 2'den fazla olarak kabul edecek birçok işlev hayal edemiyorum.

Karmaşık bir nesnenin birkaç farklı protokole uyması olasıdır, ancak 50 yöntemli bir API'ye ulaşmak için hala zor olabilirsiniz. Çoğu protokol 1 veya 2 yöntem, belki 3, ama asla 50! 50 yöntemi olan herhangi bir kuruluş, her biri kendi sorumluluğuna sahip bir grup küçük bileşenin toplamı haline getirilmelidir. Genel olarak varlık, içindeki apislerin toplamını soyutlayan daha basit bir arayüz sunacaktır.

Nesneler ve yöntemler açısından düşünmektense, soyutlamalar ve sözleşmeler ve bir konunun bir bağlamda hangi rolleri oynadığı konusunda düşünmeye başlayı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.