Как расширить ведение журнала без агрессивного изменения кода?[Написать чистый код] - PullRequest
0 голосов
/ 03 февраля 2019

Допустим, у меня есть метод calculate(), который усложнил вычисление со многими переменными, в то время как я хочу записать, каково значение переменных в другой фазе (РЕДАКТИРОВАТЬ: не только для проверки, но и для исследования данных).Например.

# These assignment are arbitrary, 
# but my calculate() method is more complex
def calculate(a, b):
  c = 2*a+b
  d = a-b
  if c > d+10:
    g = another_calc(a, c):
  else:
    g = another_calc(a, d):
  return c, d, g

def another_calc(a, c_d):
  e = a+c_d
  f = a*c_d
  g = e+f
  return g

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

# These assignment are arbitrary, 
# but my calculate() method is more complex
def calculate(a, b):
  info = {"a": a, "b": b}
  c = 2*a+b
  d = a-b
  info["c"], info["d"] = c, d
  if c > d+10:
    info["switch"] = "entered c"
    g, info = another_calc(a, c, info):
  else:
    info["switch"] = "entered d"
    g, info = another_calc(a, d, info):
  return c, d, g, info

def another_calc(a, c_d, info):
  e = a+c_d
  f = a*c_d
  g = e+f
  info["e"], info["f"], info["g"] = e, f, g
  return g, info

Это служит моей цели (я получил информационный объект, тогда он будет экспортирован какCSV для моего дальнейшего изучения) Но довольно уродливо добавлять больше (не функциональных) строк в исходный чистый метод calculate(), изменяя сигнатуру и возвращаемое значение.

Но могу ли я написать чищекод? Я думаю, можно ли использовать декоратор, чтобы обернуть этот метод.Надеюсь, у вас, ребята, будут отличные ответы.Спасибо.

1 Ответ

0 голосов
/ 04 февраля 2019

Один из способов написания более чистого кода (на мой взгляд) - это обернуть информационный словарь внутри класса.

Вот мой простой пример кода:

# These assignment are arbitrary, 
# but my calculate() method is more complex
def calculate(a, b, logger):
  logger.log("a", a)
  logger.log("b", b)

  c = 2*a+b
  d = a-b

  logger.log("c", c)
  logger.log("d", d)

  if c > d+10:
    logger.log("switch", "entered c")
    g = another_calc(a, c)
  else:
    logger.log("switch", "entered d")
    g = another_calc(a, d)

  return c, d, g

def another_calc(a, c_d, logger):
  e = a+c_d
  f = a*c_d
  g = e+f
  logger.log("e", e)
  logger.log("f", f)
  logger.log("g", g)
  return g

class Logger(object):

  data = []

  def log(self, key, value):
    self.data.append({key: value})

  def getLog(self):
    return self.data


logger = Logger()
print(calculate(4, 7, logger))
print(logger.getLog())

Плюсы и минусы

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

Кроме того, у вас есть способ выбрать способ печати данных или выбрать вывод.Возможно, у вас может быть интерфейс для Logger.

Я использовал словарь, потому что выглядело так, как будто вам просто нужны пары ключ-значение.

Теперь, используя регистратор, нам нужно изменить сигнатуру метода,Конечно, вы можете определить значение по умолчанию как None, например.Тогда значение None следует проверять постоянно, но именно поэтому я не определил значение по умолчанию.Если вы владеете кодом и можете изменить каждую ссылку для метода calculate(), тогда это не должно быть проблемой.

Есть еще одна интересная вещь, которая может быть важна позже.Когда вы отладили свой вывод и вам больше не нужно ничего регистрировать, тогда вы можете просто реализовать Нулевой объект .Используя Null object, вы можете просто удалить все записи, не меняя код снова.

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

...