ООП и твердотельная альтернатива жесткому кодированию - PullRequest
0 голосов
/ 06 октября 2019

Мне нужно провести рефакторинг этого кода, так как с точки зрения SOLID это не очень хорошая практика (не расширяемая), какие есть альтернативы?

У меня есть текстовый файл, из которого я читаю команды,его формат выглядит следующим образом:

ADD_CHILD name1 name2 пол

GET_RELATIONSHIP отношение name1 ..

Мне кажется, что проблема в том, что когда я передаю слова потому что, если формат текстового файла изменится, мой код сломается. Одна вещь, которая приходит на ум, это использование операторов if-elif, но они не рекомендуются по принципу открытого-закрытого. Каковы другие возможные подходы?

    path_str=input("Enter the path of input file ")
    fileinput=open(path_str,"r")
    for line in fileinput:
        words=line.split()
        function=set1solution.function_select_map.get(words[0])
        result=function(family,words)

    function_select_map={
        "ADD_CHILD":add_child,
        "GET_RELATIONSHIP":get_relationship
    }

    relation_map={
        "Paternal-Uncle":Family.get_Paternal_Uncle,
         ......}

    def add_child(family,words):
        #find person just returns an object of person class
        parent=family.find_person(words[1])
        new_addition=Person(words[2],words[3],words[1])
 result=family.add_external_child(words[1],new_addition.name,new_addition.gender)
        return result

    def get_relationship(family,words):
        person=family.find_person(words[1])
        function=set1solution.relation_map.get(words[2])
        result=function(family,person)
        return result

1 Ответ

0 голосов
/ 06 октября 2019

Как вы правильно заметили, ваш код зависит от формата файла, который не рекомендуется. add_child и get_relationship не должны знать о формате файла, поэтому в вашем коде должен быть следующий поток данных:

File => File parser => app logic

Анализатор файлов - это своего рода посредник между данными в файле и вашим кодом. Есть несколько возможных способов добиться этого, вот часть одного короткого решения (с моими комментариями):

def add_child_parser(words):
    return add_child, (family, words[0], words[1], words[2])  # return params for add_child function in correct order, not that it's not obvious from your code where family come from

def command_parser(line):
    d = {
        "ADD_CHILD": add_child_parser,
        "GET_RELATIONSHIP": get_relationship_parser
    }  # dict with all availbale command parsers
    words = line.split()
    curr_parser = d[words[0]]  # get parser for current command
    func, args_list = curr_parser(words[1:])  # call parser for current command with other words as params
    func(*args_list)  # call returned function

def file_parser(file_path):
    file_input = open(file_path, "r")
    for line in file_input:
        command_parser(line)  # process each line

def add_child(family, parent_name, child_name, child_gender):  # note, we receive all required data in params, not as single string
    parent = family.find_person(parent_name)
    new_child = Person(child_name, child_gender, parent_name)

    return family.add_external_child(new_child)
...