#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: ... И кто скажет что это отвратительно - тот просто ничего не сечёт в программировании:)
Комментариев нет:
Отправить комментарий