У меня есть некоторые необработанные данные, которые мне нужно сделать много (чтобы сдвинуть, повернуть, масштабировать по определенной оси, повернуть к конечной позиции), и я не уверен, что лучший способ сделать это для поддержания читабельности кода. С одной стороны, я могу сделать один метод со многими параметрами (10+), чтобы сделать то, что мне нужно, но это кошмар чтения кода. С другой стороны, я мог бы создать несколько методов с 1-3 параметрами каждый, но эти методы нужно было бы вызывать в очень конкретном порядке, чтобы получить правильный результат. Я читал, что для методов лучше всего делать одну вещь и делать это хорошо, но кажется, что наличие множества методов, которые необходимо вызывать для того, чтобы открыть код для трудно обнаруживаемых ошибок.
Существует ли парадигма программирования, которую я мог бы использовать, чтобы минимизировать количество ошибок и сделать код легче для чтения?
источник
Ответы:
Остерегайтесь временной связи . Однако это не всегда проблема.
Если вы должны выполнить шаги по порядку, из этого следует, что шаг 1 создает некоторый объект, необходимый для шага 2 (например, поток файлов или другую структуру данных). Это само по себе требует, чтобы вторая функция вызывалась после первой, даже невозможно случайно вызвать их в неправильном порядке.
Разделив вашу функциональность на куски размером с кусочек, каждую часть легче понять и, безусловно, легче тестировать отдельно. Если у вас есть огромная функция из 100 строк и что-то посередине, как ваш проваленный тест скажет вам, что не так? Если один из ваших пятистрочных методов ломается, ваш неудачный модульный тест немедленно направляет вас к одному куску кода, который требует внимания.
Вот как должен выглядеть сложный код :
В любой момент в процессе преобразования необработанных данных в готовый виджет каждая функция возвращает что-то необходимое для следующего шага процесса. Из шлака нельзя образовать сплав, нужно сначала его расплавить (очистить). Нельзя создать виджет без надлежащего разрешения (например, стали) в качестве входных данных.
Конкретные детали каждого шага содержатся в отдельных функциях, которые можно протестировать: вместо модульного тестирования всего процесса добычи горных пород и создания виджетов, тестируйте каждый конкретный шаг. Теперь у вас есть простой способ убедиться, что в случае сбоя процесса создания виджета вы сможете сузить конкретную причину.
Помимо преимуществ тестирования и проверки правильности, написание кода таким способом намного проще для чтения. Никто не может понять огромный список параметров . Разбейте его на мелкие кусочки и покажите, что означает каждый маленький кусочек: его можно уловить .
источник
Аргумент «должен быть выполнен по порядку» является спорным, поскольку практически весь ваш код должен выполняться в правильном порядке. В конце концов, вы не можете записать в файл, затем открыть его, а затем закрыть его, не так ли?
Вы должны сконцентрироваться на том, что делает ваш код наиболее удобным для сопровождения. Обычно это означает написание небольших функций, которые легко понять. Каждая функция должна иметь единственную цель и не иметь побочных эффектов, которые могут быть непредвиденными.
источник
Я бы создал » ImageProcesssor « (или любое другое имя, подходящее для вашего проекта) и объект конфигурации ProcessConfiguration , который содержит все необходимые параметры.
Внутри процессора изображений вы инкапсулируете весь процесс за один метод
process()
Этот метод вызывает трансформационные методы в правильном порядке
shift()
,rotate()
. Каждый метод получает соответствующие параметры из переданной ProcessConfiguration .Я использовал жидкие интерфейсы
что позволяет изящную инициализацию (как видно выше).
Очевидное преимущество, заключающее в себе необходимые параметры в одном объекте. Подписи вашего метода становятся читабельными:
private void shift(Image i, ProcessConfiguration c)
Речь идет о сдвигая в изображения и подробные параметры, так или иначе настроены .
В качестве альтернативы, вы можете создать ProcessingPipeline :
Вызов метода для
processImage
создания экземпляра такого конвейера и делает прозрачным, что и в каком порядке выполняется: сдвиг , поворотисточник
Вы рассматривали возможность использования какого-либо карри ? Представьте, что у вас есть класс
Processee
и классProcessor
:Теперь вы можете заменить класс
Processor
двумя классамиProcessor1
иProcessor2
:Затем вы можете вызвать операции в правильном порядке, используя:
Вы можете применить этот шаблон несколько раз, если у вас более двух параметров. Вы также можете группировать аргументы так, как хотите, то есть вам не нужно, чтобы каждый
process
метод принимал ровно один аргумент.источник