Ne zaman bir hizmet veya yardımcı program işlevi oluşturmalıyım?


11

Geçen hafta boyunca aklımda şu soru vardı: Ne zaman bir hizmet veya yardımcı program işlevi oluşturmalıyım?

Drupal Core'da hem Hizmetler hem de Yardımcı Program işlevlerimiz var, ancak aralarındaki farkı bulamıyorum (bir hizmet oluşturmam gerektiğinde veya bir yardımcı program işlevi oluşturmam gerektiğinde).

InternalFunctions sınıfına sahip olduğum modüller ağırlık modülünü örnek alacağım .

<?php

namespace Drupal\modules_weight\Utility;

class InternalFunctions {

  public static function prepareDelta($weight) {
    $delta = 100;

    $weight = (int) $weight;

    if ($weight > $delta) {
      return $weight;
    }

    if ($weight < -100) {
      return $weight * -1;
    }

    return $delta;
  }


  public static function modulesList($force = FALSE) {
    $modules = [];
    $installed_modules = system_get_info('module');

    $config_factory = \Drupal::service('config.factory');

    if ($force) {
      $show_system_modules = TRUE;
    }
    else {
modules.
      $show_system_modules = $config_factory->get('modules_weight.settings')->get('show_system_modules');
    }

    $modules_weight = $config_factory->get('core.extension')->get('module');

    foreach ($installed_modules as $filename => $module_info) {
      if (!isset($module_info['hidden']) && ($show_system_modules || $module_info['package'] != 'Core')) {
        $modules[$filename]['name'] = $module_info['name'];
        $modules[$filename]['description'] = $module_info['description'];
        $modules[$filename]['weight'] = $modules_weight[$filename];
        $modules[$filename]['package'] = $module_info['package'];
      }
    }
    uasort($modules, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);

    return $modules;
  }

}

Bu sınıfta iki statik işlevim var ama ikisi de yardımcı işlevler veya prepareDelta()bir yardımcı işlev ve modulesList()başka bir sınıfta olması ve bir hizmet olması gerekir?

Şu anda bulduğum tek fark, Drupal \ Component \ Utility (burada bir çok yardımcı program işlevi göreceksiniz) ad alanı içinde hiçbirinin bir hizmet içinde kullanmaması ve genellikle bir hizmetin içinde başka bir hizmet kullanmasıdır ( bunu doğrulamak için tüm hizmetleri inceleyin).

Peki, ne zaman bir hizmet veya yardımcı program işlevi oluşturmalıyım?


Slack Drupal #contribute kanalından Ken Rickard şöyle diyor: "Diğer modüllerin (veya diğer geliştiricilerin) bu kodla etkileşimde bulunmasını beklerseniz bir hizmet oluşturacağım. Yardımcı yöntemler yalnızca kendiniz için özel kısayollardır."
Adrian Cid Almaguer

Fayda yöntemleri hakkında düşündüğüm şey buydu, ancak hizmetler için bazen bunun daha önemli olduğunu düşünüyorum.
Adrian Cid Almaguer

Bence bu dersin büyük bir kısmı sınıfın yaptıklarına ve işletmek için neler yapması gerektiğine iniyor. UnicodeSınıfı temel alın - bu bir hizmet değil, statik bir yardımcı sınıftır, çünkü herhangi bir bağımlılığı yoktur ve herhangi bir durumu korumasına gerek yoktur. Bir hizmet bağımlılığı gerektiriyorsa, DI kalıbı bir hizmete dönüştürülmesini gerektirir ve gerektiğinde kaptan tekli (veya fabrikada üretilen) örneği kullanırsınız. Aksi takdirde use, mantıklı olduğunda sadece statik sınıfı yapabilirsiniz .
Clive

Bu nedenle, diğer modüllerin (veya diğer geliştiricilerin) bu kodla etkileşime girmesini beklerseniz bir hizmet oluşturabilirim . Durum böyleyse, Unicodetasarım gereği bir hizmet olurdu ve gerçekten olması gerekmez. Fayda sınıflarının bazı açılardan daha kolay, daha kolay olabileceğini, kendi modülünüzdeki diğer modüller ve diğer kodlar tarafından kullanılabileceğini unutmayın. Ama her şey bir geliştirici olarak kendi bakış açınıza / deneyiminize bağlı, çoğunlukla sağduyuya inecek zor yoldan öğrendim
Clive

2
@NoSssweat Ama Unicode ise yalnızca statik yöntemler içeren bir Drupal sınıf! Çekirdek geliştiricilerin bunu bir hizmetten ziyade statik bir sınıf olarak uygulamayı seçmiş olması, muhtemelen bir şey düşünmüyor musunuz? Bir yardımcı sınıfın doğası gereği üzerine yazılmasına gerek yoktur - bazı şeyler yapar, eğer bu şeyler istediğiniz gibi değilse, kendi sınıfınızı yazarsınız. Geleneksel olarak sınıflarda yaşayan şeylerin bir kerelik olduğunu unutmayın, "Bunu yapıyorum ve başka bir şey yapmıyorum" yöntem türleri, bir dizi parametre dışında girdiye ihtiyaç duymaz
Clive

Yanıtlar:


6

Genel kullanım hizmetlerinde. Statik yardımcı program işlevlerini kullanmanın uygun olduğu aşağıdaki blog yayınına bakın:

Yani asla statik kullanmayın?

Hayır, geçerli kullanım durumları var. Birincisi, önceden tanımlı öğelerin bir listeniz varsa, statik, herhangi bir durumda değil, sınıf düzeyinde olacağından belleği azaltmaya yardımcı olabilir.

Diğer durumlar dış bağımlılık gerektirmeyen yardımcı yöntemler, örneğin bir slugify yöntemidir.

<?php
class Util
{
    public static function slug($string)
    {
        return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '_', $string)));
    }
}

Slug yöntemi yalnızca çok iyi tanımlanmış bir davranış sergiler. Ünite testlerinde davranışı dikkate almak kolaydır ve bu çağrıyı gördüğümde çok endişelenmem.

Bu yöntemler, başlatma gerektirmedikleri için ünite testine bile tabi tutulabilir.

Kaynak: https://stovepipe.systems/post/avoiding-static-in-your-code

(Şimdi Drupal'da statik kod miktarı, prosedürel D7 kodundan geçişten kaynaklanmaktadır, bu nedenle mevcut durumda Drupal'ı örnek olarak kullanmayın.)


Sorudaki örnek hakkında, yardımcı sınıfın geri kalanı (soruda gösterilmiyor)

<?php

namespace Drupal\modules_weight\Utility;

/**
 * Provides module internal helper methods.
 *
 * @ingroup utility
 */
class InternalFunctions {

...

  /**
   * Return the modules list ordered by the modules weight.
   *
   * @param bool $force
   *   Force to show the core modules.
   *
   * @return array
   *   The modules list.
   */
  public static function modulesList($force = FALSE) {
    // If we don't force we need to check the configuration variable.
    if (!$force) {
      // Getting the config to know if we should show or not the core modules.
      $force = \Drupal::service('config.factory')->get('modules_weight.settings')->get('show_system_modules');
    }
    // Getting the modules list.
    $modules = \Drupal::service('modules_weight')->getModulesList($force);

    return $modules;
  }

}

statik bir sarıcıda modülün kendi hizmetini çağırır:

\Drupal::service('modules_weight')

Bunun nedeni, muhtemelen yardımcı sınıfın eski yordam kodunda kullanılmasıdır. OOP kodunda bu gerekli değildir, burada hizmeti doğrudan enjekte etmelisiniz.


Cevabınız için teşekkürler, dün modül kodunu biraz değiştirdim (çünkü bazı taahhütlerde bulundum) ve modules_weight hizmetini oluşturuyorum. Hizmetim var, çünkü bu diğer modüller tarafından kullanılabilir ve şimdi geneldir, tüm modülleri veya sadece çekirdek modüller listesini alabilirsiniz. Ancak modülde bu liste show_system_modules config değişkenindeki değerden etkilenebilir, bu yüzden bu var alan ve daha sonra hizmetleri çağıran başka bir işlev yaptım, ancak cevabınızı okuduğunuzda modulesList işlevinin statik olmaması gerekir.
Adrian Cid Almaguer

Bu durumda, modulesList işlevinin hizmetin içinde mi yoksa bağımlılık enjeksiyonuna sahip bir kurucu ile başka bir sınıfta olması gerektiği bir şey var mı?
Adrian Cid Almaguer

Aynı servise koyabileceğinizi ve getModulesList () 'i korumalı bir yöntem olarak ilan edebileceğinizi düşünüyorum.
4k4

ancak mesele şu ki eğer birisi getModuleList () kullanmak istiyorsa ve modulesList () sadece modül için önemli olan bir değişkene erişebilir. Belki moduleList () yöntemini başka bir yöntem olarak ekleyip bir modül yapılandırma değişkeni kullanan açıklamaya ekleyebilir misiniz?
Adrian Cid Almaguer

İki yöntemden sadece birini herkese açık hale getirirdim. Belki $force = NULLbirinin varsayılan değeri FALSE ile yapılandırmak isteyip istemediğinizi bilmesi için varsayılan bir değer ayarlayabilirsiniz .
4k4

8

Slack Drupal #contribute kanalından Ken Rickard şöyle diyor: "Diğer modüllerin (veya diğer geliştiricilerin) bu kodla etkileşimde bulunmasını beklerseniz bir hizmet oluşturacağım. Yardımcı yöntemler yalnızca kendiniz için özel kısayollardır."

Evet, hizmetler hakkında harika bir şey, herkesin üzerine yazabilmesidir. Yani diğer insanlara belirli bir kod parçasını özelleştirme yeteneği vermek istiyorsanız. Bkz. Mevcut hizmetleri değiştirme, dinamik hizmetler sağlama .

Ayrıca, PHP Birim testi için Mock testi yapmanız gerekiyorsa, bunu bir hizmet yapmalısınız. Bkz Drupal 8'de Hizmetleri ve bağımlılık enjeksiyon , bkz Birim daha karmaşık Drupal sınıfları test .

Soru ve Cevap:

Servis birimi testi

Başka bir sınıftan statik yöntemleri çağıran bir yöntem için birim testleri yazma


Teşekkürler, cevabınıza eklemek için referanslarınız var mı?
Adrian Cid Almaguer

@AdrianCidAlmaguer ekledi.
Sssweat yok

1
Teşekkürler, şimdi bu referanslar diğer kullanıcılara (ve ben de) yardımcı olabilir ;-)
Adrian Cid Almaguer

modülünüzün farklı dosyalarında tekrar kullandığınızı gördüğünüz bir hizmet oluşturmalısınız. Bir hizmet, neden aynı modülde birkaç kez kullanılan bir yardımcı program sınıfına sahip olmaktan daha yararlı (veya daha iyi uygulama) olsun? (açıklığa kavuşturmak için: tartışmıyorum, ancak bu bağlamda özellikle bir fark yok gibi görünüyor. Bir hizmetin neden daha anlamlı olduğunu düşündüğünüzü duymak isterim)
Clive

1
Evet, ilginç bir @NoSssweat. IMO, Drupal veya Symfony'den daha üst düzey prensipler tarafından yönlendirilir. Kodunuza iyi, standart, sınıf tasarım uyguladığınızı ve ardından sonuçları o sınıf için anlamlı olan herhangi bir yöntemle o anda kullandığınız çerçeveye yerleştirdiğinizi düşünüyorum
Clive
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.