Советы и подсказки

Disclaimer: все действия направленные на уменьшение кода, нужного для решение задачи, в первую очередь преследуется цель, минимизации ошибок связанных с рутиной (под этим словом я понимаю “copy and past” ), которых много в любых проектах. Стараюсь во всех своих проектах писать только уникальный код для решения конкретных задач, а не копировать код из одного места в другое с переименованием переменных ( значений, полей и т.д. ), но так же понимаю и обратную сторону, связанную с ухудшением читабельности и скрытие деталей.

Предыстория: я часто изучаю исходные коды, которые пишут мои коллеги и иногда замечаю нюансы, которые  я мог бы сделать более лаконично и компактно по разным причинам, иногда потому что знаю “короткие пути” в incframework, иногда “свежим взглядом” вижу альтернативное решение. Но часто забываю выписать эти решения и довести их до сведения всем, поэтому решил написать отдельную статью в  которой буду собирать все иантересные зметки и рассказывать обо всех своих наблюдениях, что поможет использовать incframework более производительно.

TryPush

TryPush  – это метод позволяет уменьшить простые post controller до одной строчки, для того что бы понять, как это работает давайте посмотрим, что мы пишем когда делаем push command в controller

Кратко разберем код представленный выше

  1. Проверяем ModelState
  2. Выполняем push в try
  3. Обрабатываем ошибку в Catch

примечание: обработку в Catch я делаю только для IncWebException, потому что это единственная ошибка, которую должны выбрасывать command или query если им надо остановить выполнение, остальные же ошибки считаю критическими и перехватываются на уровне global.asax ( или в других глобальных обработчиках ) . Замечу, способ передачи ModelState в IncodingResult.Error позволяет обновить валидацию формы вернув назад на view коллекцию json объектов { name:”property”,isValid:”true or false”,errorMessage:”error message” }.

Теперь рассмотрим  аналогичное решение выше приведенного кода

Решение очень минималистское, но имеет небольшую проблему связанную с тем, что надо понимать, как работает метод, поэтому далее мы погрузимся в детали работы TryPush, что бы лучше понимать, как им пользоваться для начала рассмотрим особенности:

  1. Тип возвращаемого ActionResult определяется на основе IsAjaxRequest, тем самым можно вызывать action через Ajax или обычным способом.
  2. Можно указать, что именно возвращать при Success или Error

     примечание: ErrorResult сработает, когда command  выкинет IncWebException иначе (если это не критическая ошибка ) SuccessResult.
  3. Можно выполнять CommandComposte

    примечание: код выше можно переписать иначе ( на мой взгляд решение ниже имеет более читабельный вид, но дело вкуса )

Вывод: мы рассмотрели детали работы TryPush, узнали как его можно настроить. Я не вижу веских причин, не использовать этот метод в повседневной практики, разве что только если потребуется специфичная обработка ошибок, но это как мне кажется, скорей проблема дизайна приложения.  Главное, что позволяет сделать TryPush –  убрать с программиста груз ответственности за повторение однотипных методов, которые являются “кладовой” ошибок.

FroGroup

Предыстория: в последнее время для разметки страниц мы стали использовать twitter bootstrap, важнейшим преимуществом которого, является единый стандарт. После некоторого времени использования, я выделил ряд однотипных операций, которые хотелось бы “упаковать” в удобный набор расширений, таким образом появился метод ForGroup для HtmlHelper.

ForGroup – строит разметку для элементов формы, на основе стандарта twitter bootstrap form , что позволяет экономить время при написании форм. Проще всего будет изучить код, который сподвиг меня на написания этого расширения.

@Html.TextBoxFor(r=>r.Login)

@Html.ValidationMessageFor(r=>r.Login)

Мы видим структуру построения поля формы, которая содержит Label, Input , Validation Message, такой формат используется во многих сценариях ( конечно бывают более сложные ). Основная проблема, это то, что программист скопирует данный участок кода и проведет переименование Login в скажем Password, что может привести к появлению “скрытых ошибок”. Примером скрытой ошибки, можно привести случай, если ValidationMessageFor пропустить в процессе переименовывания. Об этой ошибки не скажет ни компилятор, ни Resharper errors in solution, потому что такой тип ошибок относится к логическим, которые можно найти в процессе ручного тестирования.

примечание: пример с ValidationMessageFor особенно сложный в плане поиска, потому что обнаружить ошибку, можно только проделав ряд действий, что может привести к тому, что ошибка будет обнаружена в процессе эксплуатации.Можно использовать Find and Replace и другие средства для более безопасной замены, но это только уменьшит вероятность появления ошибки,но не предотвратит ее, да и уменьшение количества кода это не дает.

На стало время посмотреть , как же с поставленной задачей справится ForGroup

примечание: ForGroup возвращает IncoingHtmlHelperForGroup<tmodel, tproperty=””>, который содержит метод для выбора элемента управления.

У ForGroup есть важный момент, который связан с скрытием деталей работы,что приводит к следующим проблемам:

  • Если в проекте есть дизайнер, который работает с html то ему будет сложно понимать такие конструкции, но практика единого стандарта разметки и классов позволила нам полностью перенести все задачи дизайна исключительно на CSS.
  • Все программисты должны понимать, как работает ForGroup иначе это может затруднять работу.

После общего обзора, мы можем изучить тонкости настройки и детали работы. Сам ForGroup всего лишь служит для сохранением имени свойства, к которому будем применять определенный элемент управления, которые можно выбрать из готовых или написать свой пользуясь руководством. Изучим подробней готовые элементы:

  • TextBox – аналог из mvc
  • CheckBox – аналог из mvc
  • File – input с type file
  • TextArea – аналог из mvc
  • Password – аналог из mvc
  • Hidden – аналог из mvc
  • DropDown  – аналог из mvc, но можно настроить на ajax
  • ListBox – аналог из mvc, но можно настроить на ajax

Все элементы имеют одинаковый синтаксис для настройки, но некоторые имеют дополнительные поля ( например Url у DropDown или ListBox ). Далее рассмотрим несколько примеров использования ForGroup на основе кода взятого из реальных проектов.

Product

@Html.ForGroup(r => r.Name).TextBox() @Html.ForGroup(r => r.Weight).TextBox() @Html.ForGroup(r => r.Price).TextBox() @Html.ForGroup(r => r.Ingredients).TextArea() @Html.ForGroup(r => r.Description).TextArea() @Html.ForGroup(r => r.CategoryId).DropDown(control => { control.Input.Url = url.Dispatcher().Query(); control.Label.Name = “Category”; }) @Html.ForGroup(r => r.Image).File()

 @Html.RunATab().ButtonBack()

Выше продемонстрирована стандартная, html форма построенная с использованием ForGroup, которая занимает всего 20 строк , а ее аналог на “чистом” html не уместился бы и в 100.

Vlad Kopachinsky

I am a Senior developer at Incoding Software in Russian Federation. I created the Incoding Framework for rapid development

More Posts - Website - Twitter - Facebook - LinkedIn

Leave a Reply