Более чем согласен. Так же с большой настороженностью относимся к кандидатам с незаконченной вышкой.
А вообще вышка своего рода показатель меры ответственности, выносливости… Можно сказать некая школа жизни, которая прививает навыки «выкручивания» из сложных ситуаций, умение решать возникшие проблемы, планировать время, решать поставленные задачи, работать в команде, умение искать нужную информацию и т.д. То есть, в целом, не важен профиль высшего образования, важно его наличие.
Мне лично не очень удобно составлять запрос в строковом виде, лямбдами куда приятнее. Да и опять же как лямбду, так и эту строку надо от куда то брать для каждого набора данных, либо руками, либо придумывать способ автоматической генерации, что я пытался сделать в своем решении.
А вообще, мне кажется, что такие «гиганты» как C++, Java, C# еще долго будут строго-типизированными и долго будут в строю, потому что это своего рода «классика», но потихоньку будут уступать позиции тому же Python или Ruby. Тенденция программирования явно намечена на упрощение технических моментов и на сосредоточении разработчика на конкретной задаче, так что возможно когда-нибудь мы будем лишь вспоминать строгую типизацию.
«За последние семь лет работы с корпоративными приложениями я ни разу не видел такой ситуации.»
За те же 7 лет встречал ее достаточно часто.
Я понял Вашу позицию и считаю, что есть к чему прислушаться. Но для себя и того проекта, для которого это писал, оставлю пока свое решение, так как на данный момент считаю его весьма удобным.
Спасибо за дискуссию, думаю дальше развивать холливар смысла нет, наши позиции ясны. Хотя, конечно, если Вы другого мнения, буду рад ответить на Ваши замечания.
Нет нет, все в порядке. Если бы мне было не важно чужое мнение — я бы не стал публиковать статью на хабре :) А за паттерны еще раз большое спасибо, обязательно их освою!
Я не буду биться за название «фильтры», тут уж как Вам больше нравится.
На счет паттернов спасибо, почитаю про них. Но я же не паттерн проетирования описал, я описал конкретное решение и почему его нужно обзывать именами использованных/неиспользованных паттернов? Мы же не называем проект * MVC *, потому что он написан с использованием паттерна MVC, мы называем его по его тематике, и здесь точно так же — название «фильтры» мне показалось более удачным, потому что для пользователя сайта это именно фильтры данных. Но, повторюсь еще раз, я не буду говорить, что это название идеально, если Вас оно смущает, я готов обозвать это как угодно.
«Именно в формулировке, которая требует сессии (т.е. — закрытие и открытие страницы, например)?»
В формулировке сохранения данных фильтрации для конкретного пользователя после ухода его со страницы, а закрыта она или нет, это уже дело второе. Более того хранилище можно реализовать любое: хоть на куках, хоть в бд.
«А это проблема какая-то, что ли?»
Да, это проблема. Я ни разу не припомню, что бы кто то номера страниц инпутами проставлял.
«а вас не смущает, что если у пользователя отключен js, то у него и куки могут быть отключены»
а еще и браузер отсутствовать, кхе-кхе. Как не странно, js намного чаще отключают, нежели куки, по крайней мере в тех организациях, с которыми я сталкивался.
«Эээ… вообще-то это типичная задача на базовый класс, когда функциональность находится в нем, а конкретизация — в наследнике. Вплоть до использования дженерика.»
Зачем наследовать, когда можно реализовать все одним методом, как у меня и сделано? Это находится не в базовом контроллере, потому что я не хочу, что бы все мои контроллеры наследовали этот метод. Делать другой базовый? А если я захочу еще чего нибудь специфичное в базовых контроллерах? Третий? А если я захочу функционал второго и третьего одновременно — четвертый?
«Я хочу сказать, что количество порожденного вами кода существенно больше, чем надо для решения вашей задачи.»
Для решения моей задачи — нет, не больше, а меньше. Если у вас 2-5 наборов данных, которые нужно фильтровать, согласен, заморачиваться смысла нет. А когда их 20 и со временем будет еще 20?
«Еще надо помнить, что обращение к этому контроллеру (замаскированное под хелпер) должно быть того же типа (по модели)»
Вот об этом как раз и заботится и хелпер и отдельный контроллер. Конечному программисту помнить это не нужно.
«Это, знаете ли, на редкость специфичное требование.»
Отнюдь нет. Я с ним сталкивался не однократно.
«Данные фильтров не настолько велики, чтобы это было проблемой»
А если будут велики? 100 различных параметров? GET-ом отправлять? Или формировать POST запрос через JS, который может быть отключен у пользователя? Или может быть заботится о том, что бы закрывающий тэг бы в самом низу, а номера страниц input'ами выводились?
«Зато падение сессии между страницами вас больше не волнует»
Волнует. Эту проблему я указал в топике.
«А так вам надо не забыть забрать фильтрующее выражение из хранилища. Ровно то же самое.»
Соглашусь, сборку фильтра можно положить в тот же action, где и происходит выборка данных. А со сбросом данных что делать: описывать в каждом контроллере действие Reset — много код, выносить в базовый контроллер — но тогда опять встает задача определения какой же фильтр мы сбрасываем.
«Понимаете ли, задача типовой обработки решается типовыми же средствами — базовым контроллером, фильтром на action и так далее. Зачем изобретать свой, странный и непонятный велосипед.»
Для уменьшения кол-во кода, необходимого для конечного использования этой задачи. Разве не для этого пишутся различные библиотеки и фрэймворки?
«Вот только вашу задачу — конкретную — вы не указали.»
Описание моей задачи заняло бы намного больший объем, чем сама статья. Я предлагаю вариант решения, а решать подходит он для Ваших задач или нет — только Вам.
А зачем конечному разработчик узнать что и от куда приходит? Он знает как создать модель фильтра и он знает как из этой модели получит expression для выборки данных. Для выполнения фильтрации этого достаточно, зачем ему больше?
По поводу «некого хранилища». Организовано оно для того, что бы хранить данные фильтров в сессии, ну или где угодно. Зачем? Что бы когда пользователь вернулся к странице, он увидел тот же отфильтрованный набор данных, что видел и в момент ухода со страницы (требования моего проекта). Либо же для организации пейджинга, что бы на каждую страницу не таскать данные фильтров.
По поводу того, что задачу сборки модели и помещения его в хранилище решает другой контроллер. Проектируя все это передо мной стояла задача написания таких фильтров, которые бы быстро внедрялись. Передавая данные по фильтрации сразу в контроллер, обрабатывающий данные, мне бы пришлось в каждом моем контроллере (а их как я уже говорил в районе 20 штук) реализовывать логику сборки фильтра и сброса фильтра. Допустим это можно сделать одной-двумя строчками, но про эту строчку надо еще не забыть!
Я не претендую на идеальность архитектуры моего решения, но для моей задачи это было оптимальным решением.
Не могу ручаться, но на сколько мне известно, Func тоже преобразуется в SQL запрос.
Во время написания моделей фильтров к своему приложению несколько раз в FilterExpression ошибался и это приводило к SqlException, от сюда полагаю что все таки преобразуется. Как будет время, посмотрю профайлером на конечный запрос к серверу, там будет видно, включены условия выборки фильтра в него или нет
От чего же неизвестно от куда? В статье описано как собирается модель фильтра и где она хранится. От пользователя приходит запрос на служебный контроллер, из запроса собирается модель, модель кладется в специальное хранилище, объект которого находится в данных сессии и дальше идет редирект на ту страницу, от куда запрос пришел. Контроллер этой страницы получает уже сформированную модель фильтра из хранилища. Гриды для моего проекта без костылей были не подходящими по многим причинам, по этому пришлось придумывать нечто свое.
У меня в приложении примерно 20 страниц с различными данными, которые необходимо было фильтровать таким образом. С моим решением обеспечить фильтрами данных 20 разных сущностей весьма быстро и сопровождать потом просто.
«Где это происходит? Можете описать полную последовательность происходящего на высоком уровне „
В действии контроллера или в любом другом месте, где Вы выбираете данные из БД или любой другой коллекции. Последовательность такова: пользователь заходит на страницу где видит список, ну например, товаров, сверху этого списка отображается форма фильтрации. Пользователь заполняет интересующие его поля и отправляет форму. После этого он видит уже только те товары, которые удовлетворяют указанным характеристикам.
“И вас не смущает, что вы сейчас получили конфликт терминов?»
Ничуть. Фильтры действий, это фильтры действий.
«А чем вам слово «данные» не угодило? Фильтруете вы данные.»
Тут с Вами согласен, слово «данные» более уместно. Мой косяк.
А вообще вышка своего рода показатель меры ответственности, выносливости… Можно сказать некая школа жизни, которая прививает навыки «выкручивания» из сложных ситуаций, умение решать возникшие проблемы, планировать время, решать поставленные задачи, работать в команде, умение искать нужную информацию и т.д. То есть, в целом, не важен профиль высшего образования, важно его наличие.
А вообще, мне кажется, что такие «гиганты» как C++, Java, C# еще долго будут строго-типизированными и долго будут в строю, потому что это своего рода «классика», но потихоньку будут уступать позиции тому же Python или Ruby. Тенденция программирования явно намечена на упрощение технических моментов и на сосредоточении разработчика на конкретной задаче, так что возможно когда-нибудь мы будем лишь вспоминать строгую типизацию.
Меня просто смутили SqlException при ошибках в Func, но видимо они были вызваны другими вещами.
За те же 7 лет встречал ее достаточно часто.
Я понял Вашу позицию и считаю, что есть к чему прислушаться. Но для себя и того проекта, для которого это писал, оставлю пока свое решение, так как на данный момент считаю его весьма удобным.
Спасибо за дискуссию, думаю дальше развивать холливар смысла нет, наши позиции ясны. Хотя, конечно, если Вы другого мнения, буду рад ответить на Ваши замечания.
На счет паттернов спасибо, почитаю про них. Но я же не паттерн проетирования описал, я описал конкретное решение и почему его нужно обзывать именами использованных/неиспользованных паттернов? Мы же не называем проект * MVC *, потому что он написан с использованием паттерна MVC, мы называем его по его тематике, и здесь точно так же — название «фильтры» мне показалось более удачным, потому что для пользователя сайта это именно фильтры данных. Но, повторюсь еще раз, я не буду говорить, что это название идеально, если Вас оно смущает, я готов обозвать это как угодно.
В формулировке сохранения данных фильтрации для конкретного пользователя после ухода его со страницы, а закрыта она или нет, это уже дело второе. Более того хранилище можно реализовать любое: хоть на куках, хоть в бд.
«А это проблема какая-то, что ли?»
Да, это проблема. Я ни разу не припомню, что бы кто то номера страниц инпутами проставлял.
«а вас не смущает, что если у пользователя отключен js, то у него и куки могут быть отключены»
а еще и браузер отсутствовать, кхе-кхе. Как не странно, js намного чаще отключают, нежели куки, по крайней мере в тех организациях, с которыми я сталкивался.
«Эээ… вообще-то это типичная задача на базовый класс, когда функциональность находится в нем, а конкретизация — в наследнике. Вплоть до использования дженерика.»
Зачем наследовать, когда можно реализовать все одним методом, как у меня и сделано? Это находится не в базовом контроллере, потому что я не хочу, что бы все мои контроллеры наследовали этот метод. Делать другой базовый? А если я захочу еще чего нибудь специфичное в базовых контроллерах? Третий? А если я захочу функционал второго и третьего одновременно — четвертый?
«Я хочу сказать, что количество порожденного вами кода существенно больше, чем надо для решения вашей задачи.»
Для решения моей задачи — нет, не больше, а меньше. Если у вас 2-5 наборов данных, которые нужно фильтровать, согласен, заморачиваться смысла нет. А когда их 20 и со временем будет еще 20?
Вот об этом как раз и заботится и хелпер и отдельный контроллер. Конечному программисту помнить это не нужно.
«Это, знаете ли, на редкость специфичное требование.»
Отнюдь нет. Я с ним сталкивался не однократно.
«Данные фильтров не настолько велики, чтобы это было проблемой»
А если будут велики? 100 различных параметров? GET-ом отправлять? Или формировать POST запрос через JS, который может быть отключен у пользователя? Или может быть заботится о том, что бы закрывающий тэг бы в самом низу, а номера страниц input'ами выводились?
«Зато падение сессии между страницами вас больше не волнует»
Волнует. Эту проблему я указал в топике.
«А так вам надо не забыть забрать фильтрующее выражение из хранилища. Ровно то же самое.»
Соглашусь, сборку фильтра можно положить в тот же action, где и происходит выборка данных. А со сбросом данных что делать: описывать в каждом контроллере действие Reset — много код, выносить в базовый контроллер — но тогда опять встает задача определения какой же фильтр мы сбрасываем.
«Понимаете ли, задача типовой обработки решается типовыми же средствами — базовым контроллером, фильтром на action и так далее. Зачем изобретать свой, странный и непонятный велосипед.»
Для уменьшения кол-во кода, необходимого для конечного использования этой задачи. Разве не для этого пишутся различные библиотеки и фрэймворки?
«Вот только вашу задачу — конкретную — вы не указали.»
Описание моей задачи заняло бы намного больший объем, чем сама статья. Я предлагаю вариант решения, а решать подходит он для Ваших задач или нет — только Вам.
По поводу «некого хранилища». Организовано оно для того, что бы хранить данные фильтров в сессии, ну или где угодно. Зачем? Что бы когда пользователь вернулся к странице, он увидел тот же отфильтрованный набор данных, что видел и в момент ухода со страницы (требования моего проекта). Либо же для организации пейджинга, что бы на каждую страницу не таскать данные фильтров.
По поводу того, что задачу сборки модели и помещения его в хранилище решает другой контроллер. Проектируя все это передо мной стояла задача написания таких фильтров, которые бы быстро внедрялись. Передавая данные по фильтрации сразу в контроллер, обрабатывающий данные, мне бы пришлось в каждом моем контроллере (а их как я уже говорил в районе 20 штук) реализовывать логику сборки фильтра и сброса фильтра. Допустим это можно сделать одной-двумя строчками, но про эту строчку надо еще не забыть!
Я не претендую на идеальность архитектуры моего решения, но для моей задачи это было оптимальным решением.
Во время написания моделей фильтров к своему приложению несколько раз в FilterExpression ошибался и это приводило к SqlException, от сюда полагаю что все таки преобразуется. Как будет время, посмотрю профайлером на конечный запрос к серверу, там будет видно, включены условия выборки фильтра в него или нет
И на сколько я помню, в MVC 3 [ValidateInput(false)] у меня отлично работал по назначению.
У меня в приложении примерно 20 страниц с различными данными, которые необходимо было фильтровать таким образом. С моим решением обеспечить фильтрами данных 20 разных сущностей весьма быстро и сопровождать потом просто.
В действии контроллера или в любом другом месте, где Вы выбираете данные из БД или любой другой коллекции. Последовательность такова: пользователь заходит на страницу где видит список, ну например, товаров, сверху этого списка отображается форма фильтрации. Пользователь заполняет интересующие его поля и отправляет форму. После этого он видит уже только те товары, которые удовлетворяют указанным характеристикам.
“И вас не смущает, что вы сейчас получили конфликт терминов?»
Ничуть. Фильтры действий, это фильтры действий.
«А чем вам слово «данные» не угодило? Фильтруете вы данные.»
Тут с Вами согласен, слово «данные» более уместно. Мой косяк.
Если Вы имеете ввиду фильтры действий, то да, знаю. В статье я описываю фильтры контента. У Вас есть другие предложения как можно это назвать?