Рубрики
Без рубрики

Нулевая котельная, нулевые ошибки времени выполнения: Кодирование с монадами

Примечание. Этот пост будет обновлен со временем API Backend Programming может быть стрессовым и повторяющимся. F … с меткой Django, Python, WebDev, Haskell.

Примечание: Этот пост будет обновлен со временем

API Backend Programming может быть стрессовым и повторяющимся. В течение последнего года, повторную повторную факторину и переписали более 10 тысяч линий рекордного кодекса, я понял важность после правильной структуры/дисциплины во время кодирования Backeng API. К счастью, концепция Монадическое программирование уже существовало на языках, таких как haskell и angularjs.

Этот пост покажет вам шаблон для реализации кодирующей дисциплины, такой как Monads в Python, которая в случае последующей необходимости позволит вам иметь нулевые проблемы выполнения и минимальную к нему никакой бойной таблички в вашем коде. Для меня это помогло мне уменьшить мою тому объема бэкэнда до 1/3 его размера, усиливая регистрацию и стабильность, добавленные задержки с нулевым характеристиками.

Создать монадский класс Монады являются чистыми функциями. Это неявно означает, что тип ввода, который он принимает и тип вывода, он производит, будет одинаковым. В этом случае это состояние – это Dict {}. Это также означает, что у вас не может быть исключения или нет типа возврата в ваших функциях.

Наш монадский класс определен, чтобы иметь: государство : Это текущее состояние, которое мы имеем в нашем монаде, который представляет данные, которые мы в настоящее время обрабатываем. Это также аргумент, который мы переходим к функциям в монаде. Мы создаем класс MondaiC, который занимается наклонным в качестве первоначального состояния. Для API Backend Code это состояние может быть вашим параметрам запроса. Подумайте об этом, как будто вы передаете одни и те же переменные в функции, только что они обернуты в дикт, а имена переменных являются ключами в диктоме.

FNS : Он имеет список функций, которые являются указателями функции для выполнения функций для выполнения в порядке. Например, вы можете разработать ваш поток Sign_up AS: [process_request_params, check_username_password, create_token, etter_session]

.Execute позвонит эти функции в контуре до достижения конечного состояния. Заключительное состояние должно эффективно быть вашим выходом ответа. Вот что похоже на поток из одного состояния в другое состояние

EFN : Предположим, ваш код ломается между функцией в трубопроводе. Функция ошибки EFN Обрабатывают текущее состояние монады и выпустите ошибку, поскольку вам требуется в ответ. Это сохраняет вас от получения 500 ошибок сервера от Backend.

Наш монадический код опирается на параметр «Статус» в состоянии CONTIC, чтобы получить «Ошибка» отчетов в разделе «Функции».

class MaybeErrorMonad(object):

    def __init__(self, state, fns, efn):

        self.state = state  # current state (dict) in monadic pipeline
        self.fns = fns      # a list of functions in order of execution
        self.error_fn = efn # error function that reports any error, based on self.state
        self.finish = False # a flag to indicate that the self.state is final state

    def value(self):
        return self.state

    def execute(self):
        # a wrapper class that does execution of functions on current self.state in order
        def _fun():
            if self.finish:
                return self.state
            computation = self.state
            for i in self.fns:
                computation = i(computation)
                if computation.get("status") == "error":
                    return self.error_fn(computation)
            self.state = computation
            self.finish = True
            return self.state

        return _fun()

Далее мы определяем некоторые функции для тестирования нашего монады. Я добавил ошибку_handler_wrapper Функция обертки Который гарантирует, что наши функции всегда возвращают правильный ответ в Dict, если что-то сломается в середине. Вы можете разработать эту функцию, чтобы включить журналы с именем функции и аргументами с текущими параметрами для лучшего отладки в производстве. Мы также определяем нашу функцию настраиваемой ошибки для вывода нашей ошибки, когда мы получаем статус ошибки Midway.

def err_handler_wrapper(fun):
    # a error handler wrapper function to report any execution errors in dict
    def wrapper(*args):
        try:
            state = fun(*args)
        except:
            return {"status": "error", "reason": "Girlfriend not found"}
        return state
    return wrapper

def efn(state):
    return {"status": "Rejected :'(", "reason":state.get('reason') }

@err_handler_wrapper
def get_flowers(state):
    print "got flowers for %s"%state['girlfriend']
    state.update({"flowers": True})
    return state

@err_handler_wrapper
def get_chocolates(state):
    print "got chocolates for %s"%state['girlfriend']
    state.update({"chocolates": True})
    return state

@err_handler_wrapper
def propose(state):
    if state.get('flowers') and state.get('chocolates'):
        return {"status": "Success! she said yes"}
    return {"status": "she said no"}

Давайте запустим наш пример, где парень пытается предложить его раздавить. Если он покупает просто цветы, он будет отклонен. Если он покупает шоколад и цветы, он принимается. Если в исходном состоянии нет «подруги», не ошибка.

# CASE 1
to_do = [get_flowers ,get_chocolates, propose]
initial_state = {'girlfriend': 'Alice'}
executor = MaybeErrorMonad(initial_state, to_do, efn)
result = executor.execute()
print "CASE 1: %s \n"%str(result)

 #CASE 2
initial_state = {} # no girlfriend
executor = MaybeErrorMonad(initial_state, to_do, efn)
result = executor.execute()
print "CASE 2: %s \n"%str(result)

# CASE 3
to_do = [get_flowers, propose] # rejection beacuse of not enough efforts :P
initial_state = {'girlfriend': 'Alice'}
executor = MaybeErrorMonad(initial_state, to_do, efn)
result = executor.execute()
print "CASE 3: %s \n"%str(result)

И … Вот наш выход, как и ожидалось.

Это был довольно простой пример. Представьте себе мощность теперь возможность выполнять огромные функции в простой списке последовательных Todo с минимальным ветвлением. ПОПРОБУЙ ЭТО СЕЙЧАС !!!

В следующем обновлении мы узнаем, как структурировать наши данные Dict и как спрашивать исключения и получать параметры из правильного контекста выполнения.

Для получения дополнительных представлений об устранении котельной, прочитайте это: HyperCubed !!

Узнайте больше о монаде здесь: – Монадическое программирование Монадс В Python: Пимонад

Оригинал: “https://dev.to/javalin/zero-boilerplate-zero-runtime-errors-coding-with-monads-26n9”