Arayüz sabitlerinin Artıları ve Eksileri [kapalı]


105

PHP arayüzleri, bir arayüzde sabitlerin tanımlanmasına izin verir, örn.

interface FooBar
{
    const FOO = 1;
    const BAR = 2;
}
echo FooBar::FOO; // 1

Herhangi bir uygulama sınıfı otomatik olarak bu sabitlere sahip olacaktır, örn.

class MyFooBar implement FooBar
{
}
echo MyFooBar::FOO; // 1

Bu konudaki kendi görüşüm, Global olan her şeyin Kötü olduğu . Ama aynısının Arayüz Sabitleri için geçerli olup olmadığını merak ediyorum. Olduğu göz önüne alındığında , bir arabirim karşı Kodlama genel olarak iyi bir uygulama olarak kabul edilir, Arayüz sabitleri bir sınıf bağlamı dışında kullanımı kabul edilebilir tek sabitleri kullanıyor?

Kişisel fikrinizi ve Arayüz sabitlerini kullanıp kullanmamanızı merak ederken, cevaplarınızda esas olarak nesnel nedenler arıyorum. Bunun bir Anket Türü sorusu olmasını istemiyorum. Arayüz sabitlerini kullanmanın Sürdürülebilirlik üzerinde nasıl bir etkisi olduğu ile ilgileniyorum. Kaplin. Veya Birim Testi. SOLID PHP ile nasıl ilişkilidir ? PHP'de İyi Uygulama olarak kabul edilen herhangi bir kodlama ilkesini ihlal ediyor mu? Kaptın bu işi …

Not: Java için , Kötü Uygulama olmasının oldukça iyi nedenlerini listeleyen benzer bir soru var , ancak Java PHP olmadığından, bunu PHP etiketi içinde tekrar sormanın haklı olduğunu hissettim.


1
Hmm, daha önce bir arayüzde sabitleri tanımlama ihtiyacıyla hiç karşılaşmamıştım. Sınıflar bilerek It değerinde arayüzünü uygulayan sınıflar sadece birbirini uzatırken, sabitleri geçersiz kılamaz kutu geçersiz kılma sabitleri.
Charles

1
Birim test edilebilirliği söz konusu olduğunda bile tahmin edilebilir değerlere sahip oldukları için sabitlerin kötü olmadığına inanıyorum. Küresel değişkenler kötüdür çünkü bir değişken olduğu ve her şeyin kapsamı olduğu için herkes onu değiştirebilir, ancak sabitler değerini asla değiştirmeyecek, dolayısıyla sabit terimi.
mdprotacio

Yanıtlar:


135

Bence iyi ve yeterince iyi arasındaki farka indirgeniyor .

Çoğu durumda, diğer kalıpları (strateji veya belki de uçucu ağırlık) uygulayarak sabitlerin kullanımından kaçınabilirsiniz, ancak bir kavramı temsil etmek için yarım düzine başka sınıfa ihtiyaç duyulmaması için söylenecek bir şey vardır. Bence kısaca, başka sabitlere ihtiyaç olma olasılığı. Başka bir deyişle, arayüzdeki sabitler tarafından sağlanan ENUM'un genişletilmesine ihtiyaç var mı? Genişletme ihtiyacını öngörebilirseniz, daha resmi bir kalıp kullanın. Değilse, o zaman yeterli olabilir (yeterince iyi olacak ve dolayısıyla yazmak ve test etmek için daha az kod olacaktır). İşte yeterince iyi ve kötü kullanım örneği:

Kötü:

interface User {
    const TYPE_ADMINISTRATOR = 1;
    const TYPE_USER          = 2;
    const TYPE_GUEST         = 3;
}

Yeterince iyi:

interface HTTPRequest_1_1 {
    const TYPE_CONNECT = 'connect';
    const TYPE_DELETE  = 'delete';
    const TYPE_GET     = 'get';
    const TYPE_HEAD    = 'head';
    const TYPE_OPTIONS = 'options';
    const TYPE_POST    = 'post';
    const TYPE_PUT     = 'put';

    public function getType();
}

Şimdi, bu örnekleri seçmemin nedeni basit. UserArayüz kullanıcı tipleri Bir enum tanımlar. Bunun zamanla genişlemesi çok muhtemeldir ve başka bir modele daha uygun olacaktır. Ancak, HTTPRequest_1_1numaralandırma RFC2616 tarafından tanımlandığından ve sınıfın ömrü boyunca değişmeyeceğinden, uygun bir kullanım durumudur.

Genel olarak, sabitler ve sınıf sabitleri ile ilgili sorunu küresel bir sorun olarak görmüyorum . Bunu bir bağımlılık sorunu olarak görüyorum. Bu dar bir ayrım ama kesin bir ayrım. Küresel sorunları, uygulanmayan küresel değişkenlerdeki gibi görüyorum ve bu nedenle yumuşak bir küresel bağımlılık yaratıyor. Ancak sabit kodlanmış bir sınıf, zorunlu bir bağımlılık yaratır ve bu nedenle sert bir küresel bağımlılık yaratır. Yani ikisi de bağımlılıktır. Ama düşünün küresel ben götürü için sevmiyorum yüzden hangisi ... o zorlanmaz beri çok daha kötü olduğunu sınıf bağımlılıkları ile küresel bağımlılıklar aynı bayrak altında ...

Eğer yazarsanız MyClass::FOO, uygulama detaylarına kodlanmış olursunuz MyClass. Bu, kodunuzu daha az esnek hale getiren ve bu nedenle kaçınılması gereken bir sabit bağlantı oluşturur. Bununla birlikte, tam olarak bu tip bir bağlantıya izin veren arayüzler mevcuttur. Bu nedenle MyInterface::FOOherhangi bir beton bağlantı sağlamaz. Bununla birlikte, sadece ona bir sabit eklemek için bir arayüz sunmayacağım.

Eğer arayüzlerini kullanıyor ve sen Yani eğer çok emin (ya da bu konuda herkesten) Ek değere ihtiyaç yoktur ki, o zaman ben gerçekten ... iyi arayüz sabitleri ile büyük bir sorun görmüyorum tasarımlar herhangi bir sabit veya koşul veya sihirli sayı veya sihirli dizge veya sabit kodlanmış herhangi bir şey içermez. Ancak, kullanımları göz önünde bulundurmanız gerektiğinden bu, geliştirmeye ek süre ekler. Benim görüşüme göre, çoğu zaman harika bir sağlam tasarım oluşturmak için ek zaman ayırmaya kesinlikle değer. Ancak yeterince iyi olanın gerçekten kabul edilebilir olduğu zamanlar vardır (ve farkı anlamak için deneyimli bir geliştiricinin gerekir) ve bu durumlarda sorun değil.

Yine, bu sadece benim görüşüm ...


4
Bu durumda Kullanıcı için farklı bir model olarak ne önerirsiniz?
Jacob

@Jacob: Onu soyutlardım. İhtiyaçlarınıza bağlı olarak, verilerini bir veritabanı tablosundan alacak bir Access sınıfı oluşturabilirim. Bu şekilde yeni bir seviye eklemek, yeni bir satır eklemek kadar kolaydır. Diğer bir seçenek de ENUM sınıf kümesi oluşturmaktır (burada her izin rolü için bir sınıfınız vardır). Ardından, uygun izinleri sağlamak için gerektiğinde sınıfları genişletebilirsiniz. Ancak işe yarayacak başka yöntemler de var
ircmaxell

3
Çok sağlam ve iyi ifade edilmiş bir cevap! +1
Decent Dabbler

1
genel sabitlere sahip sınıfın herhangi bir yöntemi olmamalıdır. Yalnızca veri yapısı veya yalnızca nesne olmalıdır - ikisi birden değil.
OZ_

2
@FrederikKrautwald: Polimorfizm ile koşullardan kaçınabilirsiniz (çoğu durumda): Bu yanıtı kontrol edin ve bu Temiz Kod konuşmasını izleyin ...
ircmaxell

10

Sabitleri, özel olarak numaralandırılmış sabitleri arayüzünüzden ayrı bir tür ("sınıf") olarak ele almanın genellikle daha iyi olduğunu düşünüyorum:

define(TYPE_CONNECT, 'connect');
define(TYPE_DELETE , 'delete');
define(TYPE_GET    , 'get');
define(TYPE_HEAD   , 'head');
define(TYPE_OPTIONS, 'options');
define(TYPE_POST   , 'post');
define(TYPE_PUT    , 'put');

interface IFoo
{
  function /* int */ readSomething();
  function /* void */ ExecuteSomething(/* int */ param);
}

class CBar implements IFoo
{
  function /* int */ readSomething() { ...}
  function /* void */ ExecuteSomething(/* int */ param) { ... }
}

veya bir sınıfı ad alanı olarak kullanmak istiyorsanız:

class TypeHTTP_Enums
{
  const TYPE_CONNECT = 'connect';
  const TYPE_DELETE  = 'delete';
  const TYPE_GET     = 'get';
  const TYPE_HEAD    = 'head';
  const TYPE_OPTIONS = 'options';
  const TYPE_POST    = 'post';
  const TYPE_PUT     = 'put';
}

interface IFoo
{
  function /* int */ readSomething();
  function /* void */ ExecuteSomething(/* int */ param);
}

class CBar implements IFoo
{
  function /* int */ readSomething() { ...}
  function /* void */ ExecuteSomething(/* int */ param) { ... }
}

Yalnızca sabitleri kullandığınızdan değil, belirli bir kullanım ("alan"?)

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.