Кодогенерация 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
                А подсветка синтаксиса и прочие плюшки есть?
          • +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
                              интересно будет посмотреть про джанго. на самом деле, мне кажется, что кодогенерация для джанго несколько излишние предприятние.
                            • 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 года практически полностью автоматизировать одну из крупнейших оптовых контор в Казани, занимающейся алкоголем.
                                              Ну и других плюсов не мало. :)

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