Neden yalnızca set özelliklerinin olması önerilmez?


9

Bugün iş yerinde meslektaşımdan biri kodumu inceledi ve bunun yerine yalnızca bir özelliği kaldırmamı ve bir yöntem kullanmamı önerdi.

İkimiz de başka şeylerle meşgulken, bana Property Design"Çerçeve Tasarım Yönergeleri" kitabındaki bölüme bakmamı söyledi . Kitapta yazar kaçınmak istediğini söyledi:

Alıcıdan, alıcıdan daha geniş erişilebilirliğe sahip özellikler

Ve şimdi neden sadece özel mülkün tavsiye edilmediğini merak ediyorum? Birisi bana açıklık getirebilir mi?


6
Yalnızca özellikli bir mülkün uygun olduğunu düşündüğünüz durumu açıklayabilir misiniz? Cevapları biraz daha alakalı hale getirebilir.
JohnFx

1
Anlamsal olarak anlamlı bir örnek düşünmeye çalışıyorum. Akla gelen tek şey Passwordbir Usersınıftaki bir özelliktir . Ayarlayabilirsin, ama elde edemezsin. Daha sonra salt okunur bir HashedPasswordözelliğiniz olabilir. Kümenin çağrılması karma işlemini yapar ve HashedPasswordözelliği değiştirir . Eğer bunu yaparsan sana bağırmazdım.
Scott Whitlock

Yanıtlar:


15

Bence beklentilerle ilgili olabilir. Yalnızca set özellikleri nadirdir ve özellikler genellikle çok fazla işlem yapmadan bir değeri saklamak için "aptal" setler için kullanılır. Bir ayarlayıcıda çok fazla iş yapıyorsanız, bir yöntem kullanmak daha iyidir - insanlar yöntemlerin yürütülmesi potansiyel olarak uzun zaman almasını ve potansiyel olarak yan etkilere sahip olmasını bekler. Bir mülkte benzer davranışların uygulanması, beklentileri ihlal eden kodlarla sonuçlanabilir.

İşte Microsoft'un Mülk Kullanım Yönergeleri'nin ilgili bir bölümü :

Özellikler ve Yöntemler

Sınıf kütüphanesi tasarımcıları genellikle bir sınıf üyesinin bir özellik veya yöntem olarak uygulanması arasında karar vermelidir. Genel olarak, yöntemler eylemleri ve özellikler verileri temsil eder. Bu seçenekler arasında seçim yapmanıza yardımcı olması için aşağıdaki yönergeleri kullanın.

  • Üye mantıksal bir veri üyesi olduğunda bir özellik kullanın. Aşağıdaki üye bildirimlerinde, Namesınıfın mantıksal bir üyesi olduğu için bir özelliktir.
public string Name
{
    get 
    {
        return name;
    }
    set 
    {
        name = value;
    }
}

Aşağıdaki durumlarda bir yöntem kullanın:

  • İşlem gibi bir dönüşümdür Object.ToString.
  • İşlem, sonucu önbelleğe almayı düşünmeleri gerektiğini kullanıcıya bildirmek istediğiniz kadar pahalıdır.
  • Erişimciyi kullanarak bir özellik değeri elde etmenin getgözlemlenebilir bir yan etkisi olacaktır.
  • Üyeyi art arda iki kez çağırmak farklı sonuçlar doğurur.
  • Yürütme sırası önemlidir. Bir türün özelliklerinin herhangi bir sırada ayarlanabilmesi ve alınabilmesi gerektiğini unutmayın.
  • Üye statiktir ancak değiştirilebilen bir değer döndürür.
  • Üye bir dizi döndürür. Dizileri döndüren özellikler çok yanıltıcı olabilir. Genellikle, kullanıcının dahili durumu değiştirememesi için dahili dizinin bir kopyasını döndürmek gerekir. Bu, kullanıcının kolayca dizine alınmış bir özellik olduğunu varsayabilir ve verimsiz bir koda yol açar. Aşağıdaki kod örneğinde, Methods özelliğine yapılan her çağrı, dizinin bir kopyasını oluşturur. Sonuç olarak, dizinin 2 ^ n + 1 kopyası aşağıdaki döngüde oluşturulur.
Type type = // Get a type.
for (int i = 0; i < type.Methods.Length; i++)
{
   if (type.Methods[i].Name.Equals ("text"))
   {
      // Perform some operation.
   }
}

[... daha uzun bir örnek atladı ...]

Salt Okunur ve Yalnızca Yazılabilir Özellikler

Kullanıcı özelliğin mantıksal veri üyesini değiştiremediğinde salt okunur bir özellik kullanmalısınız. Salt yazılır özellikleri kullanmayın.


Evet - en az sürpriz ilkesi burada işliyor.
Paul Butcher

6

Çünkü çoğu durumda mantıklı değil. Ayarlayabileceğiniz ancak okuyamayacağınız hangi mülkünüz olabilir?

OO'nun gerçek dünyayı daha iyi temsil etmesi isteniyorsa, sadece belirli bir özellik modellemenizin oldukça kapalı olduğunu önerebilir.

Düzenleme : Ayrıca bkz: /programming/4564928/are-set-only-properties-bad-practice temelde sezgisel olmayan ve yalnızca bir set özelliği temelde başka bir adla bir yöntemdir, bu yüzden bir yöntem.


1
Daha önce sadece set özelliklerini kullandım. Davranışını yapılandırmak için nesnenin özel bir alanına yazarlar. Harici kodun geçerli değeri bilmesi gerekmediği, ancak değiştirilmesi gerektiğinde faydalıdır. Bu tabii ki nadir, ama bunun olduğunu gördüm.
Mason Wheeler

@Mason - Kesinlikle bunları asla kullanmamanız gerektiği kadar ileri gitmezdim, ancak kuraldan ziyade istisna olmalılar.
Jon Hopkins

@MasonWheeler bu kadar değil Foo Foo { private get; set; }mi? Ben sadece bu yazma
demem

6

Şey, bir şey üzerinde bir özellik ayarlayabilir ancak asla alamazsanız, başka bir şeyin ayarladığınız değeri değiştirip değiştirmediğini / üzerine yazıp yazmadığını asla bilemezsiniz. Belirlediğiniz değere güveniyorsanız ve (bir nedenden ötürü) bunu almak istediğiniz zamana kadar devam edemiyorsanız, bu bir sorun olabilir.

Yalnızca ayarlanmış özellik yerine bir yöntem kullanmak bir kullanıcı için biraz daha az kafa karıştırıcı olacaktır. Adı yönteminin genellikle gösterir set veya dinlemek daha ama özellik adları normalde bir şeyin edebilirsiniz göstermez , sadece ayarlanmalıdır ve değil kazanılmış. Mülkiyet "ReadOnlyBackgroundColour" gibi bir şey olsaydı, diğer kodlayıcılar için kafa karıştırıcı olmaz, ama bu sadece garip görüneceğini varsayalım.


Kabul ediyorum, ancak bu durumda bir ayarlayıcı yöntemi nasıl farklı olurdu?
Travis Christian

1
@Travis Christian: Görünüşe göre OP bir pasör ama alıcı olmayan bir durumla çalışıyor. Böylece bir şey ayarlayabilirler, ancak daha sonra değişip değişmeyeceğini asla bilemezler.
Hayal kırıklığına

@Frustrated Ama bir şeyin bir yöntemle tekrar değiştirilip değiştirilmediğini de asla bilemezlerdi.
Adam Lear

@Anna Lear ♦: Bir alıcı varsa, kodunuzda ayarladığınız değerin aniden şüphe duyabileceği bir nokta varsa, kullanmadan önce en azından değeri test edebilirsiniz.
Hayal kırıklığına

3
@Size katılıyorum. Sadece soru, sadece aynı şeyi yapmak için bir yöntem kullanarak vs bir set özelliğini kullanmaktı.
Adam Lear

-1

Bu çok eski bir konu ama bu geç aşamada benim görüşüme atladı ve ben sadece yazma özellikleri için bir dava yapmaya çalışırken bazı yorumlar istiyorum ...

Ben örnek ActiveReportve bir dizi kullanıcı seçimleri sonra postback üzerinde çalışan bir Web sitesinin bir parçası olan sınıflar bir dizi var.

VB kodu şuna benzer:

  Public Class SomeReport
    Private greader As New GenericReporting.CommonReader("AStoredProcedure", 
                                      {New SqlParameter("budget_id", 0)})

    Public WriteOnly Property BudgetID As Integer
      Set(value As Integer)
        greader.Parameters("budget_id").Value = value
      End Set
    End Property

    Public Sub New(Optional budget_id As Integer = 0)
      ' This call is required by the designer.
      InitializeComponent()

      ' Add any initialization after the InitializeComponent() call.
      BudgetID = budget_id
    End Sub
  End Class

Bu raporlar genel bağırsaklar kullanır, CommonReadersaklı yordamlar ve SqlParameterher biri rapor tasarımına bağlı olarak, örneklemede bir parametre olarak iletilebilen veya daha önce örneklemeden sonra kullanıcı tarafından ayarlanabilen ilişkili WriteOnly özelliğine sahip bir dizi varsayılan s alır. raporlar Runyöntemini çağırma .

  '''''''''''''''''''''''
  ' Parameter taken from a user selected row of a GridView
  '
  Dim SomeBudgetID As Integer = gvBudgets.SelectedDataKey.Values(budget_id)

  '''''''''''''''''''''''      
  ' On Instantiation
  '
  Dim R as ActiveReport = New SomeReport(SomeBudgetID)
  R.Run()

  '''''''''''''''''''''''      
  ' Or On Instantiation using "With" syntax
  '
  Dim R as ActiveReport = New SomeReport() With {.BudgetID = SomeBudgetID}
  R.Run()

  '''''''''''''''''''''''
  ' Or After
  '
  Dim R as ActiveReport = New SomeReport()
  R.BudgetID = SomeBudgetID
  R.Run()

Gördüğüm gibi, bu durumda sadece yazma özelliğine sahip olmak

  1. SqlParameterS genel türden olduğundan daha güçlü yazım denetimi sağlar
  2. Raporun oluşturulmasında daha fazla esneklik, tüm parametrelerin kullanılabilir olması veya kullanılabilir hale geldikten sonra eklenmesi durumunda rapor hemen başlatılabilir.
  3. Özellikler, örneklemede "İle" sözdizimini destekler
  4. Parametreler kullanıcı tarafından bilindiği ve Rapor tarafından değiştirilmediği için "alıcı" gerçekten gerekli mi?
  5. Yana SqlParameters sınıflar ve ilkel değil değerlerdir, writeonly Özellikleri ayar parametreleri için daha basit bir arayüz için izin

Bu benim düşüncelerim.

Bunun yerine bir yönteme dönüştürebilir miyim? emin ama arayüz ... daha az hoş görünüyor

  R2.BudgetID = SomeBudgetID

karşı

  R2.SetBudgetID(SomeBudgetID)
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.