(Окончание)
Параллельная работа программистов Подготовительный этап - разработка технического задания. Не обязательно придерживаться ГОСТов, но лучше все оформить письменно в виде некоторой постановки задачи. По своему опыту знаю - пока это не сделаешь, сам четко не будешь представлять, чего же ты хочешь сделать. Желательно хотя бы расписать перечни регистров, справочников, журналов и отчетов с краткой характеристикой каждого объекта, при этом уделить особое внимание на их взаимную увязку (что куда и зачем должно обращаться, что из чего должно браться). Этап первый - работает только один программист (руководитель проекта). Создает "системные" таблицы, разрабатывает описания заголовков процедур и функций для вызова справочников, запросам к регистру и т.п. (то есть стандарты входа/выхода для модулей взаимодействия макрообъектов). Системные таблицы помещаются в ГЛАВНУЮ РАЗРАБОТОЧНУЮ БД. Описания заголовков процедур и функций для обращения к макрообъектам помещаются в глобальный модуль с описанием параметров вызова и возвращаемых значений в виде комментариев. Сами модули делаются в виде заглушек, и не имеют внутри себя ничего содержательного. Если есть возможность объединить этот этап с подготовительным, сделайте это. К сожалению, руководитель проекта обычно принимает самое непосредственное участие в формировании постановки задачи, и это не всегда может получиться. Этап второй - работает несколько программистов. Каждый снимает копию с главной разработочной БД для себя и на ее основе независимо от других программистов делает свою часть этапа (используя, где нужно, заглушки вместо готовых модулей обращения к другим макрообъектам системы). Один разрабатывает шаблон (заготовку) справочника и модули работы с ним, второй - шаблон (заготовку) регистра и модули работы с ним, третий - шаблон (заготовку) журнала и модули работы с ним, четвертый - шаблон (заготовку) отчета и модули работы с ним и т.д. Кроме самих шаблонов (заготовок) создаются мастера для быстрого и удобного формирования экземпляров макрообъектов соответствующего вида (справочников, регистров, и т.д.) на базе разработанных шаблонов. По завершению работы каждый программист копирует свое творение из персональной БД в главную разработочную базу. Этап третий - лепка из полуфабриката кубиков и складывание их в пирамиду. На этом этапе проект представляет инструментарий, отдаленно напоминающий 1С:Предприятие. В соответствии со сделанной на подготовительном этапе постановкой задачи, на базе подготовленных шаблонов с использованием разработанных мастеров формируются конкретные экземпляры макрообъектов (справочников, регистров и т.д.). Работа идет параллельно. Перед формированием очередного объекта каждый программист копирует к себе главную разработочную базу, в копии создает новый макрообъект, доводит его до ума и после этого переносит в главную разработочную базу. Нелишне напомнить, что лучше хранить некоторое количество ее архивных копий на случай, если кто-нибудь из программистов капитально напортачит. Этап четвертый - внедрение и опытная эксплуатация. Программисты, в основном, используются в качестве материализовавшегося помощника из офисного пакета. Плотная работа с пользователями. Неизбежное устранение выявленных ошибок. Участие в работе по наполнению баз (в качестве операторов) - это муторно, но лучше не пытаться этого избежать. Если наполнение баз ПОЛНОСТЬЮ взвалить на пользователей, они возненавидят вашу систему еще до того, как узнают о заложенных в систему положительных возможностях. Этап четвертый - развитие и сопровождение - см. в следующих разделах. Архивирование, регистрация и мониторинг пользователей Вопросы архивирования разбиваются на две отдельные задачи, направленные на решение разных проблем. Первая - проблема надежности. Она требует, чтобы у вас всегда имелось в наличии несколько архивных копий БД, сделанных с интервалом не менее суток (час назад, за вчерашний день, позавчерашний и т.д.). Вторая - проблема устаревшей информации. Поскольку в системе НЕ используется физическое удаление информации в справочниках и документах (см. замечание о принципе "не удаляй физически" выше), размеры БД очень быстро могут разрастись, и скорость выборки информации многократно снизится. Может возникнуть необходимость несколько разгрузить БД, исключив из нее информацию позапрошлогодней давности, сбросив ее в специальный архив с возможностью восстановления в случае необходимости. ИН: ... пишешь, что запись должна находиться либо в архиве, либо в рабочей базе. Я думаю, что придется дублировать записи. Если в архив заносятся записи нижнего уровня(при иерархической организации), то там должны быть и записи верхнего уровня. Т.е. пока часть записей нижнего уровня, принадлежащих одному узлу верхнего уровня, находится в архиве, а часть - в рабочей базе, то записи верхнего уровня дублируются. АГ->ИН: В первом абзаце раздела "Архивирование, регистрация и мониторинг пользователей" говорится о том, что следует различать два разных архивирования. 1) Архивирование для надежности и 2) Архивирование для отсечения информации, имеющей низкую степень актуальности. Это совершенно разные вещи. Архивирование 1-го вида рассмотрено во многих источниках, поэтому о нем в статье несколько скупых фраз, а упор сделан на архивирование 2-го типа. Архивирование должно быть обратимым, иначе никакого смысла в нем просто нет. Это значит, что должна иметься возможность ВОССТАНОВИТЬ информацию, помещенную в архив, иначе ее архивирование будет приравнено к простому уничтожению информации. То архивирование, о котором идет речь в статье, сильно отличается от файлового архивирования, сделанного с помощью простого копирования данных в новое место. Файловый архив является самодостаточным - то есть его можно "подсунуть" приложению вместо оригинальной базы данных, и приложение будет оперировать с информацией, расположенной в архиве. Тот же архив, о котором идет речь в статье, не является самодостаточным. Архив нельзя использовать как самостоятельную базу, с которой приложение сможет работать. Это просто емкость для хранения, в которую слита часть информации, но которую при необходимости можно вылить обратно в основную базу данных. Для этого случая совершенно неважно поддержание логической целостности записей в самом архиве - она (логическая целостность) там не нужна. Самое главное, чтобы операции архивирования и восстановления информации из архива не приводили к нарушению логической целостности в основной базе. Поэтому вполне допускается поместить в архив логически удаленные записи нижних уровней иерархического справочника, не помещая в него записи верхнего уровня. Идентификаторы родительских записей не могут измениться или куда-то исчезнуть (поскольку не производится их физическое удаление). Дочерние же записи помещаются в архив вместе со ссылками на идентификаторы родительских записей. Поэтому восстановление архива не приводит к нарушению логической целостности в основной базе данных. Кроме того, когда речь идет об архивировании 2-го типа, нужно помнить, что объем справочников в массиве архивируемой информации относительно невелик (отсилу 3% - 5%) от всей архивируемой информации. В основном в архив будет помещаться информация РЕГИСТРОВ и ДОКУМЕНТОВ за давно прошедшие периоды. А эти объекты не имеют иерархической организации. Так что если тебя смущают некоторые аспекты архивирования справочников, их можно просто не архивировать, а оставить пожизненно в основной базе. ИН: И еще подводный камень, который я ни как не могу обойти - При добавлении записей необходимо проверять есть ли такие записи среди удаленных или в архиве ? Проверка нужна всегда или нет? АГ->ИН:Если записи удалены, значит их нет. И не важно, логически они удалены или физически. Подобная проверка нужна только по справочникам. По справочникам в архив помещаются только логически удаленные записи. То есть, смысла проверять уникальность записи со сверкой их с данными архива нет. Важно другое. Подобную проверку нельзя использовать созданием уникального индекса или Constraint. Это можно сделать только с помощью триггера. Вопрос архивирования "для надежности" может быть решен двумя путями, причем допустимо их совместное использование. Первый - автоматическое архивирование БД с помощью архиваторов ZIP, RAR и т.п. в ночное время, когда пользователи не работают. Второй - использование репликации как механизма ведения "зеркала" БД в режиме реального времени, которое может быть использовано в случае разрушения основной БД в качестве наиболее свежей резервной копии. Необходимо заметить, что ежедневное архивирование должно быть именно АВТОМАТИЧЕСКИМ. Полагаться на принудительный запуск архивации ни в коем случае нельзя. Иначе вы обязательно попадете в ситуацию, когда разрушение информации произошло как раз после того, как вы забыли снять архивную копию, или просто не смогли ее сделать, поскольку были на больничном или в местной командировке. Для того, чтобы архиваторы ZIP, RAR и т.п. смогли корректно снять архивную копию с БД, необходимо, чтобы к базе данных во время архивирования не были подключены пользователи. Следовательно, при разработке проекта, необходимо заранее продумать механизм насильственного отключения забывчивых пользователей (которые, не закончив редактирование документа, выходят на минуту из комнаты, и так и уходят домой, оставив включенный компьютер). Отключение пользователей может потребоваться не только для целей архивирования. Возможно, вам изредка понадобится выполнять какие-либо задачи по модификации структуры базы данных, требующие монопольного доступа. Кроме того, иногда вы, возможно, захотите получать информацию о том, какие пользователя с какими объектами системы работают в данный момент. Каждый пользователь, входя в систему, проходит процедуру регистрации, в процессе которой фиксируется имя пользователя и компьютер, с которого произведен вход. Попытки входа в систему пресекаются в следующих случаях: - Если пользователь ввел неверный логин или пароль
- Если попытка входа осуществляется ночью в заранее заданный период времени, предназначенный для архивирования.
- Пользователь не является администратором, а администратор выставил специальный флаг монопольного доступа. Эта мера используется в дополнение к возможностям MS Access на уровне исполняющей системы закрыть разделяемый доступ к базе данных. Она может понадобиться для исключения попыток повторного входа в систему отключенным пользователям в тот момент, когда еще не все пользователи от нее успели отключиться, и БД еще работает в режиме разделяемого доступа.
- Если обнаруживается попытка одновременного входа с разных компьютеров под одним пользовательским именем. Скорее всего, пользователи разные, но один из них входит под чужим именем, что крайне нежелательно).
Все удачные и неудачные попытки входа регистрируются в специальном журнале. Для неудачных попыток фиксируется время, компьютер и неправильно набранный пароль. По этой информации можно выявить попытки подбора чужого пароля, рабочие места, с которых пользователи осуществляют вход не под своим именем. В системе фиксируются все действия, произведенные пользователем, и каждый пользователь несет за свои действия персональную ответственность, поэтому необходимо обеспечить высокую секретность паролей. Клиентская часть при своей загрузке открывает главную форму, которая остается открытой на всем протяжении работы. Все остальные формы открываются поверх главной формы. В случае закрытия главной формы приложение завершает работу. К событию "Таймер" главной формы привязана процедура, которая с определенной периодичностью проверяет текущее время и наличие в специальной системной таблице команды на завершение работы (которая может поступить от администратора системы). Если от администратора поступила команда на завершение работы, либо подходит время архивирования (к примеру, 23:00), у пользователя на экране высвечивается предупреждение о том, что в для выполнения регламентных работ через N-е количество секунд (или минут) приложение будет закрыто плюс совет завершить ввод всех документов, закрыть все открытые формы и добровольно выйти из системы. Если пользователь не выйдет из системы добровольно по истечении указанного времени, выполняется команда DoCmd.Quit acQuitSaveNone. Повторно войти в систему пользователь не сможет до тех пор, пока не истечет срок, отведенный под архивирование, либо администратор не выставит флаг разрешения доступа. Если модули работы с объектами системы (справочниками, документами, регистрами и т.п.) содержат средства регистрации действий пользователя (запись в специальной системной таблице информации о том, что кем когда открыто и закрыто), то администратор системы сможет производить мониторинг пользователей и просматривать, какие пользователи в настоящий момент с какими объектами работают, а также к каким объектам они обращались несколько минут назад. Эта информация дополнительно может понадобиться для сбора очень важной информации - статистики аварийных выходов. Если система регистрирует с одного и того же компьютера два входа, и только один выход, значит после первого входа было аварийное завершение работы пользовательского компьютера - потенциальный источник разрушения индексов при разделяемом доступе, а также "ломки" всей базы данных. Для решения проблемы архивирования с целью уменьшения размеров базы данных и увеличения быстродействия я предполагаю использовать специально для этого разработанную программу на VB (VBA). В качестве архива выступает база данных с идентичной структурой. В нее с помощью программы архивирования переносятся старые документы, давно не используемые записи справочников, журналов, старые записи об оборотах регистров, после чего указанная информация физически удаляется из рабочей базы данных. Программа архивирования запрашивает только один параметр: учетную дату, разделяющую понятия "старая информация" и "свежая информация". Прежде всего, из рабочей базы удаляется все движение регистров до указанной даты (замещаясь вступительными остатками на эту дату). После этого из рабочей базы данных удаляются документы и соответствующие им записи в журналах, но не все а только те, НА КОТОРЫЕ НЕ ОСТАЛОСЬ ССЫЛОК ИЗ РЕГИСТРОВ, ЛИБО ИЗ ДРУГИХ ДОКУМЕНТОВ в области "свежей информации". После этого из рабочей базы данных физически удаляются записи справочников, которые на протяжении всего периода "свежей информации" числятся логически удаленными. После этого производится ЛОГИЧЕСКОЕ удаление записей справочников, на которые нет ссылок из документов, из других справочников, из регистров и журналов в области "свежей" информации. Последнюю операцию следует делать только в случае особо жгучего желания МАКСИМАЛЬНО облегчить базу - и то это желание будет удовлетворено только при следующем выполнении операции "облегчения" базы спустя длительный срок, когда логически удаленные записи справочников будут удалены из нее физически. Я предпочитаю эту операцию вообще не производить. Представьте, что у вас в справочнике хранится запись о контрагенте "ЗАО КОНТЪ", расчеты с которым закрыты год назад. Может оказаться, что система удалит эту запись из справочника, а через некоторое время отношения с этим контрагентом возобновятся. Не обнаружив в справочнике контрагентов "ЗАО КОНТЪ", пользователь введет в него нового контрагента с этим же наименованием и реквизитами. Он будет воспринят системой как новый контрагент, и в случае восстановления информации из архива, не будет соотнесен со старой записью "ЗАО КОНТЪ". Если вам понадобится после этого распечатать акт сверки взаиморасчетов за 3 года с "ЗАО КОНТ", сделать это будет уже невозможно. Если вы все-таки решились выполнить операцию удаления "потенциально ненужных" записей справочников, у вас останется шанс восстановить удаленную запись, не прибегая к операции восстановления архива (правда, только ДО следующего "облегчения" базы) - именно поэтому записи удаляются логически, а не физически. Следует обратить внимание на то, что архивирование должно быть легко обратимым. Представьте, что вы производите операцию "облегчения" базы данных раз в полгода. Это значит, что на момент, когда руководство захочет получить отчет о динамике объема продаж за три последних года, у вас в рабочей базе данных окажется только шестая часть нужной для построения отчета информации. У вас должна иметься возможность оперативного восстановления данных из архива за один прием. Для того, чтобы это было возможно, я при выполнении операции "облегчения" рабочей базы данных сливаю информацию в одну и ту же архивную базу данных. Операция восстановления производится той же программой, что и архивирование, но в обратном порядке. При этом записи удаляются физически из архивной базы данных и переписываются в рабочую (это делается во избежание конфликтов между записями в архивной базе при последующих операциях архивирования). При этом реализуется принцип "запись должна быть либо в архиве, либо в рабочей базе, но не в двух местах одновременно". Следует обратить внимание на то, что как при архивировании, так и при восстановлении архива производится перемещение больших объемов информации и существенное изменение как архивной базы данных, так и рабочей. Во избежание порчи одной из этих баз в процессе архивирования или восстановления архива (например, в результате сбоя оборудования), следует перед выполнением этих операций сделать их копии. О событийной ориентированности Это в чистом виде моя идея - ни в одном продукте я не видел ничего похожего (правда, может оказаться, что я не достаточно полно провел "патентные исследования"). Речь идет НЕ о событиях типа "клацнуть мышкой" или "открыть форму" - это события другого рода, и происходят они в процессе хозяйственной деятельности: "оплата", "отгрузка", "поступление денег" и т.д. Вкупе с ними могут работать "таймауты", но измеряемые не в секундах и миллисекундах, а в днях, неделях, месяцах и годах - истечение срока исковой давности, нарушение обязательств по срокам исполнения и т.д. Если на стадии проектирования системы заложить в нее прогон всех "шевелений" макрообъектов через единый модуль обработки событий, появляется возможность решать задачи, доселе считавшиеся "не систематизируемыми". К примеру, вы сможете рассчитать суммы просроченной и не просроченной дебиторской и кредиторской задолженности, а также получить суммы штрафных санкций по нарушенным обязательствам, как собственным, так и обязательствам ваших контрагентам (каково?!!!). И это при том, что договор с конкретным контрагентом может содержать существенные отклонения от типового договора или быть вообще уникальным. Вы также сможете составить на ближайшую неделю (месяц, квартал) достаточно близкий к реальности план денежных и товарных поступлений от контрагентов, план денежных расходов и планируемые объемы отпуска товара контрагентам (это очень важные задачи для крупных оптовиков). Для производственников можно составить план производства, выявить узкие места (нехватку и излишки материалов в техпроцессе), грамотно составить плановую калькуляцию себестоимости. Чтобы все вышеперечисленное стало возможным, необходимо систематизировать определенным образом ЛЮБОЙ текст договора или иной схемы действий (чтобы ваша система смогла "понять" не только суть договора, но и все мелкие нюансы). Для этого нужен некий промежуточный язык или система понятий, хорошо совмещающая мировоззрение коммерсанта или технолога, с "мировоззрением" автоматизированной системы. Коммерсант (не программист!) должен иметь возможность "объяснить" автоматизированной системе суть договора с использованием этой системы понятий. Вот тут-то и выходят на первое место преимущества макрообъектов ("справочник", "документ" и т.д.) как понятий, доступных и для коммерсанта, и для автоматизированной системы. Если же у коммерсанта имеется возможность заставить систему ПЕРЕХВАТЫВАТЬ СОБЫТИЯ, которые с этими объектами происходят, и при этом производить некоторую их обработку - считайте, что вы добились цели. Совсем не обязательно для реализации поставленной задачи придумывать некий "язык программирования" объектов (хотя, это один из вариантов, но далеко не лучший - коммерсант вам этого не простит). Схему договора можно изобразить визуально из понятийных компонентов "макрообъекты" (справочники, регистры, документы), "события" (возникшие с макрообъектами), "действия" (над макрообъектами, которые производятся при наступлении события), "параметры" (дополнительная информация, не имеющая привязки к макрообъектам). На более низких уровнях могут фигурировать понятия "операторы", "функции", "списки", "константы" и прочая мишура вычислительного уровня. Схема договора при этом строится визуально (из табло-подобных форм, списков, деревьев и т.п.) из кубиков вида "если СОБЫТИЕ с макрообъектом --> тогда ДЕЙСТВИЯ над макрообъектами". Единственное, что необходимо уяснить пользователю: договор (или контракт), написанный на русском (английском, гагаузском) языке на самом деле описывает схему обработки событий: "Если А поставил товар (событие - формирование документа "накладная") - у Б возникает не просроченная задолженность (обработка события - отражение накладной в регистре задолженности на аналитике "не просроченная" и запуск таймаута); если задолженность не погашена в такой-то срок (событие "таймаут истек"), то возникает просроченная задолженность и штрафные санкции (обработка события "истечение таймаута" - движение регистра задолженности с переброской суммы с аналитики "не просроченная" на аналитику "просроченная" и записью в регистр штрафных санкций суммы штрафных санкций на аналитики "не востребованные" / "не погашенные"); если произведена оплата (событие - формирование документа "платежка") - производится погашение задолженности и движение средств на текущем счете (обработка события - отражение движения в регистре задолженности и в регистре "Деньги в банках"): и т.д.". Когда же возникает необходимость использовать понятие "параметр"? Когда в договоре происходят события НЕ над макрообъектами системы. К примеру, переход права собственности и коммерческих рисков на наш товар происходит в момент погрузки тюка с НЕ НАШЕГО грузовика в НЕ НАШ ЖЕ вагон - а у вас в системе отсутствуют документы, регистрирующие этот факт. О том, что факт имеет быть, узнает наш Иванов по телефону от не нашего Петрова (можно запросить всякие бумажные справки с железнодорожной станции или у авто-перевозчика, но на практике их предоставляют только в случае судебного разбирательства по поводу пропавшего в дороге груза). Для того, чтобы этот факт все-таки в системе смог быть отражен, к схеме контроля (то бишь, к договору) прикрепляется ПАРАМЕТР с наименованием "Дата погрузки в вагон" и типом "Дата". Ввод пользователем значения параметра - это тоже событие, которое может быть обработано системой и вызовет движение регистра "товары в пути" (а если надо, то и "реализация", "налоги" и т.д. и т.п.). Поскольку обработка событий приводит к изменению состояния макрообъектов, с которыми эти события и возникают, то возможны ситуации, когда события вызывают по цепочке друг друга. Это упрощает "программирование" обработки событий, но приводит к опасности бесконечной рекурсии (зацикливания) при ошибках в схеме обработки событий. Реализация защиты от зацикливания не столь сложна при грамотном построении модулей обработки событий. Дотошный читатель наверняка догадался, что механизмы обработки событий можно использовать не только для систематизации договоров, заказов и схем производства. Этот механизм может быть заложен в само ядро системы в качестве "языка верхнего уровня" для взаимной увязки макрообъектов. Совсем не обязательно непосредственно на VBA писать программу, реализующую движение регистров при формировании документа "счет" или "накладная". Достаточно заложить алгоритм обработки соответствующих событий в типовую схему их обработки. Если идет отгрузка в соответствии с каким-либо договором, производится отработка событий на основе его схемы контроля. Если просто отгружается товар по счету - используется настройка схемы контроля, реализующая принципы некоторого типового договора, заложенные в "Гражданском кодексе". "ПРОСТО отгрузки" или "ПРОСТО оплаты" не в соответствии с некоторой схемой действий в принципе быть не может. Просто эта схема заложена не в договоре, а в общепринятых нормах поведения или в законодательстве. Схемы контроля событий одного вида подразделяются по приоритетам. Представьте, что в системе имеется множество схем контроля события "ввод расходной накладной". При возникновении конкретного события сначала выявляется, В СООТВЕТСТВИИ С КАКОЙ ИЗ НИХ оно должно быть обработано (только одной!). В первую очередь проверяются схемы, имеющие наивысший приоритет и наибольшую степень конкретизации. Если среди схем обработки события имеется такая, которая описывает движение регистров при вводе накладной ИМЕННО ОТ ЭТОГО КОНТРАГЕНТА, ИМЕННО ПО УКАЗАННОМУ В ДОКУМЕНТЕ ДОГОВОРУ - она запускается на выполнение. Если подобных схем в системе не обнаруживается, событие проверяется на соответствие схемам более низкого приоритета - на ввод накладной по типовому договору купли, бартера или комиссии (в зависимости от типа договора, к которому привязан документ, вызвавший событие). Если и такой схемы контроля не обнаруживается, производится обработка события по схеме с самым низким приоритетом и степенью конкретизации - приход товара по ЛЮБОМУ договору ПРОИЗВОЛЬНОГО типа. Конечно, "программировать" каждый договор - занятие неблагодарное. Для того, чтобы облегчить жизнь неискушенному пользователю, разработчик должен заложить в систему некоторый набор шаблонов схем контроля событий (пользователи в дальнейшем смогут его дополнить). Так, могут иметься шаблоны схем контроля для типовых договоров "Договор купли", "Договор продажи", "Договор бартера (мены)", "Договор комиссии (мы - комитент)", "Договор комиссии (мы - комиссионер), "Договор перевода долга", "Договор аренды", "Договор кредита" и т.д. Шаблоны лучше выстроить иерархически. Если договор бартера с разными группами контрагентов заключается в трех разных вариантах, следует заложить в систему три разных шаблона в группу шаблонов "Договор бартера". При заключении договора со специфическими условиями, выбирается некоторый базовый шаблон, наиболее близкий к условиям заключаемого договора, и на его основе строится конкретная схема контроля - просто корректируется имеющееся, добавляется отсутствующее и убирается лишнее. Для реализации механизма таймаутов потребуется некоторая программа-агент, которая периодически (1-2 раза в сутки) сканирует выставленные в системе таймауты и инициирует события их истечения (событие сброса ранее выставленного таймаута реализуется в обработке, например, своевременной оплаты). С помощью таймаутов, в частности, решается задача автоматического снятия товара с резерва при различного рода нарушениях обязательств контрагентами (несвоевременной оплате счета, например). Технология событийной ориентированности - это моя ГЛАВНАЯ ИДЕЯ, которой я хочу поделиться с братьями по озадаченности. Защита информации и администрирование В двух словах этот вопрос уже рассмотрен при разборе структуры справочника. Система образована комбинацией трех составляющих: клиентской части (КЧ), серверной части (СЧ) и агента распространения изменений клиентской части (АРИКЧ). На локальном диске каждого пользователя находится АРИКЧ, запускаемая только на мгновение перед началом сеанса пользователя, и задействуемая в сеансе пользователя КЧ (в том числе, у администратора/программиста). На сервере находится СЧ и последняя версия КЧ, не задействуемая в сеансе пользователя, а предназначенная только для распространения на локальные диски всех пользователей. Когда администратор/программист корректирует права доступа пользователей к макрообъектам, модуль администрирования производит корректировку прав доступа к объектам уровня MS Access - к таблицам в СЧ, к формам, запросам, отчетам, макросам и модулям КЧ, находящейся на локальном диске администратора. Можно, конечно, зная сетевые пути, по которым лежат клиентские части всех остальных пользователей, попытаться сразу по сети "перебрать" все имеющиеся в ней КЧ и подправить в них права доступа к объектам КЧ. Однако, эта затея не самая блестящая. В момент такого "перебирания" часть компьютеров может оказаться просто выключенной (кто-то вышел в отпуск, заболел или просто пошел хлебнуть кофейку). Я использую другой подход. Во всех КЧ в специальной таблице (находящейся не в СЧ, а именно в КЧ) прописан номер версии последних изменений. Когда администратор изменяет права доступа в своей КЧ, в ней автоматически на единицу увеличивается номер версии. При входе в систему любого пользователя (в том числе, администратора), автоматически запускается АРИКЧ, который сравнивает номер версии КЧ на сервере с номером версии КЧ на локальном диске. Если номер версии на локальном диске пользователя больше (свежее), запускается операция копирования КЧ с локального диска на сервер. Если номер версии КЧ сервера выше (свежее) номера версии КЧ локального диска, КЧ с сервера копируется на локальный диск. Если версии совпадают, никаких действий не производится. Таким образом, КЧ с локального диска администратора автоматически попадет на сервер, а оттуда постепенно размножится по локальным дискам всех пользователей. Этот метод страдает малой оперативностью, зато он прост в реализации и надежен. Размножение новых версий КЧ между пользователями в процессе доработки проекта может быть подключено к этому механизму. Это избавит вас от нудной процедуры "инсталляции" новой версии на нескольких десятках компьютеров после каждой мизерной корректировки программного кода. Некоторые пользователи вообще не должны догадываться о том, что в системе существует какая-либо информация кроме той, которую они видят на экране. Для этого в системе реализуется разграничение доступа к справочникам на уровне записи. Доступ к механизму разграничения на уровне записи имеют не все пользователи, а только те, которые по долгу службы обязаны знать о его существовании. В параметрах настройки пользователей заводится специальный атрибут, значение которого определяет возможность пользователя получить доступ к механизмам разграничения доступа на уровне записи. Если пользователь такого права не имеет, на всех формах справочников соответствующие элементы управления станут просто невидимыми. Каждая запись, добавленная любым пользователем в справочник, получает по умолчанию статус доступной всем остальным пользователям (имеющим вообще доступ к этому справочнику). Пользователь, имеющий доступ к механизму разграничения доступа на уровне записи, может изменить этот статус по своему усмотрению, исключив из атрибутов ее доступа группу "Users" (все пользователи) и назначив перечень группы пользователей, которым эта запись должна быть доступна. Разграничение доступа на уровне записи работает только на уровне групп пользователей (а не конкретных пользователей) - это соответствует общей стратегии администрирования и позволяет несколько сократить объем дополнительной служебной информации о правах доступа, хранящейся в базе данных. Более того, небольшая хитрость позволяет избежать расходов емкости БД для хранения служебной информации о доступе к записям справочников, доступным всем пользователям. Поскольку более 90% всех справочников составляют именно такие записи, расходы на хранение служебной информации о правах доступа оказываются минимальными. Выборка любой информации из регистров, документов, журналов, отчетов производится с учетом прав доступа к записям справочников, к которым эти макрообъекты обращаются. При просмотре любой информации он видит только отфильтрованную часть, разрешенную ему для просмотра. Механизм разграничения доступа на уровне записи работает только для справочников - для остальных макрообъектов приводится привязка к справочникам. Пара слов о том, что изменилось в моих представлениях о рассмотренных во второй части статьи проблемах. В статье вкратце описан механизм подмены физического удаления/модификации записей на логическое удаление и добавление новых записей. Этот механизм сильно напоминает работу триггеров в MS SQL Server. Сейчас этот механизм пересмотрен. Он ориентирован на Merge-репликацию MS SQL Server (версий 7.0 и выше). Merge-репликация - отличная штука. Это единственный вид репликации, изначально ориентированный на двусторонний обмен данными (в отличие от репликации транзакций, например). И это единственный вид репликации, который действительно может использоваться при отсутствии надежных или постоянных соединений между серверами. Единственный его недостаток - отсутствие согласованности транзакций - устраняется именно приведенной в статье схемой подмены модификаций/удалений логическими операциями. Однако, согласованность транзакция по этой схеме достигается только для актуальных записей. В результате конфликтов между записями истории в конфликтах типа "удаление на сервере 1 - модификация на сервере 2" в некоторых случаях может быть утеряна информация о ПОПЫТКАХ изменения, которые системой автоматически аннулированы. Это не актуальные записи, но это и не просто история записей. Ее анализ позволяет выявить имевшие место конфликты репликации (которые устраняются автоматически, но информация о них в истории не должна теряться). Предложенная в статье схема приводит к вероятности утери небольшой части информации об имевших место конфликтах. Поэтому на сегодня данная схема мною пересмотрена. И даже удаление записи подменяется физическим добавлением новой записи (помеченной, как логически удаленная). У прежней же редакции записи не должны модифицироваться даже служебные поля. Посему из служебных полей оставлены только те, которые относятся к созданию редакции записи (которые заполняются в момент совершения операции над записью только один раз), а поля, относящиеся к логическому удалению редакции записи, исключены (их заполнение потребовало бы повторной физической модификации записи). Новая концепция изящно реализуется на instead-триггерах в MS SQL Server-2000. Пересмотрена также концепция, касающаяся "событийной ориентированности". Найдена еще более изящная концепция (IMHO), основанная на принципе детерминированности учетного времени. Учетное время считается в любой момент времени определенным в обе стороны (и в прошлое, и в будущее) до бесконечности. Состояние системы считается заданным на всем протяжении учетного времени и изменяется также на всем протяжении учетного времени при возникновении событий в реальном времени. При этом отпадает необходимость запускать некие программы-агенты, отсчитывающие "таймауты" по оси учетного времени (и которые приводят к отождествлению учетного времени с календарным временем, что неправильно). Поведение системы становится более предсказуемым. На любом временнОм разрезе будущего возникает четкая картина - состояние системы при отсутствии каких-либо дополнительных воздействий. Пример. Клиент попросил нас выписать счет. Мы формируем документ - счет и отдаем его покупателю. Выписанный по счету товар автоматически поступает в мягкий резерв (в счете есть фраза "счет действителен в течение трех банковских дней и на этот срок производится резервирование товара"). То есть, до сегодняшнего дня на оси учетного времени он числится в свободном резерве, а с сегодняшнего дня - в мягком резерве. Но это еще не все. СРАЗУ ЖЕ при выписке счета имеется информация - оплаты по нему НЕТ (пока или вообще нет, не важно) - поэтому на оси учетного времени сразу отражается снятие данного товара с мягкого резерва и перевод обратно в свободный остаток - В БУДУЩЕМ. Дальнейшее развитие событий такое. Вариант1. Оплата от покупателя НЕ поступает. Состояние системы НЕ изменяется - подобная картина в ней отражена уже при выписке счета. Вариант2. Поступает оплата от покупателя до истечения 3-х банковских дней. Товар автоматически переводится в жесткий резерв (с длительным сроком резервирования). Поскольку покупатель должен произвести самовывоз, но в системе нет информации, что он это сделал, товар по истечении срока жесткого резерва (срока исковой давности) снимается с жесткого резерва обратно в положение свободного остатка, списывается дебиторская задолженность перед клиентом в счет дополнительной прибыли. Вариант3. Поступает оплата от покупателя после истечения 3-х банковских дней. Если на момент поступления оплаты в свободном остатке имеется оплаченная номенклатура, она поступает в жесткий резерв, и далее все как в Варианте2. Если же в свободном остатке ее нет, формируется сообщение контролирующему менеджеру для принятия решения (либо о дополнительной закупке у поставщика, либо о решении с клиентом вопроса о возврате денег либо о замене на другую номенклатуру). Поскольку в системе отсутствует какая-либо информация о дальнейшей судьбе данного заказа, поступившие деньги в далеком будущем опять-таки списываются по истечению срока исковой давности в счет дополнительной прибыли. Клиент производит самовывоз. Аннулируется ранее сделанное списание задолженности перед клиентом по истечению срока исковой давности и формируется погашение задолженности в регистре взаиморасчетов. Выписка счета, поступление оплаты, получение клиентом товара - это всё события, которые изменяют состояние системы сразу на всем промежутке учетного времени. Поэтому необходимость в агентах, отслеживающих таймауты, отпадает. Запросив данные по регистрам даже на момент учетного времени, находящегося в далеком будущем, мы имеем четкую картину по состоянию системы на тот случай, если в системе больше ничего не произойдет. Это важная составляющая оперативного планирования. По поводу прочитанного можете бросить камни в два огорода: >
Этот e-mail защищен от спам-ботов. Для его просмотра в вашем браузере должна быть включена поддержка Java-script
(рабочий, вскапывается ежедневно) >
Этот e-mail защищен от спам-ботов. Для его просмотра в вашем браузере должна быть включена поддержка Java-script
(домашний, вскапывается по выходным) Просмотров: 9110
Ваш коментарий будет первым | | |