[PYTHON] Versuchen Sie auch bei der Konvertierung von CSV in Leerzeichenbegrenzer ernsthaft, Eingabe / Ausgabe und Regeln zu trennen

Einführung

Ich habe beschlossen, einen Prozess zu erstellen, der CSV von außen aufnimmt und in eine in meinem System verwendete Datei konvertiert.

Es war nicht so umfangreich, also wäre es schön gewesen, ein prozedurales Programm zu schreiben, aber ich hatte etwas Zeit übrig, also habe ich die Ebenen ernsthaft aufgeteilt.

Zu diesem Zeitpunkt möchte ich zusammen mit den Anforderungen des Musters schreiben, wie ich es gemacht habe.

Dieses Mal, einschließlich des Studiums, werde ich es mit Python 3.7 und Lambda schaffen.

Beispielcode

https://github.com/jnuank/io_logic_isolation

Bitte beziehen Sie sich auf [Final Separation Image](# Final Separation Image).

Voraussichtliche Anforderungen

Transaktionsdaten werden aus der von einem Filialisten verwendeten Registrierkasse entnommen, und die an jeder Registrierkasse jedes Geschäfts generierten Transaktionen werden in der CSV von Verkäufen aus anderen Systemen erfasst und in Daten konvertiert, die im eigenen System verwendet werden können. Zu diesem Zeitpunkt wird die CSV-Lesung dieses Mal nicht in das Leerzeichen-Trennzeichen konvertiert, sondern einige müssen in den Wert konvertiert werden, den das System hat.

Bild der CSV-Daten aus der Registrierkasse

Daten für jedes Geschäft und jede Registrierkasse für einen bestimmten Tag werden in einer Datei gesammelt.

Daten aus der Registrierkasse gesaugt


#Lesen von Änderungen in Abhängigkeit vom dritten Datensatztyp
# 01: 1:Speichern Sie den Code 2:Registrierkasse Nummer 3:Typschlüssel(01:Transaktionsheader) 4:Transaktionsnummer 5:YYYYMMDDHHMMSS
# 02: 1:Speichern Sie den Code 2:Registrierkasse Nummer 3:Typschlüssel(02:Transaktionsdetails) 4:Transaktionsnummer 5:Produktname 6:Stückpreis 7:Menge

"1","1","01","0000001", "20200816100000"
"1","1","02","0000001","Produkt A.","1000", "2"
"1","1","02","0000001","Produkt B.","500", "4"
"1","1","02","0000001","Produkt C.","100", "10"
"1","1","01","0000002", "20200816113010"
"1","1","02","0000002","Produkt D.","10000", "1"
"1","1","02","0000002","Produkt E.","2000", "1"
"1","2","01","0000001", "20200816102049"
"1","2","02","0000001","Produkt A.","1000", "3"
"1","2","02","0000001","Produkt D.","10000", "2"
"1","2","02","0000001","Produkt F.","500", "5"
"1","2","02","0000001","Produkt G.","4400", "2"
"2","1","01","0000001", "20200816152009"
"2","1","02","0000001","Produkt F.","500", "1"
"2","1","02","0000001","Produkt G.","4400", "1"

Bild der Daten nach dem Import

Monat speichern


# 1:Speichern Sie den Code 2:Verkaufsdatum(YYYYMM) 3:Verkaufszahlen
001 202008 500000
002 202008 300000
003 202008 900000

Bis zum Geschäftstag


# 1:Speichern Sie den Code 2:Verkaufsdatum(YYYYMMDD) 3:Verkaufszahlen
001 20200816 51300
002 20200816 4900

Speichern Sie tägliche Details


# 1:Speichern Sie den Code 2:Transaktionsnummer 3:Registrierkasse Nummer 4:Verkaufszeit(YYYYMMDDHHMMSS) 5:Verkaufszahlen
001 0000001 001 20200816100000  5000
001 0000002 001 20200816113010 12000
001 0000001 901 20200816102049 34300
002 0000001 001 20200816152009 4900

Bild des Modells der Daten nach der Erfassung

――Was möchten Sie aus den heruntergeladenen Daten wissen?

image.png

Grobes Bild von Lambda zum Konvertieren von CSV

Ich werde so ein Lambda machen.

image.png

Der unangenehme Teil dieser Konfiguration

Da es sich nur um eine Konvertierung handelt, fällt es mir leicht, in der Handler-Methode eine solide Logik zu schreiben, aber ich neige dazu, dies zu tun. In einem solchen Fall zwingen Sie die folgenden Ereignisse, die Logik zu ändern.

--Wenn sich die Struktur der CSV-Daten ändert --Wenn sich die Struktur der durch Leerzeichen getrennten Datei ändert ――Es handelt sich in erster Linie nicht um CSV, sondern nicht durch Leerzeichen

Es scheint, dass ** 2 Typen ** Änderungsanforderungen aufgrund von Änderungen in der Eingabe- / Ausgabedatenstruktur und Regeln wie Berechnungen möglich sind.

Insbesondere beim Empfang von Daten von einem anderen System wie dieser Zeit kann sich die Definition der Datenelemente von der anderen Partei verzögern oder es kann schwierig sein, Beispieldaten zu erhalten. Wenn die Entwicklung dort nicht fortgesetzt würde oder wenn sie mit den Spezifikationen durchgeführt würde, die ich mündlich gehört hatte, würde man sagen: "Eigentlich waren das alte Informationen, also ist es jetzt anders."

Fluss der Trennung

  1. Trennung von Lambda-Handler und Logik
  2. Trennung von Datenquelle und Logik
  3. Trennung der Konvertierungsregel von CSV zu Leerzeichen
  4. Trennung der CSV-Zuordnungsregeln

Trennung von Lambda-Ein- / Ausgang und Logik

Persönlich war ich nicht an Python gewöhnt, aber ich fing an, Tests zu schreiben.

Trennen Sie zu diesem Zeitpunkt den Lambda-Handler und die Logik.

image.png

Der Lambda-Handler empfängt eine ** Anfrage (Ereignis, Kontext) und gibt schließlich eine Antwort (HTTP-Status) ** zurück. Dies liegt in der Verantwortung der Lambda-Handler. Halten Sie daher die Konvertierungslogik von den Handlern fern. Extrahieren Sie die erforderlichen Parameter, übertragen Sie sie in die Logikklasse, empfangen Sie die Ergebnisse und nehmen Sie sie (falls erforderlich) in die Antwort auf.

handler.py


def import_handler(event, context):

    try:
        #Extrahieren Sie die erforderlichen Informationen aus dem Ereignis
        body_str = event['body']
        body = json.loads(body_str)
        key = body['key']
        bucket = os.environ['BUCKET_NAME']

        #CSV importieren → Durch Leerzeichen getrennt speichern
        trans_app = CsvToSpaceSeparateApplication(bucket, key)
        trans_app.csv_to_space_separate()

        dict_value = {'message': 'hochgeladen', }
        json_str = json.dumps(dict_value)

        return {
            'statusCode': 200,
            'body': json_str
        }

Gut zu trennen

Eigentlich war ich nicht an Python gewöhnt, also konnte ich einen Test schreiben und ausprobieren, wie man CSV liest und wie man in Raumbegrenzer konvertiert, also war es gut, hier zuerst zu trennen.

Konfiguration an dieser Stelle

https://github.com/jnuank/io_logic_isolation/commit/539b7d8bcdf8ca1b253b6185ab88f0b98806f8b4

Trennung von Datenquelle und Konvertierungslogik

Ich möchte die gelesene CSV nicht in Leerzeichen umwandeln, aber ich denke, dass einige Werte möglicherweise in die Werte des Systems konvertiert werden möchten.

Der Geschäftscode und die Registrierkassennummer des externen Systems sind die installierten Seriennummern. Innerhalb des Systems gibt es Unterschiede im Nummerierungssystem, beispielsweise die Tatsache, dass jede Ziffer eine Bedeutung hat.

Daher hätte ich gerne eine Tabelle zum Konvertieren, aber da der Datenspeicher noch nicht festgelegt wurde, denke ich, dass es Zeiten gibt, in denen ich eine temporäre Tabelle zum Testen verwende. Wenn Sie die Implementierungsdetails einer bestimmten Datenquelle (z. B. Herstellen einer Verbindung) in die Konvertierungslogik schreiben, müssen Sie diese ändern, wenn sich die Datenquelle ändert.

image.png

Um dies zu vermeiden und die Entscheidung über die Implementierungsdetails zu verzögern, bereiten Sie eine abstrakte Klasse vor, die erwartet, dass sie den Wert zurückgibt, den das System hat, nachdem sie den von CSV erhaltenen Wert vorerst übergeben hat.

Abstrakte Klasse zum Konvertieren von CSV-Werten in Systemwerte


from abc import ABCMeta, abstractmethod


class CodeRepositoryBase(object, metaclass=ABCMeta):
    """
Abstrakte Klasse zum Abrufen von Code aus dem Datenspeicher
    """

    @abstractmethod
    def get_shop_code(self, external_system_shop_code: str) -> str:
        """
Holen Sie sich den Geschäftscode
        :param external_system_shop_code:Speichern Sie den von einem externen System nummerierten Code
        :return:Geschäftscode
        """
        raise NotImplementedError()

    @abstractmethod
    def get_cash_register_code(self, external_system_shop_code: str, external_system_cash_register_code: str) -> str:
        """
Holen Sie sich eine Registrierkassennummer
        :param external_system_shop_code:Speichern Sie den von einem externen System nummerierten Code
        :param external_system_cash_register_code:Registriernummern, die von einem externen System vergeben wurden
        :return:Registriernummer
        """
        raise NotImplementedError()

Testen Sie das Repository mit Daten in dikt


from source.domain.repository.code_repository_base import CodeRepositoryBase


class InMemoryCodeRepository(CodeRepositoryBase):
    """
In-Memory-Repository-Implementierung
    """

    def __init__(self):
        # key:Externer Systemspeichercodewert:Geschäftscode
        self.__shop_code_table = {
            '1': '001',
            '2': '002',
            '3': '003'
        }
        # key:(Externer Systemspeichercode,Nummer der externen Systemkasse) value:Registriernummer
        #Die erste Ziffer der Registrierungsnummer ist "0".:Permanente Registrierkasse "9":Event-Registrierkasse
        self.__cash_register_code_table = {
            ('1', '1'): '001',
            ('1', '2'): '901',
            ('2', '1'): '001',
        }

    def get_shop_code(self, external_system_shop_code: str) -> str:
        """
Holen Sie sich den Geschäftscode
        :param external_system_shop_code:Speichern Sie den von einem externen System nummerierten Code
        :return:Geschäftscode
        """
        result = self.__shop_code_table.get(external_system_shop_code)
        if result is None:
            raise ValueError(f'Der dem angegebenen Schlüssel entsprechende Geschäftscode existiert nicht. Schlüssel:{external_system_shop_code}')

        return result

    def get_cash_register_code(self, external_system_shop_code: str, external_system_cash_register_code:str) -> str:
        """
Holen Sie sich eine Registrierkassennummer
        :param external_system_shop_code:Speichern Sie den von einem externen System nummerierten Code
        :param external_system_cash_register_code:Registriernummern, die von einem externen System vergeben wurden
        :return:Registriernummer
        """

        result = self.__cash_register_code_table.get((external_system_shop_code, external_system_cash_register_code))

        if result is None:
            raise ValueError(f'Die dem angegebenen Schlüssel entsprechende Registrierungsnummer existiert nicht. Schlüssel:{external_system_cash_register_code}')

        return result

Testcode


from pytest import raises

from tests.In_memory_code_repository import InMemoryCodeRepository


class TestInMemoryCodeRepository:

    def test_Der Geschäftscode 001 wird zurückgegeben(self):
        result = InMemoryCodeRepository().get_shop_code('1')

        assert result == '001'

Getrenntes Bild

image.png


Gut zu trennen

Im Gegenteil, was ich für problematisch hielt

――Da die Datenquelle festgelegt wurde, dauerte es länger als gewöhnlich, da erneut über die Details der Implementierung nachgedacht werden musste.

Konfiguration an dieser Stelle

https://github.com/jnuank/io_logic_isolation/commit/1c54107aafb72d3faee57b3ef85a5510f794deae

Trennung von CSV-Zuordnungsregeln

Eine Trennung war möglich, bis der Wert von CSV in den Wert des eigenen Systems umgewandelt wurde.

Basierend auf den folgenden CSV-Daten werden wir sie nun in einen durch Leerzeichen getrennten Wert konvertieren.

[Repost] Von der Registrierkasse gesammelte Daten


#Lesen von Änderungen in Abhängigkeit vom dritten Datensatztyp
# 01: 1:Speichern Sie den Code 2:Registrierkasse Nummer 3:Typschlüssel(01:Transaktionsheader) 4:Transaktionsnummer 5:YYYYMMDDHHMMSS
# 02: 1:Speichern Sie den Code 2:Registrierkasse Nummer 3:Typschlüssel(02:Transaktionsdetails) 4:Transaktionsnummer 5:Produktname 6:Stückpreis 7:Menge

"1","1","01","0000001","20200816100000"
"1","1","02","0000001","Produkt A.","1000","2"
"1","1","02","0000001","Produkt B.","500","4"
"1","1","02","0000001","Produkt C.","100","10"
"1","1","01","0000002","20200816113010"
"1","1","02","0000002","Produkt D.","10000","1"
"1","1","02","0000002","Produkt E.","2000","1"
"1","2","01","0000001","20200816102049"
"1","2","02","0000001","Produkt A.","1000","3"
"1","2","02","0000001","Produkt D.","10000","2"
"1","2","02","0000001","Produkt F.","500","5"
"1","2","02","0000001","Produkt G.","4400","2"
"2","1","01","0000001","20200816152009"
"2","1","02","0000001","Produkt F.","500","1"
"2","1","02","0000001","Produkt G.","4400","1"

Schreiben Sie die Zuordnung basierend auf dem Dokument des Tabellendefinitionselements. Ich habe es sehr grob geschrieben und es sieht so aus.

app.py




#Gibt eine Liste zurück, die gemäß der Elementdefinition basierend auf der übergebenen CSV zugeordnet ist
#Ändern Sie die Liste in ein Leerzeichen, das auf der Anruferseite begrenzt ist

@dataclass
class CsvToShopSales:
    code_respository: CodeRepositoryBase

    def csv_to_sales_by_shop(self, csv_list) -> List[List[str]]:
        names_list = list(range(10))
        df = pd.read_csv(csv_list, names=names_list, dtype='object').fillna('_')

        SHOP_COLUMN = 0
        #Nach Geschäftscode gruppieren
        shop_group_list = df.groupby(SHOP_COLUMN)

        results = []
        for group_rows in shop_group_list:
            shop_code = self.code_respository.get_shop_code(group_rows[0])
            year_month = [record[4] for record in group_rows[1].values.tolist() if record[2] == '01'][0][:6]
            amount_list = [int(record[5]) * int(record[6]) for record in group_rows[1].values.tolist() if record[2] == '02']
            sales_amount = sum(amount_list)

            results.append([shop_code, year_month, str(sales_amount)])

        return results

Was ich an diesem Code nicht mag

Unabhängig davon, welche Seite der Datenstruktur sich ändert, die Daten vor der Konvertierung oder die Daten nach der Konvertierung, halte ich es nicht für eine gute Idee, denselben Code zu ändern. Ich möchte nicht mehr als einen Grund haben, für eine Klasse zu wechseln.

image.png

Lassen Sie uns diese von app.py trennen. Unten ist ein Bild des Inhalts von app.py getrennt.

image.png

CSV empfangen und in CSV-Modell konvertieren

Repository zum Konvertieren von CSV in Modell


from abc import ABCMeta, abstractmethod
from typing import List

from source.domain.models.csv_models.csv_cash_transaction_header import CsvCashTransactionHeader


class CsvCashTransactionRepositoryBase(object, metaclass=ABCMeta):
    """
Repository abstrakte Klasse zum Empfangen von CSV-Registrierkassen-Transaktionsdaten
    """

    @abstractmethod
    def load(self) -> List[CsvCashTransactionHeader]:
        """
Holen Sie sich das Transaktionsdatenmodell für Registrierkassen
        :return:Datenmodell für Registrierkassen-Transaktionen
        """
        raise NotImplementedError()

    @abstractmethod
    def save(self, data: CsvCashTransactionHeader) -> None:
        """
Speichern Sie das Transaktionsdatenmodell der Registrierkasse
        :param data:Datenmodell für Registrierkassen-Transaktionen
        """
        raise NotImplementedError('Kann noch nicht speichern')

CSV-Modell


from __future__ import annotations

from dataclasses import dataclass, field
from typing import List

from source.domain.models.csv_models.csv_cash_transaction_detail import CsvCashTransactionDetail


@dataclass(frozen=True, order=True)
class CsvCashTransactionHeader:
    """
CSV-Modell der Registrierkassen-Transaktionsdaten
    """
    #Geschäftscode
    shop_code: str = field(compare=True)
    #Registriernummer
    cash_register_code: str = field(compare=True)
    #Übergangsnummer
    transaction_code: str = field(compare=True)
    #Handelszeit
    transaction_datetime: str = field(compare=True)
    #Transaktionsdetails
    transaction_details: List[CsvCashTransactionDetail]
from dataclasses import dataclass


@dataclass(frozen=True)
class CsvCashTransactionDetail:
    """
Details zu den Transaktionsdaten der Registrierkasse CSV-Modell
    """
    #Produktname
    item_name: str
    #Stückpreis
    unit_price: int
    #Menge
    quantity: int

Als Model sieht es so aus.

image.png

Erstellen Sie ein Domain-Modell für Verkäufe und Transaktionen

Erstellen Sie ein Domänenmodell wie unter [Bild des Datenmodells nach dem Import] beschrieben (# Bild des Datenmodells nach dem Import).

from dataclasses import dataclass, field
from functools import reduce
from operator import add
from typing import List

from source.domain.models.salses.daily_sales import DailySales


@dataclass(frozen=True)
class ShopMonthlySales:
    shop_code: str
    year_month: str
    daily_sales_list: List[DailySales] = field(default_factory=list, compare=False)

    def amount(self) -> int:
        return reduce(add, map(lambda data: data.amount(), self.daily_sales_list))

from dataclasses import dataclass, field
from datetime import datetime
from functools import reduce
from operator import add
from typing import List

from source.domain.models.salses.daily_sales_detail import DailySalesDetail


@dataclass(frozen=True)
class DailySales:
    sales_date: datetime.date
    details: List[DailySalesDetail] = field(default_factory=list, compare=False)

    def amount(self) -> int:
        return reduce(add, map(lambda data: data.amount, self.details))


import datetime
from dataclasses import dataclass


@dataclass(frozen=True)
class DailySalesDetail:
    transaction_code: str
    transaction_datetime: datetime.datetime
    cash_number: str
    amount: int

Implementierung von Konvertierungsregeln

Erstellen Sie eine Regelklasse, die ein CSV-Modell in ein Vertriebsdomänenmodell umwandelt.

@dataclass(frozen=True)
class TransferRules(object):
    """
Konvertierungsregelklasse
    """
    repository: CodeRepositoryBase

    def to_shop_sales(self, sources: List[CsvCashTransactionHeader]) -> List[ShopMonthlySales]:
        results: List[ShopMonthlySales] = []

        sources.sort(key=lambda x: x.shop_code)

        #Nach Geschäft gruppieren und in Modell konvertieren
        for key, g in groupby(sources, key=lambda x: x.shop_code):
            shop_code = self.repository.get_shop_code(key)

            details: List[DailySalesDetail] = []
            dt = ''
            day = ''
            year_month = ''
            for member in g:
                dt = datetime.strptime(member.transaction_datetime, '%Y%m%d%H%M%S')
                day = date(dt.year, dt.month, dt.day)
                year_month = member.transaction_datetime[:6]

                cash_register_code = self.repository.get_cash_register_code(member.shop_code, member.cash_register_code)
                amount = sum([s.unit_price * s.quantity for s in member.transaction_details])

                detail = DailySalesDetail(member.transaction_code,
                                          dt,
                                          cash_register_code,
                                          amount)

                details.append(detail)

            daily = DailySales(day, details)
            shop_sales = ShopMonthlySales(shop_code, year_month, [daily])

            results.append(shop_sales)

        return results

Domänenmodell → Durch Leerzeichen getrennt speichern

Erstellen Sie eine Klasse, die das Domänenmodell im Datenspeicher getrennt durch Leerzeichen speichert.

Dieses Mal erstellen wir eine Klasse, die in S3 gespeichert werden soll.

class S3ShopSalesRepository(ShopSalesRepositoryBase):
    """
Implementierung des In-Memory-Store-Verkaufsrepositorys
     """
    __bucket_name: str

    def __init__(self, bucket_name):
        self.__bucket_name = bucket_name

    def save(self, sources: List[ShopMonthlySales]) -> None:
        self.shop_monthly_sales = []
        self.daily_sales = []
        self.daily_details = []
        for source in sources:
            self.shop_monthly_sales.append(
                [source.shop_code, source.year_month, str(source.amount())]
            )
            for daily in source.daily_sales_list:
                self.daily_sales.append([
                    source.shop_code,
                    daily.sales_date.strftime('%Y%m%d'),
                    str(daily.amount()),
                ])

                for detail in daily.details:
                    self.daily_details.append(
                        [source.shop_code,
                         detail.transaction_code,
                         detail.cash_number,
                         detail.transaction_datetime.strftime('%Y%m%d%H%M%S'),
                         str(detail.amount)]
                    )

        self.shop_monthly_sales = self.__comma2dlist_to_space2dlist(self.shop_monthly_sales)
        self.daily_sales = self.__comma2dlist_to_space2dlist(self.daily_sales)
        self.daily_details = self.__comma2dlist_to_space2dlist(self.daily_details)

        try:
            self.__s3_upload(self.shop_monthly_sales, self.__bucket_name, 'Ladenverkäufe.txt')
            self.__s3_upload(self.daily_details, self.__bucket_name, 'Bis zum Geschäftstag.txt')
            self.__s3_upload(self.daily_details, self.__bucket_name, 'Speichern Sie tägliche Details.txt')
        except Exception as error:
            raise error

Der Prozess des Speicherns im Datenspeicher und des Konvertierens in Leerzeichen wird in dieser Klasse kombiniert. Der Grund dafür ist, dass es diesmal in einen durch Leerzeichen getrennten Speicher konvertiert wird. Bei der Konvertierung in einen anderen Datenspeicher kann es jedoch in ein anderes Format konvertiert werden, also in die Implementierungsklasse von "ShopSalesRepositoryBase" Ich überlasse es dir.

Handler und Anwendungsservice

handler.py


def import_handler(event, context):

    try:
        #Extrahieren Sie die erforderlichen Informationen aus dem Ereignis
        body_str = event['body']
        body = json.loads(body_str)
        key = body['key']
        bucket_name = os.environ['BUCKET_NAME']

        code_repository = InMemoryCodeRepository()
        csv_repository = S3CsvCashTransactionRepository(key, bucket_name)
        #Vorausgesetzt, dieser Eimer wurde bereits entschieden
        shop_sales_repository = S3ShopSalesRepository('xxxxx-bucket')

        #CSV importieren → Durch Leerzeichen getrennt speichern
        trans_app = CsvToSpaceSeparateApplication(code_repository, csv_repository, shop_sales_repository)
        trans_app.csv_to_space_separate()

        #Antwortmontage
        dict_value = {'message': 'hochgeladen', }
        json_str = json.dumps(dict_value)

        return {
            'statusCode': 200,
            'body': json_str
        }

    except ValueError as error:
        logger.exception(f'{error}')

        dict_value = {'message': f'{error}', }
        json_str = json.dumps(dict_value)

        return {
            'statusCode': 500,
            'body': json_str
        }
    except Exception as error:
        logger.exception(f'{error}')

        dict_value = {'message': f'Ein Verarbeitungsfehler ist aufgetreten. Bitte versuchen Sie es nach einer Weile erneut', }
        json_str = json.dumps(dict_value)

        return {
            'statusCode': 500,
            'body': json_str
        }

application


@dataclass
class CsvToSpaceSeparateApplication(object):
    """
CSV → Durch Leerzeichen getrennter Konvertierungsprozess
    """
    code_repository: CodeRepositoryBase
    csv_repository: CsvCashTransactionRepositoryBase
    shop_sales_repository: ShopSalesRepositoryBase

    def csv_to_space_separate(self) -> None:
        """
CSV → durch Leerzeichen getrennte Konvertierung
        """

        #In CSV-Modell konvertieren
        csv_models = self.csv_repository.load()

        #In Domänenmodell konvertieren
        shop_monthly_sales = TransferRules(self.code_repository).to_shop_sales(csv_models)

        #In Leerzeichen konvertieren und speichern
        self.shop_sales_repository.save(shop_monthly_sales)


Bild der endgültigen Trennung

Das vom Handler aufgerufene Bild in der CsvToSpaceSeparateApplication sieht folgendermaßen aus. Jede Prozedur "Ausgabe-> Konvertierung-> Ausgabe" wird durch die Methode in der Anwendungsschicht ausgedrückt.

Die Absicht jedes Prozesses wird auch durch Gruppieren in eine Klasse ausgedrückt.

image.png

Konfiguration an dieser Stelle

https://github.com/jnuank/io_logic_isolation/commit/b4e8885b2f269a608d0cfe3bfb414d4135277022

Ergebnis des Tuns

Ich habe versucht, eine ähnliche Konfiguration vor Ort zu üben.

――Da die Eingabe / Ausgabe und Konvertierung getrennt wurden und kurz vor der Veröffentlichung stehen, wurde ich darüber informiert, dass sich die CSV-Konfiguration von anderen Systemen ändern wird. --Erstellen Sie eine neue Klasse, die die abstrakte Klasse des Repositorys auf der CSV-Seite erbt, und DI sie von handler.py. ―― Eigentlich war die Regel des Domänenmodells nur die Berechnung des Gesamtbetrags, aber es wurde darüber gesprochen, ob die Berechnungsregel in der Mitte geändert werden könnte. ――Es kam nicht als Ergebnis, aber ich konnte zu diesem Zeitpunkt beurteilen, dass es nicht schwierig war, etwas hinzuzufügen, da ich nur die Logik des Berechnungsurteils getrennt habe.

Zusammenfassung

Es war ein kleiner Prozess, aber dieses Mal habe ich versucht, die Eingabe- / Ausgabe- und Berechnungs- / Beurteilungsregeln zu trennen, und ich hatte das Gefühl, dass dies für den Aufbau eines großen Systems in der Zukunft nützlich sein würde. Es scheint, dass es Gespräche über Kosteneffizienz geben wird, aber wenn ich etwas Zeit habe, würde ich gerne versuchen, mich dessen regelmäßig bewusst zu werden. (Natürlich ist dies bei dem Code, den Sie wegwerfen möchten, nicht der Fall, aber meistens nicht ...)

Referenziert

Recommended Posts

Versuchen Sie auch bei der Konvertierung von CSV in Leerzeichenbegrenzer ernsthaft, Eingabe / Ausgabe und Regeln zu trennen
Verschrotten Sie die Liste der Go To EAT-Mitgliedsgeschäfte in der Präfektur Fukuoka und konvertieren Sie sie in CSV
Verschrotten Sie die Liste der Go To EAT-Mitgliedsspeicher in der Präfektur Niigata und konvertieren Sie sie in CSV
Versuchen Sie, den Hintergrund und das sich bewegende Objekt des Videos mit OpenCV zu trennen
So geben Sie mit Jupyter Notebook einen Wert in der Mitte einer Zelle aus
So zählen Sie die Anzahl der Elemente in Django und geben sie in die Vorlage aus
Geben Sie "Farn programmgesteuert zeichnen" in den Zeichenprozess in Python ein
Koordination jedes Prozesses im MPI und Pufferung der Standardausgabe
Lernen Sie Buchhaltungsdaten kennen und versuchen Sie, Konten aus dem Inhalt der Beschreibung vorherzusagen, wenn Sie Journale eingeben
[Python] Die Rolle des Sterns vor der Variablen. Teilen Sie den Eingabewert und weisen Sie ihn einer Variablen zu
Geben Sie den Inhalt von ~ .xlsx im Ordner mit Python in HTML aus
Versuchen Sie, die kumulierte Rendite des Rollovers im Futures-Handel zu modellieren
Eingabe / Ausgabe von Werten aus der Standardeingabe in der Wettbewerbsprogrammierung usw.
[Python] Was tun, wenn beim Importieren aus dem zu sys.path hinzugefügten Verzeichnis gegen PEP8 verstoßen wird?
[Abgeschlossene Version] Versuchen Sie, die Anzahl der Einwohner der Stadt anhand der Adressliste mit Python herauszufinden
So geben Sie eine Zeichenfolge in Python ein und geben sie unverändert oder in die entgegengesetzte Richtung aus.