[PYTHON] Versuchen Sie es mit Designmustern (Exporter Edition)

Überblick

Dieser Inhalt ist für Anfänger gedacht, die versuchen möchten, Entwurfsmuster mit Maya Python zu verwenden. Ich werde die ausführliche Erklärung des Entwurfsmusters anderen Websites überlassen. Wie verbessert sich der Code, wenn Sie ihn tatsächlich verwenden? Konzentrieren Sie sich auf. Nehmen Sie als Anwendungsbeispiel so etwas wie einen Datenexporter als Beispiel.

Motivation

Ich möchte die Entwurfsleistung und die Codequalität verbessern, indem ich tatsächlich Entwurfsmuster verwende. Ich möchte ein Muster finden, das insbesondere bei der Implementierung von Werkzeugen verwendet werden kann.

Entwurfsmuster

Dieses Mal wird das folgende Muster verwendet. Einzelheiten zum Muster finden Sie auf der Referenzseite unten auf der Seite.

Muster Übersicht (meine Wahrnehmung) verdienen
TemplateMethod Abstrahieren Sie die von der übergeordneten Klasse aufgerufene Methode und überlassen Sie die Implementierung innerhalb der Methode der Unterklasse. ProzessablaufVon jedem Prozess beim BindenVerhaltenWird der Unterklasse überlassen.
FactoryMethod Wenn Sie ein anderes Objekt in der Klasse verwenden, abstrahieren Sie den Generierungsprozess und verwenden Sie das (abstrahierte) Generierungsobjekt. Der Generierungsprozess und die Methodenimplementierung werden jeder Unterklasse überlassen. Es erbt die Güte der Vorlagenmethode. Beim Erstellen eines anderen Objekts und Aufrufen einer MethodeProzessablaufGenerierenVerhaltenKann getrennt werden.
Factory Bereiten Sie eine Klasse vor und verwenden Sie sie, die nur Objekte unter den angegebenen Bedingungen erstellt. Von der Seite, die das Objekt verwendet, entspricht das Objekt den BedingungenGenerierenKann getrennt werden.

** Versuchen Sie es für das Exporter-Skript **

Ich dachte, dass der Export von Maya-Szeneninformationen relativ umfangreich ist, also habe ich ihn gewählt. Das Bild ist wie die Ausgabe geeigneter Daten mithilfe des FBX-Exports. Es wird erkannt, dass die Spezifikationen wahrscheinlich später geändert werden, z. B. die Auswahl von Ausgabedaten oder die Durchführung einer speziellen Verarbeitung in Abhängigkeit von den Bedingungen. Es beschreibt, wie der Code vor und nach dem Anwenden des Entwurfsmusters aussehen wird.

Basiscode

Wenn Sie die Prozesse anordnen, ohne über etwas Besonderes nachzudenken, sieht dies wie folgt aus.

scene_exporter.py


def scene_export(option):
    """Ausgabemodelle und Animationen in der Szene"""
    #Vorverarbeitung

    if option.mode == ExportMode.head:
        #Suchen Sie nach Kopfnetzdaten in der Hierarchie
        #Etwas tun
        #Export
    if option.mode == ExportMode.body:
        #Suchen Sie nach Body-Mesh-Daten in der Hierarchie
        #Etwas tun
        #Export
    if option.mode == ExportMode.animation:
        #Suchen Sie Skelettdaten in der Hierarchie
        #Etwas tun
        #Export

    #Nachbearbeitung

Anpassung der Vorlagenmethode

Wenden Sie vorerst das Muster der Vorlagenmethode an, um den Exportprozess zu standardisieren.

exporter.py


from abc import ABCMeta, abstractmethod


class BaseExporter(object):
    """Exporter Grundklasse"""
    __metaclass__ = ABCMeta

    def export(self):
        select_export_targets()
        export_selection()

    @abstractmethod
    def select_export_targets(self):
        """Wählen Sie das Exportziel"""
        pass

    @abstractmethod
    def export_selection(self):
        """Exportieren Sie ausgewählte Objekte"""
        pass


class HeadExporter(BaseExporter):
    """Exporteurklasse für HEAD"""
    def select_export_targets(self):
        cmds.select("|char|mesh|head")

    def export_selection(self):
        #Implementierte Ausgabeverarbeitung für HEAD

class BodyExporter(BaseExporter):
    """Exporteurklasse für KÖRPER"""
    def select_export_targets(self):
        cmds.select("|char|mesh|body")

    def export_selection(self):
        #Implementierte Ausgabeverarbeitung für BODY

class AnimExporter(BaseExporter):
    """Exporterklasse für ANIM"""
    def select_export_targets(self):
        cmds.select("|char|skel|root")

    def export_selection(self):
        #Implementierte Ausgabeverarbeitung für ANIM

scene_exporter_v2.py


def scene_export(option):
    """Ausgabemodelle und Animationen in der Szene"""
    #Vorverarbeitung

    if option.mode == ExportMode.head:
        HeadExporter().export()
    if option.mode == ExportMode.body:
        BodyExporter().export()
    if option.mode == ExportMode.animation:
        AnimExporter().export()

    #Nachbearbeitung

Wenden Sie das Factory-Muster weiter an

Selbst wenn TemplateMethod angewendet wird, wurde die Wartbarkeit beim Hinzufügen eines Modus noch nicht verbessert. Erstellen Sie eine neue Factory-Klasse und lassen Sie sie verzweigen und generieren. Der Hauptprozess verwendet nur die BaseExporter-Unterklasse, in der export () vorhanden ist.

exporter_factory.py


class BaseExporterFactory(object):
    """Factory-Klasse der BaseExporter-Klasse"""
    def create(option):
        if option.mode == ExportMode.head:
            return HeadExporter()
        if option.mode == ExportMode.body:
            return BodyExporter()
        if option.mode == ExportMode.animation:
            return AnimExporter()

scene_exporter_v3.py


def scene_export(option):
    """Ausgabemodelle und Animationen in der Szene"""
    #Vorverarbeitung

    BaseExporterFactory().create(option).export()

    #Nachbearbeitung

Wenden Sie außerdem das Factory-Methodenmuster an

Wenn die Spezifikation hinzugefügt wird, erstellen und verwenden wir "ein Protokollobjekt innerhalb der BaseExporter-Klasse". Wenden Sie FactoryMethod an, da Sie Objekte in der BaseExporter-Klasse erstellen und verwenden.

Implementieren Sie das übergeordnete Element und die Unterklassen von ExporterLog, dem Produkt von FactoryMethod.

exporter_log.py


from abc import ABCMeta, abstractmethod


class BaseExporterLog(object):
    """Basisklasse des Exporterprotokolls"""
    __metaclass__ = ABCMeta

    @abstractmethod
    def open(self):
        """Starten Sie die Protokollierung"""
        pass

    @abstractmethod
    def close(self):
        """Protokollierung beenden"""
        pass


class MyExporterLog(BaseExporterLog):
    """Unterklasse des Exporterprotokolls"""
    def open(self):
        print "export logging start"

    def close(self):
        print "export logging close"

Definieren Sie die Protokollgenerierung und -verwendung in BaseExporter, dem Ersteller von FactoryMethod, und überlassen Sie die Implementierung Unterklassen.

exporter.py


from abc import ABCMeta, abstractmethod


class BaseExporter(object):
    """Exporter Grundklasse"""
    __metaclass__ = ABCMeta

    def export(self):
        self.log = create_exporter_log()
        self.log.open()

        select_export_targets()
        export_selection()

        self.log.close()

    @abstractmethod
    def create_exporter_log(self):
        """Generieren Sie ein Exportprotokoll"""
        pass

    @abstractmethod
    def select_export_targets(self):
        """Wählen Sie das Exportziel"""
        pass

    @abstractmethod
    def export_selection(self):
        """Exportieren Sie ausgewählte Objekte"""
        pass


class HeadExporter(BaseExporter):
    """Exporteurklasse für HEAD"""
    def create_exporter_log(self):
        return MyExporterLog()

    def select_export_targets(self):
        cmds.select("|char|mesh|head")

    def export_selection(self):
        #Implementierte Ausgabeverarbeitung für HEAD

Danach denke ich, dass es so sein kann, als würde man Protokolle auf der Hauptverarbeitungsseite verwenden.

scene_exporter_v4.py


def scene_export(option):
    """Ausgabemodelle und Animationen in der Szene"""
    #Vorverarbeitung

    exporter = BaseExporterFactory().create(option)
    exporter.export()

    #Gibt an, ob das Protokoll verarbeitet werden soll

    #Nachbearbeitung

** Eindruck **

Unabhängig davon, ob die Erkennung und die Beispiele angemessen sind, ist es etwas überzeugend, den Code nach der Musteranpassung zu betrachten. Wenn es nur die Menge an Code ist, ist der Basiscode der kleinste, aber da er später geändert wird, habe ich ein Muster verwendet Es ist effektiv, Zeit mit Refactoring zu verbringen.

Mit dem diesmal verwendeten Muster fällt es mir schwer, das Muster der Factory-Methode zu verstehen. Es fühlt sich an wie eine Ableitung des Factory-Musters aus dem Namen, aber ich habe erkannt, dass es sich um eine Ableitung der Vorlagenmethode handelt. Weil ich das dachte, brachte der Fluss der Musteranpassung auch zuerst die Vorlagenmethode.

Ich möchte weiter studieren und auf Ratschläge und Ratschläge aus verschiedenen Bereichen warten.

** Referenzseite **

Recommended Posts

Versuchen Sie es mit Designmustern (Exporter Edition)
Versuchen Sie es mit Tkinter
Versuchen Sie es mit Docker-Py
Versuchen Sie es mit einem Ausstecher
Versuchen Sie es mit PDFMiner
Versuchen Sie es mit Geopandas
Versuchen Sie es mit Selen
Versuchen Sie es mit scipy
Versuchen Sie es mit pandas.DataFrame
Versuchen Sie es mit Django-Swiftbrowser
Versuchen Sie es mit matplotlib
Versuchen Sie es mit tf.metrics
Versuchen Sie es mit PyODE
Versuchen Sie es mit virtualenv (virtualenvwrapper)
[Azure] Versuchen Sie, Azure-Funktionen zu verwenden
Versuchen Sie es jetzt mit virtualenv
Versuchen Sie es mit W & B.
Versuchen Sie es mit Django templates.html
[Kaggle] Versuchen Sie es mit LGBM
Versuchen Sie es mit dem Feed-Parser von Python.
Versuchen Sie es mit Pythons Tkinter
Versuchen Sie es mit Tweepy [Python2.7]
Versuchen Sie es mit Pytorchs collate_fn
Dezapata_0 Warum Designmuster lernen?
Versuchen Sie, PythonTex mit Texpad zu verwenden.
[Python] Versuchen Sie, Tkinters Leinwand zu verwenden
Versuchen Sie es mit Jupyters Docker-Image
Versuchen Sie es mit Scikit-Learn (1) - K-Clustering nach Durchschnittsmethode
Versuchen Sie die Funktionsoptimierung mit Hyperopt
Versuchen Sie es mit matplotlib mit PyCharm
Versuchen Sie es mit Azure Logic Apps
Versuchen Sie es mit Kubernetes Client -Python-
[Kaggle] Versuchen Sie es mit xg boost
Versuchen Sie es mit der Twitter-API
Versuchen Sie es mit OpenCV unter Windows
Versuchen Sie, Jupyter Notebook dynamisch zu verwenden
Versuchen Sie es mit AWS SageMaker Studio
Versuchen Sie, automatisch mit Selen zu twittern.
Versuchen Sie es mit SQLAlchemy + MySQL (Teil 1)
Versuchen Sie es mit der Twitter-API
Entwurfsmuster in Python: Einführung
Versuchen Sie es mit SQLAlchemy + MySQL (Teil 2)
Versuchen Sie es mit der Vorlagenfunktion von Django
Versuchen Sie es mit der PeeringDB 2.0-API
Versuchen Sie es mit der Entwurfsfunktion von Pelican
Versuchen Sie es mit pytest-Overview und Samples-
Versuchen Sie es mit Folium mit Anakonda