Sınıf ve arayüz dosyalarını en iyi nasıl düzenleyebilirim?


17

Tamam .. tüm tartışmalardan sonra, ele aldığım somut bir örneği daha iyi yansıtmak için sorumu biraz değiştiriyorum.


İki sınıf var ModelOneve ModelTwobu sınıflar benzer işlevsellik gerçekleştirmek ancak birbirleriyle ilgisiz. Ancak CommonFunc, her ikisinde de uygulanan ModelOneve ModelTwobaşına göre çarpan bazı kamu işlevselliği içeren üçüncü bir sınıf var DRY. İki model ModelMainsınıf içinde somutlaştırılır (kendisi daha yüksek bir seviyede somutlaştırılır vb. - ama bu seviyede duruyorum).

Kullandığım IoC kapsayıcısı Microsoft Unity . Ben bir uzman gibi davranmıyorum, ama benim anlayış konteyner ile bir dizi arayüzü ve sınıf kayıt olduğunu ve somut bir sınıf istediğinizde IoC konteyner belirli bir arayüzle eşleşen herhangi bir nesne isteyin. Bu, Unity'den örneklemek istediğim her nesne için eşleşen bir arayüz olması gerektiğini ima eder. Sınıflarımın her biri farklı (ve örtüşmeyen) işlevler gerçekleştirdiğinden, arabirim ve sınıf 1 arasında 1: 1 oran olduğu anlamına gelir . Ancak bu, yazdığım her sınıf için körü körüne bir arayüz yazdığım anlamına gelmez.

Böylece kod bilge ben 2 ile bitirmek :

public interface ICommonFunc 
{ 
}

public interface IModelOne 
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelTwo
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelMain 
{ 
  IModelOne One { get; } 
  IModelTwo Two { get; } 
  ..
}

public class CommonFunc : ICommonFunc { .. }

public class ModelOne : IModelOne { .. }

public class ModelTwo : IModelTwo { .. }

public class ModelMain : IModelMain { .. }

Soru, çözümümü nasıl organize edeceğimle ilgili. Sınıfı ve arayüzü birlikte tutmalı mıyım? Yoksa sınıfları ve arayüzleri bir arada tutmalı mıyım? ÖRNEĞİN:

Seçenek 1 - Sınıf adına göre düzenlenmiş

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-Main
          |   |
          |   |-IModelMain.cs
          |   |-ModelMain.cs
          |
          |-One
          |   |
          |   |-IModelOne.cs
          |   |-ModelOne.cs
          |
          |-Two
              |
              |-IModelTwo.cs
              |-ModelTwo.cs
              |

Seçenek 2 - İşlevselliğe göre düzenlenmiştir (çoğunlukla)

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-IModelMain.cs
          |-IModelOne.cs
          |-IModelTwo.cs
          |-ModelMain.cs
          |-ModelOne.cs
          |-ModelTwo.cs
          |

Seçenek 3 - Arabirim ve Uygulamayı Ayırma

MySolution
  |
  |-MyProject
      |
      |-Interfaces
      |   |
      |   |-Models
      |   |   |
      |       |-Common
      |       |   |-ICommonFunc.cs
      |       |
      |       |-IModelMain.cs
      |       |-IModelOne.cs
      |       |-IModelTwo.cs
      |
      |-Classes
          | 
          |-Models
          |   |
              |-Common
              |   |-CommonFunc.cs
              |
              |-ModelMain.cs
              |-ModelOne.cs
              |-ModelTwo.cs
              |

Seçenek 4 - İşlevselliği daha ileri götürmek

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Components
          |   |
          |   |-Common
          |   |   |
          |   |   |-CommonFunc.cs
          |   |   |-ICommonFunc.cs
          |   |   
          |   |-IModelOne.cs
          |   |-IModelTwo.cs
          |   |-ModelOne.cs
          |   |-ModelTwo.cs
          |
          |-IModelMain.cs
          |-ModelMain.cs
          |

Yoldaki sınıf adı nedeniyle seçenek 1'i beğenmedim. Ancak IoC seçimim / kullanımım (ve bu tartışmalı olabilir) nedeniyle 1: 1 oranına yöneldiğim için, dosyalar arasındaki ilişkiyi görmede avantajları var.

Seçenek 2 bana çekici geliyor, ama şimdi ModelMainve alt modeller arasındaki suları karıştırdım .

Seçenek 3, arayüz tanımını uygulamadan ayırmak için çalışır, ancak şimdi yol adlarında bu yapay aralar var.

Seçenek 4. Seçenek 2'yi aldım ve bileşenleri ana modelden ayırmak için ayarladım.

Birini diğerinden tercih etmek için iyi bir neden var mı? Ya da kaçırdığım diğer potansiyel düzenler?


1. Frank, 1: 1 oranına sahip olmanın C ++ günleri .h ve .cpp dosyalarına geri döndüğünü yorumladı. Nereden geldiğini biliyorum. Birlik anlayışım beni bu köşeye koyuyor gibi görünüyor, ama aynı zamanda bir bakış açısını da izliyorsanız, bundan nasıl çıkacağımdan da emin değilim Program to an interface .

2. Her nesne yapıcısının ayrıntılarını dışarıda bıraktım. IoC kapsayıcısı gerektiği gibi nesne enjekte eder.


1
Ugh. 1: 1 arayüz / sınıf oranınız olduğunu kokuyor. Hangi IoC kapsayıcısını kullanıyorsunuz? Ninject, 1: 1 oran gerektirmeyen mekanizmalar sağlar.
RubberDuck

1
@ RubberDuck FWIW Unity kullanıyorum. İçinde bir uzman olduğunu iddia yok, ama benim sınıfları iyi tek sorumlulukları ile tasarlanmıştır eğer, nasıl yapmak değil neredeyse bir 1 ile bitirmek: 1 oranında?
Peter M

IBase'ye ihtiyacınız var mı yoksa temel soyut olabilir mi? Neden zaten IBase uyguladığında IDerivedOne var? Sen türetilmiş değil, IBase bağlı olmalısın. Unity'yi bilmiyorum, ancak diğer IoC kapları "bağlama duyarlı" enjeksiyon yapmanızı sağlar. Temelde bir Client1ihtiyacı olduğunda bir IBasesağlar Derived1. İhtiyaç Client2duyulduğunda IBase, IoC bir sağlar Derived2.
RubberDuck

1
Tabanı soyut ise, bunun için bir neden yoktur interface. An interfacegerçekten tüm sanal üyeleri olan soyut bir sınıftır.
RubberDuck

1
RubberDuck doğrudur. Gereksiz arayüzler sadece can sıkıcıdır.
Frank Hileman

Yanıtlar:


4

Bir arabirim soyut olarak bir temel sınıfa benzediğinden, bir temel sınıf için kullandığınız aynı mantığı kullanın. Bir arayüz uygulayan sınıflar arayüzle yakından ilişkilidir.

"Temel Sınıflar" adlı bir dizini tercih edeceğinizden şüpheliyim; çoğu geliştirici bunu istemez, ne de "Arabirimler" adı verilen bir dizin. C # 'da, dizinler varsayılan olarak ad alanlarıdır ve bu da iki kat daha kafa karıştırıcıdır.

En iyi yaklaşım, bazılarını ayrı bir kütüphaneye koymak ve sınıfları / dizinleri benzer bir şekilde düzenlemek zorunda kalırsanız sınıfları / arayüzleri nasıl parçalayacağınızı düşünmektir. .Net framework tasarım yönergeleri, yardımcı olabilecek ad alanı önerilerine sahiptir.


Sağladığınız bağlantıya biraz aşinayım, ancak dosya organizasyonu ile nasıl ilgili olduğundan emin değilim. VS varsayılan ilk ad alanı için yol adlarını varsayılan olsa da, bu keyfi bir seçim olduğunu biliyorum. Ayrıca kodumu 'örnek' ve düzen olasılıklarını güncelledim.
Peter M

@PeterM Hangi IDE'yi kullandığınızdan emin değilim, ancak Visual Studio, örneğin bir sınıf eklerken ad alanı bildirimlerini otomatik olarak oluşturmak için dizin adlarını kullanıyor. Bu, dizin adları ile ad alanı adları arasında farklar olsa da, bu şekilde çalışmanın daha acı verici olduğu anlamına gelir. Yani çoğu insan bunu yapmaz.
Frank Hileman

VS kullanıyorum. Ve evet acıyı biliyorum. Visual Source Safe dosya düzeninin anılarını geri getirir.
Peter M

1
@PeterM 1: 1 arabirim ile sınıf oranı arasındaki ilişki. Bazı araçlar bunu gerektirir. Bunu aracın bir arızası olarak görüyorum - .net, böyle bir araçta bu tür kısıtlamalara ihtiyaç duymayacak yeterli yansıtma yeteneğine sahiptir.
Frank Hileman

1

İkinci yaklaşımı, karmaşık projelerde daha fazla klasör / isim alanı ile birlikte kullanıyorum. Bu, arayüzleri somut uygulamalardan ayırdığım anlamına gelir.

Farklı bir projede, arayüz tanımını bilmek zorunda kalabilirsiniz, ancak bunu uygulayan herhangi bir beton sınıfı bilmek gerekli değildir - özellikle bir IoC konteyneri kullandığınızda. Dolayısıyla, bu diğer projelerin uygulama projelerine değil, sadece arayüz projelerine başvurması gerekir. Bu, referansları düşük tutabilir ve döngüsel referans sorunlarını önleyebilir.


Kod örneğimi gözden geçirdim ve biraz daha seçenek ekledim
Peter M

1

Her zaman olduğu gibi herhangi bir tasarım sorusunda olduğu gibi, yapılacak ilk şey kullanıcılarınızın kim olduğunu belirlemektir. Kuruluşunuzu nasıl kullanacaklar?

Derslerinizi kullanacak kodlayıcılar mı? Daha sonra arayüzleri koddan ayırmak en iyisi olabilir.

Kodunuzun bakıcıları mı? Daha sonra arayüzleri ve sınıfları bir arada tutmak en iyisi olabilir.

Otur ve bazı kullanım örnekleri oluştur. O zaman en iyi organizasyon sizden önce görünebilir.


-2

Arabirimleri ayrı kütüphanede saklamanın daha iyi olduğunu düşünüyorum. İlk olarak, bu tür tasarım bağımlılığı artırır. Bu yüzden bu arayüzlerin uygulanması başka bir programlama dili ile yapılabilir.

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.