[PYTHON] Schreiben Sie eindeutig Code, der die bedingte Verzweigung erhöht

Einführung

Gelegentlich kann beim Schreiben von Code eine bedingte Verzweigung multipliziert (kombiniert) auftreten. Zum Beispiel

etc.

In diesem Artikel geht es darum, wie Sie Änderungen standhalten können, ohne die Sichtbarkeit in diesen Situationen zu beeinträchtigen. Das Codebeispiel wird in Python gezeigt, aber die Idee ist nicht auf die Programmiersprache beschränkt. Wenn die Implementierung eine objektorientierte Sprache ist, kann dieselbe Implementierung erreicht werden.

Beispiel) Filmpreise

Hier möchte ich als Beispiel die Filmpreise betrachten. Zum Beispiel gibt es allgemeine Erwachsene, Studenten und Senioren als Käufer, und der Preis ändert sich je nach Tageszeit (tagsüber, späte Show).

Während des Tages Späte Show
Allgemeines 1800 Yen 1300 Yen
Schüler 1.500 Yen 1.500 Yen
Senior 1100 Yen 1100 Yen

Angenommen, es gibt eine Abzinsungsregel für den Standardsatz (1800 Yen), und die Anwendung dieser Regel wird im Code ausgedrückt.

Abzinsungsregel vom Standardbetrag

Wochentags Wochentage (späte Show)
Allgemeines +-0 Yen -500 Yen
Schüler - -500 Yen
Senior -700 Yen -700 Yen

Wenn prozedural geschrieben

In einem solchen Fall ist es wie folgt schmerzhaft, wenn Sie einfach mit prozeduraler bedingter Verzweigung schreiben.

from datetime import datetime
import enum


#Viewer-Klassifizierung
class ViewerType(enum.Enum):
  ADULT = "adult"
  STUDENT = "student"
  SENIOR = "senior"


#Geben Sie die Sendegebühr basierend auf der Zuschauerklassifizierung, der Filmstartzeit und der Standardgebühr zurück
def charge(viewer_type: ViewerType, movie_start_at: datetime  base_charge: int) -> int:
  #Späte Show nach 20:00 Uhr
  if movie_start_at.hour < 20:
    if viewer_type == ViewerType.ADULT:
      return base_charge
    elif viewer_type == ViewerType.STUDENT:
      return base_charge - 300
    else:
      return base_charge - 700

  if viewer_type == ViewerType.ADULT or viewer_type == ViewerType.STUDENT:
    return base_charge - 500
  else:
    return base_charge - 700

Selbst wenn Sie es auf einen Blick betrachten, sind die allgemeinen Aussichten schlecht, und ich denke, es ist schwierig zu sagen, ob es richtig umgesetzt wird. Wenn sich die Arten von Käufern wie registrierten Mitgliedern erhöhen oder sich die Regeln für vorrangige Gebühren ändern, ist es auch schwierig zu wissen, wo die Verarbeitung hinzugefügt werden muss.

Stellen Sie sich die bedingte Verzweigung als Kontext vor

In einem solchen Fall können Sie eine bessere Ansicht erhalten, indem Sie ** das Ereignis (Daten, die die Quelle der bedingten Verzweigung darstellen) ** berücksichtigen, das sich auf den Prozess auswirkt, den Sie als ** Kontext ** ausführen möchten.

In diesem Fall wird die ** Startzeit der Show **, die das Kriterium dafür ist, ob es sich um eine späte Show handelt, im Code als Kontext ** für die Bestimmung des endgültigen ** Preises ausgedrückt.

from datetime import datetime
import dataclasses

@dataclasses.dataclass
class MovieStartAtContext:
  movie_start_at: datetime

  def is_late_show(self) -> bool:
    return self.movie_start_at.hour >= 20

Vorläufig konnte ich den Kontext ** ausdrücken, ob die Startzeit der Show eine späte Show ist **, aber es macht keinen Sinn, dies in den obigen Verfahrenscode zu erweitern.

from datetime import datetime
import dataclasses

@dataclasses.dataclass
class MovieStartAtContext:
  movie_start_at: datetime

  def is_late_show(self) -> bool:
    return self.movie_start_at.hour >= 20

  #Preisberechnung durch den Betrachter
  #
  #Die vom Betrachter aufgerufene Methode ändert sich je nachdem, ob es sich um eine späte Show handelt oder nicht.
  #
  # -Für späte Shows: late_show_charge()
  # -Während des Tages:      normal_charge()
  def charge_for(self, viewer: Viewer, base_charge: int) -> int:
    if self.is_late_show():
      return viewer.late_show_charge(base_charge)

    return viewer.normal_charge(base_charge)

Auf diese Weise ist es ausreichend, die Berechnungsmethoden für die verspätete Show und die reguläre Gebühr für jeden Zuschauertyp zu definieren (es liegt in der Verantwortung der Kontextzeit der Showzeit, die entsprechende Methode aufzurufen).

Implementierung der Gebührenberechnungslogik für jeden Betrachter

Die Implementierung der Gebührenberechnung für jeden Betrachter ist wie folgt.

class Viewer:
  def normal_charge(self, base_charge: int) -> int:
    pass

  def late_show_charge(self, base_charge: int) -> int:
    pass


class AdultViewer(Viewer):
  def normal_charge(self, base_charge: int) -> int:
    return base_charge

  def late_show_charge(self, base_charge: int) -> int:
    return base_charge - 500


class StudentViewer(Viewer):
  def normal_charge(self, base_charge: int) -> int:
    return base_charge - 300

  def late_show_charge(self, base_charge: int) -> int:
    return base_charge - 500


class SeniorViewer(Viewer):
  def normal_charge(self, base_charge: int) -> int:
    return base_charge - 700

  def late_show_charge(self, base_charge: int) -> int:
    return base_charge - 700

Sie können sehen, dass die Abzinsungsregel-Regeltabelle im Code fast so ausgedrückt wird, wie sie ist.

Abzinsungsregel vom Standardbetrag

Wochentags Wochentage (späte Show)
Allgemeines +-0 Yen -500 Yen
Schüler -300 Yen -500 Yen
Senior -700 Yen -700 Yen

Code-Integration

Wenn Sie den bisher definierten Code integrieren, sieht Ihre ursprüngliche Funktion "load ()" folgendermaßen aus:

class ViewerFactory:
  viewer_mapping = {
    ViewerType.ADULT: AdultViewer(),
    ViewerType.STUDENT: StudentViewer(),
    ViewerType.SENIOR: SeniorViewer()
  }

  @classmethod
  def create(cls, viewer_type: ViewerType) -> Viewer:
    return cls.viewer_mapping[viewer_type]


def charge(viewer_type: ViewerType, movie_start_at: datetime, base_charge: int) -> int:
  context = MovieStartAtContext(movie_start_at)

  viewer = ViewerFactory.create(viewer_type)

  return context.charge_for(viewer, base_charge)

Auf diese Weise können Sie eine neue Viewer-Klasse definieren, wenn sich der im Beispiel erwähnte Typ des Mitgliedsregistranten erhöht, und selbst wenn sich eine neue Gebührenkategorie wie die Urlaubsgebühr erhöht. Ich denke, dass Sie es implementieren können, ohne sich am Montageort zu verlaufen.

Zusammenfassung

Wenn bedingte Verzweigung multiplikativ (kombinatorisch) auftritt

Hoffentlich können Sie Ihren Code sauberer und einfacher erweitern. Ich hoffe, es wird für die Implementierung hilfreich sein.

Recommended Posts

Schreiben Sie eindeutig Code, der die bedingte Verzweigung erhöht
Schreiben Sie die Standardeingabe in den Code
Schreiben Sie Spigot in VS Code
Ein Liner, der neunundneunzig in Python ausgibt
Ich hatte Probleme mit der bedingten Verzweigung in Djangos Vorlagen.