Недостатки объектной модели Microsoft Project Standard/Professional

Уже неоднократно от некоторых MVP по MS Project, а также со стороны представителей компании Microsoft мы получали предложения высказать свое мнение, какие улучшения мы бы хотели увидеть в будущих версиях Project. Поскольку мы не являемся профессиональными менеджерами проектов или консультантами по управлению проектами, не будем рассуждать о том, какие нужные пользователям функции стоит добавить в продукт. Тем более что на эту тему уже есть обсуждения, например…

Зато у нас в компании Brise есть опыт создания дополнительных компонентов как для настольного Project, так и для сервера, и мы можем взглянуть на продукт «со своей колокольни». Опишем те недостатки программного интерфейса (API) MS Project, которые делают разработку дополнений к нему затруднительной, а кое-где и делают невозможной реализацию некоторых востребованных функций. Может быть, к нашему мнению никто не прислушается, и ситуация не улучшится, но мы хотя бы предостережем других разработчиков, которые хотят программировать под Project, от тупиковых путей.

Эта статья посвящена объектной модели десктопного Project Standard/Professional. Наш перечень замечаний не исчерпывающий, но это те неудобства, с которыми часто приходится сталкиваться в работе. Описанные недостатки относятся к любым актуальным версиям продукта, потому что с 2007 года практически ничего не изменилось, – основные перемены были связаны с появлением ленты инструментов (ribbon). Те проблемы, которые не мешают достигать результата, но затрудняют программирование, могут показаться субъективными. Но это нарушения логики, мешающие осваивать программный интерфейс и держать в голове его устройство.

Самые популярные и наболевшие проблемы

Ограниченные возможности подключения к серверу

Надстройка для Project Professional подключается к Project Server от имени того доменного пользователя, который запустил Project. Это становится проблемой, если пользователь не доменный, или если к серверу подключается не тот пользователь, который работает в Windows. Такая ситуация – не редкость, и в худшем случае надстройка вообще не «видит» сервер. Объектная модель Project Professional не предоставляет своей надстройке возможности использовать то же подключение, которым пользуется Project.

Нет справочника полей, существующих в MS Project, с их свойствами

В объектной модели Microsoft Project отсутствует программно доступный справочник полей задач, ресурсов, назначений, с их свойствами, такими как название, тип, доступность для редактирования. В результате дополнению к Project неизвестны свойства не только корпоративных полей, но и встроенных. Разработчики дополнений к Project вынуждены создавать свои справочники стандартных полей, а корпоративные поля надстройка должна «спрашивать» у сервера при подключении.

В частности, нет удобного способа проверки существования определенного настраиваемого поля в проекте. Для проверки приходится сделать попытку использования поля, а потом поймать исключение.

try {
    Globals.ThisAddIn.Application.FieldNameToFieldConstant("Нужное поле", MSProject.PjFieldType.pjTask);
}
catch {
    System.Windows.Forms.MessageBox.Show("Нужное поле не существует");
}

Проблемы при работе со значениями полей

Существуют методы Resource.SetField (установить значение поля) и Task.SetField, но нет метода Assignment.SetField. Аналогично, метод Assignment.GetField также отсутствует. При этом методы Resource.SetField и Task.SetField в качестве значений полей принимают только строки. Поэтому, при необходимости работать со значениями локальных (встроенных) полей с учетом их типов, приходится избегать SetField, и использовать свойства объектов Task и Resource. Но для корпоративных полей Project Server таких свойств нет, поэтому их значения всегда представляются строками. Например, для полей типа «Флаг» это строки «Да» и «Нет», хотя логично и естественно хранить значение такого поля в переменной булевого типа. Особенное неудобство возникает при чтении числовых корпоративных полей: они всегда округляются до 2-х знаков после запятой во время преобразования в строку, тогда как локальные поля можно читать и с большей точностью.

Некоторые методы и свойства объекта Application относятся к текущему проекту

Это может быть даже удобно, если использовать такие свойства, как Application.ActiveProject (активный проект) и ActiveCell (активная ячейка). Интуитивно понятно, что они касаются текущего активного проекта. Но если попытаться воспользоваться свойством Calculation (режим автоматического расчета), то выяснится, что оно также относится к текущему проекту, хотя это даже не сказано в официальной документации по объектной модели. С опытом ее использования разработчик приходит к важному выводу: множество важных манипуляций с проектом можно выполнить, только когда его окно активно. Какие именно это манипуляции – интуитивно неясно даже опытным пользователям Project, и становится понятным только в процессе создания приложения. Вот некоторые из них:

  • CustomFieldGetName (получить имя поля)
  • ViewApplyEx (переключить представление)
  • FilterApply (применить фильтр)
  • SelectAll (выделить все строки)

Пустые элементы в коллекциях задач и ресурсов

Microsoft Project позволяет добавлять пустые строки на листы задач (или ресурсов) в проекте. Они не являются задачами, и используются исключительно для оформления. Однако на уровне объектной модели такие задачи включены в коллекцию Project.Tasks в виде пустых объектов (null). Об этом приходится всегда помнить при переборе по коллекциям Tasks и Resources, поскольку элементарный код может вызвать NullReferenceException на некоторых проектах:

foreach (MSProject.Task task in proj.Tasks) {
    if ((bool)task.Summary) { // NullReferenceException!
        …
    }
}

События MS Project: нелогичность и недостаточность

Для подключения обработчиков некоторых событий проекта нужно использовать объект Project. Казалось бы, так и должно быть, но картина намного более странная. Дело в том, что для обработки большинства событий, относящихся к ресурсам, задачам, проектам, объектная модель MS Project предлагает подписываться на события объекта Application. Если бы по этому принципу обрабатывались абсолютно все события MS Project, это было бы понятно и логично. Но на самом деле, несколько событий объявлены в объекте Project, а вот это, следуя логике и интуиции, предугадать уже никак не возможно: Activate, BeforeClose, BeforePrint, BeforeSave, Calculate, Change, Deactivate, Open.

Если бы это была единственная проблема, связанная с обработкой событий в приложении, можно было бы вздохнуть с облегчением. Но есть и более неприятный недостаток объектной модели: далеко не все действия пользователя в MS Project вызывают события, на которые можно подписаться и отловить. Полный перечень таких действий был бы слишком объемный, можно обобщить наиболее типичные из них:

  • Работа с повременными данными назначений;
  • Операции копирования/вставки задач, ресурсов, назначений;
  • Добавление/удаление подпроектов;
  • Изменения некоторых сущностей проекта с помощью надстройки для Project.

В итоге, становится весьма проблематичным создание дополнения к MS Project, основанного на отслеживании выполняемых изменений проекта. Рано или поздно в результате действий пользователя проект изменится так, что данные о проекте, хранящиеся в такой надстройке к Project, уже перестанут быть актуальными. Тогда надстройка должна будет заново анализировать проект целиком, что при большом объеме данных может быть очень длительной и ресурсоемкой задачей.

Кто виноват, и что делать?

Хотя виноват, естественно, Microsoft, было бы полезно разобраться в причинах, почему возникли и так долго не исправляются недостатки API MS Project. Можно сказать, что они сложились исторически. Объектная модель Project проектировалась еще в 90-е годы прошлого века, когда не было даже Microsoft .NET, а только COM. Кроме того, одна и та же структура объектов используется как в надстройках для Project, создаваемых на основе технологии VSTO и работающих в среде .NET, так и в макросах, которые пишутся на Visual Basic. Также у Microsoft есть принцип «не кидать разработчиков», благодаря которому устаревший код в течение многих лет продолжает работать на новых версиях продуктов. В связи с перечисленным, объектная модель MS Project очень консервативна, и меняется от версии к версии только в части новых возможностей продукта.

Первое, что могут сделать разработчики Microsoft Project для упрощения освоения и использования API – дать больше информации. Возможно, описанные нами странности, имеют причины, связанные с глубокими особенностями архитектуры продукта, и появились не на пустом месте. Тогда нужны статьи в MSDN, описывающие общую логику организации объектной модели Project. Иначе нужно серьезно дорабатывать API: устаревшие его компоненты вначале поддерживать в режиме совместимости, а в следующей версии отключать, тем самым обеспечивая мягкий переход существующих дополнений к продукту на новый фундамент. И вообще, не следует чересчур оберегать разработчиков. Те из них, кто создают новые перспективные дополнения к Project и расширяют его возможности, по достоинству оценят более удобную и мощную объектную модель.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>