Общий раздел > ПО Аналитика
Сравнение CASE-средств для кодогенерации ( от eUML2 до Enterprise Architect)
singleton:
...a помимо Enterprise Architect за борт были выкинуты:
* MagicDraw 14
* Visual Paradigm 6.1 Enterprise
* Rational RSD 7
* Borland Together
* Poseidon 6.0 и ArgoUML
* Netbeans UML Plugin
* Eclipse Omondo Plugin
* Fujaba
* MID Innovator 2007
Все это добро было протестировано в перспективе дизайнера (не путать с аналитиком) при подготовке модели к реализации на Java 6.0. Таким образом сформировались минимальные требования к UML инструментам, которые, будучи далеко не полными, позволили все-же отсеять почти всех кандидатов. Требования эти, в свете сказанного, были простые и понятные, :
1. Class Diagrams, UML2
2. Good Associations Support, 1:1 / 1:n / qualifiers
3. Contemporary code generator, type safe java 1.5 generics
Казалось бы, что может быть проще? Диаграммы классов у всех кандидатов есть. Ассоциативные связи между классами это тоже, вроде как, нечто фундаментальное... И тем не менее, уже тут у некоторых начинаются проблемы. Которые только усугубляются при попытке сгенерировать в конечном итоге достойный код.
- - - to be continued - - -
singleton:
- - -
ПАРА СЛОВ В НАЧАЛЕ
прежде чем изложить подробности и результаты теста, хочу сказать пару слов о целях ради которых пишу.
Во-первых, захотелось обратить внимание комьюнити на беспрецедентный кризис в области средств поддержки uml моделирования. Заявления типа "Full UML 2.1 support", "XMI 2.1 support" или "sophisticated round-trip engineering" это пустой звук, вранье, маркетинг - называйте как хотите. Поразительно, но программисты именитых фирм не в состоянии написать нормальные средства поддержки uml, которые будут делать то, что от них ожидается. Это при том, что потребители находятся в том же домэйне, что и создатели: те же, по-сути, программисты.
Во-вторых, во мне теплится остаток надежды, что я все-же где-то что-то недоглядел, не нашел правильную опцию, не поставил галочку и в итоге отбраковал вполне себе хороший продукт. По-этому, дорогие пользователи упомянутых продуктов, если есть поправки - не стесняйтесь - пишите!
- - -
КАК ТЕСТИРОВАЛ:
Итак, сконцентрируемся на Диаграммах Классов, а точнее на ассоциативных связях. Собственно, для простоты эксперимента только их и будем рассматривать. Выбрав таким образом наше самое-самое-главное и фсе, с точки зрения дизайнера, можем смело привязывать к позорному столбу всех тех, кто даже к таким вещам отнесся не очень серьезно. Ведь без ассоциаций никуда!
Свойства ассоциаций (для удобства последующей оценки) я поделил на три функциональные группы
* Базовые свойства: => макс 3 пункта
- navigable (bi, a-b, b-a),
- multiplicity (1, 0..1, 1..*, *, итд)
- special: aggregation, composition
* Последовательности, множества, мультимножества: => макс. 2 пункта
- {unique}
- {ordered}
- их комбинация
* Qualifiers (Qualified Associations): => макс. 3 пункта
- 1:1, "хэш"
- 1:n, "мультихэш" и, как следствие, все те же опции мультимножеств
- несколько квалификаторов к рамках одной ассоциативной связи
Вот и вся функциоальность. Далее из построенных, на сколько это было возможно, моделей, генерировался код. Его качество влияло на оценку той или иной из описанных выше трех функциональных групп следующим образом:
* код неверный семмантически, либо синаксически:
=> оценка функ. группы понижается вдвое
* код верный, но не отвечает стандартам "type safety", реализуемым с помощью <generics> c 2004 года:
=>оценка функ. группы остается неизменной (+0%)
* код верный и обеспечена "type safety", с помощью Java 1.5 <generics> :
=>оценка функ. группы удваивается
singleton:
- - - РЕЗУЛЬТАТЫ ТЕСТА - - -
Sparx Enterprise Architect 7.0 Score: 9.5 points from 16
* basic features: 3 points x 2 = 6
Пришлось немного покопаться, прежде чем удалось хитростью уговорить EA генерировать type safe код для множеств. В Options->Source Code Engineerig->Java следует прописать в строчке Default Collection Class вот это заклинание: "java.lang.Collection<#TYPE#>". К GUI претензий нет. 6 пунктов как с куста.
* (multi-)set options: 1 points x 2 = 2
EA умеет различать {ordered} множества. Как и в случае с базовами функциями, надо немного поколдовать и указать в опциях в качестве Collection Class for Ordered Multiplicity вот такую, например строчку "java.lang.List<#TYPE#>" или "java.lang.LinkedHashSet<#TYPE#>".
В первом случае сгенерируются упорядоченные мультимножества (допускают дубликаты), во втором - упорядоченные множества. Одновременно создать в генерируемом коде обе эти разновидности не возможно. Для этого воспетому в рунете Архитектору элементарно не хватает поддержки {unique}.
* Qualified Associations: 3 points x 0.5 = 1.5
Квалификаторы, поддерживаются! Но только на бумаге. Вернее в GUI. А вот с кодом возникли серьезнве проблемы. В частности код, сгенерированный по Qualified 1:1 Association ничем от обычной 1:1 Association не отличается. Если квалифиаторов несколько, это только усогубляет ситуацию... Итого один пункт с натяжкой.
Rational RSD 7. score 10 points from 16
* basic features: 3 points x 2 = 6
ibm-овский софт позволяет моделировать все базовые функции. Полученный в итоге код грамотно использует generic-шаблоны.
* (multi-)set options: 2 points x 2 = 4
Перед генерацией для всех видов (мульти-)множеств можно задать задать свои альтернативы java.util.Collection. Впрочем, заданные по умалчанию, чаще всего подойдут:
java.util.Collection; // non-ordered, non-unique
java.util.List; // {ordered}, non-unique
java.util.Set; // non-ordered, {unique}
java.util.SortedSet; // {ordered}, {unique}
Полученный в итоге код грамотно использует generic-шаблоны.
* Qualified Associations: 0 points
Перерыл все и... не нашел квалификаторов! Может я, конечно, не там искал, но больше получаса на поиски не было...
Visual Paradigm 6.1 Enterprise score: 6 points from 16
* basic features: 3 points x 2 = 6
Парадигм подобно Rational RSD справляется с базовой задачей и генерирует безупречный код.
* (multi-)set options: 0 points x 0.5 = 0
Свойства {ordered} и {unique} в парадигму Парадигмы как-то не вписались. И зря. 0 пунктов
* Qualified Associations: 0 points x 0.5 = 0
Квалификаторов нет. На нет и суда нет. И пунктов тоже нет.
Borland Together 2006 R2 Score: 5.5 points from 16
* basic features: 3 points x 1 = 3
Борланд предлагает выбирать одну из 20 реализаций класса Collection каждый раз, когда надо создать новую 1:n связь. Хорошо это или плохо оценить не берусь. С одной стороны долго, с другой стороны больше свободы действий. Вручаем Борланду три пункта и фактор x1, т.к. код получается хоть и правильный, но актуальным его можно было назвать 4 года назад. До введения generics.
* (multi-)set options: 2 points x 0.5 = 1
Свойства {ordered} и {unique} отражены в GUI. Но на коде это никак не сказывается. Один пункт. В долг.
* Qualified Associations: 3 points x 0.5 = 1.5
Квалификаторы тоже исключительно в GUI. Зато очень просто и удобно.
Poseidon 6.0 и ArgoUML Score: 4 points from 16
* basic features: 3 points x 1 = 3
ArgoUML и его коммерческий отпрыск Poseidon вот уже 3 года не в состоянии реализовать поддержку шаблонов. Форумные мольбы клиентов, заплативших за софт последние кровные, в последнее время просто игнорируются. В остальном же код получается корректный. С фактором х1 базовые функции приносят повелителю морей три очка.
* (multi-)set options: 1 points x 1 = 1
Хорошая новость: {ordered} констрэйн присутствует и даже более-менее грамотно переводится в java код (без generics). А плохая новость: {unique} нету. Совсем нету.
* Qualified Associations: 0 points x 0.5 = 0
Квалификаторы не имеют место быть. А как громко была заявлена поддержка UML2...
MagicDraw 14. score: 4 points from 16
* basic features: 3 points x 0.5 = 1.5
волшебный художник позволяет моделировать все базовые ассоциативные функции. Но полученный в итоге код совершенно неверен. Элементарная "1:n" связь между Class1 и Class2 генерируется как
private Class2 m_class2;
т.е. кардинальность получается "1:1"
* (multi-)set options: 2 points x 0.5 = 1
Свойства {ordered} и {unique} есть. Но о генерации правильного кода говорить не приходится, по причине описанной выше.
* Qualified Associations: 3 points x 0.5 = 1.5
Квалификаторы есть! Более того, их можно задать сколь угодно много для одной и той же ассоциации. Два пункта честно заработаны, но успех делим пополам, поскольку, опять же, код от MagicDraw просто безобразие! (или, все же надо где-то что-то подкрутить?)
Fujaba 5.0.4 Score: 3 points from 16
* basic features: 3 points x 0.5 = 1.5
Для некоммерческого проекта весьма неплохо. GUI выглядит некузяво, но свое дело делает. А вот генерация кода, как и ожидалось, для продуктивных целей не подходит. Диагноз примерно как и в случае с MagicDraw: неважно какие нюансы вводились в модель ассоциации двух классов. На выходе всегда простейшая 1:1 кардинальность, типа
public class Class1 {
private Class2 bbb;
}
Основное различие: 900$. Такова цена MagicDraw UML Professional Edition for Java
* (multi-)set options: 0 points x 0.5 = 0
{ordered} и {unique} fujaba профуябила.
* Qualified Associations: 3 points x 0.5 = 1.5
Квалификаторы, к моему удивлению есть! Но кода для них опять нет.
Netbeans UML Plugin Score: 1.5 points from 16
* basic features: 3 points x 0.5 = 1.5
Очень и очень сырым оказался прилагаемый к Netbeans UML Plugin. Если в modelling GUI базовыми функциями еще кое-как можно пользоваться, то получаемый код вообще не компилируется. Что-то они там намудрили, да так, что перлы типа Collection<void> не редкость. Ага, ушел итерировать пустоту...
* (multi-)set options: 0 points x 0.5 = 0
{ordered} и {unique} отсутствуют-с. Будем ждать и надеяться. А пока 0 пунктов.
* Qualified Associations: 0 points x 0.5 = 0
Квалификаторы не имеют место быть. Но ходють слухи, что скоро появятся.
Eclipse Omondo Plugin "EclipseUML" Score: not rated
* Коммерческий плагин для eclipse. Тестировать его не счел нужным, поскольку вот уже год как произошел раскол в стенах Omondo. R&D команда в полном составе весело позвякивая карабинами сбежала и организовала свою фирму: Soyatec. Там они по сей день совершенствуют новую версию своего продукта, переименованного из EclipseUML в eUML2. Но о нем отдельно и подробнее.
Soyatec eUML2 Score: 12 points from 16
* basic features: 3 points x 2 = 6
Забегая вперед скажу, что eUML2 всех победил. Это очень простой, но в тоже время идеально заточенный под нужды дизайна инструмент. Нарисованная за пол-минуты базовая диаграмма была без дополнительных усилий с моей стороны переведена в безупречный код.
* (multi-)set options: 1 points x 2 = 2
{unique} отсутствуют, как и у многих других (интересно почему?) и это минус.
{ordered} множества поддерживаются, на выходе по-умолчанию Collection, либо List. Оба корректно параметризированы, разумеется.
* Qualified Associations: 2 points x 2 = 4
Квалификаторы есть. Модель упрощенная, и потому здесь нельзя присвоить одной ассоциации больше одного квалификатора. По-правде сказать, в реальности я не встречался с необходимости подобной структуры... Но eUML2 теряет на этом еще один пункт, зарабатывая в данной категории два очка из трех возможных.
Зато код, сгегерированый из этой, немного упрощенной модели... не имеет равных. Предлагаю вам самим убедиться в этом и попробовать найти хоть одного конкурента, справляющегося с повседневными и, вообще-то, не особенно и сложными задачами так, как это делает eUML2!
модель:
результат (free edition):
--- Код: ---/**
* @uml.property name="project"
* @uml.associationEnd multiplicity="(0 -1)"
* inverse="person:model.Company"
* qualifier="key:java.lang.Object model.Project"
*/
private Map<Object, Collection<Project>> projectMap;
/**
* Getter of the property <tt>project</tt>
* @return Returns the project.
* @uml.property name="project"
*/
public Map<Object, Collection<Project>> getProject()
{
return projectMap;
}
/**
* Setter of the property <tt>project</tt>
* @param company The project to set.
* @uml.property name="project"
*/
public void setCompany(Map<Object, Collection<Project>> project) {
this.projectMap = project;
}
--- Конец кода ---
Результат возможный с помощью Velocity Templates (тока за дэнги)
--- Код: ---
/**
* @uml.property name="project"
* @uml.associationEnd multiplicity="(0 -1)"
* inverse="company:model.Project" qualifier="key:java.lang.Object model.Project"
*/
private Map<Object, Collection<Project>> projectMap;
/**
* Getter of the property <tt>project</tt>
* @return Returns the projectMap.
* @uml.property name="project"
*/
public Map<Object, Collection<Project>> getProject() {
return projectMap;
}
/**
* Returns a set view of the keys contained in this map.
* @return a set view of the keys contained in this map.
* @see java.util.Map#keySet()
* @uml.property name="project"
*/
public Set<Object> projectKeySet() {
return projectMap.keySet();
}
/**
* Returns a collection view of the values contained in this map.
* @return a collection view of the values contained in this map.
* @see java.util.Map#values()
* @uml.property name="project"
*/
public Collection<Collection<Project>> projectValues() {
return projectMap.values();
}
/**
* Returns <tt>true</tt> if this map contains a mapping for the specified key.
* @param key key whose presence in this map is to be tested.
* @return <tt>true</tt> if this map contains a mapping for the specified key.
* @see java.util.Map#containsKey(Object)
* @uml.property name="project"
*/
public boolean projectContainsKey(Object object) {
return projectMap.containsKey(object);
}
/**
* Returns <tt>true</tt> if this map maps one or more keys to the specified value.
* @param value value whose presence in this map is to be tested.
* @return <tt>true</tt> if this map maps one or more keys to the specified value.
* @see java.util.Map#containsValue(Object)
* @uml.property name="project"
*/
public boolean projectContainsValue(Collection<Project> project) {
return projectMap.containsValue(project);
}
/**
* Returns the value to which this map maps the specified key.
* @param key key whose associated value is to be returned.
* @return the value to which this map maps the specified key, or
* <tt>null</tt> if the map contains no mapping for this key.
* @see java.util.Map#get(Object)
* @uml.property name="project"
*/
public Collection<Project> getProject(Object object) {
return (Collection<Project>) projectMap.get(object);
}
/**
* Returns <tt>true</tt> if this map contains no key-value mappings.
* @return <tt>true</tt> if this map contains no key-value mappings.
* @see java.util.Map#isEmpty()
* @uml.property name="project"
*/
public boolean isProjectEmpty() {
return projectMap.isEmpty();
}
/**
* Returns the number of key-value mappings in this map.
* @return the number of key-value mappings in this map.
* @see java.util.Map#size()
* @uml.property name="project"
*/
public int projectSize() {
return projectMap.size();
}
/**
* Setter of the property <tt>project</tt>
* @param value the projectMap to set.
* @uml.property name="project"
*/
public void setProject(Map<Object, Collection<Project>> project) {
projectMap = project;
}
/**
* Associates the specified value with the specified key in this map
* (optional operation).
* @param key key with which the specified value is to be associated.
* @param value value to be associated with the specified key.
* @return previous value associated with specified key, or <tt>null</tt>
* @see java.util.Map#put(Object,Object)
* @uml.property name="project"
*/
public Collection<Project> putProject(Object object, Collection<Project> project) {
return (Collection<Project>) projectMap.put(object, project);
}
/**
* Removes the mapping for this key from this map if it is present
* (optional operation).
* @param key key whose mapping is to be removed from the map.
* @return previous value associated with specified key, or <tt>null</tt>
* if there was no mapping for key.
* @see java.util.Map#remove(Object)
* @uml.property name="project"
*/
public Collection<Project> removeProject(Object object) {
return (Collection<Project>) projectMap.remove(object);
}
/**
* Removes all mappings from this map (optional operation).
* @see java.util.Map#clear()
* @uml.property name="project"
*/
public void clearProject() {
projectMap.clear();
}
--- Конец кода ---
до следующего раза. поправляйте и дополняйте :)
Ваш Dimitri Alexeev a.k.a. singleton
Galogen:
--- Цитата: singleton от 13 Сентября 2007, 05:20:55 ---до следующего раза. поправляйте и дополняйте :)
Ваш Dimitri Alexeev a.k.a. singleton
--- Конец цитаты ---
Дмитрий очень интересный и содержательный анализ.
Поскольку в дискуссиях форума частенько звучало негативное отношение к автогенерации кода. Мол зачем она нужна, она все равно кривая и косая. Теперь становится понятно, где и что кривое и косое.
Вопрос: А Вы в своей практике активно стараетесь использовать автогенерацию? Если да, то насколько это облегчает Вам жизнь? Насколько это вообще актуально?
singleton:
--- Цитата: Galogen от 13 Сентября 2007, 08:57:02 ---Вопрос: А Вы в своей практике активно стараетесь использовать автогенерацию? Если да, то насколько это облегчает Вам жизнь? Насколько это вообще актуально?
--- Конец цитаты ---
Все мои предыдущие попытки использовать uml на стадии дизайна не только как нотацию я рассматриваю как поражение. Отвечая на второй вопрос, жизнь в итоге становилась только сложнее. Но давайте оставаться оптимистами: чем крупнее разрабатываемая система, чем качественнее используемый инструментарий, тем актуальнее использование автогенерации. Безусловно, речь не идет о генерации готового кода. Но надежда на создание статического и функционального каркаса приложения, который не надо корректировать, а только заполнять - эта надежда еще не умерла. Тем более что uml case продукты медленно, но верно выходят на качественно новый уровень. Вместо того, чтобы просто сетовать на недостатки тех или иных решений, в последнее время пытаюсь устанавливать контакт с разработчиками Может это сподвигнет их к улучшениям...
з.ы. Жаль что никто пока не поделился своим критическим мнением касательно справедивости результатов моего теста... Тот же MagicDraw, например, хоть и не в состоянии генерировать нормальный java-код (за что и получил только четверть пунктов), но ребята не поленились сделать экспорт в EMF2, а это открывает широкие возможности для внешних кодогенераторов на базе eclipse framework.
Навигация
Перейти к полной версии