Кодогенерация UML->Python (Django)

    Четыре года назад, устроившись на новое место работы, увидел учетную систему приличных размеров на python + wxWidgets + MSSql. Весь исходный код генерировался автоматически на основе UML диаграмм. Спустя несколько лет, я настолько проникся таким способом разработки, что и в собственных проектах на Django стал использовать автогенерацию кода.
    Давайте в общих чертах рассмотрим, как выглядит процесс создания «кодогенерируемого» проекта?


    Для начала нам нужно найти UML редактор с большими возможностями. Я использую Sybase Power Designer. В нем можно практически все.
    Сразу после установке PowerDesigner может генерировать C++, Java, C#, Visual Basic проекты. Написать свой кодогенератор совсем не сложно, так что немного повозившись пишем и используем свой.

    Все готово для рисования первого класса:


    Давайте назовем его Foo и добавим ему метод __call__:


    Пусть наш метод будет печатать значение одного переданного ему параметра:


    Теперь посмотрим, что мы будем иметь на выходе кодогенератора для созданного класса:


    Кодогенератор исходный код каждого класса размещает в отдельный модуль. Модуля располагаются согласно иерархи пакетов.
    Пока ничего впечатляющего мы не сделали и кодогенератор не оправдал своего существования.
    Давайте расширим наш пример еще двумя классами CheckHelper, PrintHelper. И покажем, что Foo имеет с ними связи типа composition:


    Посмотрим на генерируемый код:

    # -*- coding: cp1251 -*-

    #***********************************************************************
    #* Module: foo.py
    #* Path: foo
    #* Author: danil
    #* Modified: 11 ноября 2009 г. 10:50:37
    #***********************************************************************
    import checkHelper
    import printHelper

    class Foo(object):
      
      
      class __C_CheckHelper(object):
        def __get__(self, obj, cls):
         if obj is None:
           return checkHelper.CheckHelper
         value = getattr(obj, '#checkHelper', None)
         if value is None:
           value = checkHelper.CheckHelper()
           setattr(obj, '#checkHelper', value)
         return value
        def __set__(self, obj, value):
         raise AttributeError
        def __delete__(self, obj):
         setattr(obj, '#checkHelper', None)
      checkHelper = __C_CheckHelper() #B #B
      
      
      class __C_PrintHelper(object):
        def __get__(self, obj, cls):
         if obj is None:
           return printHelper.PrintHelper
         value = getattr(obj, '#printHelper', None)
         if value is None:
           value = printHelper.PrintHelper()
           setattr(obj, '#printHelper', value)
         return value
        def __set__(self, obj, value):
         raise AttributeError
        def __delete__(self, obj):
         setattr(obj, '#printHelper', None)
      printHelper = __C_PrintHelper() #B #B
      
      def __call__(self, val):
        if self.checkHelper(val):
          self.printHelper(val)


    * This source code was highlighted with Source Code Highlighter.


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

    Давайте подытожим, что нам дает такой подход к разработке проектов:
    1. Скорость разработки за счет автоматической генерации типовых кусков кода.
    2. Простота чтения проектов, навигация по UML диаграммам значительно проще, нежели чтение исходных текстов в файлах.
    3. Легкость модернизации за счет быстрого отслеживания всех связей между объектами.

    Это лишь обзорная статья, если хабросообществу интересно, напишу step by step пособия по генерации django проектов.
    Поделиться публикацией

    Комментарии 45

      0
      Очень интересно, пишите!
        +14
        Вряд ли быстрее будет разработка, скорее наоборот.
        Но пишите, интересно.
          +3
          Мне думается, что тут акцента надо не на быстроту ставить, а на то, что проект имеет явную структуру, а потому легче привлекать новых членов в команду разработчиков, передавать проект, выкладывать как open source.
            0
            если для проекта делается аналитика в виде UML-диаграмм, то для большого проекта генерация исходного кода по ним может быть неплохим стартом для работы кодера.

            возможные бонусы:
            — сокращается время на то, чтоб проект начал собираться (имеется ввиду первая сборка проекта);
            — наличие визуального представления структуры будущего проекта и документация интерфейсов (главное при отклонении реализации от модели, своевременно ее обновлять), важно когда вы пишите код и используете чужой модуль которого еще нет :-)
            +1
            Только классы исходя из диаграмм классов можно генерить?
              +2
              Можно все. Кодогенератор очень красиво настраивается под свои нужны.
                0
                А подсветка синтаксиса и прочие плюшки есть?
                  0
                  Я не использую.
              +2
              Да, было бы интересно почитать ещё
                +10
                Вы бы в самом начале указали ценник на PowerDesigner, у многих желание кодогенерацией заниматься надолго пропадёт. Кстати я смотрю на скриншотах у вас 12 версия :).
                  +4
                  Да, действительно, Power Designer стоит немало (от 230 000 руб). Я недавно перешел с 11 на 15 версию.
                  +8
                  Не проняло.

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

                  А тут мы имеем какую-то сгенерированную жуть.

                  Наверное, это все какие-то стандартные и ожидаемые доводы против таких штук) В любом случае, для себя лично практической пользы не увидел.
                    +2
                    На мой взгляд UML диаграммы «читаются» проще чем любой код.
                      +2
                      Ну а про фломастеры и вкус я думаю все знают.
                        +4
                        Вы, наверное, руководитель, а не рядовой разработчик? Да, UML-диаграммы делают Python более «ынтерпрайзным». Но при этом код, который получается после генерации, становится похожим на написанный на Java, на которой без IDEA (по отзывам несчастных) очень муторно писать.

                        У Вас кодогенерация демонстрируется на каком-то оторванном от жизни абстрактном примере. Какой-то Foo, CheckHelper, PrintHelper — что обозначают все эти названия? Давайте в следующей статье про Django какой-то более жизненный пример. Например, систему регистрации-авторизации пользователей. Стандартный компонент registration мне показался не лишенным недостатков, когда работал c Django.
                          +1
                          Я руковожу отделом, в котором 3 программиста, так что отношу себя к разработчикам. Исходный код, после генерации, является промежуточным звеном между UML и python. Нет необходимости его читать и тем более править.
                          0
                          Ну так читайте UML-диаграммы, раз хотите. Вопрос генерации кода из них — это совсем другой вопрос, который ведет к другому способу разработки, имеющему (на мой взгляд) значительные недостатки.

                          Кстати, не совсем по делу, но картинки, чтоб посмотреть структуру моделей, можно сгенерить из этих самых моделей:

                          code.google.com/p/django-command-extensions/wiki/GraphModels
                          code.djangoproject.com/wiki/DjangoGraphviz
                            0
                            UML — очень полезная штука, но генерировать повторяющийся код — серьезная ошибка. UML следует рисовать отдельно (лучше всего на бумажке:) или получать путем анализа существующего кода. Хорошо, если вручную: лучше разберетесь в коде и заодно поймете, что в нем надо изменить. Если же вручную разбираться в коде мучительно — значит, код ужасен и, вероятно, сгенерирован кем-то из UML.
                          +1
                          У меня вопрос к автору как человеку осведомленному в области UML.
                          Есть какие то достойные бесплатные аналоги Sybase Power Designer?
                            +3
                            Я пользовался только PowerDesigner'ом, BPWin'ом и MS Visio все они платные. Достойные обзоры уже были на хабре тут и тут
                              +1
                              бесплатных достойных нет :) из платных, но очень достойных могу посоветовать Enterprise Architect, к тому же он вполне подъемный: Desktop — ~4500р, Pro — ~6700р, Corp — ~8100р.
                                0
                                использовал в работе Enterprise Architect, года 2 назад он показался проще и удобней. тоже рекомендую. в нем есть возможность выбора процесса разработки и набор доступных диаграмм и инструментов адаптируется под него.
                              0
                              Вопрос ко всем поклонникам UML. Есть ли что-то приятное и бесплатное/имеющее кряк для Linux? BoUML и Umbrello, как мне кажется, имеют маловато возможностей по кодогенерации. В плагинах к NetBeans/Eclipse, она тоже отсутствует.
                                +1
                                Есть TopCoder UML Tool. Написано на Java. Я лично не пробовал, но эта штука активно используется в разработке на topcoder.com.

                                +3
                                интересно будет посмотреть про джанго. на самом деле, мне кажется, что кодогенерация для джанго несколько излишние предприятние.
                                  +1
                                  абсолютно излишнее.
                                  0
                                  В области встроенного ПО автогенеренный код применяется с большим успехом и очень давно. Дело все именно в удобстве документирования и разработке, основанной на примитивах (model-based development, например).

                                  А если разработка ведется по какому-либо отраслевому стандарту. то время экономится еще и за счет квалификации программного обеспечения для разработки и, как следствие, удешевлению верификации и сертификации.
                                    +9
                                    Может у меня что-то с глазами, но я не вижу никакой связи с Джанго в посте.
                                    Или это такой способ привлечь внимание?
                                      +3
                                      Я тоже удивился, а ещё удивило # -*- coding: cp1251 -*- разве на питоне не все пишут в # -*- coding:utf-8 -*-?
                                        0
                                        cp1251 — следствие использования плохого редактора по виндой.
                                        Проходит со временем.
                                      +3
                                      Описанный пример — пример неграмотного и глупого решения задачи. Какой смысл плодить сгенерированный дублирующийся код? Все ради того, чтобы рисовать стрелочки в ГУИ?

                                      А уж такую задачу, как связь и создание объектов по требованию можно решить легко без автогененированной каши.
                                        –2
                                        ну вы не правы, дорогой, вспомните долгие рассуждения о том, как правильно писать инклуды на спп, или как муторно искать нужный файл с классом в котором надо поправить 76 строчку, или подумайте какой-это геморрой делать апгрейд проекта в котором 150 файлов со странными названиями.
                                          +2
                                          Долгие рассуждения фиксятся документом под названием code convention. Нет времени его придумывать — возьмите Google Code Convention или Lockheed-Martin.

                                          >>Геморрой делать апгрейд проекта
                                          А это, извините, специфика разработки — чтобы что-то поменять, надо что-то поменять. В случае с UML у вас даже юнит-тестов на сгенерированный не будет.

                                          >> 150 файлов со странными названиями
                                          Такое будет как раз после использования кодогенератора.

                                          Кроме того, сравните возможности этого notepad-кодогенератора и нормального редактора кода — с подсветкой, ассистом и браузером кода.
                                            –2
                                            1. я о code-convension не знал, видимо в ближайшее время не узнаю,
                                            2. речь не о том, что бы сделать так, чтобы работало и сверять юнит-тестом, а быстро вспомнить что почем, и не рисовать картинки на столе
                                            3.прикольно а у вас проект все в одном файле лежат?)

                                            Не знаю, как вам, я тоже давно прирос к кодогенератору, и если вы не имеете проблем с синтаксисом языка и соглашениями о его оформлении, то проблем с кодогенератором у вас не будет. Я же стараюсь любой громоздкий проект перевести в него, потому как с картинками работать удобнее, чем с текстом.
                                              +1
                                              2. Ну так чтобы вспомнить, что почем, необязательно иметь кодогенератор, достаточно wiki c UML-схемой. Если конечно, у вас не директива «сначала UML, потом код по нему»
                                              3. Нет, у меня все выстроено иерархически, по папкам и проектам, так что вопросы к проекту на предмет «что-где» не появляются )

                                              Кодогенератор нужно использовать там, где нужен кодогенератор.
                                              Иначе code-generation превращается в co-degeneraton, со связанными руками, наколенными хаками и все такое. Тот же RUP, несмотря на всю формальность, со стороны архитекторов предусматривает только генерацию протоколов/интерфейсов, а код пишут люди.
                                              –1
                                              а зачем unit-тесты для кода, который из генератора вылезает?
                                                +2
                                                А вы посмотрите на иллюстрации в статье внимательно. Там генерирует только «скелет», а «мясо» вписывается руками. Я считаю, что его _надо_ тестировать.
                                              +1
                                              > вспомните долгие рассуждения о том, как правильно писать инклуды на спп

                                              Претензии к авторам C++ за отсутсвие модулей.

                                              > или как муторно искать нужный файл с классом в котором надо поправить 76 строчку

                                              Не знаю, у меня в php классы в строгом порядке по папкам, я всегда знаю где какой искать (и имена файлов соотвествуют классам).

                                              > или подумайте какой-это геморрой делать апгрейд проекта в котором 150 файлов со странными названиями

                                              Бросайте курить всякую дурь и называйте файлы нормально :)

                                              p.s. Вы про code convention не слышали, наверно и про inline documentation и системы типа javadoc/cppdoc не слышали? Теорию учите тогда и учитесь оформлять код правильно.
                                            +4
                                            UML в Django — это в первую очередь создание ORM-моделей.

                                            Не увидел пути к этому в посте:( А очень-очень хотел, правда.
                                              0
                                              Да, я тоже этого ожидал.
                                              У самого была (давным давно, когда был юн и холост) идея сделать на PyQt подобную генерилку, но руки так и не дошли.
                                                +1
                                                А не проще ли:
                                                а) придумать хорошие названия моделям,
                                                б) разбить модели по модулям
                                                и спокойно обозревать всё это добро без каких-либо доп. инструментов?

                                                Пункт «а», наверно, самый важный. Иногда название ну никак не придумывается. Это явный признак плохого дизайна. Когда названия ясны и точны, вопросов о структуре и связях не возникает и схемы практически не нужны.
                                                  0
                                                  Так вот об архитектуре и речь. UML позволяет создать архитектуру, «подвигать» её в разные стороны, не написав ни единой строки кода. Вообще говоря, UML-модель — это нечто еще обльшее, что еще шире охватывает архитектуру вашего приложения, чем простое проектирование структуры объектной модели.

                                                  Мы здесь не пытаемся отказаться от UML. Задача в том, чтобы не писать одно и то же сто, а иногда и тысячу раз. Не знаю как вам, а мне достаточно трудно обозревать в коде проект состоящий из 6-8 app-ов, в каждом из которых не меннее 10-12 моделей.

                                                  Задача автоматической генерации Django-моделей из диаграммы классов UML выглядит достаточно тривиальной. Интереснее было бы генерировать код для view из Sequence-диаграммы, автотесты из Use Case диаграмм и т.п.

                                                  Согласитесь, что при наличии подробного ТЗ, формальной формой которого является UML-модель, создание проектов с использованием Django сводится к однообразному механическому кодированию. Так почему бы не отдать однообразную бездумную работу инструменту, которые для этого создан?
                                              0
                                              Мне для диплома надо написать кодогенератор UML -> САА; хорошо, что прочитал эту статью, спасибо.
                                                –1
                                                Сильно рекомендую посмотреть на Active Record для Ruby
                                                  0
                                                  Лет 5-6 назад я участвовал в проекте, для которого мы написали ядро для кодогенерации кода python из PowerDesigner, и кстати тоже использовали wxWidgets и MSSQL (может это тот же проект? Тогда привет Марселю и Вите. :) )
                                                  Но основная фишка того проекта — это генерация типизированных форм из диаграмм объектов. Это позволило 3 разработчикам за 1.5 года практически полностью автоматизировать одну из крупнейших оптовых контор в Казани, занимающейся алкоголем.
                                                  Ну и других плюсов не мало. :)

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

                                                  Самое читаемое