Pull to refresh

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

Reading time3 min
Views12K
Четыре года назад, устроившись на новое место работы, увидел учетную систему приличных размеров на 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:
Hubs:
+35
Comments45

Articles

Change theme settings