Empfehlung der Serviceklasse in Ruby on Rails

Hallo, das ist @ hairgai. Dieses Mal werde ich meine eigene Verwendung der Vor- und Nachteile der Service-Klasse schreiben.

Was ist die Serviceklasse?

Eine Gruppe von Klassen, die eine Funktion beschreiben, die von einem Dienst in DDD (Domain Driven Design) abgeleitet (und selbst erkannt) wird. Ich werde es weglassen, weil es viele Leute gibt, die es ausführlich erklären, aber ich benutze es oft, weil ich Geschäftslogik sauber zwischen dem Modell und dem Controller schreiben kann. Dieses Mal (obwohl meine Verwendung möglicherweise falsch ist) werde ich meine eigene Verwendung und den Teil schreiben, der ihr Verdienst zu sein scheint.

Grundlegende Verwendung

Zunächst möchte ich die grundlegende Verwendung anhand eines Codebeispiels vorstellen. (Ich bin nicht sicher, ob dies die richtige Antwort ist, aber ich denke, es ist gut, weil es leicht zu sehen ist.) Wenn Sie beispielsweise die Funktion "Folgen" auf SNS usw. als Serviceschicht in einer Datei beschreiben, sieht dies folgendermaßen aus. ** * Ich wiederhole, aber das ist nicht die richtige Antwort. ** ** **

class FollowService
  attr_reader :user, :target_user
  attr_accessor :follow

  def initialize(user, target_user)
    @user = user
    @target_user = target_user
  end

  def perform
    check!

    create_follow!
    run_after_worker!
  end

  private

  def check!
    check_following!
    check_blocking!
  end

  def check_following!
    return true unless user.following?(target_user)

    raise ArgumentError, 'User following target user'
  end

  def check_blocking!
    return true unless user.blocking?(target_user)

    raise ArgumentError, 'User blocking target user'
  end

  def create_follow!
    self.follow = user.follows.create!(target_user: target_user)
  end

  def run_after_worker!
    AfterFollowWorker.perform_in(0.2.seconds, follow.id)
  end
end

Erstellen Sie mit reinen Ruby-Klassen

Grundsätzlich mache ich nichts mit Gem etc. Wir streben den Effekt an, "die Barriere für das Verständnis der Implementierung zu senken", indem wir sie in reinem Ruby implementieren. Die Serviceklasse hat in der Regel eine komplizierte Logik (wenn es um umfangreiche Funktionen geht), daher versuche ich, sie so einfach wie möglich zu halten, damit jeder sie sofort verstehen kann.

Bestimmen Sie den Klassennamen

Ich denke, Sie mögen die Benennung, aber da es sich um eine Klasse handelt, die die Funktion symbolisiert, wird sie mit "verb Service" vereinheitlicht. Eine Namenskonvention hat den Vorteil, dass das Ableiten von Funktionen erleichtert wird.

Lassen Sie öffentliche Methoden nur ausführen

Ich denke, es gibt hier eine Menge Präferenzen (viele Leute nennen es "call"), aber im Grunde wird nur eine öffentliche Methode erstellt, und die anderen können nicht aufgerufen werden. Dies liegt daran, dass die Service-Klasse eine Klasse ist, die eine einzelne Funktion symbolisiert, und die Funktionen, die mit ihr realisiert werden können, auf eine einzelne beschränkt sind. Es gibt ziemlich viele Leute, die diese einzige öffentliche Methode sagen, aber ich habe sie auch übernommen, weil es zum Zeitpunkt des Entwurfs kein Zögern gab und die Implementierungsgeschwindigkeit dramatisch anstieg.

Nur private Methoden werden von öffentlichen Methoden aufgerufen

Dies wird auch übernommen, weil es die Sichtbarkeit verbessert. + 1 Die Verantwortung für jede Methode wird leichter und die Schutzklausel wird einfacher zu verwenden. Ich denke, hier haben Sie unterschiedliche Geschmäcker.

Einzelansatz zur Nachbearbeitung etc.

Wie ich oben in Follow Service geschrieben habe, denke ich zuerst über die Antwort an den Benutzer nach, solange sie im Geschäftsleben verwendet wird. Als Ansatz in einem solchen Fall gibt es ein Verfahren zum "Durchführen nur der erforderlichen Verarbeitung während einer Antwort", und die nachfolgende Verarbeitung usw. wird in der Warteschlange als Job gespeichert und vom Jobserver usw. verarbeitet. Zu diesem Zeitpunkt ist die Sichtbarkeit des gesamten Projekts schlecht, wenn der Prozess des Aufrufs des Jobs auf verschiedene Stellen wie Controller und Modell verteilt ist.

Daher können Sie den Gesamtausblick verbessern, indem Sie eine Namenskonvention wie "AfterHogeJob" für Nachbearbeitungsjobs von "HogeService" verwenden und nur in der Serviceklasse aufrufen.

Beseitigung des Aufblähens des Controllers

Unnötig zu erwähnen.

class FollowsController < ApplicationController
  def create
    target_user = user.find(params[:target_user_id])
    service = FollowService.new(current_user, target_user)
    service.perform

    redirect_to user_path(target_user)
  end
end

Beseitigung von Modellaufblähungen

Unnötig zu erwähnen. Bringen Sie alles, was im Modell geschrieben ist, in die Service-Klasse, und das Modell besteht nur aus Datenassoziation, Validierung und anderen Methoden, die sich auf ein einzelnes Modell beziehen. Infolgedessen enthält das Modell keine logikreichen Methoden mehr und keine aufgeblähten, schwer zu erkennenden Modelle.

Nachwort

Wenn ich es auf diese Weise noch einmal schreibe, denke ich, dass ich auf eine Weise schreibe, die der Service-Klasse verschiedene Verantwortlichkeiten auferlegt. Ich denke, es ist fraglich, ob die Service-Klasse nicht notwendig ist, aber da eine solche Geschichte des Designs nur eine der Methoden ist, wäre es schön, wenn sie entsprechend unserem Geschäft angemessen verwendet werden könnte.

Recommended Posts

Empfehlung der Serviceklasse in Ruby on Rails
Ruby on Rails Japanisch-Englisch kompatibler i18n
[Ruby on Rails] Einführung der Anfangsdaten
[Rails] Hinzufügen der Ruby On Rails-Kommentarfunktion
Ruby on Rails in Visual Studio-Codespaces
[Ruby on Rails] Japanische Fehlernotation
Erklärung von Ruby auf Schienen für Anfänger ①
[Ruby on Rails] Implementierung einer ähnlichen Funktion
Anfänger haben mit Ruby on Rails ein Portfolio erstellt
Lösche N + 1 in Acts_as_tree von Ruby on Rails Baumstruktur Gem
Implementierung der Ruby on Rails-Anmeldefunktion (Sitzung)
[Ruby on Rails] Bis zur Einführung von RSpec
Rails neu in Ruby on Rails ~ Memorandum bis zur Bereitstellung 2
Ruby on Rails ~ Grundlagen von MVC und Router ~
Ruby on Rails Elementary
[Ruby on Rails] Ein Memorandum mit Layoutvorlagen
Ruby on Rails Grundlagen
Rails neu in Ruby on Rails ~ Memorandum bis zur Bereitstellung 1
(Ruby on Rails6) Erstellen von Daten in einer Tabelle
Ruby On Rails Association
Eine Reihe von Ablauf der Tabellenerstellung → Datensatzerstellung, Löschung → Tabellenlöschung in Ruby on Rails
[Ruby on Rails] Individuelle Anzeige von Fehlermeldungen
[Ruby on Rails] Asynchrone Kommunikation der Posting-Funktion, Ajax
[Ruby on Rails] Wie schreibe ich eine Enumeration auf Japanisch?
Implementierung der Ruby on Rails-Anmeldefunktion (Devise Edition)
[Ruby On Rails] So setzen Sie die Datenbank in Heroku zurück
[Ruby / Rails] Legen Sie einen eindeutigen (eindeutigen) Wert in der Klasse fest
[Ruby on Rails] Post-Bildvorschau-Funktion in Refile
Erklärung von Ruby auf Schienen für Anfänger ⑥ ~ Erstellung der Validierung ~
Erklärung von Ruby on Rails für Anfänger ② ~ Links erstellen ~
Ordne die Beiträge in der Reihenfolge ihrer Likes auf Rails an (Rangfolge)
Versuchen Sie es mit dem Ruby on Rails-Abfrageattribut
Erklärung von Ruby on Rails für Anfänger ⑦ ~ Flash-Implementierung ~
Ruby on Rails Lernrekord -2020.10.03
Ruby on Rails Lernrekord -2020.10.04
Schreiben Sie die Klassenvererbung in Ruby
[Ruby on Rails] Debuck (bindend.pry)
Ruby on Rails Lernrekord -2020.10.05
Ruby on Rails Lernrekord -2020.10.09
Ruby on Rails lernen Rekord-2020.10.07 ②
Ruby on Rails lernen Rekord-2020.10.07 ①
Brechen Sie die Ruby on Rails-Migration ab
Ruby on Rails Lernrekord -2020.10.06
Zusammenfassung der Ruby on Rails-Validierung
Ruby on Rails Grundlegendes Memorandum
Schwierigkeiten beim Erstellen einer Ruby on Rails-Umgebung (Windows 10) (SQLite3)