11 ноября 2009 в 11:40

Кодогенерация 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 проектов.
Гусев Данил @gusdan
карма
19,0
рейтинг 0,0
Самое читаемое Разработка

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

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