Объектно-ориентированное проектирование с примерами

Сценарии работы


Сейчас, когда мы представили себе систему в целом, продолжим наш анализ и изучим несколько сценариев ее работы. Сначала перечислим ряд основных режимов использования:

    Клиент звонит по телефону в удаленную телемаркетинговую организацию, чтобы сделать заказ.

    Клиент посылает заказ по почте.

    Клиент звонит, чтобы узнать состояние дел по его заказу.

    Клиент звонит, чтобы добавить или убрать некоторые позиции из заказа.

    Кладовщик получает указание отгрузить клиенту необходимое количество товара.

    Служба доставки получает со склада заказанные клиентом товары и готовит их к отправке.

    Бухгалтерия готовит счет для клиента.

    Отдел закупок готовит заказ на новый товар.

    Отдел закупок добавляет или удаляет имя поставщика из списка.

    Отдел закупок запрашивает поставщика о состоянии заказа.

    Отдел приема товара принимает груз от поставщика и проверяет его соответствие заказу.

    Кладовщик заносит новый товар в список.



    Бухгалтерия отмечает прибытие нового товара.

    Плановый отдел генерирует отчет о показателях продаж по различным типам продуктов.

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

    Каждый из основных сценариев может включать в себя ряд вторичных:

      Заказанного клиентом товара нет на складе.

      Заказ клиента неверно оформлен, или в нем присутствуют несуществующие или устаревшие идентификаторы товаров.

      Клиент звонит, чтобы проверить состояние заказа, но не помнит точно что, кем и когда было заказано.

      Кладовщик получил расходную накладную, но некоторые перечисленные в ней товары не нашлись.

      Служба доставки получает заказанные клиентом товары, но они не соответствуют заказу.

      Клиент не заплатил по счету.

      Отдел закупок делает новый заказ, но поставщик либо ушел из бизнеса, либо больше не поставляет заказанный тип товара.

      Отдел приема товара принимает груз, не полностью соответствующий заказу.

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

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


      Для системы такой сложности, наверно, будут выявлены десятки основных сценариев и еще большее количество вторичных. Этот этап анализа может занять несколько недель, пока не удастся добиться более или менее подробного уровня детализации [Но помните о параличе анализа: если фаза анализа не укладывается в сроки, диктуемые бизнесом, то "оставь надежду всяк сюда входящий", - этот бизнес не для вас]. Поэтому мы настоятельно советуем применять правило восьмидесяти процентов: не ждите, пока сформируется полный список всех сценариев (никакого времени на это не хватит), изучите около 80% наиболее интересных из них и, если возможно, попытайтесь хотя бы оценочно проверить правильность общей концепции. В этой главе мы подробно остановимся на двух основных сценариях.

      На рис. 10-2 представлен сценарий, в котором покупатель размещает свой заказ в телемаркетинговой фирме. В выполнении этой системной функции задействовано несколько различных объектов. И хотя управление осуществляется взаимодействием клиента (aCustomer) с агентом (anAgent), есть и другие ключевые объекты, а именно: сведения о клиенте (aCustomerRecord), база данных о товарах (inventoryDatabase) и заявка на комплектование (aPackingOrder), являющиеся абстракциями системы складского учета. Этот список абстракций формируется как раз на этапе рассмотрения сценариев работы.



       Рис. 10-2. Сценарий заказа.

       


      Рис. 10-3. Сценарий выполнения заказа.

      Рис. 10-3 отражает продолжение данного сценария. На нем представлена схема взаимодействия кладовщика и расходной накладной. Мы видим, что здесь кладовщик является главной фигурой. Он взаимодействует с другими объектами, например с отгрузкой (shipping), которой не было в предыдущем сценарии. Однако большинство объектов, фигурирующих на рис. 10-3, присутствуют также и на рис. 10-2, хотя они играют в этих сценариях различные роли. Например, в сценарии взаимодействия с клиентом мы создаем заказ (anOrder) как документ, в котором отражены требования клиента. В складском сценарии тот же самый заказ исполняется.



      При составлении каждого из таких сценариев мы должны постоянно задавать себе ряд вопросов. Какой объект будет нести ответственность за выполнение того или иного действия? Как объект будет проводить ту или иную операцию: самостоятельно или используя свойства другого объекта? Не слишком ли много операций вменяется в круг обязанностей данного объекта? Что произойдет при ошибке в ходе выполнения сценария (какие постусловия могут нарушиться)? Что случится, если будут нарушены некоторые предусловия?

      Занимаясь подобным антропоморфизмом для каждого функционального свойства системы, мы откроем в системе целый ряд интересных объектов высокого уровня. Сначала перечислим лиц, взаимодействующих с системой:


        Customer - клиент

        Supplier - поставщик

        OrderAgent - сотрудник отдела продаж

        Accountant - бухгалтер

        ShippingAgent - сотрудник отдела отгрузки

        Stockperson - кладовщик

        PurchasingAgent - сотрудник отдела закупок

        ReceivingAgent - сотрудник отдела приема товаров

        Planner - сотрудник планового отдела

        Для нас очень важно выявить эти категории лиц: каждой из них соответствует своя отдельная роль в сценариях. Если мы хотим отслеживать, когда и почему произошли определенные события внутри системы и кто стал их причиной, то необходимо формализовать роли всех пользователей. Например, при рассмотрении жалобы нам возможно придется выяснить, кто вел переговоры с недовольным клиентом. Кроме того, нам понадобится эта классификация при разработке механизма ограничения доступа к различным частям системы для различных групп пользователей. В открытой системе централизованный контроль вполне эффективен и неизбежен: он уменьшает риск случайного или целенаправленного неправильного использования.

        В результате анализа был выделен ряд ключевых абстракций, каждая из которых представляет собой определенный тип информации в системе:


          CustomerRecord - информация о клиенте

          ProductRecord - информация о товаре

          SupplierRecord - информация о поставщике

          Order - заказ от клиента

          PurchaseOrder - заказ поставщику



          Invoice - счет

          PackingOrder - расходная накладная

          StockingOrder - приходная накладная

          ShippingLabel - документ на отгрузку

          Классы CustomerRecord, ProductRecord и SupplierRecord связаны соответственно с абстракциями Customer, Product и Supplier. Мы, однако разделили эти два типа абстракций, так как они будут играть несколько разные роли.

          Заметим, что существуют два вида счетов: те, которые посылаются компанией клиентам для оплаты заказанного товара, и те, которые компания получает от поставщиков товаров. Не отличаясь ничем по своей структуре, они, тем не менее, играют совершенно разные роли в системе.

          По классам PackingOrder и StockingOrder потребуются некоторые дополнительные разъяснения. В соответствии с первыми двумя сценариями, после того, как сотрудник отдела продаж (OrderAgent) принимает заказ (order) от клиента (Customer), он должен дать указание кладовщику (StockPerson) на выдачу заказанного товара. В нашей системе соответствующая транзакция связана с объектом класса PackingOrder (расходная накладная). Этот класс ответственен за сбор всей информации, касающейся выписки расходной накладной по данному заказу. На операционном уровне это означает, что наша система формирует, а затем передает заказ на переносной компьютер одного из свободных в данный момент кладовщиков. Такая информация должна, как минимум, включать в себя идентификационный номер заказа, наименование и количество каждого из товаров. Нетрудно догадаться, как можно намного улучшить данный сценарий: наша система в состоянии передать кладовщику местоположение товаров, и, возможно, даже примерную последовательность вывоза их со склада, обеспечивающую максимальную эффективность этой операции [Конечно, в общем случае это известная задача о бродячем торговце, которая как известно, NP-полная. Однако, можно существенно ограничить задачу так, чтобы получались приемлемые решения. На самом деле, правила перевозки могут предписывать некое частичное упорядочение: сначала класть тяжелые грузы, потом легкие.


          Желательно также группировать грузы по типу: штаны с рубашками, молотки с гвоздями, колеса с шинами (мы предупредили, что речь идет об общецелевой системе учета!)]. В нашей системе достаточно информации, чтобы обеспечить помощь недавно принятому на работу кладовщику - например, дать ему возможность вывести на экран своего переносного компьютера изображение внешнего вида того или иного товара. Такая поддержка может пригодиться и опытному кладовщику на период смены ассортимента товаров.
           


          Рис. 10-4. Ключевые классы при приеме и выполнении заказа.

          Рис. 10-4 содержит диаграмму классов, которая отражает наше понимание процесса взаимодействия некоторых из перечисленных абстракций в сценарии приема и выполнения заказа. Мы дополнили эту диаграмму некоторыми украшениями атрибутов, играющих важную роль в функционировании каждого из классов.

          Основные мотивы введения именно такой структуры классов связаны с учетом перехода между экземплярами классов. Получив заказ, мы бы хотели, в частности, сформировать маркер, обозначающий клиента, сделавшего заказ; для этого необходимо перейти от экземпляра класса заказа (order) обратно к клиенту (customer). Получив расходную накладную, надо возвратиться к клиенту и к сотруднику отдела продаж для передачи информации об отгрузке; это означает, что нам потребуется перейти от расходной накладной к заказу, и затем от него - к клиенту и сотруднику отдела продаж. Что касается клиента, то желательно знать, какие товары он чаще всего заказывает в то или иное время года. Для выполнении такого запроса необходимо вернуться от клиента ко всем предыдущим его заказам.

          Стоит подробнее остановиться еще на некоторых деталях диаграммы. Почему между классом Order и классом PackingOrder существует отношение 1:N (один ко многим)? По нашим бизнес-правилам каждая расходная накладная может соответствовать одному и только одному заказу. Однако обратное неверно. Предположим, например, что некоторые позиции, указанные в заказе, на данный момент отсутствуют на складе.


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

          Отметим ограничение на связь между объектами StockPerson и PackingOrder: сохранение контроля за качеством работы требует, чтобы кладовщик одновременно обслуживал не более одного заказа.

          Завершая данный этап анализа, введем еще два ключевых класса:


            Report - отчет

            Transaction - транзакция

            Мы ввели абстракцию Report для обозначения базового класса, объединяющего все различные типы печатных документов и пользовательских запросов, При детальном анализе всех сценариев может выясниться много конкретных типов документов, но, ввиду открытости нашей системы, будет лучше выработать общий механизм генерации отчетов, позволяющий без труда добавлять новые типы отчетов. Действительно, выделив общие для всех отчетов свойства, мы сможем наделить их общим поведением и структурой, что позволит придать соответствующим элементам системы стандартизованный вид и облегчит для конечного пользователя работу с системой.

            Наш список далеко не полон, но у нас накопилось достаточно информации для перехода к разработке архитектуры системы. Однако, до того, необходимо рассмотреть некоторые принципы, влияющие на организацию структур данных внутри программы.


            Содержание раздела