Birden fazla miras Tek Sorumluluk İlkesini ihlal ediyor mu?


18

İki ayrı sınıftan miras alan bir sınıfınız varsa, bu, alt sınıfınızın her bir üst sınıftan bir tane olmak üzere otomatik olarak (en az) 2 şey yaptığı anlamına gelmez mi?

Birden fazla arabirim mirasınız varsa hiçbir fark olmadığını düşünüyorum.

Düzenleme: Açıkça, birden fazla sınıf alt sınıf SRP ihlal, sonra birden (marker olmayan veya temel arabirimi (örneğin karşılaştırılabilir)) arabirimleri uygulamak SRP de ihlal inanıyorum.


Açık olmak gerekirse, birden fazla arabirim uygulamanın SRP'yi ihlal ettiğine inanıyorsunuz?

Birden fazla sınıfın alt sınıfının SRP'yi ihlal etmesi durumunda, birden çok (markasız) arabirimin uygulanmasının SRP'yi de ihlal ettiğini düşünüyorum.
m3th0dman

Bu soruyu onaylayacağım, ancak fikrinizi katılmadığım soruya eklediniz.
Nicole

1
@NickC: Fikrimi söylemedim (yukarıdaki yorumu okumalısınız); Soruyu daha açık hale getirmek için düzenleyeceğim.
m3th0dman

1
@NickC Bir fikrim yok, bu yüzden sordum. Sadece ikisinin birbiriyle ilişkili olduğunu söyledim (arayüz kalıtımı ve sınıf kalıtımı); eğer sınıf mirasını ihlal ederse arayüz mirası için de ihlal eder, eğer biri için değilse, diğeri için de ihlal etmez. Ve yukarı oy umurumda değil ...
m3th0dman

Yanıtlar:


17

Çok dar anlamda, cevap "Evet" dir: temel sınıflarınızın veya arayüzlerinizin tek bir amaç için tasarlandığı varsayılarak, her ikisini de miras almak birden fazla sorumluluk içeren bir sınıf oluşturur. Ancak, "kötü bir şey" olup olmadığı, miras aldığınız sınıfların veya arayüzlerin doğasına bağlıdır.

Sınıflarınızı ve arayüzlerinizi, sisteminizin temel karmaşıklığına hitap eden ve kazara karmaşıklığını ele alan iki ana gruba ayırabilirsiniz. Birden fazla "temel karmaşıklık" sınıfından miras alınırsa, kötüdür; bir "temel" ve bir veya daha fazla "kazayla" sınıftan miras alırsanız, sorun olmaz.

Örneğin, bir faturalandırma sisteminde faturaları ve faturalandırma döngülerini temsil etmek için sınıflara (temel karmaşıklığı ele alırlar) ve kalıcı nesneler için sınıflara (yanlışlıkla karmaşıklığı ele alır) sahip olabilirsiniz. Eğer böyle miras alırsan

class BillingCycleInvoice : public BillingCycle, public Invoice {
};

bu kötü: BillingCycleInvoicesistemin temel karmaşıklığıyla ilgili olduğu için karışık bir sorumluluğunuz var.

Öte yandan, eğer böyle miras alırsanız

class PersistentInvoice : public Invoice, public PersistentObject {
};

sınıfınız iyi durumda: teknik olarak, aynı anda iki kaygıya hizmet ediyor, ancak bunlardan sadece biri gerekli olduğundan, kazara olanı devralmayı "iş yapma maliyeti" olarak yazabilirsiniz.


3
İkinci örneğiniz, en boy yönelimli programlamada kesişen bir kaygıya çok benzer. Bu, nesnelerinizin bazen temel odak noktası olmayan şeyler (günlüğe kaydetme, erişim kontrol testleri veya kalıcılık gibi) yapması gerektiğini ve bunu birden fazla mirasla yapabileceğinizi söylüyor. Bu, aracın uygun bir kullanımıdır.

En basit olanı Yeni bir arayüz uygulamak sınıf işlevselliğini tamamlamak gerekiyorsa, o zaman değil. Onun yeni sorumluluk ekleyerek eğer bağımlılık olarak SRP ihlal asla iğne Ama sonra başka sınıfla arabirimini uygular
Ramankingdom

9

SRP, kötü olan tanrı sınıflarından kaçınmak için bir rehberdir, ancak tam anlamıyla alınabilir ve bir proje, bir avuç birleştirilmeden gerçekten hiçbir şey yapamayan tonlarca sınıfla balonla başlar. Birden fazla miras / birden fazla arayüz, bir sınıfın çok büyük hale geldiğinin bir işareti olabilir, ancak aynı zamanda odağınızın elinizdeki görev için çok ayrıntılı olduğunu ve çözümünüzün aşırı tasarlanmış olduğunu veya sadece mükemmel bir şekilde olabileceğini gösteren bir işaret olabilir. birden fazla miras için geçerli kullanım durumu ve endişeleriniz asılsız.

Yazılım tasarımı bilim kadar sanattır, birçok rakip ilginin dengeleyici bir eylemidir. Bildiğimiz şeylerin sorunlara neden olan bir yönden uzak durmasına yardımcı olacak kurallarımız var, ancak bu kurallar bizi ilk etapta kaçınmaya çalıştığımız kadar kötü veya daha kötü bir yere götürebilir.


4

Biraz. SRP'nin ana prensibine odaklanalım:

Bir sınıfın değişmesi için sadece bir nedeni olmalıdır.

Birden fazla miras bunu zorlamaz, ancak buna yol açar. Sınıf temel sınıflarını geçersiz kılar veya uygularsa, bu değişmesi için daha fazla neden olur. Bu şekilde, çoklu arayüz kalıtımı, sınıf kalıtımından daha zahmetli olma eğilimindedir. İki sınıf devralınır ancak geçersiz kılınmazsa, değişmenin nedenleri yeni sınıfta değil, temel sınıflarda vardır.

Birden fazla mirasın SRP'yi ihlal etmediği yerler, temel türlerden biri dışında tümü sınıfın uyguladığı bir şey olmadığında, ancak sınıfın sahip olduğu bir özellik olarak hareket ettiği zamandır. IDisposableC # 'ı düşünün . Tek kullanımlık olan şeylerin iki sorumluluğu yoktur, arayüz sadece özelliği paylaşan ancak kesinlikle farklı sorumluluklara sahip olan sınıflara bir bakış görevi görür.


2

Bence değil. Bana göre, tek bir sorumluluk "başvurumun bir kullanıcısını modellemek" tir. Bu verileri bir web hizmeti aracılığıyla sunmam ve ilişkisel bir veritabanında depolamam gerekebilir. Birkaç karışıklık sınıfını devralarak bu işlevselliği sağlayabilirim.

Bu, sınıfın üç sorumluluğu olduğu anlamına gelmez. Bir kullanıcıyı modelleme sorumluluğunun bir kısmının serileştirmeyi ve kalıcılığı desteklemesi gerektiği anlamına gelir.


2

Bir şey değil. Java'da, bir tür etki alanı nesnesini (örneğin, bir Foo) temsil eden bir arabiriminiz olabilir. Diğer Foo nesneleriyle karşılaştırılması gerekebilir ve bu nedenle Karşılaştırılabilir (bir Karşılaştırıcı sınıfında haricileştirilmiş karşılaştırma mantığı ile) uygular; bu nesnenin aynı zamanda Serileştirilebilir olması da gerekebilir, böylece ağ üzerinden taşınabilir; ve Klonlanabilir olması gerekebilir. Böylece sınıf üç arayüz uygular, ancak Foo tarafından desteklenenin ötesinde onları destekleyecek bir mantık yoktur.

Bununla birlikte, SRP'yi uç noktalara götürmek aptalca. Bir sınıf birden fazla yöntem tanımlarsa, SRP'yi ihlal ediyor mu? Tüm Java Nesneleri toString () yöntemine ve eşittir (Nesne) yöntemine sahiptir; bu, Java'daki HER nesnenin hem eşitlik hem de kendini temsil etmekten sorumlu olduğu anlamına gelir. Bu kötü bir şey mi?


1

Sorumluluğu nasıl tanımladığınıza bağlıdır sanırım. Klasik iostream örneğinde SRP'yi ihlal etmez. IOstream bir çift yönlü akışı yönetmekten sorumludur.

İlkel sorumluluklarınız bittikten sonra daha genel üst düzey sorumluluklara geçersiniz, sonuçta ana giriş noktanızın sorumluluğunu nasıl tanımlarsınız? Sorumluluğu 'ana giriş noktası' olmalı, 'uygulamamın yaptığı her şey' olmamalı, aksi takdirde SRP'yi ihlal etmemek ve bir uygulama üretmek mümkün değildir.

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.