Многоуровневая абстракция

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

    Данная статья содержит лишь теорию. Практической будет следующая статья (постараюсь чередовать).

    Многоуровневая абстракция


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

    Зачем вообще делят на уровни абстракции?


    1. Борьба со сложностью. На каждом уровне применяются методы именно данного уровня.
    2. Уменьшение связности.
    3. Обеспечение взаимозаменяемости классов на всех уровнях кроме верхнего.

    Многоуровневая абстракция работы с данными


    Идем по убыванию уровня абстракции:
    * Класс-сущность реального мира
    * Провайдер данных
    * Реальные библиотеки работы с данными

    Пример:
    * User
    * IUserProvider, SqlUserProvider, XmlUserProvider,…
    * SqlClient, XmlDocument,…

    При этом мы получаем низкую связность: User знает про интерфейс IUserProvider, SqlUserProvider и XmlUserProvider выполняют IUserProvider и пользутся библиотеками SqlClient и XmlDocument. Более того, объекты определенного уровня абстракции работают только с объектами следующего (нижнего) уровня абстракции, но никак не наоборот, что не допускает циркулярных связей.

    Когда возникают проблемы?


    1. Обычно в одном проекте несколько многоуровневых абстрактных моделей. Проблемы возникают если несколько абстрактных моделей надо подвергнуть однообразным изменениям. При этом приходится вносить изменения во все промежуточные уровни абстракции включая верхний.
    2. При прототипировании накладные расходы на проектирование многоуровневой абстрактной модели могут быть слишком высоки и возможно написание временного кода без уровней абстракции, который придется выкинуть после утверждения прототипа.
    3. Абстракция от источников данных может породить (и порой порождает) неоптимальную работу с источниками данных.

    Что делать?


    Кодогенерация во многих случаях (не всегда) может заменить многоуровневую абстракцию. При этом будут генерироваться конечные классы (из верхнего уровня абстракции), содержащие в себе методы работы с выбранным источником данных.
    1. Имея в основе метаданные, мы можем вносить изменения в алгоритмы генерации кода и разом модифицировать всю модель.
    2. При наличии метаданных прототип модели можно получить в кратчайший срок.
    3. За счет наличия генераторов для каждого источника данных, модель будет сгенерирована с приемлемой оптимальностью работы с выбранным источником данных, учитывая его специфику.

    Чем кодогенерация может помочь в сложных моделях


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

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

    Кодогенерация + многоуровневая абстрактная модель


    Данные подходы не противоречат друг другу и могут использоваться совместно. Например, в ASP.NET существует система хранения личных данных пользователей в профилях (Profile). Там выстроена абстрактная модель с несколькими уровнями абстракции, а сверху лежит ProfileBase. Если список свойств мы зададим в конфигурации, то будет сгенерирован потомок класса ProfileBaseProfileCommon, который будет содержать те свойства, которые мы указали в конфигурации. Фактически, в конфигурации мы указали метаданные.

    В следующей статье мы разработаем определенный несложный кодогенератор.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 20

      –6
      чего только не придумают люди, лишь бы не использовать Ruby
        0
        А причем тут "не использовать Ruby" и вообще Ruby?
          –1
          да, дело в том, что смотрю я на примеры кодогенерации и вижу давно реализованные в RoR вещи, простые интуитивные кодогенераторы.
          Это так, к слову, холивар не собираюсь разжигать.
          Если незнаком с Ruby - советую почитать ради интереса, я сам был сильно удивлен, когда первый раз увидел фишки "кодогенерации" в Ruby.
            +2
            В RoR это не придумали, а реализовали. Как и в куче других MVC-фреймворков и не только.
              0
              ничего уникального в ROR нету. просто у фреймворка отличный дизайн (имхо)
                0
                кстати, по поводу "давно", однако Ror сделали в 2004 году
            –3
            как раз руби (точнее рельсы) и реализуют зачастую кодогенерацию.
              +1
              Если бы в RoR ее небыло - им бы было совсем неудобно пользоваться. Отказались от абстракции - приняли кодогенерацию.
                0
                Уточню - от многоуровневой абстракции :)
            0
            Прошу меня извинить, что вот я уже на протяжении двух статей докапываюсь к автору, просто я не согласен с его мнением. Дизайн паттерны http://en.wikipedia.org/wiki/Design_patt…(computer_science) заслуживают отдельной ветки, и они не совсем связаны с кодогенерацией.
            Мне просто не приятно как разработчику читать такие статьи, когда говориться не зная про что. Чтобы вы не приняли мои слова за пустоту, постараюсь вам объяснить. Я разработчик ПО для ОПСОСов. Одной из моих задач является создание сценариев поведения при звонках, это обработка биллинга, разрешение абоненту звонить/получать и отправлять другие виды траффика. Все сценарии выглядят однотипно, в виде блоков. Блоки это обращение к разным системам за информацией. То есть легче написать приложение, куда выносишь эти блоки граффически, делаешь между ними связи и вперёд, генеришь нужный код, потом его компилишь.
            А теперь вернёмся к этой статье.
            Кодогенерация по большому счёту создание кода, который схож между собой, но, например, последовательность его разная, или разные стуктуры данных (например код для каждой таблицы в базе данных со своими полями). Вот для этого используется кодогенерация, чтобы не писать почти одно и тоже тысячу раз, а позволить это делать программе.
            Автор же в этой статье пытается всунуть Дизайн паттерны, которые имею совсем другой смысл, и не связаны с кодогенерацией. Дизайн паттерны указывают на стиль написания вашего кода, но они никогда не заменяют кодогенерацию или как то связаны с ней, наоборот, в кодогенерации сгенерированный код может быть по какому-то из шаблонов, но рассматривать все стили программирования чтобы объяснить кодогенерацию это бред.
            Кто хочет разобраться побольше с Дизайн паттернами советую посмотреть на Spring.NET(http://www.springframework.net).
            Возвращаясь к статье, хочу сказать, нет, она в приципе не плохая, ну конечно неполно написано, но в целом нормально, но она не по адресу.
              0
              По-вашему многоуровневая абстракция - паттерн?)
            –3
            В комментариях часто упоминают Ruby, там одна из фишек языка как раз и заключается в кодогеннерации. RoR просто её умело использует.
              0
              Только это не фишка языка. Это фишка системы.
                0
                поясните, что Вы имеете ввиду под понятием "система" ?. Все топики где упоминается Ruby заминусовали. Лисп и его макросы тоже позволяют кодогенерацию. Да и темплейты в c++ тоже можно рассматривать как кодогенераторы.
                  0
                  В RubyOnRails существует кодошенерация - есть специальные скрипты генерации Моделей, Контроллеров и Видов.
                  Насчет макросов языка Ruby - не встречал.
                    0
                    Макросы в лиспе, а в Ruby для этого можно использовать eval, module_eval/class_eval.
              0
              В качестве примеров систем кодогенерации можно привести ERWin (модель Бд -> приложение на VB) и Rational Rose (модель класов -> c++, java).
                0
                Вот никак в толк не возьму, если у вас есть некие метаданные для некоего кодогенератора, то чего бы сразу и не написать прогу, которая по этим данным и работает без всякой кодогенерации? Медленно? Так медленно только на очень ограниченном куске программы — его отдельно написать. Лежат себе в базе данные, а прога их читает и отрабатывает. Кодогенераторы иногда используются чтобы сбросить структуру данных в исходник программы и предоставить программисту готовые переменные с названиями по этим данным. Все это глючит всегда и у всех и используется только в одну сторону — любое изменение в программе и прощай кодогенерация. Правильные пацаны кодогенераторов не используют.

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