Kapan saya harus membuat layanan atau fungsi utilitas?

11

Saya memiliki pertanyaan ini dalam pikiran sepanjang minggu lalu: Kapan saya harus membuat layanan atau fungsi utilitas?

Dalam Drupal Core kami memiliki fungsi Layanan dan Utilitas, tetapi saya tidak dapat menemukan perbedaan di antara mereka (ketika saya perlu membuat layanan atau ketika saya harus membuat fungsi utilitas).

Saya akan mengambil contoh Modul Berat di mana saya memiliki kelas 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;
  }

}

Di kelas ini saya memiliki dua fungsi statis tetapi keduanya adalah fungsi utilitas atau prepareDelta()fungsi utilitas dan modulesList()harus di kelas lain dan memiliki layanan?

Satu-satunya perbedaan yang saya temukan saat ini adalah bahwa di dalam namespace Drupal \ Component \ Utility (di mana Anda akan melihat banyak fungsi utilitas) tidak ada yang menggunakan di dalam layanan dan biasanya layanan menggunakan layanan lain di dalam (saya tidak telah meninjau semua layanan untuk memvalidasi ini).

Jadi, kapan saya harus membuat layanan atau fungsi utilitas?

Adrian Cid Almaguer
sumber
Ken Rickard dari saluran Slack Drupal #contribute mengatakan: "Saya akan membuat layanan jika Anda mengharapkan modul lain (atau pengembang lain) berinteraksi dengan kode itu. Metode utilitas hanyalah cara pintas pribadi untuk Anda sendiri."
Adrian Cid Almaguer
Itulah yang saya pikirkan tentang metode Utilitas, tetapi untuk layanan terkadang saya pikir itu lebih merupakan pertimbangan.
Adrian Cid Almaguer
Saya pikir banyak yang turun ke apa yang dikerjakan kelas, dan apa yang perlu disediakan untuk dapat beroperasi. Ambil Unicodekelas dalam inti - itu adalah kelas utilitas statis, bukan layanan, karena tidak memiliki dependensi, dan tidak perlu mempertahankan status apa pun. Jika diperlukan dependensi layanan, pola DI akan mengharuskannya dikonversi ke layanan, dan Anda akan menggunakan instance singleton (atau yang dihasilkan pabrik) dari wadah saat Anda membutuhkannya. Kalau tidak, Anda bisa hanya usekelas statis ketika masuk akal.
Clive
Karena itu, saya akan membuat layanan jika Anda mengharapkan modul lain (atau pengembang lain) berinteraksi dengan kode itu tidak berdering benar bagi saya. Jika itu yang terjadi, Unicodeakan menjadi layanan dengan desain, dan itu tidak benar-benar perlu. Jangan lupa kelas utilitas dapat dengan mudah, lebih mudah dalam beberapa hal, digunakan oleh modul lain dan kode lain di modul Anda sendiri. Tapi itu semua tergantung pada perspektif / pengalaman Anda sendiri sebagai pengembang, itu sebagian besar akan datang ke akal sehat belajar dengan cara yang sulit
Clive
2
@NoSssweat But Unicode adalah kelas Drupal yang hanya berisi metode statis! Fakta bahwa dev inti memilih untuk mengimplementasikannya sebagai kelas statis, daripada layanan, mungkin berarti sesuatu yang tidak Anda pikirkan? Kelas utilitas tidak benar-benar perlu ditimpa, berdasarkan sifatnya - ia melakukan beberapa hal, jika hal-hal itu tidak sesuai keinginan Anda, Anda menulis kelas sendiri. Ingatlah jenis-jenis hal yang secara tradisional hidup dalam kelas utilitas adalah sekali pakai, jenis metode "Saya melakukan ini dan tidak ada yang lain", yang tidak memerlukan input kecuali seperangkat parameter
Clive

Jawaban:

6

Secara umum menggunakan layanan. Lihat posting blog berikut ini jika boleh menggunakan fungsi utilitas statis:

Jadi jangan pernah menggunakan statis?

Ya tidak, ada kasus penggunaan yang valid. Salah satunya adalah jika Anda memiliki daftar item yang ditentukan sebelumnya statis dapat membantu mengurangi memori karena akan di tingkat kelas dan tidak dalam hal apa pun.

Kasus lain adalah metode utilitas yang tidak memerlukan dependensi luar, misalnya metode slugify.

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

Metode siput hanya melakukan perilaku yang didefinisikan dengan sangat baik. Sangat mudah untuk memperhitungkan perilaku dalam unit test dan saya tidak akan terlalu khawatir ketika saya melihat panggilan ini.

Metode ini bahkan dapat diuji unit karena tidak memerlukan inisialisasi.

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

(Jumlah kode statis sekarang di Drupal adalah karena transisi dari kode D7 prosedural, jadi jangan gunakan Drupal dalam keadaan saat ini sebagai contoh.)


Tentang contoh dari pertanyaan, seluruh kelas utilitas (tidak ditampilkan dalam pertanyaan)

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

}

memanggil layanan modul sendiri dalam pembungkus statis:

\Drupal::service('modules_weight')

Ini mungkin karena kelas utilitas digunakan dalam kode prosedural lama. Dalam kode OOP ini tidak perlu, di sini Anda harus menyuntikkan layanan secara langsung.

4k4
sumber
Terima kasih atas jawabannya, kemarin saya mengubah sedikit kode modul (karena saya membuat beberapa komitmen) dan saya membuat layanan modules_weight. Saya memiliki layanan karena ini dapat digunakan oleh modul lain dan sekarang umum, Anda bisa mendapatkan semua modul atau hanya daftar modul inti. Tetapi dalam modul daftar ini dapat dipengaruhi oleh nilai di dalam variabel config show_system_modules, jadi saya membuat fungsi lain yang mengambil var ini dan kemudian memanggil layanan, tetapi membaca jawaban Anda sepertinya fungsi modulesList tidak boleh statis.
Adrian Cid Almaguer
Dalam hal ini apakah Anda yakin bahwa fungsi modulesList harus berada di dalam layanan atau di kelas lain dengan konstruktor dengan injeksi dependensi?
Adrian Cid Almaguer
Saya pikir Anda dapat menempatkannya di layanan yang sama dan mendeklarasikan getModulesList () sebagai metode yang dilindungi.
4k4
tetapi intinya adalah bahwa jika seseorang ingin menggunakan getModuleList () tidak akan mungkin dan modulesList () memiliki akses ke variabel yang hanya penting untuk modul. Mungkin menambahkan modulesList () sebagai metode lain dan menambahkan deskripsi yang menggunakan variabel konfigurasi modul?
Adrian Cid Almaguer
Saya hanya akan membuat salah satu dari dua metode ini publik. Mungkin Anda dapat menetapkan nilai default $force = NULL, sehingga Anda tahu jika seseorang ingin menimpa nilai konfigurasi dengan FALSE.
4k4
8

Ken Rickard dari saluran Slack Drupal #contribute mengatakan: "Saya akan membuat layanan jika Anda mengharapkan modul lain (atau pengembang lain) berinteraksi dengan kode itu. Metode utilitas hanyalah cara pintas pribadi untuk Anda sendiri."

Ya, hal keren tentang layanan adalah siapa pun dapat menimpa mereka. Jadi, jika Anda ingin memberi orang lain kemampuan untuk menyesuaikan potongan kode tertentu. Lihat Mengubah layanan yang ada, menyediakan layanan dinamis .

Selain itu, Anda harus menjadikannya layanan jika Anda perlu melakukan tes Mock untuk pengujian Unit PHP. Lihat Layanan dan injeksi ketergantungan di Drupal 8 , lihat Unit testing kelas Drupal yang lebih rumit .

Tanya Jawab:

Tes unit layanan

Unit tes menulis untuk metode yang memanggil metode statis dari kelas lain

Tidak ada Sssweat
sumber
Terima kasih, apakah Anda memiliki beberapa referensi untuk ditambahkan ke jawaban Anda?
Adrian Cid Almaguer
@AdrianCidAlmaguer menambahkan.
No Sssweat
1
Terima kasih, sekarang referensi ini dapat membantu pengguna lain (dan saya juga) ;-)
Adrian Cid Almaguer
Anda harus membuat layanan jika itu sesuatu yang Anda lihat diri Anda gunakan lagi di berbagai file modul Anda. Mengapa layanan lebih berguna (atau praktik yang lebih baik) daripada memiliki kelas utilitas yang digunakan beberapa kali dalam modul yang sama? (untuk memperjelas: Saya tidak berdebat, tetapi sepertinya tidak ada perbedaan dalam konteks itu secara khusus. Saya ingin mendengar mengapa menurut Anda suatu layanan lebih masuk akal)
Clive
1
Ya itu yang menarik @NoSssweat. IMO itu dipandu oleh prinsip-prinsip tingkat yang lebih tinggi daripada Drupal atau Symfony. Saya pikir Anda menerapkan desain kelas yang baik, standar, ke kode Anda, dan kemudian memasukkan hasilnya ke dalam kerangka apa pun yang Anda gunakan saat itu dengan metode apa pun yang masuk akal untuk kelas itu
Clive