Katı, anemik alanlardan kaçınarak bağımlılık enjeksiyonu?


33

Bu bir programlama dili agnostik sorusu olsa da, .NET ekosistemini hedefleyen cevaplarla ilgileniyorum.

Bu senaryo: kamu yönetimi için basit bir konsol uygulaması geliştirmemiz gerektiğini varsayalım. Uygulama araç vergisi ile ilgili. Onlar (sadece) aşağıdaki iş kurallarına sahiptir:

1.a) Eğer araç bir araba ise ve sahibinin son ödeme yaptığı tarihte vergi 30 gün önceydi, bu durumda işletme sahibinin tekrar ödeme yapması gerekiyordu.

1.b) Eğer araç bir motosiklet ise ve sahibi en son vergiyi 60 gün önce ödediyse, sahibi yeniden ödemek zorunda kalır.

Başka bir deyişle, bir arabanız varsa, her 30 günde bir ödemek zorundasınız veya bir motosikletiniz varsa, her 60 günde bir ödemek zorundasınız.

Sistemdeki her araç için, uygulama bu kuralları test etmeli ve bunları karşılamayan araçları (plaka numarası ve sahip bilgileri) yazdırmalıdır.

İstediğim şey:

2.a) KATI ilkelerine uygun (özellikle Açık / kapalı prensibi).

İstemediğim şey (sanırım):

2.b) Anemik bir etki alanı, bu nedenle iş mantığı iş varlıklarının içine girmelidir.

Bununla başladım:

public class Person
// You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.
{
    public string Name { get; set; }

    public string Surname { get; set; }
}

public abstract class Vehicle
{
    public string PlateNumber { get; set; }

    public Person Owner { get; set; }

    public DateTime LastPaidTime { get; set; }

    public abstract bool HasToPay();
}

public class Car : Vehicle
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 30;
    }
}

public class Motorbike : Vehicle
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 60;
    }
}

public class PublicAdministration
{
    public IEnumerable<Vehicle> GetVehiclesThatHaveToPay()
    {
        return this.GetAllVehicles().Where(vehicle => vehicle.HasToPay());
    }

    private IEnumerable<Vehicle> GetAllVehicles()
    {
        throw new NotImplementedException();
    }
}

class Program
{
    static void Main(string[] args)
    {
        PublicAdministration administration = new PublicAdministration();
        foreach (var vehicle in administration.GetVehiclesThatHaveToPay())
        {
            Console.WriteLine("Plate number: {0}\tOwner: {1}, {2}", vehicle.PlateNumber, vehicle.Owner.Surname, vehicle.Owner.Name);
        }
    }
}

2.a: Açık / kapalı prensibi garanti edilir; Bisiklet vergisini istiyorlarsa, henüz Araçtan devralırsanız, HasToPay yöntemini geçersiz kılarsınız ve bitirdiniz. Açık / kapalı prensip basit kalıtım yoluyla sağlanmıştır.

"Sorunlar":

3.a) Bir araç ödemek zorunda olup olmadığını neden bilmek zorunda? Kamu Yönetimi endişesi değil mi? Kamu idaresi araç vergisini değiştirirse, neden Araba değişmeli? Bence şunu sormalısınız: "öyleyse neden Araç içine bir HasToPay yöntemi koydunuz?" Ve cevabı şudur: Çünkü PublicAdministration içindeki araç tipini test etmek istemiyorum. Daha iyi bir alternatif görüyor musun?

3.b) Belki vergi ödemesi her şeyden önce araçla ilgili bir meseledir, veya belki de ilk Şahıs-Araç-Otomobil-Motosiklet-Kamu Yönetimi tasarımım tamamen yanlış ya da bir filozofa ve daha iyi bir iş analistine ihtiyacım var. Bir çözüm olabilir: HasToPay yöntemini başka bir sınıfa taşıyın, buna TaxPayment diyebiliriz. Sonra iki TaxPayment türevi sınıf oluşturduk; CarTaxPayment ve MotosikletTaxPayment. Ardından, Araç sınıfına bir soyut Ödeme özelliği (TaxPayment türünden) ekliyoruz ve doğru TaxPayment örneğini Araba ve Motosiklet sınıflarından alıyoruz:

public abstract class TaxPayment
{
    public abstract bool HasToPay();
}

public class CarTaxPayment : TaxPayment
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 30;
    }
}

public class MotorbikeTaxPayment : TaxPayment
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 60;
    }
}

public abstract class Vehicle
{
    public string PlateNumber { get; set; }

    public Person Owner { get; set; }

    public DateTime LastPaidTime { get; set; }

    public abstract TaxPayment Payment { get; }
}

public class Car : Vehicle
{
    private CarTaxPayment payment = new CarTaxPayment();
    public override TaxPayment Payment
    {
        get { return this.payment; }
    }
}

public class Motorbike : Vehicle
{
    private MotorbikeTaxPayment payment = new MotorbikeTaxPayment();
    public override TaxPayment Payment
    {
        get { return this.payment; }
    }
}

Ve biz eski süreci şu şekilde çağırırız:

    public IEnumerable<Vehicle> GetVehiclesThatHaveToPay()
    {
        return this.GetAllVehicles().Where(vehicle => vehicle.Payment.HasToPay());
    }

Ama şimdi bu kod derlenmeyecek çünkü CarTaxPayment / MotorbikeTaxPayment / TaxPayment içinde bir LastPaidTime üyesi yok. CarTaxPayment ve MotorbikeTaxPayment'i iş varlıklarından ziyade "algoritma uygulamaları" gibi görmeye başlıyorum. Her nasılsa şimdi bu "algoritmalar" LastPaidTime değerine ihtiyaç duyuyor. Elbette, değeri TaxPayment'in kurucusuna aktarabiliriz, ancak bu araç kapsüllemesini veya sorumluluklarını ihlal eder ya da OOP misyonerleri ne diyorsa söylesin değil mi?

3.c) Varsayalım ki zaten bir Varlık Çerçevesi ObjectContext (etki alanı nesnelerimizi kullanır; Kişi, Araç, Araba, Motosiklet, Kamu İdaresi). PublicAdministration.GetAllVehicles yönteminden bir ObjectContext başvurusu almak ve bu nedenle işlevselliği uygulamak için ne yapardınız?

3.d) Ayrıca CarTaxPayment.HasToPay için aynı ObjectContext referansına, ancak "enjekte" işleminden sorumlu olan MotorbikeTaxPayment.HasToPay için farklı bir referansa ihtiyacımız olursa, bu başvuruları ödeme sınıflarına nasıl iletirsiniz? Bu durumda, anemik bir alandan (ve dolayısıyla hiçbir hizmet nesnesinden yoksun) kaçınmak bizi felakete sürüklemiyor mu?

Bu basit senaryo için tasarım tercihleriniz nelerdir? Açıkçası gösterdiğim örnekler kolay bir görev için "çok karmaşık", ancak aynı zamanda fikir SOLID ilkelerine bağlı kalmak ve anemik etki alanlarını (yıkılmak üzere görevlendirilmiş) önlemek.

Yanıtlar:


15

Ne bir kişinin ne de bir aracın ödemenin yapılıp yapılmadığını bilmemesi gerektiğini söyleyebilirim.

problem alanını yeniden incelemek

Sorunlu alana bakarsanız, "otomobilleri olan insanlar": Bir otomobil satın almak için mülkiyeti bir kişiden diğerine aktaran bir tür sözleşmeniz vardır, ne otomobil ne de kişi bu süreçte değişmez. Modelin bundan tamamen yoksun.

Düşünce deneyi

Evli bir çift olduğunu varsayarsak, adam arabanın sahibi ve vergileri ödüyor. Şimdi adam ölür, karısı arabayı miras alır ve vergileri öder. Yine de, plakalarınız aynı kalacak (en azından ülkemde kalacaklar). Hala aynı araba! Bunu etki alanınızda modelleyebilmelisiniz.

=> Sahiplik

Kimseye ait olmayan bir araba hala bir arabadır ama kimse bunun için vergi ödemeyecektir. Aslında, araba için vergi ödemiyorsunuz, araba sahibi olma ayrıcalığı için . Öyleyse önerim şöyle olurdu:

public class Person
{
    public string Name { get; set; }

    public string Surname { get; set; }

    public List<Ownership> getOwnerships();

    public List<Vehicle> getVehiclesOwned();
}

public abstract class Vehicle
{
    public string PlateNumber { get; set; }

    public Ownership currentOwnership { get; set; }

}

public class Car : Vehicle {}

public class Motorbike : Vehicle {}

public abstract class Ownership
{
    public Ownership(Vehicle vehicle, Owner owner);

    public Vehicle Vehicle { get;}

    public Owner CurrentOwner { get; set; }

    public abstract bool HasToPay();

    public DateTime LastPaidTime { get; set; }

   //Could model things like payment history or owner history here as well
}

public class CarOwnership : Ownership
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 30;
    }
}

public class MotorbikeOwnership : Ownership
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 60;
    }
}

public class PublicAdministration
{
    public IEnumerable<Ownership> GetVehiclesThatHaveToPay()
    {
        return this.GetAllOwnerships().Where(HasToPay());
    }

}

Bu mükemmel olmaktan uzak ve muhtemelen uzaktan doğru C # kodunu bile düzeltmiyor, ancak umarım bir fikriniz olur (ve birisi bunu temizleyebilir). Tek dezavantajı, muhtemelen CarOwnershipbir CarvePerson


Bence araç kendisi için ödenen vergileri kaydetmeli ve bireyler tüm araçları için ödenen vergileri kaydetmelidir. Bir vergi vergi kodu, bir arabadaki verginin 1 Haziran’da ödenmesi ve 10 Haziran’da satılması durumunda, yeni mal sahibinin 10 Haziran, 1 Temmuz’daki veya 10 Temmuz’daki vergiden sorumlu hale gelebilmesi için yazılabilir. şu anda değişebilmesinin bir yolu). 30 günlük kural, mülkiyet değişiklikleri olsa bile, otomobil için sabitse, ancak kimse tarafından sahip olunan arabalara vergi ödeyemezse, o zaman 30 yıl veya daha uzun bir süredir sahipsiz kalan bir araba satın alındığında, vergi ödemesi ...
supercat

... hayali bir "Sahipsiz araç vergi kredisi" kişisinden kaydedilmiştir, böylece satış süresi itibariyle aracın ne kadar süre kullanılmadığına bakılmaksızın vergi borcu sıfır ya da otuz gün olacaktır.
supercat,

4

İş kurallarının hedef nesnelerin dışında olmasını istediğiniz bu tür bir durumda, yazım testi yapmanın kabul edilemez olduğunu düşünüyorum.

Elbette, birçok durumda bir Strateji paterni kullanmalı ve nesnelerin işleri kendi başlarına halletmesine izin vermelisiniz, ancak bu her zaman arzu edilmez.

Gerçek dünyada, bir katip aracın türüne bakar ve buna dayanarak vergi verilerini arar. Yazılımınız neden aynı işletme kurallarına uymamalıdır?


Tamam, beni ikna ettiğini ve GetVehiclesThatHaveToPay yönteminden araç tipini incelediğimizi söyleyin. LastPaidTime'dan kim sorumlu olmalıdır? LastPaidTime bir Araç meselesi mi yoksa bir Kamu İdaresi mi? Çünkü o bir Taşıtsa, bu iş mantığı Taşıt'ta yer almamalı mı? Bana 3.c sorusu hakkında ne söyleyebilirsiniz?

@DavidRobertJones - İdeal olarak, araç lisansına dayalı olarak, Ödeme geçmişi günlüğündeki son ödemeyi arardım. Vergi ödemesi bir vergi kaygısıdır, araç kaygısı değildir.
Erik Funkenbusch

5
@DavidRobertJones Kendinizi kendi metaforunuzla karıştırdığınızı düşünüyorum. Sahip olduğun şey, bir aracın yaptığı her şeyi yapması gereken gerçek bir araç değil. Bunun yerine, basitlik için bir TaxableVehicle (veya benzeri bir şey) bir Araç olarak adlandırdınız. Tüm alan adınız vergi ödemesidir. Gerçek araçların ne yaptığı hakkında endişelenme. Ve gerekirse metaforu bırak ve daha uygun bir tane bul.

3

İstemediğim şey (sanırım):

2.b) Anemik bir etki alanı, iş dünyasında iş mantığı anlamına gelir.

Bunu geriye doğru aldın. Anemik bir etki alanı, mantığın işletme varlıklarının dışında olduğu alandır. Mantığı uygulamak için ek sınıflar kullanmanın kötü bir fikir olmasının birçok nedeni vardır; ve sadece birkaç neden bunu yapman gerektiğinden.

Bu yüzden anemik denmesinin nedeni: sınıfın içinde hiçbir şey yok.

Ne yapardım:

  1. Arayüz olarak soyut Araç sınıfınızı değiştirin.
  2. Araçların uygulaması gereken bir ITaxPayment arayüzü ekleyin. HasToPay'inizi buradan askıya alın.
  3. MotorBikeTaxPayment, CarTaxPayment, TaxPayment sınıflarını kaldırın. Gereksiz komplikasyonlar / karışıklıktırlar.
  4. Her araç tipi (otomobil, bisiklet, kamyonet ve karavan) asgari bir araç kullanmalı ve vergilendirilmişse ITaxPayment'i de uygulamalıdır. Bu şekilde, vergilendirilmemiş araçlar ile olanlar arasında ayrım yapabilirsiniz ... Bu durumun var olduğunu varsayarsak.
  5. Her araç tipi, sınıfın sınırları dahilinde arayüzlerinizde tanımlanan yöntemleri uygulamalıdır.
  6. Ayrıca, ITaxPayment arayüzünüze son ödeme tarihini ekleyin.

Haklısın. Asıl soru bu şekilde formüle edilmedi, bir kısmı sildim ve anlamı değişti. Şimdi düzeltildi. Teşekkürler!

2

Bir aracın ödemesi gerekip gerekmediğini neden bilmek zorunda? Kamu Yönetimi endişesi değil mi?

Hayır. Anladığım kadarıyla bütün uygulamanız vergi ile ilgili. Bu nedenle, bir aracın vergilendirilmesinin gerekip gerekmediği konusundaki kaygı, artık Programın tamamında başka bir şey olan Kamu İdaresi endişesi değildir. Buradan başka bir yere koymak için hiçbir sebep yok.

public class Car : Vehicle
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 30;
    }
}

public class Motorbike : Vehicle
{
    public override bool HasToPay()
    {
        return (DateTime.Today - this.LastPaidTime).TotalDays >= 60;
    }
}

Bu iki kod parçacığı yalnızca sabite göre değişir. HasToPay () işlevinin tamamını geçersiz kılmak yerine, işlevi geçersiz kılar int DaysBetweenPayments(). Bunu sabit kullanmak yerine çağırın. Gerçekten hepsi farklı olanlarsa sınıfları düşürürdüm.

Ayrıca Motorbike / Car'in alt sınıflardan ziyade aracın kategori niteliğinde olması gerektiğini öneriyorum. Bu size daha fazla esneklik verir. Örneğin, bir motosiklet veya araba kategorisini değiştirmeyi kolaylaştırır. Elbette, bisikletlerin gerçek hayatta arabalara dönüşmesi pek mümkün değildir. Ancak bir aracın yanlış girileceğini ve daha sonra değiştirilmesi gerektiğini biliyorsunuz.

Elbette, değeri TaxPayment'in kurucusuna aktarabiliriz, ancak bu araç kapsüllemesini veya sorumluluklarını ihlal eder ya da OOP misyonerleri ne diyorsa söylesin değil mi?

Pek sayılmaz. Parametre kasıtlı olarak başka bir nesneye parametre olarak geçen bir nesne büyük kapsülleme kaygısı değildir. Asıl mesele, verileri çıkarmak veya nesnenin içindeki verileri değiştirmek için bu nesnenin içine ulaşan diğer nesnelerdir.


1

Doğru yolda olabilirsiniz. Sorun, fark ettiğiniz gibi, TaxPayment içinde LastPaidTime üyesi yok . Genel olarak maruz kalması gerekmese de, ait olduğu yer burası:

public interface ITaxPayment
{
    // Your base TaxPayment class will know the 
    // next due date. But you can easily create
    // one which uses (for example) fixed dates
    bool IsPaymentDue();
}

public interface IVehicle
{
    string Plate { get; }
    Person Owner { get; }
    ITaxPayment LastTaxPayment { get; }
} 

Her ödeme aldığınızda ITaxPayment, geçerli politikalara göre, öncekinden tamamen farklı kurallara sahip olabilen yeni bir örnek oluşturursunuz .


Mesele şu ki, ödemenin ödenmesi mal sahibinin son ödemesine (farklı araçlar, vade tarihleri) bağlıdır. ITaxPayment, bir aracı (veya mal sahibinin) en son hesaplamayı yapmak için ne zaman ödeme yaptığını nasıl biliyor?

1

@Sebastiangeiger tarafından sorunun cevabın araçlar yerine araçlarla ilgili olduğu yönündeki cevabına katılıyorum . Cevabını kullanarak ancak birkaç değişiklikle önereceğim. OwnershipSınıfı genel bir sınıf yapardım :

public class Vehicle {}

public abstract class Ownership<T>
{
    public T Item { get; set; }

    public DateTime LastPaidTime { get; set; }

    public abstract TimeSpan PaymentInterval { get; }

    public virtual bool HasToPay
    {
        get { return (DateTime.Today - this.LastPaidTime) >= this.PaymentInterval; }
    }
}

Ve her araç türü için ödeme aralığını belirtmek üzere devralmayı kullanın. Ayrıca TimeSpandüz tamsayılar yerine güçlü bir şekilde yazılmış sınıfı kullanmanızı öneririm :

public class CarOwnership : Ownership<Vehicle>
{
    public override TimeSpan PaymentInterval
    {
        get { return new TimeSpan(30, 0, 0, 0); }
    }
}

public class MotorbikeOwnership : Ownership<Vehicle>
{
    public override TimeSpan PaymentInterval
    {
        get { return new TimeSpan(60, 0, 0, 0); }
    }
}

Şimdi gerçek kodunuzun sadece bir sınıfla başa çıkması gerekiyor - Ownership<Vehicle>.

public class PublicAdministration
{
    List<Ownership<Vehicle>> VehicleOwnerships { get; set; }

    public IEnumerable<Vehicle> GetVehiclesThatHaveToPay()
    {
        return VehicleOwnerships.Where(x => x.HasToPay).Select(x => x.Item);
    }
}

0

Bunu kırmaktan nefret ediyorum ama anemik bir etki alanınız var , yani nesnelerin dışındaki iş mantığı. Eğer bunun için gidiyorsanız, sorun yok, ancak bunlardan kaçınmak için nedenleri okumalısınız.

Sorunlu alanı modellememeye çalışın, ancak çözümü modelleyin. Bu yüzden paralel miras hiyerarşileri ve ihtiyaç duyduğunuzdan daha fazla karmaşıklıkla sonuçlanıyorsunuz.

Bunun gibi bir şey, bu örnek için ihtiyacınız olan şey:

public class Vehicle
{
    public Boolean isMotorBike()
    public string PlateNumber { get; set; }
    public String Owner { get; set; }
    public DateTime LastPaidTime { get; set; }
}

public class TaxPaymentCalculator
{
    public List<Vehicle> GetVehiclesThatHaveToPay(List<Vehicle> all)
}

Eğer SOLID'i izlemek istiyorsanız bu harika, ama Bob Amca'nın kendisinin dediği gibi, onlar sadece mühendislik prensipleri . Sıkıca uygulanmaları amaçlanmamıştır, ancak dikkat edilmesi gereken kurallardır.


4
Çözümünüzün özellikle ölçeklenebilir olmadığını düşünüyorum. Eklediğiniz her araç türü için yeni bir boole eklemeniz gerekir. Bu bence kötü bir seçim.
Erik Funkenbusch

@Garrett Hall, Person sınıfını "etki alanımdan" kaldırmanızı sevdim. İlk önce o sınıfa sahip olamazdım, bunun için çok üzgünüm. Ama MotorBike bir anlam ifade etmiyor. Uygulama hangisi olurdu?

1
@DavidRobertJones: Mystere ile aynı fikirdeyim, bir isMotorBikeyöntem eklemek iyi bir OOP tasarım seçeneği değil. Polimorfizmi bir tür kodla değiştirmek gibi (bir boolen de olsa).
Groo

@ MystereMan, kolayca bir havuzları düşebilir ve enum Vehicles
13

+1. Sorunlu alanı modellememeye çalışın, ancak çözümü modelleyin . Pithy . Anı olarak dedi. VE ilkeleri yorum. Tam anlamıyla yorumda çok fazla girişim görüyorum ; saçmalık.
radarbob

0

Ödeme süresinin asıl Araba / Motosiklet'in malı olmadığına inanıyorum. Ancak bu, araç sınıfının bir özelliğidir.

Nesne türü üzerinde if / select olan yoldan aşağıya inerken, bu çok ölçeklenebilir değildir. Daha sonra kamyon ve Segway eklerseniz ve bisiklet ve otobüs ve uçaklara basarsanız (olası görünmeyebilir, ancak kamu hizmetlerini asla bilmiyorsunuzdur) o zaman durum büyür. Bir kamyonun kurallarını değiştirmek istiyorsan, onu o listede bulmalısın.

Öyleyse neden, kelimenin tam anlamıyla, onu bir öznitelik haline getirip bir yansıma kullanmıyorsunuz? Bunun gibi bir şey:

[DaysBetweenPayments(30)]
public class Car : Vehicle
{
    // actual properties of the physical vehicle
}

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class DaysBetweenPaymentsAttribute : Attribute, IPaymentRequiredCalculator
{
    private int _days;

    public DaysBetweenPaymentAttribute(int days)
    {
        _days = days;
    }

    public bool HasToPay(Vehicle vehicle)
    {
        return vehicle.LastPaid.AddDays(_days) <= DateTime.Now;
    }
}

Ayrıca daha rahatsa statik bir değişkenle de gidebilirsiniz.

Dezavantajları

  • Bunun biraz daha yavaş olacağını ve birçok aracı işlemeniz gerektiğini farz ediyorum. Eğer bu bir sorunsa, o zaman daha pragmatik bir bakış açısına geçebilir ve soyut özellik veya arabirim yaklaşımı ile bağlantı kurabilirim. (Yine de, türe göre de önbelleğe almayı düşünüyorum.)

  • Her Araç alt sınıfının bir IPaymentRequiredCalculator özniteliğine sahip olduğunu (veya bir varsayılana izin verdiğini) başlangıçta doğrulamanız gerekir, çünkü 1000 Otomobil'i işlemesini istemezsiniz, çünkü yalnızca Motosiklet bir PaymentPeriod bulunmaz.

Sonuç olarak, daha sonra bir takvim ayı ya da yıllık ödeme ile karşılaşırsanız, yeni bir özellik sınıfı yazmanız yeterli olacaktır. OCP'nin tanımı budur.


Bununla ilgili en büyük sorun, bir Araç için ödemeler arasındaki gün sayısını değiştirmek isterseniz yeniden inşa etmeniz ve yeniden konuşlandırmanız gerekecek ve ödeme sıklığı işletmenin özelliğine göre değişiyorsa (örneğin motor büyüklüğü) olacaktır. Bunun için zarif bir düzeltme elde etmek zor.
Ed James,

@EdWoodcock: İlk sorunun çoğu çözüm için doğru olduğunu düşünüyorum ve bu beni gerçekten endişelendirmezdi. Daha sonra bu esneklik seviyesini isterlerse, onlara bir DB uygulaması verirdim. İkinci noktada, tamamen katılmıyorum. Bu noktada, aracı HasToPay () 'a isteğe bağlı bir argüman olarak ekler ve ihtiyaç duymadığınız bir yerde onu görmezden gelirsiniz.
pdr

Sanırım, uygulamanız için sahip olduğunuz uzun vadeli planlara ve müşterinin özel gereksinimlerine, eğer zaten yoksa bir DB'ye bağlamaya değip değmeyeceğine bağlı (sanırım tüm yazılımların DB olduğunu varsayma eğilimindeyim) -driven, ki biliyorum ki her zaman böyle değildir). Ancak, ikinci noktada, önemli nitelik zarif ; Öznitelikteki bir yönteme fazladan bir parametre eklemenin, özniteliğin eklendiği sınıfın bir örneğini almasının özellikle şık bir çözüm olduğunu söyleyemem. Ancak, yine, müşteri gereksinimlerine bağlıdır.
Ed James

@EdWoodcock: Aslında, sadece bunu düşünüyordum ve sonPaid argümanı zaten bir Taşıtın mülkü olacaktı. Düşüncelerinizi dikkate alarak, bu argümanı yerine daha sonra değiştirmek yerine şimdi değmeyebilir.
pdr
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.