Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Java: Общие вопросы > Множественные вложенные IF-ы |
Автор: _Y_ 5.8.2012, 16:33 |
Вопрос по правильному кодописанию. Столкнулся с такой задачей. Имеется множество ветвящихся условий. То-есть многоуровневая система IF-ов вложенных друг в друга. Код, естественно, совершенно нечитаем. Вопрос естественный - что же делать? Как код написать "красиво"? Кто как делает? Сам я пока придумал только одно улучшение. Писать множество вложенных приватных методов с осмысленными названиями. В каждом - один IF с обращением в двух ветвях к двум следующим методам. Но проблема в том, что, с одной стороны, не всегда такому вложенному методу можно дать осмысленное название, с другой, все время приходится пеедавать чертову уйму параметров. Да и вообще не бог весть какое хорошее решение. |
Автор: leniviy 5.8.2012, 16:42 | ||
1. сделай отступ 1 пробел 2. больше каментов например, в конце большого блока, если он не умещается на странице, надо делать такой камент:
3. делай "параграфы", "главы" выделяй их разным количеством пустых строк |
Автор: _Y_ 5.8.2012, 17:38 |
leniviy, спасибо, но это, вроде, само собой разумеется. Вопрос о вложенных IF структурах, которые уже ни в какие рамки не лезут. Скажем так, если каждый вложеннй уровень сдвигать вправо должным количеством пробелов (как это всегда делается), то сам код уедет за правый край экрана, а в поле видимости останутся только IF-ы, скобки и масса пустого места ![]() ![]() |
Автор: Stolzen 5.8.2012, 20:10 |
А в чем проблема? Если вложенность больше 2 (3) - делаем extract method - самое лучшее решение. |
Автор: _Y_ 5.8.2012, 23:42 |
Что такое extract method? Я не в курсе ![]() |
Автор: LSD 6.8.2012, 07:32 |
Рефакторинг. К.О. Разбивай метод на более простые и читабельные. Т.е. вместо одного метода с 10 if-ами, пусть лучше будет 10 маленьких методов с одним if-ом каждый. Опять же можно попробовать заменить if на switch. В любом случае универсального решения нет, надо смотреть по ситуации. |
Автор: jk1 6.8.2012, 09:43 | ||
Иногда сложную условную логику удобно заменить полиморфизмом, ввести несколько стратегий. Особенно если условная логика идет по типам, вроде часто встречаемого
|
Автор: baldina 6.8.2012, 11:00 |
лучше от нее избавиться (см. выше). насчет большого числа параметров: если параметр - массив или объект, он может быть один. или вообще без параметров, через контекст. |
Автор: jManiak 6.8.2012, 15:27 |
ЕСЛИ этот ветвящийся код описывает поведение одного объекта в зависимости от условий, то можно прибегнуть к одному из шаблонов проектирования: http://www.javenue.info/post/12 Если нет, то либо что-то другое либо рефакторингом обходиться. |
Автор: baldina 6.8.2012, 15:44 | ||
на самом деле это хороший способ в простых случаях значит надо пересмотреть разделение на методы. осмысленному действию легче дать осмысленное название |
Автор: NoliX 10.8.2012, 13:45 | ||||||||
Очень помогает инвертировать условие: Вместо:
Код становится одноуровневым и читабельным. If c else выносить в отдельный метод с возвращаемым значением: Вместо:
(Я упростил, естественно, в данном случае проще заменить на тернарный оператор, но суть примерно понятна) Писать комментарии категорически не советую, особенно ерунду типа /* END if (1==1) */. Ни IDE, ни коллеги эти комметы поддерживать не будут, и через пару коммитов это станет неправдой + это вообще лишняя работа совершенно. |
Автор: _Y_ 14.8.2012, 23:55 | ||
Спасибо. Подведу итого того, что понял. Моя идея выносить каждый вложенный IF в отдельный метод была оценена как достойная. Даже умному назвнию "extract method" Stolzen с LSD научили. Полиморфизм, предложенный jk1 и jManiak я очень уважаю, а, в случае конечных автоматов, даже люблю. За высокий уровень инкапсуляции. Но здесь он "не окупится". Большинство классов будут имплементировать одну строчку кода.
Это, конечно, не массив, но любые данные можно превратить в объект. А вот как делать через конекст я не знаю. Как это? NoliX, IF-ы с return-ами я объединяю практически всегда, когда возможно. ИМХО такой код гораздо читабельнее. Но здесь этим не обойдешься. ................... Собственно, наверное стОит объяснить задачу. Имеем много полей ввода разных типов. Некоторые значения некоторых полей открывают дополнительные поля ввода. Довольно обычный высоконагруженный пользовательский интерфейс. А вот дальше начинаются сложности. Данные должны попасть в БД. Но, при этом, должны делаться проверки как введенных данных, так и уже имеющихся в базе. Т.е. данные и отношения между ними могут создавать новые записи, а могут и дополнять имеющиеся. При этом от самих данных зависит "чья возьмет". Т.е. данные в БД могут иметь больший или меньший приоритет по сравнению с тем, что ввел пользователь. Собственно, логика простая, но подразумевающая множество проверок, специфических для различных комбинаций данных..... Понятней, надо понимать не стало ![]() |
Автор: korian 15.8.2012, 00:32 |
Давайт больше конкретики, тогда можно будет подумать. Возможно есть смысл насоздавать новых объектов или еще чего. |
Автор: baldina 15.8.2012, 10:06 | ||
данные объекта это и есть контекст наоборот, стало. это имхо не if-ами должно решаться. надо эти отношения переместить из кода в данные. тогда код будет обобщенный (без конкретной логики), короткий и понятный, а логика будет задаваться в данных. что-то похожее на конечный автомат с реакцией в узлах состояний. если не очень понятно, позже подробней отпишусь |
Автор: LSD 15.8.2012, 11:02 | ||
Я в похожей ситуации использовал шаблон http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html. Есть куча маленьких классов, каждый из которых проверяет свое маленькое условие. Если все проверки прошли, операция разрешается, если что-то сфейлилось, то возвращаем сообщение об ошибке. Благодаря тому что каждый фильтр маленький и простой, тестировать его намного проще. И добавлять новые фильтры можно не трогая старый код. |
Автор: baldina 15.8.2012, 11:16 |
у ТС немного сложнее, ему нужна не просто валидация, а еще и определенная реакция. причем, подозреваю, результаты этой реакции могут включаться в поток проверок. на фильтре можно такое сделать, но тогда одни и те же проверки будут повторяться |
Автор: _Y_ 15.8.2012, 22:06 | ||||||
Спасибо. Сам я, честно говоря, в чужой конкретике копаться не люблю и, потому, нагружать окружающих деталями как-то неудобно. Да и задача не рабочая - типа хобби, чтобы Java не забывалась. Я уже несколько лет на другом языке работаю в совсем другой области.
На мой взгляд, это и есть конечный автомат. Но, в моем случае, он будет строго линейным. Никаких переходов - проверил то - поступил так, проверил это - поступил эдак. Если что-то не позволяет пойти по одному из разрешенных путей, все равно провел все проверки, а уже потом выдал суммарное сообщение о неприятной ситуации.
Не совсем так, но похоже. Будут повторяться не проверки, а запросы к БД. Я вот подумал над вашими ответами и пришел к такой идее. Можно, наверное, действительно сделать что-то вроде набора фильтров, но плоховато инкапсулированных. Исходные данные и объекты, выводящие параметры, пропускать через все фильтры по очереди (все равно параметры по ссылке передаются если они объекты). Пусть каждый фильтр их модифицирует если хочет. Фильтры делать по принцыпу "один запрос к БД на один фильтр". Что на эту тему думаете? |