А как выглядит ваш прикладной код?

    При разработке платформы я считаю крайне важным уделять особое внимание простоте, понятности и удобстве работы с прикладным кодом. Испробовав разные подходы, я хочу поделиться удобными рецептами из своего опыта.

    Под прикладным кодом имеется в виду код, относящийся непосредственно к бизнес-логике конкретного приложения, при этом, в отличии от ядра (framework-а, платформы) такой код максимально подвержен изменениям и в крупных проектах может составлять львиную долю проекта. От удобства прикладного разработчика зависит скорость и качество разработки самым существенным образом.

    Например на языке Brainfuck Hello world выглядит так:
    image
    А вот наши критерии удобства:
    • Строгая статическая типизация
    • Документированность
    • Отсутствие “мусора”
    • Однотипность
    • Лаконичность


    Типичным примером прикладной задачи является разработка кнопки с каким-нибудь действием по её нажатию. Кнопка может находиться на форме, на гриде или в системном меню. В зависимости от расположения у неё есть набор доступных входящих параметров (что за форма? что за грид? какие записи выделены?) и набор возможных действий (обновить, изменить, открыть и т.д.), их совокупность мы называем контекстом.

    В нашей системе для создания кнопки нужно разработать класс этой кнопки, реализующий специальный интерфейс (IAction) — он описывает её внешний вид и поведение.

    В примере рассмотрим приложение из предыдущей статьи — агенство недвижимости.

    Кнопка добавления в закладки


    image

    Комментарии

    В заголовке класса имеются XmlDoc комментарии, они имеют двойное назначение:
    во первых это классический комментарий, чтобы в коде было понятно что же делает это действие
    во вторых это текст (первая строка) и подсказка (последующие строки) кнопки.

    Реализация интерфейса

    На первый взгляд IAction<IItemContext<RentOfferBase>> может испугать, но это не так страшно:

    IAction — интерфейс всех действий системы, для того чтобы класс был кнопкой он должен реализовывать этот интерфейс.

    Generic-параметр IItemContext — контекст действия, в данном случае нам необходим элемент сущности для расположения кнопки. Таким образом кнопка, с таким контекстом может появится в:
    • Форме заявки
    • Контестном меню списка заявок (правый клик на элементе)


    RentOfferBase — указывает на сущность (Предложения от арендодателя) на которой доступна эта кнопка. Учитывая принцип наследования, кнопка будет доступна для:
    • Предложений от арендодателя
    • предложений комнат (потомок)
    • предложений квартир (потомок)


    Атрибут

    [Icon(ExtIcon.BookmarkAdd)]
    
    Указывает с какой иконкой кнопка будет отображаться.

    Метод

    public void Execute(IItemContext<RentOfferBase> context)
    
    Непосредственно код, выполняемый по нажатию на кнопку.
    context — это и есть Контекст действия, что в нем есть:

    ExceptionHelper.Interactive — Интерактивные исключения
    ParameterManager.GetParameter — запрос параметра с клиента (похоже на интерактивные исключения, но с возможностью ввести данные)
    context.ShowNotification() — способ взаимодействия с клиентом.

    Кнпока расчета средней цены


    image

    Атрибут

    [RequireRole(Role.Agent)]
    
    указывает на требование наличия роли Agent у пользователя для видимости кнопки.

    Контексты

    В этой кнопке используется IFormContext — контекст формы, в отличии от контекста элемента такие кнопки не будут доступны по контекстному меню, зато будут доступны при редактировании формы.
    При этом контекст содержит дополнитеьльные параметры, например
    context.FormData — это ещё не сохраненные данные формы и дополнительные методы, имеющие смысл только на форме, например:
    context.ChangeFieldValue(a => a.Price, averagePrice) — изменение значения поля (без сохранения)

    Больше возможностей


    Контекстов много

    В реальности используется несколько контекстов, использование соответствующего контекста позволяет расположить кнопку в нужном месте и получить доступ до необходимых свойств и вызывать соответствующие методы.

    Атрибутов тоже много

    Например в кнопке удалить:
    image

    Кроме уже известной нам иконки для неё мы так-же указываем следующие атрибуты:
    • подтверждения с текстом подтверждения
    • требования выделения (без выделения кнопка не доступна)
    • горячую клавищу


    Не только кнопки

    Аналогичный подход мы применяем и для остальных прикладных объектов системы
    • Событий сущности
    • Событий форм
    • Событий входа в систему
    • Операций документов
    • Нумераторов


    Тема для дискуссии


    А у вас есть примеры ERP (или других учетных) систем где прикладной код вам нравится?
    1С — образец для подражания?

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 66

      0
      > Строгая типизация

      Имелась в виду статическая?
        0
        спасибо, поправил
          +6
          В си-решётке? Да вы опасный парень.
            0
            Можно перевести этот комментарий на русский?
              0
              В C# динамическая типизация.
                0
                Вы с дубу рухнули?
                  0
                  Starting with version 4.0, C# supports a «dynamic» data type that enforces type checking at runtime only.
                  © wiki
                    0
                    И? После этого во всем C# ВНЕЗАПНО типизация превратилась в динамическую?

                    Typing discipline static, dynamic, strong, safe, nominative, partially inferred


                    C# просто поддерживает и то и другое.
        +1
        Стоп-стоп-стоп… Что за ExceptionHelper?
        Вы что, исключения используете для управления control flow?
          +4
          Увидел ссылку, сорри. Уже обсуждали.
          +15
          Никогда не понимал комментарии вида «Добавить в закладки» для AddToBookmark. и «Средняя цена» для AveragePrice
            +2
            в данном случае это не только комментарий, но и текст используемый для отображения кнопки
              +6
              Комментарии бесполезны в таком виде «Выполнение действия», «Контекст действия». Это понятно и из имени метода, и из типа параметра. А текст должен браться из атрибутов, иначе огребете при попытке локализации.
                –2
                Что значит бесполезен?
                Он может быть простым переводом, но при этом он используется в отображении кнопки
                Кроме того, последующие строки могут быть использованы для ToolTip-а
                  +6
                  Это «мусор» по вашей классификации. Такие коментарии не несут смысловой нагрузки, елси вы не пишете framework. Он только загрязняет код.

                  И, имхо, смешивать логику и коментарии, не слишком удачная идея. Вдруг в каком-то месте придется написать что-то, относящееся именно к коду — это сразу же вылетит на UI, чего быть не должно.
                    0
                    в UI «вылетает» только из summary и только из класса (для кнопок)
                    можно ещё использовать remarks или другие теги
                      +4
                      Такие договоренности не работают.
                        –2
                        Кто сказал?
                          +5
                          Это общее правило. Такое требование противоречит общепринятому паттерну, поэтому оно будет нарушаться. Если же заменить его на более строгое — например, на те же аттрибуты, которые уже используются для похожих целей, то соглашение пропадает, а решение остается.
                            –1
                            Коменты — это хорошо. Данное решение убивает двух зайцев:
                            1) комент автоматом идет в гуй (естественно, что не все коменты идут в гуй, у нас конкртено, только описания сущностей, классов действий, кнопок и т.п.)
                            2) комент к классам и т.п. у нас обязателен на уровне прохождения билда в TeamCity
                            так что все работает
                              0
                              Рискуя нарваться на больший негатив, но второе требование может привести вот к такому:

                              ///
                              /// Mains this instance.
                              ///
                              public static void Main()

                              www.google.by/search?q=«mains+this+instance»
                                –3
                                Может и не привести, если правльно настроить все. А, вообще, лучше такой комент, чем никакого
                                  +6
                                  Этот коммент хуже никакого и даже хуже пустого. Он явно генерен и сразу же подрывает доверие к остальным коментам в коде. Следуя Роберту Мартину, код должен быть самодокументируемый, что, в принципе, выполняется в примере выше — Exceute выполняет действие, Context — контекст и так далее. Такому коду коменты не нужны. Такое требование законно для авторов фреймворков и тулкитов — но даже там они не должны превращаться во что-то «для галочки». Это очень похоже на требование полного покрытия тестами кода — легко написать тест, который будет полностью покрывать код, но не будет иметь ни одного ассерта — а, значит, будет бесполезен, и даже вреден.
                                    –2
                                    Прочитайте уже, что вам пишут. Я теперь вам специально выделю ключевые слова. Не все коменты обязательны. Некоторые коменты являются одновременно инофрмацией для гуя.
                              +2
                              И, кстати, хотелось бы увидеть тот самый «общепринятый паттерн»
                                0
                                Хотя бы так. msdn.microsoft.com/en-us/library/2d6dt3kf(v=vs.71).aspx
                                  +2
                                  И как он противоречит написанному?
                                    –1
                                    Хотя бы в том, что коммент относится к типу и к члену типа, а не к надписи на кнопке.
                                      +1
                                      Он относится и к тому и к другому. Тип этот как раз и является реализацией кнопки и без кнопки просто бесполезен.
                            +1
                            Наверно, у разных людей работают разные договоренности. Не будьте таким критичным.
                              +7
                              «Не пишите в коменты по коду, потому что они окажется на UI» — это плохое соглашение, я выше попытался объяснить.
                                +1
                                А. Ну это да. Хотя, идея интересная…
                                И комменты есть, и осмысленность у них вынужденно будет хорошей. И не приходится по два раза какие-то очевидные вещи писать, сперва в комментах, потом в тексте кнопки.

                                Но я бы реквеставал статью по тому, как организованна локализация.

                              –5
                              Такие договоренности работают.

                              Точка в конце фразы круто смотрится, как бы подчеркивая что речь идет об устоявшемся факте. Может эти договоренности у вас не работают? Может это ваш косяк? Так напишите статью об этом фейле, я с удовольствием её прочитаю, выскажу пару рекомендаций по организации связей, и может и у вас заработает. Надо быть добрее к людям, и не скатываться в полемику, дискуссия продуктивнее.
                      +5
                      т.е. тексты которые будут на кнопке написаны в коде, да ещё и в комментах?
                        0
                        текст из комментария — «Средняя цена» будет использоваться для отображаемого имени кнопки
                        если в комментарии поменять «Средняя цена» на «Некоторая цена» — то на кнопке будет «Некоторая цена»
                        При этом для локализации можно редактировать не исходный код, а файл с xml-комментариями
                      0
                      Может для генерации API доков
                    • UFO just landed and posted this here
                        +16
                        омг, стринги в коде, привет будущей локализации… коменты на русском, глаза боль
                          0
                          В данном случае пишется некий прикладной код. Объекты, присущие предметной области (и DSL) — в наличии. Почему бы не сравнить? Правда я в 1С мало писал, но смотря на код:

                          Процедура ДатаПриИзменении(Элемент)

                          Если НачалоМесяца(мТекущаяДатаДокумента) <> НачалоМесяца(Дата) Тогда
                          мУпрощенныйУчетНДС = УчетНДС.ПолучитьУПУпрощенныйУчетНДС(Организация, Дата);
                          Если ВидОперации = Перечисления.ВидыОперацийРеализацияТоваров.ОтгрузкаБезПереходаПраваСобственности Тогда
                          мВыписыватьСчетФактуру = ПолучитьВыписыватьСчетФактуру();
                          КонецЕсли;
                          ЗаполнитьТекстПроСчетФактуру();
                          КонецЕсли;

                          мТекущаяДатаДокумента = Дата; // запомним текущую дату документа для контроля номера документа

                          УстановитьВидимость();

                          КонецПроцедуры

                          часто умиляюсь :)
                          • UFO just landed and posted this here
                              0
                              Ему самому и умиляюсь :)
                              Не, конечно 1С молодцы и язык, наверно, развит не плохо, но просто уж очень забавно выглядит.
                              • UFO just landed and posted this here
                                  +1
                                  Боюсь представить, как забавно/умильно выглядят программы вообще для людей, для которых английский язык — родной.
                              0
                              А почему решили вместо атрибутов использовать комментарии?
                                0
                                Плюсы:
                                — Не надо дублировать описание в атрибуте. Классу и так и так нужна документация, а кнопке описание (в том числе и в тултипе). Поразмыслив пришли к выводу что для классов кнопок комментарий является полным отражением того, что было бы в атрибуте.
                                — Меньше мусора в коде. Удалось избавиться от одного атрибута.

                                Минусы:
                                — Нестандартное использование комментариев.

                                Вообще рабочий процесс так устроен, что с этим ни разу проблемы не возникало. Т.е. были опасения что из-за неаккуратного использования комментов пойдут косяки в UI, но такого не произошло. Там не только комментарии, ещё и версионность, выгрузка всех этих опций в XML и накатка обновлений. Все это позволило сделать прозрачной работу с заголовками кнопок как комментариями.

                                На локализацию это в общем-то не повлияло, ведь дальше кода, в базе это все выглядит так же, как и будь оно атрибутом. Наши механизмы локализации об это не запнулись. Так что вышло что это однозначное благо.
                                +6
                                Может быть я и не прав, но xml-теги , и т.д. и т.п. — лишний машинный мусор, который несет очень мало пользы для программиста.
                                  +1
                                  парсер — лох, съел сами теги. Я имел в виду summary, param…
                                    +2
                                    А читать хорошие API доки приятно?
                                      +2
                                      Ну есть же и другие форматы для автосгенерированной API-документации, разве нет? Я о том, что xml отнимает слишком много внимания на самого себя, а не на документацию, которую он, в данном случае, призван поддерживать.
                                        +2
                                        Посмотрел ваши статьи, вы видимо не пишете на C#. Просто в Visual Studio XML комментарии — это стандарт. Они очень глубоко интегрированы в среду, в сборку, в средства поддержки кода. Их очень просто писать, срабатывает все возможные шаблоны и автодополнения. Так что тут просто нет смысла искать альтернативу, в таком формате документация крайне хороша для Visual Studio и C#.

                                        Если вы используете другие среды и языки, то вопрос и вправду открыт. Самому режет глаз формат документации MS для JavaScrpt. А вот для C# это безальтернативно, удобно и продуманно (вплоть до типизации специфических элементов языка, типа Generic параметров типа).

                                        И в статье, в контексте документации, речь идет о том как избавиться от лишнего атрибута используя уже имеющиеся и нужные части кода (комментарии к классам бизнес логики). Речь не идет о том, что нужно везде писать комментарии, или о том, что комментарии надо писать только в XML. Просто сборки C# используют этот формат, он удобно обрабатывается средствами под .NET, например PostSharp. Вооооот… Надеюсь прояснил.

                                        PS Я и сам под впечатлением от книги Чистый код, считаю что комментарий — признак отчаянья, но вот прикладные программисты пишут код по спецификации, и им просто необходимо писать комментарии на основе этой спецификации. А аналитики пишут на своем естественном нативном языке (по большей части у нас на русском).
                                          0
                                          хотелось вам возразить, но P.S. все прояснил:) вообще, комментарии нужны либо для генерации документации (если клиент требует), либо в местах со сложной/неочевидной логикой (если такие места появляются — у вас проблемы). лучшая документация для разработчиков — тесты.
                                    +1
                                    я наверно пропустил, но получается что для каждой кнопки нужен свой класс?
                                      0
                                      В общем, да
                                        0
                                        ээээ, а если у меня 100500 кнопок, различающихся только настраиваемыми параметрами? Мне что, для каждой делать отдельный класс?
                                          0
                                          Все зависит от того, какие параметры вы хотите настраивать.

                                          Вообще общий функционал реализуется в базовых классах. Далее наследники реализуют интерфейс, который обозначает что это кнопка и она работает в таком-то окружении. Вы можете настроить эту кнопку из интерфейса, определить права, иконки, порядок, изменить текст и прочее. Т.е. можно из одной кнопки в коде сделать 100500 кнопок в интерфейсе. Вообще строго говоря это не кнопка, а само действие, его обработчик. Кнопка — это уже элемент View, который связывается с этим действием, и берет из этого действия для своего отображения все что может.

                                          Можно отнаследоваться и сделать 100500 классов, можно настроить одну «кнопку» и размножить её в интерфейсе, настройки выгрузить в файлы конфигурации и распространять их с системой. Она сама все подгрузит и свяжет при развертывании. Вопрос лишь в том что вам нужно сделать и что настроить. Я с ходу не могу придумать сценарий где реально нужно 100500 классов. Хотя можно сделать одну кнопку и программно нагенерировать её конфигов отображений (скажем в цикле), которые потом пользователю представятся как много много пунктов меню скажем. Но это уже более сложная вещь, порог вхождения в необходимость таких средств ещё больше, чем для вещей описанных в статье. Увы :\ Но если интересно — могу рассказать подробнее, только опишите гипотетическую проблему, чтоб можно было придумывать решение.
                                            0
                                            а что, низзя сделать обработчик кнопки без создания лишнего класса?
                                              0
                                              Теоретически можно. Но это неудобно. Будет тенденция к огромным классам с тысячами методов-кнопок. Это тяжело поддерживать, тяжело тестировать. Да и класс это не такая дорогая вещь, чтоб опасаться её создавать по необходимости.

                                              И ещё, если у вас будет много разных обработчиков в одном классе — это нарушит принципы SOLID, и вообще не в духе ООП.

                                              Один класс — одно назначение. У кнопки, как правило, одно назначение, так что её концепция хорошо ложится на класс. В принципе можно сделать как бы одним классом как бы много кнопок, но это само по себе адЪ.
                                                +1
                                                Посмотрел ваши статьи, вы видимо на Qt специализируетесь.

                                                В этой статье описан прикладной код для корпоративных приложений на специализированной платформе. Задача платформы — избавить прикладного программиста (которые программирует бизнесс процессы) от необходимости ручками писать сами контролы как таковые. Вот с такой реализацией как в статье — можно забыть о контролах, обвесе, инфраструктуре, и писать только бизнесс код в песочнице, где ничего не сломается, все покрыто правильными транзакциями и все исключения перехватываются. По этому и такая модель, такая структура кода, такие атрибуты и реализация. Все в этом коде призвано сделать максимально простым и быстрым написание именно обработчика. От сюда и использование комментариев как заголовков, а не атрибутов, и специфичные контексты, и интерфейс, сигнатура которого реализуется. По факту для создания пустой кнопки надо ввести символов 10 с клавиатуры, все остальное делается автодополнением. Об этом и статья.

                                                Пишу это потому что мне показалось что вы взглядом Qt разработчика не распознали о чем тут речь, и код показался стремным и корявым. Хотя практика показывает что описанные принципы жизнеспособны. Эхехе, увы статья провалилась, очень хочется понять почему…
                                        +1
                                        — захаркоженые строки;
                                        — логику поиска существующих закладок, добавления новой нужно выносить в отдельные методы/класс.
                                        — комментарии, дублирующие название методов — зло. вы тесты пишете?

                                        почитайте про S.O.L.I.D. принципы
                                          –1
                                          комменты не читай@сразу отвечай
                                            0
                                            с чего вы взяли, что я не прочел комментарии? вы не нашли ничего нового в моем? посмотрите внимательней.
                                              0
                                              1) естественно, что это только в примере
                                              2) см. 1
                                              3) см. как минимум, 2 комента выше
                                                0
                                                1-2 вы тут (как я понял вы тоже имеете отношение к этому коду — поправьте, если ошибаюсь) вроде как «прикладной код» демонстрируете, нет? примеры как раз нужно стараться всегда писать правильно, а не выкладывать говнокод на всеобщее обозрение. так как кто-то, возможно, будет ваш пример использовать.

                                                3 — еще раз: вы тесты пишете? про SOLID слышали, читали?
                                                  0
                                                  Слышали, читали, применяем. При чем тут он, конкретно?
                                                    0
                                                    кто он? если SOLID — то это они — принципы. конкретно — не видно по вашему коду, что слышали.
                                                    хотя, может это объясняется подходом «пишем только для примера». если это действительно так, то представьте, что все ваши junior разработчики, которые присоединяться к вашей компании, будут писать так, как в ваших примерах, начитавшись подобных статей. и что вы с этим потом будет делать, и как вы с этим будете потом жить.

                                        Only users with full accounts can post comments. Log in, please.