Tür Kodunu Sınıfla Değiştir (Yeniden Düzenlemeden [Fowler])


9

Bu strateji, bunun beğenilerini değiştirmeyi içerir:

public class Politician
{
    public const int Infidelity = 0;
    public const int Embezzlement = 1;
    public const int FlipFlopping = 2;
    public const int Murder = 3;
    public const int BabyKissing = 4;

    public int MostNotableGrievance { get; set; }
}

İle:

public class Politician
{
    public MostNotableGrievance MostNotableGrievance { get; set; }
}

public class MostNotableGrievance
{
    public static readonly MostNotableGrievance Infidelity = new MostNotableGrievance(0);
    public static readonly MostNotableGrievance Embezzlement = new MostNotableGrievance(1);
    public static readonly MostNotableGrievance FlipFlopping = new MostNotableGrievance(2);
    public static readonly MostNotableGrievance Murder = new MostNotableGrievance(3);
    public static readonly MostNotableGrievance BabyKissing = new MostNotableGrievance(4);

    public int Code { get; private set; }

    private MostNotableGrievance(int code)
    {
        Code = code;
    }
}

Neden bu tür bir numaralandırma yapmak için tam olarak tercih edilir, şöyle:

public class Politician
{
    public MostNotableGrievance MostNotableGrievance { get; set; }
}

public enum MostNotableGrievance
{
    Infidelity = 0,
    Embezzlement = 1,
    FlipFlopping = 2,
    Murder = 3,
    BabyKissing = 4
}

Türle ilişkili bir davranış yoktur ve eğer olsaydı, yine de farklı bir tür yeniden düzenleme kullanacaksınız, örneğin, 'Tür Kodunu Alt Sınıflarla Değiştir' + 'Koşullu Polimorfizmle Değiştir'.

Ancak, yazar neden bu yönteme (Java'da?) Kaşlarını çattığını açıklıyor:

Sayısal tür kodları veya numaralandırmalar, C tabanlı dillerin ortak bir özelliğidir. Sembolik isimlerle oldukça okunabilir olabilirler. Sorun, sembolik ismin sadece bir takma ad olmasıdır; derleyici hala temel numarayı görüyor. Derleyici türü, sembolik adı değil 177 sayısını kullanarak kontrol eder. Tür kodunu bağımsız değişken olarak alan herhangi bir yöntem bir sayı bekler ve sembolik bir adı kullanılmaya zorlayacak hiçbir şey yoktur. Bu, okunabilirliği azaltabilir ve bir hata kaynağı olabilir.

Ancak bu ifadeyi C # 'a uygulamaya çalışırken, bu ifade doğru görünmüyor: numaralandırma aslında bir sınıf olarak kabul edildiğinden sayı kabul etmiyor. Yani aşağıdaki kod:

public class Test
{
    public void Do()
    {
        var temp = new Politician { MostNotableGrievance = 1 };
    }
}

Derlenmeyecek. Peki, bu yeniden düzenleme C # gibi daha yeni üst düzey dillerde gerekli olmayabilir mi, yoksa bir şey düşünmüyor muyum?


var temp = new Politician { MostNotableGrievance = MostNotableGrievance.Embezzlement };
Robert Harvey

Yanıtlar:


6

Sanırım orada kendi sorunuzu neredeyse cevapladınız.

İkinci kod parçası birincisine göre tercih edilir çünkü tip güvenliği sunar. İlk parça ile, benzer bir Balık numaralandırmanız varsa, böyle bir şey söyleyebilirsiniz.

MostNotableGrievance grievance = Fish.Haddock;

ve derleyici umursamaz. Fish.Haddock = 2 ise, yukarıdakiler tam olarak eşdeğer olacaktır

MostNotableGrievance grievance = MostNotableGrievance.FlipFlopping;

ancak belli ki anında okunabilir değil.

Numaralandırmaların genellikle daha iyi olmama nedeni, int'e ve int'ten örtük dönüştürmenin sizi tamamen aynı sorunla terk etmesidir.

Ancak, C # 'da, böyle bir örtük dönüşüm yoktur, bu nedenle bir enum kullanmak daha iyi bir yapıdır. Kullanılan ilk iki yaklaşımdan birini nadiren göreceksiniz.


5

Değeri ile ilişkili bir davranış yoktur ve bunu yanında saklamak gerektiğini hiçbir ekstra bilgiler varsa ve dil tamsayılar için örtük dönüştürme desteklemiyor, ben bir enum kullanmak istiyorsunuz; onlar bunun için oradalar.


1

Size yardımcı olabilecek başka bir örnek, Etkili Java'da bulunabilir (aramak istiyorsanız, madde 30). C # için de geçerlidir.

Diyelim ki yılanlar ve köpekler gibi farklı hayvanları modellemek için int sabitlerini kullandınız.

int SNAKE_PYTHON=0;
int SNAKE_RATTLE=1;
int SNAKE_COBRA=2;

int DOG_TERRIER=0;
int DOG_PITBULL=1;

Bunların sabit olduğunu ve hatta farklı sınıflarda tanımlandığını varsayalım. Bu size iyi gelebilir ve aslında işe yarayabilir. Ancak bu kod satırını göz önünde bulundurun:

snake.setType(DOG_TERRIER);

Açıkçası, bu bir hatadır. Derleyici şikayet etmeyecek ve kod yürütülecektir. Ama yılanın köpeğe dönüşmeyecek. Çünkü derleyici sadece şunu görür:

snake.setType(0);

Yılanınız aslında bir python (ve bir terrier değil). Bu özelliğe tür güvenliği denir ve aslında örnek kod olmanızın nedeni budur

var temp = new Politician { MostNotableGrievance = 1 };

derlenmeyecek. MostNotableGrievance bir tam sayı değil bir MostNotableGrievance'dir. Numaralandırmalar ile bunu tür sisteminde ifade edebilirsiniz. Bu nedenle Martin Fowler ve ben sayımların harika olduğunu düşünüyorum.

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.