#php #архитектура #инспекция_кода
Проблема
Есть задача при использовании switch у разных case выполнять еще и код из default
(или например final реализовать), что бы не дублировать одинаковый код в разных кейсах.
switch ("b") {
case 'a':
case 'z':
case 'q':
echo "a\n"; // not need run default action
break;
case 'b':
echo "b\n"; // need run default case without case 'c'
break;
case 'c':
echo "c\n";
default:
echo "default"; // need run for "b" & "c" cases
}
Выводит:
b
А хотелось бы:
b
default
Если убрать break у варианта b, то будет выполнен лишний код
b
c
default
Есть решение через goto, что является плохим стилем кодирования:
switch ("b") {
case 'a':
echo "a\n";
break;
case 'b':
echo "b\n";
goto caseFinal;
break;
case 'c':
echo "c\n";
goto caseFinal;
break;
default:
caseFinal:
echo "default";
}
Полная задача
Есть массив полей разных сущностей и нужно разные действия у разных полей сделать.
switch ($fieldName) {
case 'id': // не нужно default
unset($properties['actions']['create']);
unset($properties['actions']['edit']);
break;
case 'content':
// одинаковый код нужно вынести в defaut
unset($properties['actions']['dashboard']);
// ...
break;
case 'isDeleted':
// одинаковый код нужно вынести в defaut
unset($properties['actions']['dashboard']);
// ...
break;
default:
// код нужне для всех остальных полей + кейсы выше
unset($properties['actions']['dashboard']);
}
Вопрос
Как это сделать без использования goto? Может есть вариант с другим подходом в архитектуре.
P.S. Если goto здесь уместен (лично я не боюсь динозавров), то почему это плохой
стиль кодирования?
Ответы
Ответ 1
Зачем усложнять? Можно вынести повторяющийся код в функцию/метод класса и вызывать их из каждого кейса. Кода получится ровно столько же, зато goto мы не используем и код остаётся читаемый и легко поддерживаемый: function someAction() { //some code } switch ($fieldName) { case 'id': unset($properties['actions']['create']); unset($properties['actions']['edit']); break; case 'content': someAction(); unset($properties['actions']['dashboard']); // ... break; case 'isDeleted': someAction(); unset($properties['actions']['dashboard']); // ... break; default: someAction(); unset($properties['actions']['dashboard']); }Ответ 2
Если только одно действие не должно быть продолжено default, почему бы не попробовать вынести default действие за switch и огородить if ($fieldName != 'id') { unset($properties['actions']['dashboard']); }Ответ 3
Можно оформить условия как отдельные функции (методы). Ключевая функция. Получает действие на входе и выполняет соответствующую функцию: function make($action) { if ($action()) $default(); return; } Собственно действия. Возвращают true или false как маркеры необходимости выполнять действие по умолчанию. function a() { echo "a\n"; return false; // дефолтное действие выполнять не нужно } function b() { echo "b\n"; return true; // дефолтное действие выполнить нужно } Функция (метод) для действия по умолчанию: function default() { echo 'default'; return; } Используем: make('a');Ответ 4
После изучения ответов, статей и умозрительных эксперементов, пришел к выводу. Вывод В данном случае использование goto допустимо, пока не будет добавлена подобная конструкция в синтаксис switch и если соблюдаются условия: Ты уже не Junior Переходить можно только вперёд Заходить в блоки и выходить категорически нельзя Любой while и вложенные if так же опасны как goto. Для выхода из множественных циклов есть break N. Плюсы которые я вижу Краткость и простота кода при соблюдении вышеописанных условиях Меньше занимаемой памяти и скорее всего быстрота выполнения Лучше "плохой тон", чем много избыточного кода, который сложнее поддерживать Для себя я решил использовать только в группах исключающих условий: switch ("b") { case 'a': echo "a\n"; break; case 'b': echo "b\n"; goto caseFinal; break; case 'c': echo "c\n"; goto caseFinal; break; default: caseFinal: echo "default"; } Конечно при усложнении логики и увеличении строк кода, лучше всего воспользоваться ответом n4nn31355 и выносить в классы и отдельные методы, но внутри у них все равно наверно будет что-то похожее ;) Интересные статьи на эту тему: Запретный плод GOTO сладок GOTO or not GOTO вот в чём вопросОтвет 5
Усугубим goto ... if (b == 'a') { echo "a\n"; goto done; } else if (b == 'b') { echo "b\n"; goto default; } else if (b == 'c') { echo "c\n"; goto default; } default: echo "default"; done: ... И кто скажет что это отвратительно - тот просто ничего не сечёт в программировании:)
Комментариев нет:
Отправить комментарий