11 November 2009

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

PythonUML Design
Четыре года назад, устроившись на новое место работы, увидел учетную систему приличных размеров на 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 проектов.
Tags:pythonumlpower designerкодогенерация
Hubs: Python UML Design
+35
9.9k 39
Comments 45
Top of the last 24 hours