web-dev-qa-db-ja.com

いつサービスまたはユーティリティ関数を作成する必要がありますか?

私は先週ずっとこの質問を念頭に置いていました:サービスまたはユーティリティ関数をいつ作成するべきですか?

Drupalコアにはサービスとユーティリティ関数の両方がありますが、それらを区別できません(サービスを作成する必要があるとき、またはユーティリティ関数を作成する必要があるとき))。

Modules Weight モジュールの例として、 InternalFunctions クラスを使用します。

_<?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;
  }

}
_

このクラスには2つの静的関数がありますが、どちらもユーティリティ関数であるか、prepareDelta()はユーティリティ関数であり、modulesList()は別のクラスにあり、サービスを持っている必要がありますか?

現時点で私が見つけた唯一の違いは、名前空間Drupal\Component\Utility(多くのユーティリティ機能が表示されます)内ではサービス内で使用せず、通常、サービスは内部で別のサービスを使用することです(私はしません)これを検証するためにすべてのサービスを確認してください)。

それで、サービスまたはユーティリティ関数をいつ作成する必要がありますか?

11

一般的な使用サービス。静的ユーティリティ関数を使用してもよい場合は、次のブログ投稿を参照してください。

だから静的を使用しないでください?

いいえ、有効なユースケースがあります。 1つは、事前定義された項目のリストがある場合、静的ではインスタンスレベルではなくクラスレベルになるため、メモリの削減に役立つことです。

その他のケースは、外部の依存関係を必要としないユーティリティメソッドです(slugifyメソッドなど)。

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

Slugメソッドは、非常に明確に定義された動作のみを実行します。単体テストで動作を考慮に入れるのは簡単で、この呼び出しを見てもそれほど心配する必要はありません。

これらのメソッドは初期化を必要としないため、ユニットテストを行うこともできます。

ソース: https://stovepipe.systems/post/avoiding-static-in-your-code

(Drupalに含まれる静的コードの量は、手続き型D7コードからの移行によるものであるため、例として現在の状態でDrupalを使用しないでください。 )


質問の例について、ユーティリティクラスの残りの部分(質問には表示されていません)

<?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;
  }

}

静的ラッパーでモジュール独自のサービスを呼び出します。

\Drupal::service('modules_weight')

これはおそらく、ユーティリティクラスが従来の手続き型コードで使用されているためです。 OOPコードではこれは必要ありません。ここではサービスを直接注入する必要があります。

6
4k4

SlackのKen Rickard Drupal #contributeチャネルは、次のように述べています。「他のモジュール(または他の開発者)がそのコードとやり取りすることを期待する場合、サービスを作成します。ユーティリティメソッドは、自分専用のショートカットです。 」

はい、サービスの優れた点は、誰でも上書きできることです。したがって、特定のコードをカスタマイズする機能を他の人に提供したい場合。 既存のサービスの変更、動的サービスの提供 を参照してください。

また、PHPユニットテストのモックテストを実行する必要がある場合は、サービスにする必要があります。 Drupal 8 、参照 より複雑なユニットテストDrupalクラス

Q&A:

サービス単体テスト

別のクラスから静的メソッドを呼び出すメソッドの書き込みユニットテスト

8
No Sssweat