Как я должен рефакторинг кусок кода, который присутствует во многих различных функциях, но имеет оператор возврата в нем - PullRequest
0 голосов
/ 15 декабря 2010

Фрагмент кода взят из кода представления django, но это не имеет большого значения.

Допустим, у меня есть следующий фрагмент кода ...

def unsubscribe(request):
  #start of block
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    return ajax_response(False, [('subscription', 'Given subscription does not exist.')])
  if sub.user != user:
    return ajax_response(False, [('subscription', 'Invalid permission.')])
  #end of block.
  sub.is_active = False
  sub.save()
  return ajax_response(True)

и произнеситеУ меня есть другая функция resubscribe(), которая делает то же самое, что и вышеприведенная функция, за исключением того, что она sub.is_active = True.

. В таком случае, какой будет лучший способ организовать код, чтобы код между#block и #endblock не дублируются?Я думаю, в общем, этот вопрос можно записать так:

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

РЕДАКТИРОВАТЬ: исправлен фрагмент кода.

РЕДАКТИРОВАТЬ2: На самом деле, простой способ решить этот вопросэто создание функции, скажем, toggle_active_status, которая принимает request и логическое значение.(Я понял это после публикации вопроса).

Тем не менее, меня интересует случай, когда различная логика между функциями составляет более 1 строки ... как, скажем, код между #blockи #endlbock выполняет только проверку входных данных, и потенциально любая произвольная логика приложения может последовать.

Ответы [ 3 ]

3 голосов
/ 15 декабря 2010

Вычтите дублированный кусок и передайте разницу, создав функции-оболочки, которые передадут разницу:

def alter_subscription(request, make_active):
  # start of block
  # (...)
  # end of block
  sub.is_active = make_active
  sub.save()
  return ajax_response(True)

def unsubscribe(request):
  return alter_subscription(request, False)

def resubscribe(request):
  return alter_subscription(request, True)
1 голос
/ 15 декабря 2010

Пара вариантов, которые еще не были показаны:

Поскольку это процедура проверки, используйте исключения, чтобы указать на сбой, и нормальное значение None (игнорируется), чтобы указать на успех:

def verify_permissions(request):
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    raise PermissionError, 'Given subscription does not exist.'
  if sub.user != user:
    raise PermissionError, 'Invalid permission.'

def subscribe(request):
  try:
    verify_permissions(request)
    sub.save()
    return ajax_response(True)
  except PermissionError, why:
    return ajax_response(False, [('subscription', why)])

Или, поскольку Python динамически типизирован и, по-видимому, нормально вызывать ajax_response несколькими способами: вернуть аргументы, использованные для построения ответа, и проверить значение первого.

def verify_permissions(request, purpose):
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    return (False, [(purpose, 'Given subscription does not exist.')]) 
  if sub.user != user:
    return (False, [(purpose, 'Invalid permission.')])
  return (True,)

def subscribe(request):
  result = verify_permissions(request, 'subscription')
  if result[0]: sub.save()
  return ajax_response(*result)
1 голос
/ 15 декабря 2010

Один из способов - просто создать отдельную функцию, содержащую дублирующиеся функции.Вы можете использовать параметры функции, чтобы ввести необходимые различия.

Если фрагмент кода возвращает что-то, вы можете использовать соглашение, например, возвращать None, если функция не должна возвращаться, иливозразить иначе.В вашей функции вызывающей стороны просто проверьте, является ли возвращенный параметр None или нет, и верните возвращенную переменную, если она не None.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...