[RUBY] Eine Geschichte, die Geschäftslogik und Modell trennt

Überblick

Es ist eine Geschichte, die den Zugriff auf eine bestimmte Datenressource aus der Geschäftslogik und der Verarbeitungsverarbeitung in dem Dienst, der betrieben wird, ausschließt und standardisiert.

Ist das wirklich ein Modell?

Ich verstehe nicht. Ist das Entitäts- oder Domänenobjekt besser? Lass es mich wissen, bitte.

Vor dem Modellieren

Dies ist beispielsweise der Code. Das Folgende ist eine Klasse, die die Seite einer Präfektur verwaltet, und es wird angenommen, dass Sie ein Ereignis erworben haben, das dieser Präfektur zugeordnet ist.

area/pref.rb


module Area
  class Pref
    def event
      events = Api.call('/events', params)
      events.each_with_object([]) do |event, memo|
        memo << {
          name: event[:name],
          address: create_full_address(event)
        }
      end
    end

    def create_full_address(event)
      #Gibt die vollständige Adressfolge zurück, indem einige Informationen kombiniert werden
    end
  end
end

Als nächstes wurde die Seite der Städte, Gemeinden, Städte und Dörfer unter der Präfektur erstellt. Nachfolgend finden Sie Veranstaltungen zu dieser Stadt.

area/city.rb


module Area
  class City
    def event
      events = Api.call('/events', params)
      events.each_with_object([]) do |event, memo|
        memo << {
          name: event[:name],
          address: create_city_address(event)
        }
      end
    end

    def create_city_address(event)
      #Ich möchte die Adresse kurz anzeigen, daher gebe ich die Adresszeichenfolge nach Stadt, Gemeinde, Stadt und Dorf zurück
    end
  end
end

Die Verarbeitung, die Ereignisinformationen verarbeitet, wird dupliziert. Lassen Sie uns dies wie folgt ausschneiden und es allgemein machen.

area/common.rb


module Area
  class Common
    class << self
      def events(params)
        Api.call('/events', params)
      end

      def create_full_address(event)
        #Gibt die vollständige Adressfolge zurück, indem einige Informationen kombiniert werden
      end

      def create_city_address(event)
        #Ich möchte die Adresse kurz anzeigen, daher gebe ich die Adresszeichenfolge nach Stadt, Gemeinde, Stadt und Dorf zurück
      end
    end
  end
end

Der Anrufer sieht wie folgt aus.

area/pref.rb


require_relative 'common'

module Area
  class Pref
    def event
      events = Common.events(params)
      events.each_with_object([]) do |event, memo|
        memo << {
          name: event[:name],
          address: Common.create_city_address(event)
        }
      end
    end
  end
end

Ich fand es okay, aber als nächstes gab es eine neue Klasse, um die Stationsseiten zu verwalten. Angenommen, Sie benötigen auf dieser Seite keine Adressinformationen, sondern nur Informationen zur Station.

Letztes Mal habe ich auf Bereichsseiten wie area / common.rb gemeinsam gemacht. Da die auf der Bereichsseite erfassten Informationen nicht erforderlich sind und die gewünschten Informationen geringfügig abweichen, habe ich beschlossen, den Zugriff auf Ereignisinformationen selbst zu implementieren.

traffic/station.rb


module Traffic
  class Station
    def event(params)
      events = Api.call('/events', params)
      events.each_with_object([]) do |event, memo|
        memo << {
          name: event[:name],
          stations: create_stations(event)
        }
      end
    end

    def create_stations(event)
      #Gibt einige Stationsinformationen zurück
    end
  end
end

Das Obige ist die allgemeine Situation vor dem Modellieren. Das Beispiel ist lang und ich denke, dass es nicht gut genug ist. Lassen Sie mich entschuldigen, dass die Situation tatsächlich etwas komplizierter ist.

Probleme vor dem Modellieren

Um die Probleme zusammenzufassen, kann gesagt werden, dass die Situation wie folgt war.

Wenn es sich bei der praktischen API im Unternehmen um eine Datenressource handelt, wird eine Antwort mit einiger Sorgfalt zurückgegeben, sodass es Fälle geben kann, in denen sie in der Geschäftslogik aufgerufen wird, ohne ordnungsgemäß getrennt zu sein. Ich denke. Selbst wenn es zunächst einfach implementiert werden kann, wird es chaotisch, wenn verschiedene Anwendungen an verschiedenen Orten beginnen.

Nach dem Modellieren

Als Lösung habe ich mich entschlossen, das Modell richtig zu betreiben. Ich habe beschlossen, das Modell für jede Datenressource zu schneiden und immer über das Modell auf die Datenressource zuzugreifen. Durch die Konsolidierung der Dekoration der Antwort im Modell haben wir versucht, sie allgemein zu gestalten, und einen klaren Zustand geschaffen, in dem sie implementiert werden kann.

Insbesondere ist es wie folgt.

Das Modell, das jedes Ereignis verwaltet, ist wie folgt definiert.

model/event.rb


module Model
  class Event
    attr_accessor :name, :address

    def initialtize(event)
      {
        'name' => '@name',
        'address' => '@address',
      }.each do |key, prop|
        instance_variable_set(prop, event[key])
      end
    end

    def full_address
      #Gibt die vollständige Adressfolge zurück, indem einige Informationen kombiniert werden
    end

    def city_address
      #Ich möchte die Adresse kurz anzeigen, daher gebe ich die Adresszeichenfolge nach Stadt, Gemeinde, Stadt und Dorf zurück
    end

    def stations
      #Gibt einige Stationsinformationen zurück
    end
  end
end

Das Modell, das die Liste der Ereignisse verwaltet, lautet wie folgt.

model/events.rb


require_relative 'event'

module Model
  module Events
    attr_accessor :events

    def initialize(events)
      @events = events.each_with_object([]) do |event, memo|
        memo << Model::Event.new(event)
      end
    end

    class << self
      def get(params)
        events = Api.call('/events', params)
        Model::Events.new(events)
      end
    end
  end
end

Die Benutzerseite sieht so aus.

area/pref.rb


module Area
  class Pref
    def event
      events = Model::Events.get(params)
      events.each_with_object([]) do |event, memo|
        memo << {
          name: event.name,
          address: event.full_address
        }
      end
    end
  end
end

Wir haben model / event.rb als ein Modell definiert, das Ereignisinformationen verarbeitet. Dies ist für das Speichern und Dekorieren von Ereignisinformationen zuständig, und der gesamte Zugriff auf Ereignisinformationen erfolgt über dieses Modell.

Da die Antwort der API zum Abrufen des Ereignisses als Listentyp zurückgegeben wird, definieren Sie model / events.rb und verwalten Sie die API-Antwort hier. Zu diesem Zeitpunkt werden einzelne Ereignisinformationen zur Dekoration an event.rb übergeben, und events.rb enthält das Ergebnis als Liste.

Auf diese Weise können Benutzer auf die dekorierten Gegenstände zugreifen, ohne sich dessen bewusst zu sein.

Vermeiden Sie FETT

Durch die oben beschriebene Modellierung konnten wir den Zugriff und die Dekoration auf Datenressourcen konsolidieren.

Andererseits besteht bei diesem Design die Sorge, dass das Modell anschwillt. Um das FAT-Modell zu vermeiden, ergreifen wir die folgenden Maßnahmen.

Obwohl es sich um einen Delegierten handelt, ist es effektiv, wenn es andere Modelle für das Festival als die Veranstaltung gibt und Sie für jede eine ähnliche Methode haben möchten.

model/event.rb


module Model
  class Event
    #Halten Sie gedrückt, um die Veranstaltung zu beurteilen?Die Methode ist Modell::Übertragen Sie auf Bedingung und verwenden Sie diese Implementierung
    delegate :hold?, to: Model::Condition
  end
end

Kann wie folgt aufgerufen werden

area/pref.rb


module Area
  class Pref
    def hold_event?
      Model::Events.hold?
    end
  end
end

SpecialThanks Vielen Dank an @nazomikan für die Bereitstellung des Entwurfs, an HK und SS für die Bewerbung und an alle Mitglieder der Abteilung!

Recommended Posts

Eine Geschichte, die Geschäftslogik und Modell trennt
[MVC-Modell] Ein Memo, das ein Anfänger MVC gelernt hat
Geschäftslogik?
Eine Geschichte, die Zeit brauchte, um eine Verbindung herzustellen
Ruby Sum ist eine nüchterne und erstaunliche Geschichte
Eine Geschichte über das Erstellen eines Builders, der den Builder erbt
Klasse und Modell
[Ruby] Ein Programm / Konzept, das each_with_index und search kombiniert