2016-02-16 4 views
0

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

def func1(*pars, **kwargs): 
    be = Backend(...) 
    result = be.do_something(...) 
    result = adapt(result) 
    ... 
    return result 

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

def func1(config, *pars, **kwargs): 
    be = Backend(config, ...) 
    result = be.do_something(...) 
    result = adapt(result) 
    ... 
    return result 

мне нужно было бы изменить все функции в моем интерфейсе, чтобы принять и передать этот новый параметр config. У вас есть лучшее предложение о том, как продолжить рефакторинга, так что:

  • минимизирует изменения
  • упрощаются будущих рефакторинга, где больше параметров может потребоваться внутреннего интерфейса

В В общем, есть ли у вас указания относительно того, как обеспечить чистые функциональные интерфейсы в python?

+1

«Конфиг» используется только 'Backend'? Является ли 'Backend' зависимым от других параметров? Если да и нет, добавьте бэкэнд вместо конфигурации. – poke

+0

@poke: Это интересная идея, но я неохотно подталкиваю зависимость «Backend» к верхнему уровню: мой слой django использует «интерфейс», который * внутренне * используется с помощью «Backend». – dangonfast

ответ

0

Ну, я думаю, вам нужно будет обновлять каждую из ваших функций независимо, но вы можете сделать это так, чтобы облегчить будущие обновления. Рассмотрю следующий декоратор:

def backend_wrapper(function): 
    def _wrapper(arg1, arg2, arg3, *pargs, **kwargs): 
     backend_args = (arg1, arg2, arg3) 
     return function(backend_args, *pargs, **kwargs) 
    return _wrapper 

Если обновить все функции используйте этот декоратор и принять новый позиционный аргумент backend_args, то вы можете применить все будущие обновления только декоратор.

class Backend: 
    def __init__(self, *args): 
     print 'Backend args: {}'.format(args) 

@backend_wrapper 
def func1(backend_args, *pargs, **kwargs): 
    be = Backend(*backend_args) 
    print 'Positional args: {}'.format(pargs) 
    print 'Keyword args: {}'.format(kwargs) 

func1('arg1', 'arg2', 'arg3', 'parg1', kwarg1='kwarg1') 
# Backend args: ('arg1', 'arg2', 'arg3') 
# Positional args: ('parg1',) 
# Keyword args: {'kwarg1': 'kwarg1'} 

Итак, теперь, если мы изменим декоратор быть:

def backend_wrapper(function): 
    def _wrapper(arg1, *pargs, **kwargs): 
     backend_args = (arg1,) 
     return function(backend_args, *pargs, **kwargs) 
    return _wrapper 

Затем func1 будет по-прежнему работать, как задумано.

func1('arg1', 'parg1', kwarg1='kwarg1') 
# Backend args: ('arg1',) 
# Positional args: ('parg1',) 
# Keyword args: {'kwarg1': 'kwarg1'} 

Эта проблема здесь в том, что вы все еще будете нуждаться, чтобы обновить вызовы функций перейти в новые параметры, а также. Если вы не можете сделать глобальные переменные backend_args, я не вижу способа обойти это. Однако, если это так, то вы можете использовать что-то вроде:

class Backend: 
    def __init__(self, *args): 
     print 'Backend args: {}'.format(args) 

def backendFactory(*backend_args): 
    def _wrapper(): 
     return Backend(*backend_args) 
    return _wrapper 

def func1(*pargs, **kwargs): 
    be = BackendFactory() 
    print 'Positional args: {}'.format(pargs) 
    print 'Keyword args: {}'.format(kwargs) 

BackendFactory = backendFactory('arg1', 'arg2', 'arg3') 
func1('parg1', kwarg1='kwarg1') 
# Backend args: ('arg1', 'arg2', 'arg3') 
# Positional args: ('parg1',) 
# Keyword args: {'kwarg1': 'kwarg1'} 

Это создает глобальную переменную BackendFactory, которая действует аналогично классу, за исключением того, что он хранит переменные Инстанцирование. Обратите внимание, что это грязно и опасно, потому что он отвечает на то, что вы определяете глобальную переменную, которая затем используется в ваших функциях.

Смежные вопросы