Звучит довольно просто, я знаю, но недавно мой коллега сказал мне, что вызываемый метод startHttpServer
слишком сложен для понимания, потому что он запускает сервер, только если он еще не запущен. Я обнаруживаю, что попадаю в неприятности, когда отвечаю: «Серьезно? Я занимаюсь этим десятилетиями - это обычная практика в программировании» Чаще, чем я хочу признаться, он возвращается с некоторыми документальными свидетельствами, которые показывают, что все сообщество программистов отстает от его точки зрения, и я в конечном итоге чувствую себя застенчивым.
Вопрос : Есть ли документированный шаблон проектирования, стоящий за концепцией метода, который является запретным, если требуемое действие уже действует? Или, если не шаблон, у него тоже есть имя? И если нет, есть ли причина думать, что слишком сложно подумать о написании метода таким образом?
источник
startHttpServer
), и да, термин «идемпотент» применяется здесь Что ж.Ответы:
Как уже сказал Ник Уильямс : понятие, которое описывает ОП, называется идемпотентом (существительное Идемпотентность ). Это действительно обычная практика, особенно в API высокого уровня.
НО: переименуйте функцию.
Вместо того чтобы
startHttpServer
называть этоmakeSureHttpServerIsRunning
илиensureHttpServerIsRunning
.Когда вызывается функция
startHttpServer
, читатели ожидают, что она запустит HTTP-сервер; при вызове десять раз подряд у меня будет десять запущенных серверов. Ваша функция не делает это большую часть времени. Кроме того, имя «start» говорит о том, что если я хочу, чтобы работал только один сервер, мне нужно будет отслеживать, была ли функция уже вызвана или нет.Когда функция вызывается
makeSureHttpServerIsRunning
, я предполагаю, что она сделает все необходимое, чтобы убедиться, что HTTP-сервер работает, скорее всего, проверив, запущен ли он, и запустив его в противном случае. Я также предполагаю, что функция гарантирует, что сервер действительно работает (запуск сервера может занять некоторое время, когда он еще не работает).источник
Переименуйте его в
EnsureServerRunning
.Совершенно однозначно и ясно, что он гарантирует, что он работает (если это не так), не подразумевая перезапуск, если это так.
(Альтернатива
StartServerIfNotRunning
:?)источник
Не совсем шаблон дизайна, но я бы назвал ваш метод идемпотентным . Термин обычно используется для обозначения удаленных вызовов, но описание кажется совпадающим с тем, что вы делаете.
Побочным эффектом сервера здесь является то, что http-сервер запускается после вызова метода. Я не вижу ничего плохого в том, что метод делает это.
Если вам нужен шаблон проектирования, я думаю, вы могли бы представить свой httpServer как одиночный, который запускается при инициализации.
источник
Как тот , кто реализует этот инструмент ,
startHttpServer
вы должны пытаться сделать это самый простой, гладкой и бесшовные для использования ...Логика функции
Технически, расщеплением
startHttpServer
«s логики в 2 -х функций и называя их по отдельности , все , что вы делаете это перемещениеstartHttpServer
» s идемпотентность в код вызова обе функции вместо ... Кроме того, если вы не завернуть как логику в третьей функции (что делаетstartHttpServer
в первую очередь), это вынуждает вас писать незадействованный код, экспоненциально дублируя его везде, где вам нужно будет позвонитьstartHttpServer
. Короче говоря,startHttpServer
должна сама вызыватьisHttpServerRunning
функцию.Итак, моя точка зрения такова:
isHttpServerRunning
функцию, потому что это может понадобиться независимо в любом случае ...startHttpServer
используя его,isHttpServerRunning
чтобы определить его следующее действие соответственно ...Тем не менее, вы можете
startHttpServer
вернуть любое значение, которое может понадобиться пользователю этой функции, например:0
=> Ошибка запуска сервера1
=> Успешный запуск сервера2
=> сервер уже запущенНаименование функции
Прежде всего, какова основная цель пользователя? Чтобы запустить HTTP-сервер , верно?
По сути, нет проблем с намерением начать то, что уже началось, АКА
1*1=1
. Так что, по крайней мере для меня, называть это "ensureHttpServerIsRunning
", кажется, не является критически необходимым, я бы больше заботился о том, насколько длинным, естественным и запоминающимся является название функции.Теперь, если вы хотите узнать, как подробно работает функция под капотом, для этого есть документация или источник кода, я имею в виду, как и для любой другой функции из библиотеки / framework / API / etc ...
Вы изучаете функцию один раз, а пишете ее несколько раз ...
Так или иначе, я бы придерживался того,
startHttpServer
что короче, проще и понятнее, чемensureHttpServerIsRunning
.источник
Я полагаю, что ваш коллега имел в виду, что
startHttpServer
делает слишком много:Это две не связанные части кода. Например, похожая ситуация существует, когда настольное приложение должно гарантировать, что оно еще не запущено при запуске; будет часть кода, которая обрабатывает экземпляры приложения (например, с использованием мьютекса), и код, который запускает цикл сообщений приложения.
Это означает, что у вас должен быть не один, а как минимум… два метода :
isHttpServerRunning: boolean
startHttpServer
Точка входа в приложение вызовет первый метод, а затем второй, если возвращаемое значение равно
false
. Теперь каждый метод делает одно и то же, и его легко понять.¹ Если логика, необходимая для того, чтобы узнать, работает ли сервер, слишком сложна, может потребоваться дальнейшее разделение на несколько методов.
источник
startHttpServer
в коде указано более одного места? Нужно ли копировать несколько одинаковых строк везде? Должно ли это быть сделано со всеми функциями? Довольно скоро ваша программа будет бесконечного размера.startHttpServer
метода будет выглядеть примерно такif (isHttpServerRunning()){ return; }
. Вы утверждаете бизнес-правило, что «запуск http-сервера недействителен, если он уже запущен», но затем возлагаете на кого-то ответственность за соблюдение этого правила. Специально и неоднократно в каждом месте, где они могут позвонитьstartHttpServer
.Поскольку вы не указываете язык, во JavaScript многие библиотеки имеют функцию «один раз», например Underscore . Поэтому, если вам это знакомо, назовите его «один раз» и, возможно, переименуйте ваш метод.
Сам, исходя из Java, на ум приходят термины «кэширование» или «ленивая оценка». «Идемпотент» технически правильный и хороший выбор, особенно если у вас есть более функциональный фон.
источник
restartHttpServer()
метод. Но просто остановка - какой там вариант использования? Вам нравятся спорадические сбои соединения? :-)ensureRunning()
? :-) Что касается того, чтобы администратор остановил его, то, чтобы этот другой код постоянно перезапускался, пока администратор пытается что-то изменить или исправить, было бы невероятно раздражающим и неправильным. Пусть админ перезапустит это, а не код.Я бы предпочел
startHttpServerIfNotIsRunning
.Таким образом, условие четко упоминается уже в названии метода.
Ensure
илиmakeSure
кажется мне немного расплывчатым, поскольку это не техническое выражение. Похоже, мы не знаем точно, что произойдет.источник
Ensure
виду. Мне все еще не нравится это слово для технического выражения.Ensure
это что-то человеческое. Система не может ничего гарантировать, она только сделает то, что должна.Ваш коллега должен был сказать вам, что вы не имеете права писать этот метод. Это уже было написано много раз, и написано лучше, чем вы, вероятно, напишите это. Например: http://docs.ansible.com/ansible/latest/systemd_module.html https://docs.saltstack.com/en/latest/ref/states/all/salt.states.service.html
С точки зрения архитектуры, наличие некоторого произвольного кода, управляющего веб-сервером, является кошмаром. Если только управление службами не является исключительно тем, что делает ваш код. Но я предполагаю, что вы не написали monit (или kubernetes или ...).
источник
startServer
функции или подобного не является чем-то необычным , Это не значит, что вы напишете мельчайшие детали низкого уровня.