Biri içinde iki işlev veya şube tanımlayın?

6 Cevap php

PHP bir dosyanın kodlamasını tespit ve bazı blog veya bir yere, bunu yapmak için önerildi konusunda okuyordu:

if (function_exists('mb_detect_encoding')) {
    function is_utf8($str) {
        // do stuff using the mb* libraries
    }
} else {
    function is_utf8($str) {
        // do stuff manually
    }
}

Benim için bu çok dağınık hissediyor ve bu ile değiştirilmesi olabilir:

function is_utf8($str) {
    if (...) {
        // mb stuff here
    } else {
        // manual stuff here
    }
}

Ancak, ben de o da bazı faydaları olduğunu görebilirsiniz. if ifadedir ve ne sıklıkta fonksiyon denir nasıl karmaşık bağlı olarak, bu çok daha verimli olabilir. Hangi noktada ilk örnekteki gibi ikiye bir işlevi bölme düşünün: Benim soru budur? Ben kaçırdığımız başka artıları / eksileri vardır?

Edit: Burada örnek üzerinde asılı alamadım Lütfen, soru genelde bu uygulama ile ilgili.

6 Cevap

Benim gut tepki is_utf8 fonksiyonu tek bir beyanname ile gitmektir. PHP motoru optimizasyonu ve function_exists() ihmal olmalıdır birden aramaların yükü de güçlü iyidir.

İyi bir uygulama, belki de bu durumda, ancak genel olarak fabrika yöntemleri ile OOP (nesne) kullanımını gerektirebilir değil.

class my_utf8 
{
  // A static method that determine what object to create
  public static function factory() {
    if (function_exists('mb_detect_encoding')) {
      return new my_utf8_with_mb;
    } else {
      return new my_utf8_without_mb;
    }
  }
}

class my_utf8_with_mb extends my_utf8 {
    public function is_utf8($str) {
        // do stuff using the mb* libraries
    }
}

class my_utf8_without_mb extends my_utf8 {
    public function is_utf8($str) {
        // do stuff without the mb* libraries
    }
}

Ve uygulama:

global $myUtfInstance;
// Call once
$myUtfInstance = my_utf8::factory();

// later and forever...
$myUtfInstance->is_utf8($str);

Ayrıca ne bağlı bir singleton deseni içerebilir. Bu EĞER atlamak ama küresel bir değişkenin ihtiyacını ortadan kaldırmaz.

class my_utf8 
{
  private static $instance;

  public static function factory() {
    if (function_exists('mb_detect_encoding')) {
      return new my_utf8_with_mb;
    } else {
      return new my_utf8_without_mb;
    }
  }


  public static function getInstance()
  {
    if (!self::$instance) {
      self::$instance = self::factory();
    }

    return self::$instance;
  } 
}

Ve kodu:

my_utf8::getInstance()->is_utf8($str);

Üslup, ben saniye itmek eğiliminde değilim. Performans olsa da bir sorun ise, ilk kullanarak dikkate iyi yaparım.

    if (function_exists("sin")) {
        function baz($farfs) {
            print "I am the first baz";
        }
    } else {
        function baz($farfs) {
            print "I am the second baz";
        }
    }

    function blarg($fgar) {
        if (function_exists("sin")) {
            print "I am the first blarg";
        } else {
            print "I am the second blarg";
        }
    }

    for ($i=0;$i

Burada benim iş istasyonunda bu koştu, ve baz çağrı toplam süresi test edilen fonksiyon aslında var olmadığına bağlı Blarg için toplam aramaların% 50-75 yerde ortaya çıkardı.

İşte gerçek sayılar:

  • function_exists("foobar")
    • blarg: 36.64 ms
    • baz: 14.71 ms
  • function_exists("sin")
    • blarg: 35.24 ms
    • baz: 23.59 ms

Bu iki işlev arasındaki tek fark, çıkış koşullu ve iki ilave karakterdir. İlginçtir ki, function_exists için 10001 görüşmeleri sadece iki testten sırasıyla 0.18 ve 0.11 ms alır. Havai profili birinde hesaba olmayan bazı işlev çağrısı olup olmadığını merak ediyorum.

Gerçi stil gelince, ben gerçekten ilk sevmediğim. İki farklı yerde ismiyle bir işlevi tanımlayan küresel kapsamda gerçekleştirilen değil işlev tanımları zaten küresel kapsamını etkiler yapar PHP oddness dayanarak, özellikle yapmak için gölgeli bir şey gibi görünüyor. Öte yandan, benim önyargıları sadece gösteriyor olabilir, ve PHP toplumun geri kalanı bu durumda önişlemci bir tür olarak PHP yorumlayıcısı güvenerek bir sorun olmayabilir.

shrug Böyle tarzı konulardır.

Varsayılan olarak, en okunabilir çözümü ile her zaman gitmek. Kodu bu özel parça uygulama üzerinde (farz değil ölçülen) önemli bir engel olduğu ortaya çıkarsa, o zaman optimize.

Ben büyük olasılıkla oldukça çirkin PHP ne için şimdiden özür dilerim, ama ben daha böyle bir şey yapmak istiyorum:

if (function_exists('mb_detect_encoding')) {
    function is_utf8_mb($str) {
        // do stuff using the mb* libraries
    }
}
function is_utf8_manual($str) {
    // do stuff manually
}

if (function_exists('is_utf8_mb')) {
    function is_utf8($str) {
        is_utf8_mb($str)
    }
} else {
    function is_utf8($str) {
        is_utf8_manual($str)
    }
}

Yani: bu ortamda çalışabilir eğer bir is_utf8 varyantı sadece bağımlı yürütme ortamında var olacaktır. Her varyant bu varyant yüklü olmalıdır belirlemek için, ve işlevini gerçekleştirmek için gerekli minimum boyutta bir kod bloğu bulunmaktadır. Ana nedeni ben küçük size işlevi yazmak gerekiyor alan miktarı, o kadar kolay işlevin davranışı bir anlayış oluşturmak için bir okuyucu için olduğunu düşünüyorum olmasıdır. Gözlerin daha az seyahat etmek zorunda, daha az kaydırma yapmak zorunda, ilk kez bir fonksiyonu anlamak katılanların önemsiz sıkıntılarınızı genellikle az bulunmaktadır. İkinci nedeni kodunuzu test daha iyi bir yol sağlar - daha kolayca aynı anda hepsini erişebilirsiniz zaman is_utf8 varyant rutinleri aynı sonucu üreten bir kontrol otomatik olarak yapabilirsiniz.

Performans (sana ihtiyacım yok ne için ödeme yapmayın) ve okunabilirlik: İki Burada oyun yönleri vardır.

Birçok bilge posterler demek: bir sorun olduğu kanıtlandı kadar performansı hakkında rahatsız değil.

Fakat okunabilirliği ilgili, benim görüşüme göre, bir işlev mümkün olduğunca sorumluluk az katmanları göstermek gerekir. Tam olarak bir şey yapmak fonksiyonları kolay anlaşılır.

Sizin soru 'nasıl iki sorumluluk karıştırmak gerektiği' konusunda aslında:

  1. what: Bir kütüphane varlığını tespit ve doğru kod bloğu için 'sevk'
  2. how olmadan nasıl vs kütüphane kullanımı.

Ben gerçekten iki 'katmanlar' yaratacak yüzden: Bir katman uygun işlevine gönderme, ve uygun bir isim ile bir işlev sarılmış 'kod blokları' içeren başka bir katman.

Ve sonra yine açıkça sevk yapmak için, ya da on-the-fly işlevlerini bildirmek için PHP'nin imkanı kullanmak isteyip seçim var.

// functionality: defines how to detect utf8 encoding 
//

function is_utf8_mb( $arg ) {
... // using the mb library
}

function is_utf8_bare( $arg ) {
... // hand coded
}

// dispatching layer: decide what library to use
//

// option 1: define on-the-fly
function define_utf8_function() {
   if( function_exists('mb_detect_encoding') ) {
     function is_utf8( $arg ) { return is_utf8_mb( $arg ); }
   } else {
     function is_utf8( $arg ) { return is_utf8_bare( $arg ); }
   }
}

// option 2: check the dispatching on each function call
function is_utf8_runtimedispatch( $arg ) {
  if( function_exists('mb_detect_encoding') ) 
    return is_utf8_mb( $arg );
  else 
    return is_utf8_bar( $arg );
}