Руководство собственных ком

Introduction to COM — What It Is and How to Use It.

Эта статья переведена по следующей ссылке:
http://www.codeproject.com/Articles/633/Introduction-to-COM-What-It-Is-and-How-to-Use-It

Цель этой статьи

Я написал эту статью, чтобы дать руководство тем, кто плохо знаком с COM, и помочь им понять основные концепции COM. В этой статье кратко представлены некоторые функции COM, некоторые термины в COM и способы использования существующих компонентов COM.В этой статье не описывается, как писать собственные COM-объекты.

Введение

COM (компонентная объектная модель) в это время встречается повсюду в мире Windows. Каждый день появляется множество статей, посвященных COM, в которых содержится множество терминов, таких как COM-объекты, интерфейсы, серверы и т. Д., Но в этих статьях предполагается, что вы уже знаете COM и знаете, как его использовать. .

Эта статья предназначена для начинающих и знакомит с базовым механизмом COM, от мелкого до более глубокого, и учит вас, как использовать сторонние COM-объекты в вашей программе (возьмите Windows Shell в качестве примера). После понимания содержания этой статьи вы можете использовать COM-объекты, встроенные в Windows, и COM-объекты, предоставленные третьими сторонами.

В этой статье предполагается, что вы знакомы с C ++. Я использовал часть кода MFC и ATL в примере кода. Даже если вы не понимаете эти две технологии, это не имеет значения. Я объясню их подробно. Эта статья разделена на следующие главы:

  • Что такое COM Краткое введение в стандарт COM, какие проблемы решает появление COM. Вам не нужно понимать эту часть, чтобы использовать COM. Но я все же рекомендую вам прочитать эту главу, чтобы понять, почему вещи в COM так написаны.

  • основная концепция Термины COM и их соответствующие значения.

  • Использовать COM-объекты Кратко расскажите, как создавать, использовать и уничтожать COM-объекты.

  • Базовый интерфейс-I Неизвестно Представьте базовый интерфейс IUnknown и функции этого интерфейса.

  • Обработка нотной строки Описывает, как обрабатывать строки в COM-коде.

  • Интеграция знаний — пример кода Используйте два примера кода, чтобы проиллюстрировать концепции, упомянутые в этой статье.

  • Обработка HRESULT Расскажите о типах HRESULT и о том, как проверять коды ошибок.

  • Цитата Предложите несколько книг, которые стоит прочитать.

Что такое COM

Проще говоря, COM — это способ совместного использования двоичного кода между разными программами и языками программирования. Это отличается от C ++, который поддерживает совместное использование на уровне исходного кода. ATL — хороший пример.Хотя совместное использование исходного кода — это хорошо, его можно использовать только в C ++. Это также создает возможность конфликтов пространств имен, не говоря уже о расширении проекта, вызванном постоянным копированием и повторным использованием кода.

Windows использует библиотеки DLL для совместного использования двоичного кода. Приложения Windows запускаются путем повторного использования kernel32.dll и user32.dll. Но все эти библиотеки DLL написаны на C, и использовать их могут только языки, соответствующие правилам вызова C. Это накладывает на другие языки бремя повторного использования dll.

MFC предоставляет механизм библиотек DLL расширения MFC для совместного использования двоичного кода, но он является более строгим: библиотеки DLL, созданные с помощью этого механизма, могут использоваться только программами MFC.

COM решает указанные выше проблемы, определяя двоичный стандарт. Другими словами, COM требует, чтобы его двоичные модули (dll и exe) были скомпилированы в формат, который может соответствовать указанной структуре. Этот стандарт также определяет, как организовать COM-объекты в памяти. И это не зависит от характеристик любого языка программирования (например, пространства имен C ++). Как только вышеуказанные правила установлены, к бинарному модулю можно будет легко получить доступ с любого языка программирования. Этот стандарт возлагает дополнительную работу, необходимую для совместного использования двоичного кода, на компилятор (а не на саму dll). Пока двоичный код, созданный компилятором языка программирования, совместим со стандартом, другие могут использовать его с удобством.

Структура COM-объектов в памяти «случайно» аналогична структуре, используемой виртуальными функциями C ++. Вот почему много кода COM написано на C ++. Но помните, не имеет значения, на каком языке написан COM-компонент, потому что его можно использовать на любом языке.

Кстати, COM не ограничивается платформой Windows. Теоретически его можно перенести на Unix или другие операционные системы. Но я никогда не видел обсуждения COM в других системах.

основная концепция

Мы вводим основные концепции COM по порядку снизу вверх.

  • interface Интерфейс, который представляет собой набор функций в COM. Эти функции называются методами. Интерфейс начинается с I, например IShellLink. В C ++ интерфейс обычно записывается как абстрактный базовый класс с чистыми виртуальными функциями. Подобно C ++, COM-интерфейсы также могут быть унаследованы от других интерфейсов.Наследование COM-интерфейса работает аналогично одиночному наследованию C ++, оно не допускает множественного наследования.

  • coclass(Класс объекта-компонента) включен в DLL или EXE. Он содержит один или несколькоinterface Код.coclass Также известен как этиinterface издостичь. Здесь я хотел бы напомнить вам, что «класс» в COM — это не то же самое, что «класс» в C ++, хотя классы C ++ обычно используются для написания кодов классов COM в реальной работе.

  • COM Object(COM-объект) В памяти COM-объект являетсяcoclass Пример. Может быть один или несколько COM-объектовinterface

  • COM server(Служба COM) — это служба, содержащая один или несколькоcoclass Бинарный модуль (DLL или EXE).

  • Registration Это процесс создания раздела реестра, который сообщает Windows, как найтиCOM serverUnregistration Вместо этого он удаляет раздел реестра из Windows.

  • GUID (Глобальный уникальный идентификатор) — 128-битное число.GUID Это метод идентификации, предоставляемый COM, независимо от языка программирования. Каждыйinterface с участием coclass Все соответствуют одномуGUID. Потому чтоGUID Он имеет глобальную уникальность, поэтому может избежать конфликтов имен (пока он создается с помощью COM API, имена не будут конфликтовать). Иногда вы увидите другую принадлежностьUUID (Универсальный уникальный идентификатор), их функции такие же.

  • class ID Или жеCLSID Означаетcoclass изGUID. В то время какinterface ID Или жеIID Означаетinterface изGUID

    GUID так широко используется в COM по двум причинам:

    1. GUID — это просто строка чисел, с ней может справиться любой язык программирования.

    2. Независимо от того, является ли это кем-либо или любой машиной, после создания GUID он становится уникальным. Поэтому разработчики COM могут создавать свои собственные GUID, не беспокоясь о конфликтах с GUID других людей. Это позволяет избежать проблем с централизованной публикацией идентификаторов GUID.

  • HRESULT Это целое число, используемое в COM для возврата кода ошибки. Хотя он начинается с буквы «H», это не «дескриптор» какого-либо объекта.HRESULT Более подробное описание.

  • COM library Это часть операционной системы, в которой вы выполняете операции, связанные с COM. как правило COM library Он называется «COM», но, чтобы избежать путаницы, здесь это имя не используется.

Использовать COM-объекты

Каждый язык программирования имеет свой способ работы с объектами. Например, в C ++ вы можете создавать объекты в стеке или использовать new для динамического выделения объектов в куче. Поскольку COM должен быть независимым от языка, библиотека COM предоставляет собственные методы управления объектами. Ниже перечислены различия между управлением объектами COM и C ++:

Создать объект

  • C ++, используйте оператор new или создайте прямо в стеке;
  • COM, вызовите API в библиотеке COM;

Уничтожить объект

  • C ++, используйте оператор удаления или автоматически уничтожайте объекты в стеке за пределами области видимости;
  • COM, все объекты сохраняют свои собственные счетчики ссылок, когда у пользователя заканчиваются COM-объекты, он должен указать COM-объекту уменьшить счетчик ссылок. Когда счетчик ссылок на COM-объект уменьшается до 0, COM-объект уничтожается из памяти.

целевая аудитория пользователей После создания COM-объекта вам необходимо использовать этот объект. В COM-объекте может быть один или несколько методов.Если вы хотите использовать метод, вы должны сообщить библиотеке COM, какой интерфейс вам нужен. Если COM-объект был успешно создан, COM-библиотека вернет указатель на требуемый интерфейс. Вы можете использовать этот указатель для вызова этого метода, как при вызове интерфейса объекта C ++.

Создать COM-объект

Когда вам нужно создать COM-объект и получить в нем указатель на интерфейс, вы можете вызвать COM API CoCreateInstance (). Прототип этой функции выглядит следующим образом:

HRESULT CoCreateInstance(
    REFCLSID rclsid,
    LPUNKNOWN pUnkOuter,
    DWORD dwClsContext,
    REFIID riid,
    LPVOID* ppv );

Смысл параметров следующий:

rclsid :

CLSID компонентного класса.Например, вы можете передать CLSID_ShellLink этому параметру, чтобы создать COM-объект, который можно использовать для создания сочетаний клавиш.

pUnkOuter :

Этот параметр используется только при агрегировании COM-объектов. Его можно использовать для добавления новых методов к существующим коклассам. Здесь нам нужно только передать NULL, чтобы указать на отсутствие необходимости в агрегировании.

dwClsContext

Укажите, какой тип COM-сервера вам нужен. В этой статье используется только один из простейших серверов, внутрипроцессная DLL, поэтому передайте CLSCTX_INPROC_SERVER. Обратите внимание, что CLSCTX_ALL здесь не используется (это значение ATL по умолчанию), потому что это вызовет ошибку в Windows 95 без установленного DCOM.

riid :

IID интерфейса, который вы хотите вернуть. Например, вы можете передать IID_IShellLink этому параметру, чтобы получить интерфейс IShellLink.

ppv :

Адрес указателя интерфейса, библиотека COM вернет запрошенный интерфейс через этот параметр.

Когда вы вызываете функцию CoCreateInstance (), она запрашивает CLSID в реестре, находит местоположение COM-сервера, загружает сервер в память, а затем создает экземпляр запрошенного вами компонентного класса.

Следующий код дает простой пример. Он создаст экземпляр объекта CLSID_ShellLink и запросит интерфейс IShellLink, указывающий на COM-объект:

HRESULT hr;
IShellLink* pISL;

hr = CoCreateInstance( CLSID_ShellLink,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        IID_IShellLink,
                        (void**) &pISL );
if ( SUCCEEDED(hr) )
{
         // Успешно создаем COM-объект, используем pISL для вызова интерфейса
}
else
{
         // Невозможно создать COM-объект, код ошибки существует в часах
}

Уничтожить COM-объект

Как упоминалось ранее, вам не нужно вручную уничтожать COM-объект из памяти, вам просто нужно сказать ему, что он вам больше не нужен.Все классы COM наследуются от интерфейса IUnKnown, который предоставляет функцию под названием Release (). Вызовите эту функцию, чтобы сообщить COM-объекту, что он вам больше не нужен. После вызова Release () вы не можете продолжать использовать соответствующий интерфейс, потому что COM-объект мог быть удален из памяти.

Если ваша программа использует много разных COM-объектов, очень важно, чтобы вы вызывали Release (), когда вам не нужно использовать интерфейс. Если вы не освободите эти интерфейсы, COM-объект и соответствующая ему dll всегда будут существовать в памяти, что приведет к увеличению ненужных накладных расходов. Если ваша программа будет работать долгое время, вы можете вызвать API CoFreeUnusedLibraries () во время периода простоя. Этот API удалит любой COM-сервер, который не вызывается явно. Это может до некоторой степени уменьшить использование памяти.

В следующем примере кода показано, как использовать Release ():

if ( SUCCEEDED (hr) )
{
         // Использование интерфейса pISL для некоторых операций

         // После использования сообщаем COM-объекту, что этот интерфейс не нужен
    pISL->Release();
}

Интерфейс IUnKnown будет подробно описан в следующем разделе.

Базовый интерфейс-I Неизвестно

Каждый COM-интерфейс наследуется от интерфейса IUnknown. Название IUnknown вводит в заблуждение и не означает «неизвестный» интерфейс. Причина этого имени в том, что если у вас есть указатель IUnknown на COM-объект, вы не знаете, что это за базовый объект, потому что каждый COM-объект реализует интерфейс IUnknown.

Интерфейс IUnknown выполняет три функции:

  1. AddRef () Этот интерфейс сообщает COM-объекту об увеличении счетчика ссылок.
  2. Release () Этот интерфейс сообщает COM-объекту уменьшить счетчик ссылок.
  3. QueryInterface () запрашивает указатель интерфейса у COM-объекта.Когда компонентный класс реализует несколько интерфейсов, вам необходимо использовать эту функцию для получения указанного интерфейса.

Прототип функции QueryInterface () выглядит следующим образом:

HRESULT IUnknown::QueryInterface {
    REFIID iid,
    void** ppv );

Смысл параметров следующий:

iid

IID запрошенного вами интерфейса

ppv

Адрес указателя интерфейса, если вызов QueryInterface () успешен, интерфейс будет передан через этот параметр.

В предыдущем примере мы получили указатель pISL интерфейса IShellLink через CoCreateInstance (), а с помощью pISL и QueryInterface () также можно получить другие указатели интерфейса в COM-объекте:

HRESULT hr;
IPersistFile* pIPF;

hr = pISL->QueryInterface( IID_IPersistFile, (void**)pIPF);

Вы можете использовать макрос SUCCEEDED, чтобы проверить, успешно ли получен указатель интерфейса.Когда pIPF израсходован, release () должен быть вызван как pISL для уменьшения счетчика ссылок.

Обработка нотной строки

В этом разделе мы сделаем обходной путь и обсудим, как обрабатывать строки в COM-коде. Если вы знакомы с принципами работы строк Unicode и ANSI и знаете, как выполнять преобразование между этими двумя кодировками, вы можете пропустить эту главу.

Всякий раз, когда строка, возвращаемая функцией COM, кодируется в Unicode. Unicode — это набор кодировок символов, аналогичный ANSI, за исключением того, что все символы Unicode состоят из двух байтов. Если вы хотите лучше управлять строкой, вы можете преобразовать ее в тип TCHAR.

TCHAR и функции, начинающиеся с _t (такие как _tcscpy), предназначены для использования одного и того же кода для обработки строк Unicode и ANSI. В большинстве случаев вы будете использовать строки ANSI и ANSI API, поэтому для простоты в будущих статьях я буду использовать char вместо TCHAR. Но вы все равно должны хорошо владеть типом TCHAR.

После получения строки из функции COM вы можете использовать следующую функцию для преобразования ее в тип char:

  • Вызовите WideCharToMultiByte ();
  • Вызвать CRT-функцию wcstombs ();
  • В MFC для преобразования можно использовать конструктор CString;
  • Используйте макросы преобразования строк ATL;

Ниже приводится подробное описание этих методов:

WideCharToMultiByte()

Прототип этой функции выглядит следующим образом:

int WideCharToMultiByte(
    UINT CodePage,
    DWORD dwFlags,
    LPCWSTR lpWideCharStr,
    int cchWideChar,
    LPSTR lpMultiByteStr,
    int cbMultiByte,
    LPCSTR lpDefaultChar,
    LPBOOL lpUserDefaultChar );

CodePage

Целевая кодовая страница при преобразовании символов Юникода. Вы можете передать CP_ACP для преобразования Unicode в кодовую страницу ANSI, используемую текущей системой. Кодовая страница представляет собой набор из 256 символов, из которых 0–127 совпадают с ANSI, а 128–255 — другие. Она может содержать графические символы или символы произношения. Каждый язык имеет свою собственную кодовую страницу, поэтому важно использовать правильную кодовую страницу, чтобы символы могли отображаться правильно.

dwFlags

Этот флаг определяет, как эта функция будет обрабатывать «составные» строки Unicode. За этой составной строкой будет следовать символ произношения, например è. Если этот символ присутствует на указанной кодовой странице, это не проблема, но если его нет, Windows должна преобразовать этот символ в другую форму для отображения.
Передайте WC_COMPOSITECHECK в dwFlags, тогда API обнаружит «составную строку»;
Передайте WC_SEPCHARS в dwFlags, тогда API разделит символы в форме «символ + акцент», например è -> e`
Передайте WC_DISCARDNS в dwFlags, тогда API отбросит символы произношения;
Передайте WC_DEFAULTCHAR в dwFlags, после чего API заменит знак ударения на символ по умолчанию, который можно указать в lpDefaultChar.
Значение по умолчанию для dwFlags — WC_SEPCHARS.

lpWideCharStr

Преобразуемая строка Unicode.

cchWideChar

Длина строки lpWideCharStr. Если передано -1, конец 00 будет автоматически проверен для подтверждения длины.

lpMultiByteStr

Буфер символьной строки типа char, используемый для приема преобразованной символьной строки ANSI;

cbMultiByte

lpMultiByteStr Длина буфера в байтах.

lpDefaultChar

Необязательный параметр. Когда dwFlags передается в WC_COMPOSITECHECK | WC_DEFAULTCHAR, если API проверяет, что символ не существует на целевой кодовой странице, он заменит этот символ этим символом по умолчанию. Если в этом параметре передается NULL, API заменит его системным символом по умолчанию (обычно это вопросительный знак).

lpUserDefaultChar

Необязательный параметр — это указатель на значение BOOL.Если lpDefaultChar вставлен в целевую строку, значение BOOL будет установлено в TRUE, чтобы пометить его.

Эта функция очень сложная, вот пример:

char szANSIString [MAX_PATH];
 WideCharToMultiByte (CP_ACP, // Использовать текущую кодовую страницу системы
                                         WC_COMPOSITECHECK, // Проверяем составные символы
                                         wszSomeString, // строка Unicode для преобразования
                                         -1, // Автоматически проверять длину строки Unicode
                                         szANSIString, // строковый буфер ANSI
                                         sizeof (szANSIString), // длина буфера
                                         NULL, // заменить составные символы на системные символы по умолчанию
                                         NULL); // Не проверять, заменять ли

wcstombs()

CRT-функция wcstombs () намного проще, но в конце концов она по-прежнему вызывает WideCharToMultiByte ().

size_t wcstombs(
    char* mbstr,
    const wchar_t* wcstr,
    size_t count);

mbstr

Преобразованная строка ANSI сохраняется в этом буфере;

wcstr

Преобразуемая строка Unicode;

count

Длина строки mbstr в байтах.

wcstombs () использует флаги WC_COMPOSITECHECK | WC_SEPCHARS, вы можете вызвать wcstombs () следующим образом:

wcstombs(szANSIString, wszSomeString, sizeof(szANSIString));

CString

CString в MFC может принимать строки Unicode в конструкторе или операторе присваивания, которые можно использовать для преобразования:

CString str1(wszSomeString);
CString str2;
str2 = wszSomeString;

Макрос преобразования строки ATL

ATL предоставляет набор макросов для преобразования строк:

  • W2A () (Wide To ANSI) используется для преобразования Unicode в ANSI;
  • OLE2A () (OLE или COM String To ANSI) имеет ту же функцию, что и вышеупомянутый макрос, но описание более точное. «OLE» ясно указывает, что это COM-строка.
  • W2T () (Wide To TCHAR) преобразует Unicode в TCHAR;
  • W2CT() (Wide To const TCHAR)
  • OLE2CA() (OLE String To const char String)

Вот пример:

char szANSIString[MAX_PATH];
 USES_CONVERSION; // Объявление локальных переменных, необходимых для макросов OLE2A
lstrcpy(szANSIString, OLE2A(wszSomeString);

Причина, по которой вам нужно вызвать lstrcpy для копирования результата, возвращаемого OLE2A (), в szANSIString, заключается в том, что результат, возвращаемый OLE2A (), временно сохраняется в стеке и может использоваться в течение длительного времени только при копировании.

Интеграция знаний — пример кода

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

COM-объекты с использованием единого интерфейса

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

#include <Windows.h>
#include <WinInet.h>
#include <ShlObj.h>
#include <locale>

int main()
{
    setlocale(LC_ALL, "chs");

    HRESULT hr;
    IActiveDesktop* pIAD;
    WCHAR wszWallpaper[MAX_PATH];

         // 1. Инициализируем библиотеку COM
    CoInitialize(NULL);

         // 2. Создание экземпляра COM-объекта
    hr = CoCreateInstance(CLSID_ActiveDesktop,
        NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);

    if ( SUCCEEDED(hr) )
    {
                 // 3. Вызов функции GetWallpaper
        hr = pIAD->GetWallpaper(wszWallpaper, MAX_PATH, 0);
        if ( SUCCEEDED(hr) )
        {
            wprintf(L"wallpaper path = %sn", wszWallpaper);
        }
        else
        {
            wprintf(L"GetWallpaper Error! n");
        }

                 // 4. Освободить интерфейс
        pIAD->Release();
    }
    else
    {
        wprintf(L"CoCreateInstance Error! n");
    }

         // 5. Деинициализировать библиотеку COM
    CoUninitialize();

    return 0;
}

Setlocale () в приведенном выше коде позволяет wprintf () правильно выводить китайский язык в консоль.

COM-объекты, использующие несколько интерфейсов

В следующем примере показано, как использовать QueryInterface () для получения интерфейса. Сначала он создает COM-объект ShellLink, получает его интерфейс IShellLink, а затем вызывает QueryInterface () для получения интерфейса IPersistFile.

Функция этого примера — создать ярлык для файлов обоев.

#include <Windows.h>
#include <WinInet.h>
#include <ShlObj.h>

int main()
{
    WCHAR wszWallpaper [MAX_PATH] = L "C: \ Users \ Dongyu \ Pictures \ desktop black.png";

         // 1. Инициализируем библиотеку COM
    CoInitialize(NULL);

    HRESULT hr;
    IShellLink* pISL;
    IPersistFile* pIPF;

         // 2. Создание экземпляра COM-объекта ShellLink
    hr = CoCreateInstance(CLSID_ShellLink, 
        NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pISL);

    if ( SUCCEEDED(hr) )
    {
                 // 3. Устанавливаем путь к целевому файлу
        hr = pISL->SetPath(wszWallpaper);

        if ( SUCCEEDED(hr) )
        {
                         // 4. Получаем второй COM-интерфейс
            hr = pISL->QueryInterface(IID_IPersistFile, (void**)&pIPF);

            if ( SUCCEEDED(hr) )
            {
                                 // 5. Вызов метода Save для сохранения ярлыка обоев
                hr = pIPF->Save(L"E:\wallpaper.lnk", FALSE);

                                 // 6. Выбегаем, отпускаем
                pIPF->Release();
            }
        }
                 // 7. Израсходовать, отпустить
        pISL->Release();
    }

         // 8. Деинициализируем библиотеку COM
    CoUninitialize();

    return 0;
}

Обработка HRESULT

В предыдущем примере макрос SUCCEEDED, FAILED использовался для простой обработки HRESULT.Теперь я хочу подробнее рассказать о HRESULT.

Возвращаемое значение HRESULT — 32-разрядное целое число со знаком. Неотрицательные числа указывают на успех, а отрицательные числа — на неудачу.

HRESULT имеет три домена: [бит результата], [код функции] и [код состояния]. Бит результата указывает, является ли результат успешным или неудачным; код функции указывает, из какого компонента возникла ошибка. Например, COM и планировщик задач имеют соответствующие коды функций. Код функции — это 16-битное значение, не имеющее другого внутреннего значения. Нет никакой корреляции между этим числом и значением, как и возвращаемое значение GetLastError ().

Если вы перейдете к winerror.h, вы увидите кучу определений HRESULT. Правила их именования: [Функция][результат][Описание], если HRESULT не принадлежит какому-либо конкретному компоненту, то [функция] не пишет:

  • REGDB_E_READREGDB: функция = REGDB (база данных реестра), результат = ошибка, описание = READREGDB (указывает, что база данных не может быть прочитана);
  • S_OK: Функция = Общие, Результат = Успех, Описание = ОК (означает, что проблем нет);

В дополнение к прямому просмотру winerror.h вы можете использовать инструмент поиска ошибок, чтобы понять конкретное значение HRESULT.

Вы можете использовать @ err.hr в окне мониторинга во время отладки, чтобы увидеть конкретное значение HRESULT.

Цитата

Essential COM Дон Бокс «Теория сущности COM»
MFC Internals by George Shepherd and Scot Wingo
Beginning ATL 3 COM Programming by Richard Grimes

Выше приведены несколько книг, рекомендованных в статье. «Com Essence» стоит прочитать, но понять ее немного сложно.
«COM Technology Insider» также стоит прочитать.

Заглянуть под капот Kubernetes можно на курсе Kubernetes: Мега-поток, который стартует уже 12 апреля.

На курсе вы узнаете как работает Kubernetes внутри: изучите тонкости установки и конфигурации production-ready кластера («the-not-so-easy-way»), механизмы обеспечения стабильности и безопасности, отказоустойчивости приложений и масштабирование, разберете стратегические задачи, касающиеся инфраструктуры.

Программа курса

Тема №1. Введение
Тема №2. Создание отказоустойчивого кластера изнутри

Разбор архитектуры Kubernetes, различных методов обеспечения высокой доступности.Создание кластера вручную, с помощью утилиты kubeadm.

Тема №3. Аутентификация пользователей в кластере

Аутентификация и авторизация пользователей в кластере k8s, механизмы аутентификации, практическая работа по настройке интеграции Active Directory и Kubernetes.

Тема №4. Network Policy

Обзор популярных сетевых плагинов для Kubernetes. Изучение механизма настройки кластерного фаервола в Kubernetes.

Тема №5. Безопасность и высокодоступные приложения в кластере

Познакомимся с инструментами Kubernetes, которые позволяют сделать работу в Kubernetes более безопасной, а приложение более отказоустойчивым. Узнаем, как контролировать указание Limits/Requests разработчиками, как запретить использование root-контейнеров в Namespace.

Тема №6. Kubernetes под капотом

Подробно разбираем работу scheduler, API Server, Controller manager, учимся делать собственные операторы для Kubernetes.

Тема №7. Stateful приложения в кластере

Поговорим о том, как запускать базу данных в Kubernetes и стоит ли это делать. Обсудим, какие базы данных лучше подойдут для запуска, а какие менее. Обсудим какие есть подводные камни при запуске баз данных в Kubernetes.

Тема №8. Хранение секретов

Приемы работы с секретами в кубернетес. Интеграция Hashicorp Vault, автоматизированная передача настроек из Vault в приложение с помощью веб-хука от Banzai Clod.

Тема №9. Horisontal Pod Autoscaler

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

Тема № 10. Резервное копирование кластера

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

Тема №11. Ротация сертификатов в кластере

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

Тема №12. Deploy
Тема №13. Service Mesh

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

Узнать подробнее: https://slurm.club/3iXUi0l

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

Как мы могли бы использовать его более продуктивно? С недавним выпуском OpenAI API серии GPT 3.5, мы можем делать гораздо больше, чем просто общаться в чате. Одним из очень продуктивных вариантов использования для бизнеса и вашей личной эксплуатации является QA (Question Answering) — вы спрашиваете бота на естественном языке о ваших собственных документах / данных, а он может быстро ответить вам, извлекая информацию из документов и генерируя ответ [1]. Вы можете использовать его для поддержки клиентов, обобщения пользовательских исследований, управления вашей личной информацией и многого другого!

Пошаговое руководство по созданию чат-бота на основе ваших собственных документов с помощью GPT

В этой статье я расскажу, как создать собственного Q&A чат-бота на основе ваших данных, а также о том, почему некоторые подходы его создания не будут работать.

(Если вы только хотите узнать, как создать Q&A чат-бота, вы можете перейти непосредственно к разделу “Пошаговое создание чат-бота для вопросов и ответов”)

Изучение различных подходов

Моя повседневная работа — менеджер по продуктам – чтение отзывов клиентов и внутренних документов занимает большую часть моей жизни. Когда появился ChatGPT, мне сразу пришла в голову идея использовать его в качестве помощника, который помог бы мне обобщать отзывы клиентов или находить связанные старые документы по продукту о функции, над которой я работаю.

Сначала я подумал о тонкой настройке модели GPT с помощью моих собственных данных для достижения поставленной цели. Но тонкая настройка стоит немалых денег и требует большого набора данных с примерами. Также невозможно выполнять точную настройку каждый раз, когда в документ вносятся изменения. Ещё более важным моментом является то, что тонкая настройка просто НЕ может позволить модели “знать” всю информацию в документах, скорее она обучает модель новому навыку. Следовательно, для контроля качества (с несколькими) документами тонкая настройка – это не тот путь, которым следует идти.

Второй подход, который приходит мне на ум, – это разработка подсказок путем предоставления контекста в них. Например, вместо того, чтобы задавать вопрос напрямую, я могу добавить исходное содержимое документа перед самим вопросом. Но модель GPT имеет ограниченный объём внимания — она может вместить всего несколько тысяч слов в подсказку (около 4000 токенов или 3000 слов). Невозможно предоставить весь контекст в подсказке, при условии, что у нас есть тысячи электронных писем с отзывами клиентов и сотни документов о продукте. Это также дорого, если вы переходите в длительном контексте к API, потому что цена основана на количестве используемых вами токенов.

I will ask you questions based on the following context:
— Start of Context —

YOUR DOCUMENT CONTENT

— End of Context—
My question is: “What features do users want to see in the app?”

(Если вы хотите узнать больше о точной настройке и быстром проектировании GPT, вы можете прочитать эту статью: https://medium.com/design-bootcamp/3-ways-to-tailor-foundation-language-models-like-gpt-for-your-business-e68530a763bd)

Поскольку подсказка имеет ограничения на количество входных токенов, мне пришла в голову идея сначала использовать алгоритм для поиска документов и выбора соответствующих выдержек, а затем передавать только эти соответствующие контексты в модель GPT с моими вопросами. Пока я изучал эту идею, я наткнулся на библиотеку под названием gpt-index (теперь переименованную в LlamaIndex), которая делает именно то, что мне надо, и проста в использовании [2].

Пошаговое руководство по созданию чат-бота на основе ваших собственных документов с помощью GPT

В следующем разделе я дам пошаговое руководство по использованию LlamaIndex и GPT для создания чат-бота для вопросов и ответов на основе ваших собственных данных.

Пошаговое создание Q&A чат-бота

В этом разделе мы создадим Q&A чат-бота на основе существующих документов с помощью LlamaIndex и GPT (text-davinci-003), чтобы вы могли задавать вопросы о вашем документе и получать ответы от чат-бота. И всё это будет происходить на естественном языке.

Подготовка

Прежде чем мы начнём, нам нужно подготовить несколько вещей:

  • Ваш ключ OpenAI API, который можно найти по адресу https://platform.openai.com/account/api-keys .
  • База данных ваших документов. LlamaIndex поддерживает множество различных источников данных, таких как Neptune, Google Docs, Asana и т.д. [3]. В этом руководстве мы будем использовать простой текстовый файл для демонстрации.
  • Локальная среда Python или Google Colab notebook.
План

Рабочий процесс прост и занимает всего несколько шагов:

  1. Создание индекса данных вашего документа с помощью LlamaIndex
  2. Запрос индекса с помощью естественного языка
  3. LlamaIndex извлечёт соответствующие части и передаст их в подсказку GPT
  4. Спросите GPT с соответствующим контекстом, а он выведет ответ

Что делает LlamaIndex, так это преобразует данные вашего исходного документа в векторизованный индекс, который очень эффективен для запроса. Он будет использовать этот индекс для поиска наиболее релевантных частей на основе сходства запроса и данных. Затем он вставит полученное в подсказку, которую отправит в GPT, чтобы у GPT был контекст для ответа на ваш вопрос.

Установка

Сначала нам нужно будет установить библиотеки. Просто запустите следующую команду в своём терминале или в Google Colab notebook. Эти команды установят как LlamaIndex, так и OpenAI.

!pip install llama-index
!pip install openai

Далее мы импортируем библиотеки на python и настроим ваш ключ OpenAI API в новом файле .py.

# Import necessary packages
from llama_index import GPTSimpleVectorIndex, Document, SimpleDirectoryReader
import os

os.environ['OPENAI_API_KEY'] = 'sk-YOUR-API-KEY'
Создание индекса и его сохранение

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

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

# Loading from a directory
documents = SimpleDirectoryReader('your_directory').load_data()

# Loading from strings, assuming you saved your data to strings text1, text2, ...
text_list = [text1, text2, ...]
documents = [Document(t) for t in text_list]

LlamaIndex также предоставляет множество соединителей данных, включая Neptune, Asana, Google Drive, Obsidian и т.д. Вы можете найти доступные соединители данных по адресу https://llamahub.ai/.

После загрузки документов мы можем создать индекс с помощью следующем команды:

# Construct a simple vector index
index = GPTSimpleVectorIndex(documents)

Если вы хотите сохранить индекс и загрузить его для дальнейшего использования, вы можете использовать следующие методы:

# Save your index to a index.json file
index.save_to_disk('index.json')
# Load the index from your saved index.json file
index = GPTSimpleVectorIndex.load_from_disk('index.json')
Запрашивание индекса и получение ответа

Запросить индекс очень просто:

# Querying the index
response = index.query("What features do users want to see in the app?")
print(response)

И вуаля! Вы получите свой ответ. Под капотом LlamaIndex примет вашу подсказку, выполнит поиск соответствующих фрагментов в индексе и передаст её и соответствующие фрагменты в GPT.

Некоторые примечания для расширенного использования

Приведённые выше шаги показывают только очень простое начальное использование для ответа на вопросы с помощью LlamaIndex и GPT. Но вы можете сделать гораздо больше, чем это. Фактически, вы можете настроить LlamaIndex на использование другой модели большого языка (LLM), использовать другой тип индекса для разных задач, обновлять существующие индексы новым индексом и т.д. Если вам интересно, вы можете прочитать их документацию по адресу https://gpt-index.readthedocs.io/en/latest/index.html .

Заключение

В этой статье мы рассмотрели, как использовать GPT в сочетании с LlamaIndex для создания чат-бота, отвечающего на вопросы о документах. Хотя GPT (и другие LLM) мощны сами по себе, их возможности могут быть значительно усилены, если мы объединим их с другими инструментами, данными или процессами.

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

Ссылки на используемую литературу

[1] What Is Question Answering? — Hugging Face. 5 Dec. 2022, https://huggingface.co/tasks/question-answering.

[2] Liu, Jerry. LlamaIndex. Nov. 2022. GitHub, https://github.com/jerryjliu/gpt_index.

Просмотры: 1 264

Зачем нужны службы компонентов

Как работают службы компонентов

   Организация пулов объектов и ресурсов

   Управление транзакциями

   Вопросы безопасности

Особенности объектов COM+

   Требования к объектам COM+

   Особенности управления объектами COM+

   Классы Delphi для создания объектов

Создание серверных объектов

   Создание объекта COM+ для доступа к данным

   Тестирование объекта COM+ для доступа к данным

Настоящая статья посвящена созданию и применению COM-серверов,
используемых совместно с Microsoft Component Services и иногда называемых в
отечественной литературе службами компонентов (расширение COM, которое позволяет
создавать приложения, использующие Component Services, получило название COM+).
Применение подобных серверов позволяет решить некоторые задачи, не предусмотренные
спецификацией COM, таких как авторизованный доступ к COM-серверам и организация
распределенных транзакций, а также в ряде случаев снизить требования к ресурсам,
необходимым для эксплуатации COM-серверов.

Зачем нужны службы компонентов

Разработчики
и пользователи COM-серверов часто сталкиваются с различными проблемами, возникающими
на этапе эксплуатации при одновременном обслуживании большого числа клиентов.
В частности, при создании COM-серверов доступа к данным, обслуживающих нескольких
клиентов, следует позаботиться о поддержке нескольких соединений с базой данных
и о работе с несколькими потоками. Однако при большом числе обслуживаемых клиентов
подобные приложения  предъявляют серьезные требования к потребляемым им
ресурсам, например из-за необходимости поддерживать много соединений с базой
данных. Создание же и уничтожение COM-объектов по требованию клиентских приложений
(особенно объектов, предоставляющих доступ к данным), влечет за собой затраты
времени, что неблагоприятно сказывается на производительности таких приложений.
Поэтому нередко разработчики пытаются создать дополнительный код для осуществления
совместного доступа многих клиентов к нескольким экземплярам COM-объектов, постоянно
находящихся в оперативной памяти (иногда говорят о так называемом пуле объектов), 
при этом количество данных объектов должно быть по возможности минимальным (обычно
такое совместное использование объектов обозначают термином object  pooling).
При необходимости обращения к COM-объекту клиентское приложение может воспользоваться
одним из объектов, позаимствовав его из пула, а затем вернуть назад, не инициируя
ни его создания, ни уничтожения.

Еще
одна проблема, нередко возникающая в
процессе практической реализации проектов,
содержащих COM-серверы,
состоит в том, что реально создаваемые
приложения, в отличие от учебных и книжных
примеров, могут иметь довольно сложную
архитектуру и, в частности, содержать
несколько различных сервисов
промежуточного слоя для решения разных
задач. Например, некоторые из них могут
отвечать за предоставление доступа к
данным из нескольких различных СУБД (особенно
это актуально в компаниях, когда-то
подвергшихся так называемой островковой
автоматизации), и при этом может возникнуть
потребность в инструменте, 
реализующем комплексную
функциональность, в частности
осуществление распределенных транзакций,
затрагивающих базы данных, которые
обслуживаются  разными
серверными СУБД (например, Microsoft SQL
Server и Oracle).

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

Таким
образом, существует потребность в
расширении COM-технологии посредством
службы, обеспечивающей создание COM-объектов
для совместного использования многими
клиентами, авторизованный доступ к этим
объектам, а при необходимости также
обработку транзакций этими объектами. 
Расширенная таким образом технология COM
стала именоваться COM+,
а сам сервис, реализующий это расширение и
являющийся составной частью Windows
2000, получил название Microsoft Component Services (службы компонентов).

Следует
напомнить, что предыдущая версия
реализации этого сервиса входит в состав Windows
NT4
Option
Pack
—  свободно
распространяемый пакет обновления для Windows
NT 4.0 и
называется Microsoft
Transaction Server 2.0 (MTS).

Службы
компонентов обеспечивают централизацию
использования серверов автоматизации,
совместное использование многими
клиентами пула COM-объектов
и ресурсов (в частности, соединений с базой
данных), а также управление транзакциями.
Отметим, что, помимо создания COM-объектов
для коллективного пользования,
предоставления сервисов авторизации
пользователя при доступе к объектам и
обработки транзакций, службы компонентов
предоставляют средства мониторинга
объектов и транзакций.

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

Как работают службы компонентов

Рассмотрим
типичный сценарий работы приложения, использующего службы компонентов. Пользователь
запускает клиентское приложение, реализованное в виде исполняемого файла или
Web-приложения. Клиентское приложение пытается установить соединение с объектом
COM+. Если компонент COM+, содержащий такой объект, реализован  в виде
внутрипроцессного сервера, этот объект   может выполняться в адресном
пространстве приложения dllhost.exe или в адресном пространстве клиентского
приложения. (Если речь идет о Windows NT и Microsoft Transaction Server, то
компонент, содержащий такой объект,  обязательно должен  быть реализован
во внутрипроцессном сервере, а  выполняется он в адресном пространстве
приложения mtx.exe; объект MTS также может выполняться и в адресном пространстве
клиентского приложения.)  В общем случае в объекте  COM+  может
быть реализована практически любая функциональность, например такой объект вполне
может быть сервером доступа к данным.

Если
запрос на установку соединения корректен,
то в адресном пространстве того приложения,
в котором должен функционировать объект, 
создается так называемый контекст
объекта (если при этом приложение dllhost.exe
не запущено, происходит его запуск). 
Контекст объекта содержит такие
дополнительные сведения, которые не
предусмотрены спецификацией COM и потому
не содержатся в COM-объектах, — это  правила
доступа к объекту и способ участия его 
в транзакциях. Контекст создается для
каждого клиента, обслуживает именно его (в
отличие от собственно COM-объекта)
и «по поручению» клиента взаимодействует с COM-объектом,
который может быть и только что созданным, и
взятым из имеющегося пула объектов.

После
создания контекста клиентское приложение
может посылать объекту COM+ 
запросы на выполнение его методов. Эти
методы могут, например, выполнять запросы к 
СУБД или реализовывать какие-то иные
действия, в том числе обращаться 
к другому объекту  COM+ (в
последнем случае мы можем говорить о «родительских»
и «дочерних» объектах).

Если
при выполнении какого-либо метода объекта COM+
(родительского или дочернего) возникает
исключение, объект информирует об этом
службы компонентов, а те, в свою очередь,
информируют об этом обратившееся к данному
объекту приложение (или соответственно
другой объект COM+), а при
необходимости производят и дополнительную
обработку исключения.

Если
же метод  объекта COM+ 
успешно завершил свою работу (неважно, с
помощью дочерних объектов или без таковой),
он информирует об этом  службы
компонентов, равно как и о том, что данный
клиент в нем больше не нуждается. 
Затем данный объект может быть разрушен,
возвращен в пул или использован другим
клиентом.

После
этого краткого введения рассмотрим
подробнее особенности функционирования
объектов COM+.

Организация пулов объектов и ресурсов

В
общем случае словосочетания «организация
пула ресурсов» и «организация пула
объектов» означают, что в приложении
создается некоторое количество ресурсов
определенного типа (например, соединений с
базой данных) и что если клиенту данного
приложения потребуется такой ресурс (или
соответственно объект), то он не создается, 
а берется из пула и по окончании работы
возвращается в пул, а не уничтожается.

Зачем
нужна организация пулов объектов? Нередко
бывает, что  серверные
объекты при своем создании потребляют
немалый объем иных ресурсов,  создавая, в частности, большие
временные файлы или  сетевой
трафик и т.д. Исходя из изложенных выше
соображений, такие типы объектов должны
быть созданы однократно в заранее
определенном количестве с целью
последующего их использования клиентскими
приложениями. Если в какой-то момент число
клиентов, которым нужен такой серверный
объект, превысит количество имеющихся
экземпляров данных объектов, то следует
создать дополнительные их экземпляры.
Уничтожение дополнительных экземпляров
объектов, которые стали ненужными,
требуется производить в соответствии с
заранее установленным для них максимальным
временем существования в неактивном
состоянии.

Реализация 
пулов ресурсов в COM+
осуществляется с помощью специальных
объектов, которые кэшируют ресурсы для того,
чтобы организовать их коллективное
использование несколькими объектами COM+,
объединенными в приложение. Эти объекты
носят названия  resource dispensers (dispenser
означает раздаточное устройство или
распределитель; назначение называемых этим
словом объектов — кэширование общих данных,
не подверженных изменению с помощью
транзакций) и resource
managers
(менеждеры ресурсов; они используются при
управлении транзакциями и позволяют
осуществить такие стандартные требования к
ним, как изоляция и атомарность транзакций).
 

При
создании приложений COM+ 
довольно часто применяется организация
пула соединений с базами данных, в
частности пула соединений с 
ODBC-
и OLE
DB-источниками. 
При применении такого пула снижается 
сетевой трафик между службами
компонентов и сервером баз данных
посредством снижения частоты установки и
разрыва соединений с сервером. Организация
пулов поддерживается драйверами,
удовлетворяющими спецификациям 
ODBC 3.0 и ODBC
3.5 и некоторыми OLE
DB-провайдерами,
в частности OLE DB Provider for Microsoft SQL Server.

Управление транзакциями

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

Для
управления распределенными транзакциями
используется специальный сервис — Microsoft
Distributed Transaction Coordinator (MS DTC), который может быть
активизирован из приложения Component
Services Explorer (средства
администрирования объектов COM+,
доступного в разделе Administrative Tools панели
управления Windows
2000), либо из приложения Service
Control
Manager
панели управления Windows
2000, либо из приложения Enterprise
Manager,
входящего в комплект поставки Microsoft
SQL
Server 7.0
или 2000 (если таковой имеется на компьютере).
MS DTC представляет собой службу операционной
системы, которая  координирует транзакции,
использующие различные менеджеры ресурсов,
и позволяет  реализовать
действия, затрагивающие различные базы
данных (эти базы могут быть произведены
разными производителями и находиться на
разных компьютерах)  в рамках единой транзакции.  

Как
в COM+ 
реализованы распределенные транзакции?
Когда какой-либо объект COM+ 
запрашивает доступ к базе данных, то
драйвер соответствующей СУБД проверяет в
контексте этого объекта, требуется ли ему
транзакция, и, если требуется, информирует
об этом DTC.
Затем драйвер обращается к менеджеру
ресурсов, отвечающему за базу данных, с
запросом о начале транзакции в ней. И только
 теперь компонент
может начать манипулировать данными с
помощью этого драйвера.

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

Когда объект COM+, ответственный за какую-либо часть такой транзакции, завершает
свою работу,  он вызывает либо собственный метод SetComplete,
если выполняемые им операции завершились успешно, либо метод SetAbort, если
произошел откат транзакции. Далее DTC обращается к обоим менеджерам ресурсов
с запросом на завершение или откат обеих транзакций. Таким образом, изменения
в обеих базах данных будут либо вместе сохранены, либо вместе отменены (рис.
1).

Если
объект COM+ 
должен предотвратить завершение 
или откат распределеной транзакции, он
может вызвать собственный метод DisableCommit.
Метод EnableCommit
позволяет DTC
завершить все открытые несохраненные
транзакции.

Как
правило, подобного рода транзакции
возможны с участием СУБД, поддерживающих двухфазное
завершение транзакций (two-phase
commit).
Сведения о том, поддерживает ли выбранная
СУБД двухфазное завершение транзакций,
должны содержаться в документации,
поставляемой с этой СУБД.

Следует
отметить, что части распределенной
транзакции обычно реализуются
в различных объектах COM+.
Ранее мы уже отмечали, что одни объекты,
называемые родительскими, могут
инициировать создание других объектов,
называемых дочерними. Если такой дочерний
объект генерирует исключение в процессе
манипуляции с базой данных, службы
компонентов будут проинформированы о
необходимости отката транзакции. В этом
случае DTC
инициирует откат транзакции родительского
объекта и уведомляет об этом клиентское
приложение.  Поэтому
для реализации подобного управления
транзакциями следует поместить код,
реализующий различные части
распределенной транзакции, в разные
объекты  COM+,
а затем создать для них родительский объект.
При использовании такого механизма
контроля транзакций клиентское приложение
может не содержать ни кода, связанного с
завершением или с откатом транзакций, ни
кода, отвечающего за соединение с базой
данных.

Вопросы безопасности

Службы
компонентов  позволяют
использовать список пользователей и групп
пользователей Windows 2000 в качестве списка
пользователей своих объектов. При этом 
для каждого объекта можно установить
правила его эксплуатации различными
пользователями и группами пользователей.
Помимо этого  cлужбы
компонентов  поддерживают
также механизм ролей. Роль в службах
компонентов —  это
совокупность пользователей и групп
пользователей, которые имеют право
обращаться к интерфейсам объектов,
включенных в данное приложение COM+. При
использовании ролей можно не включать код
реализации правил безопасности в объекты COM+.

Необходимо
подчеркнуть, что роли служб компонентов не
следует интерпретировать в качестве
аналогов ролей серверных СУБД — последние
представляют собой не совокупность
пользователй, а совокупность привилегий.

Рассмотрев
возможности служб компонентов, перейдем к
самим объектам COM+, а именно к тому,
каким требованиям они должны удовлетворять
и как они регистрируются.

Особенности объектов COM+

Требования к объектам COM+

Объекты
COM+
являются серверами автоматизации и, как
и другие подобные серверы, реализуют
интерфейс IDispatch.
Все объекты COM+
поддерживают специфический для них
интерфейс IObjectControl, содержащий
методы для активации и деактивации объекта COM+
и управления ресурсами, в том числе
соединениями с базами данных.

Серверный
объект COM+
должен иметь стандартную фабрику классов и
библиотеку типов (и та и другая
автоматически создаются при использовании
эксперта Transactional Object
wizard). Помимо этого компонент должен, как и
все внутрипроцессные серверы
автоматизации, экспортировать функцию DllRegisterServer
 и осуществлять автоматическую
регистрацию его CLSID (эксперт
Transactional
Object wizard автоматически генерирует
соответствующий код).

Если
предполагается коллективное использование
серверного объекта, он должен не хранить
внутри себя сведения о состоянии данных,
связанных с конкретным клиентом (например,
результаты запросов, номера текущей записи
в наборе данных и т.д.), а немедленно
пересылать такие сведения клиентскому
приложению. Объекты, удовлетворяющие этому
требованию, обозначаются термином «не
хранящие состояние»  (stateless
objects).

В
общем случае при создании кода объектов COM+ 
рекомендуется пользоваться
соединением с базой данных минимальное
время и как можно быстрее вернуть его в
соответствующий пул ресурсов. Ссылка же на
контекст объекта при этом может
сохраняться достаточно долго. По этой же
причине рекомендуется также вызывать метод
SetComplete
как можно чаще, чтобы как можно быстрее
вернуть объект в соответствующий пул
объектов.

Особенности управления объектами COM+

Объекты
COM+
объединяются в
приложения COM+
— Applications (в
MTS
они назывались; «пакетами»
— packages),
каждый из которых может содержать один или
несколько объектов. Управление объектами и
приложениями COM+
осуществляется с помощью приложения Componet
Services Explorer, которое
доступно в разделе Administrative
Tools
панели управления Windows 2000.

Каждый
объект, зарегистрированный как объект COM+,
обладает свойством Transaction Support, определяющим правила
участия объекта в транзакциях. Это свойство
принимает пять возможных значений:

Disabled — для
данного объекта не создается контекст
транзакции;

Not Supported — службы
Component Services не запускают
компонент внутри контекста транзакции;

Supported — службы Component
Services
запускают компонент внутри контекста
транзакции, если таковая запрошена, в
противном случае — вне контекста;

Required — службы
Component
Services
помещают объект в контекст транзакции
при вызове любого из методов. Если для этого
объекта транзакция недоступна,
инициируется новая;

Requires new — службы Component
Services
инициирует новую транзакцию при создании
объекта независимо от того, какие
транзакции в этот момент выполняются.

Говоря
о COM+, нужно
отметить механизм обработки событий,
возникающих в таких объектах. В отличие от
событий COM,
где за уведомлением клиентов следит сам
сервер, в COM+
за событиями и уведомлением следят службы
компонентов. При этом для генерации событий
создается отдельный объект-издатель, к
которому производится обращение в момент
наступления события. Затем службы
компонентов обращаются ко всем клиентам,
подписанным на это событие (они содержат
объекты-подписчики).

Объекты-издатели
не должны содержать реализации своих
интерфейсов — она содержится не в
серверном объекте, а в клиентском
приложении (в подписчике на данное событие).
Поэтому после описания интерфейсов
компонент компилируется и регистрируется в
службах компонентов. При наступлении
события в объекте COM+
следует инициировать создание объекта-издателя
и вызвать метод, соответствующий данному
событию. В объекте-подписчике (это обычный COM-объект),
как правило, реализуется интерфейс объекта-издателя,
а также методы
этого интерфейса (в данном случае
реализация методов), которые играют роль
обработчиков событий,
генерируемых объектом-издателем. Отметим,
что и объект-издатель, и объект-подписчик
должны быть зарегистрированы в одном и том
же приложении COM+.

Рассмотрев
особенности управления объектами COM+,
выясним, как создаются такие объекты. В
качестве средства разработки мы будем
использовать Delphi
6 и начнем мы с классов Delphi,
с помощью которых можно создать такие
объекты.

Классы Delphi для создания объектов

В
Delphi
6 Enterprise
имеются два класса для создания приложений COM+
— TMtsAutoObject
и TMtsDataModule. Оба
класса
предназначены
для создания серверов автоматизации,
реализующих интерфейс IObjectControl
(строго говоря, реализация этого интерфейса
обязательна только для объектов MTS,
но не обязательна для объектов COM+,
хотя и в последнем
случае она рекомендуется). В отличие от
класса TMtsAutoObject, класс TMtsDataModule
представляет собой модуль данных, в который
можно помещать невизуальные компоненты.
Он реализует интерфейс IAppServer,
позволяющий применять в приложениях COM+
компоненты DataSnap.

Оба
эти класса реализуют ряд методов,
характерных для объектов COM+.

Метод Описание
SetComplete Вызывается  после того, как объект COM+ успешно выполнил свою работу
и больше не нуждается в данных, связанных с обслуживаемым им клиентом. После
вызова этого метода объект становится неактивным. Если объект выполняется
в контексте транзакции, вызов метода SetComplete означает, что эта
часть транзакции готова к завершению
SetAbort Вызывается в том случае, когда возникает необходимость отката транзакции,
в которой участвует данный объект. Если транзакция была запущена автоматически
службами Component Services специально для этого объекта, она будет прекращена,
а объект будет уничтожен. Если же объект был частью «чужой» транзакции, 
она не будет завершена. Обычно этот метод вызывается при обработке исключений
в блоке except предложения try..except
EnableCommit Вызывается, если объект COM+  может завершить свою транзакцию, не
избавляясь от данных, связанных с клиентом. Метод не инициирует уничтожения
объекта. Его вызов означает, что транзакцию с участием этого объекта можно
завершить
DisableCommit Вызывается в случае, если объект не может завершить текущую транзакцию
до тех пор, пока не будет вызван EnableCommit или SetComplete
IsInTransaction С помощью этого метода можно определить, выполняется ли данный объект
внутри транзакции
IsCallerInRole Этот метод обладает входным параметром типа  WideString.
С его помощью можно проверить, соответствует ли клиент роли, имя которой
указано во входном  параметре
IsSecurityEnabled Данный метод позволяет проверить, защищен ли объект службами безопасности
COM+

Создание серверных объектов

Возможности,
предоставляемые службами компонентов, намного шире, чем те, которые мы проиллюстрируем
примерами. Однако, на наш взгляд, нельзя обойти вниманием такие вопросы, как
создание объектов для доступа к данным (поскольку на сегодняшний день это наиболее
распространенный тип задач), а также реализацию распределенных транзакций (подобная
задача нередко встречается на предприятиях, подвергшихся в свое время островковой
автоматизации, так как эти предприятия на сегодняшний день нуждаются в интеграции
разнородных приложений, использующих СУБД (от различных производителей). Именно
эти задачи мы и рассмотрим.

Мы
начнем с создания, во-первых, простейшего
сервера доступа к данным, который позволяет
манипулировать данными таблицы 
Products базы
данных Northwind, входящей
в комплект поставки Microsoft
SQL
Server,
а во-вторых, клиентского приложения для его
тестирования. Затем
мы создадим второй объект COM+
для манипуляции данными в таблице, хранящей
сведения о заказанных товарах (ее мы
создадим в этой же базе данных). Далее мы
создадим объект, выполняющий транзакцию,
которая затрагивает обе таблицы, и
активизирующий оба ранее созданных объекта
внутри своей транзакции. И наконец, мы
перенесем таблицу Products
из базы данных Northwind
в базу данных Oracle 8 и внесем соответствующие
изменения в компоненты доступа к данным
нашего первого объекта COM+,
чтобы рассмотреть, как распределенные
транзакции управляются с помощью 
Distributed Transaction Coordinator.

Клиентские
приложения и объекты COM+
могут располагаться как на одном и том же компьютере,
так и на разных компьютерах одного домена (в
этом случае мы можем использовать доступ с
помощью DCOM).
Компьютер, на котором расположены
объекты COM+ (далее
мы будем называть его серверным
компьютером), должен иметь доступ к базам
данных, к которым они будут обращаться.

Для
доступа к данным обеих СУБД мы будем
использовать ADO,
а результаты запросов в клиентское
приложение будем передавать в виде наборов
данных ADO
Recordset.
Если примеры выполняются не в Windows 2000 (и,
следовательно, используется не Component
Services,
а MTS), нужно
удостовериться, что на клиентском и
серверном компьютерах установлены
библиотеки MDAC
(Microsoft Data Access
Components) и
служба DCOM
и что на серверном компьютере установлен MTS
(напомним, что он входит в состав 
Windows NT Option Pack, а
последний доступен на Web-сервере
корпорации Microsoft).
Перед тестированием компонентов следует
также запустить Distributed Transaction
Coordinator.

В нашем первом примере мы покажем, как создать простейший
объект COM+, а затем создадим простейшее
клиентское приложение для его тестирования.

Создание объекта COM+ для доступа к данным

Первый
объект COM+,
который мы создадим, будет манипулировать
данными в таблице Products
базы данных Northwind из
комплекта поставки Microsoft
SQL
Serve
7.0 или 2000. В нем мы
реализуем методы для уменьшения значения
поля UnitsInStock и
увеличения значения поля 
UnitsOnOrder данной таблицы (эти операции
производятся, когда со склада заказывают
товар), а также для отправки результатов в
клиентское приложение с целью контроля
результатов этой манипуляции данными.

Наше первое приложение будет состоять из следующих частей, изображенных на
рис. 2.

Создание
объекта COM+
мы начнем с нового проекта библиотеки ActiveX,
вызвав пункт меню File | New | Other и выбрав значок ActriveX
Library со
страницы ActiveX окна
репозитария объектов. Сохраним
проект под именем STOCK.
Далее на странице
Multitier окна
репозитария объектов выберем значок Transactional
Data Module и заполним диалоговую панель
соответствующего эксперта. Как и в случае
обычного COM-объекта,
нам следует ввести имя COM-класса
(назовем его Stock_Data) и выбрать модель потоков (обычно
в объектах COM+
применяется модель Apartment).
Кроме того, следует выбрать значение
свойства Transaction
Support создаваемого объекта (в данном
эксперте она носит название
Transaction
model). Сейчас мы выберем значение
Requires a transaction,
что позволит в дальнейшем использовать
данный объект в качестве участника
транзакции, инициированной другим объектом.
После этого будут сгенерированы модуль
данных (потомок класса TMtsDataModule) и
соответствующая библиотека типов.

Теперь
поместим в созданный модуль данных
компоненты TADOConnection
и TADOCommand. Свойство Connection
компонента ADOCommand1
установим равным ADOConnection1,
а свойство ConnectionString
компонента ADOConnection1
установим равным:

Provider=SQLOLEDB.1;Password="";  
Persist Security Info=True;User ID=sa;  
Initial Catalog=Northwind;Data Source=MAINDESK  

Следует
иметь в виду, что имя сервера, имя
пользователя и пароль на вашем компьютере
могут быть другими. Нужно также установить
свойство  LoginPrompt
компонента  ADOConnection1
равным False, чтобы
избежать появления диалога аутентификации
пользователя на серверном компьютере при
попытке активации  создаваемого
объекта.

Теперь
откроем библиотеку типов созданного
объекта и создадим в ней три новых метода.
Первый из них, Dec_UnitsInStock, будет уменьшать значение
поля  UnitsInStock
одной из записей таблицы Products, второй,
Inc_UnitsOnOrder, будет увеличивать значение
поля  UnitsOnOrder
той же записи. Оба
эти метода должны иметь два целых входных
параметра — ProductID, равный
значению первичного ключа,
идентифицирующего запись, и
OrdQuantity, равный
количеству единиц заказанного товара.
Третий метод (назовем
его Get_ProductList)
будет возвращать набор данных (ADO
Recordset) с
результатом запроса к таблице Products в
клиентское приложение. Чтобы иметь
возможность использовать такой тип данных,
сошлемся на библиотеку Microsoft
ActiveX DataObjects Recordset 2.6 Library в библиотеке типов
объекта stock (это
можно сделать, выбрав пункт контекстного
меню Show All Type Libraries
закладки Uses в
редакторе библиотеки типов и отметить
указанную выше библиотеку в появившемся
списке). Для создания метода Get_ProductList
определим свойство ProductList
типа Recordset,
доступное только для чтения.

Результат редактирования библиотеки типов представлен на рис.
3.

Описав
методы объекта COM+,
нажмем кнопку Refresh
Implementation в редакторе библиотек типов. Теперь нам следует реализовать
эти методы. Первый из них, как было сказано
ранее, уменьшает значение поля
UnitsInStock.
Возможные значения этого поля должны быть
больше или равны нулю (таково ограничение,
присутствующее в базе данных и отражающее
очевидное бизнес-правило: число
единиц товара на складе не должно быть
отрицательным). Следовательно,
этот метод является потенциальным
источником исключения,
связанного с нарушением серверного
ограничения. Поэтому мы учтем этот факт в
коде и обработаем исключение согласно
правилам, принятым в COM+
и рассмотренным выше. Таким образом,
реализация данного метода имеет вид:

procedure TStock_Data.Dec_UnitsInStock(ProductID,   
  OrdQuantity: Integer);  
begin  
  try  
  //Соединяемся с базой данных  
  ADOConnection1.Open;  
  //Текст запроса к базе данных  
  ADOCommand1.CommandText :=   
  'UPDATE Products SET UnitsInStock=UnitsInStock-'  
  +IntToStr(OrdQuantity)+' WHERE ProductID='   
  +IntToStr(ProductID);  
  //Выполняем запрос  
  ADOCommand1.Execute;  
  //Разрываем соединение с базой данных  
  ADOConnection1.Close;  
  //Информируем Component Services об успешном  
  //выполнении запроса  
  SetComplete;  
 except  
  ADOConnection1.Close;  
  //Информируем Component Services о неудачной попытке  
  //выполнения запроса  
  SetAbort;  
  //Передаем исключение вызывающему приложению  
  raise;  
 end;  
end;  

Второй
метод изменяет значение поля
UnitsOnOrder. Здесь мы
также обработаем возможное исключение,
поскольку исключения могут возникать не
только из-за нарушения серверных
ограничений, но и по иным причинам (например,
из-за разрыва соединения
с базой данных). Реализация
этого метода имеет вид:

procedure TStock_Data.Inc_UnitsOnOrder(ProductID,   
  OrdQuantity: Integer);  
begin  
 try  
 //Соединяемся с базой данных  
 ADOConnection1.Open;  
  //Текст запроса к базе данных  
  ADOCommand1.CommandText :=   
  'UPDATE Products SET UnitsOnOrder=UnitsOnOrder+'  
  +IntToStr(OrdQuantity)+' WHERE ProductID='   
   +IntToStr(ProductID);  
  //Выполняем запрос  
  ADOCommand1.Execute;  
  //Разрываем соединение с базой данных  
  ADOConnection1.Close;  
  //Информируем Component Services об успешном  
  //выполнении запроса  
  SetComplete;  
 except  
  //Разрываем соединение с базой данных  
  ADOConnection1.Close;  
  //Информируем Component Services о неудачной попытке  
  //выполнения запроса  
  SetAbort;  
  //Передаем исключение вызывающему приложению  
  raise;  
 end;  
end;  

Третий
метод обращается с запросом к таблице Products
для получения ее содержимого в виде
ADO
Recordset.
Его реализация такова:

function TStock_Data.Get_ProductList: Recordset;  
 var QRY: string;  
begin  
 QRY := 'SELECT ProductID, ProductName, UnitPrice, '+   
   'UnitsInStock, UnitsOnOrder from Products '+  
   'WHERE Discontinued=0';  
 try  
 //Создаем набор данных  
  Result := CoRecordset.Create;  
  Result.CursorLocation := adUseClient;  
 //Открываем его  
 Result.Open(QRY,ADOConnection1.ConnectionString,  
  adOpenStatic,adLockBatchOptimistic, adCmdText);  
  //Разрываем соединение с базой данных  
  ADOCOnnection1.Close;  
  //Информируем Component Services об успешном  
  //выполнении запроса  
 SetComplete;  
 except  
  //Разрываем соединение с базой данных  
  ADOConnection1.Close;  
  //Информируем Component Services о неудачной попытке  
  //выполнения запроса  
  SetAbort;  
  //Передаем исключение вызывающему приложению  
  raise;  
 end;  
end;  

Для работосособности
данного метода
следует сослаться
в секции
Uses на модули
ADODB, ADODb_TLB, ADOR_TLB
(последний
генерируется при
ссылке на
библиотеку типов
Microsoft ActiveX DataObjects Recordset 2.6 Library).

Теперь
нам следует скомпилировать и сохранить
проект, а затем зарегистрировать его. Если
разработка компонента, содержащего наш
объект,  велась на
серверном компьютере, нужно выбрать пункт
главного меню Delphi
Run
| Install COM+ Objects
(в этом случае необходимо ввести имя
нового приложения COM+, в который
следует установить этот объект – пусть он
называется COMPlus_Demo).

Если
же разработка объекта велась не на
серверном компьютере, то созданный
компонент — файл STOCK.DLL — следует скопировать в любой
каталог серверного компьютера и
зарегистрировать его с помощью Component Services Explorer. В
этом случае
нужно создать
новое приложение
COM+, щелкнув правой
клавишей мыши
на элементе
Computer | COM+ Applications
в левой
части окна
Component Services Explore и
затем выбрав
из контекстного
меню этого
элемента пункт
New | Application. Назовем
наше приложение COMPlus_Demo. Далее в созданное приложение,
пока еще ничего не содержащее, добавим
созданный компонент. Для этого раскроем
список папок созданного
приложения, из контекстного меню
раздела Components
выберем пункт New | Component
и в появившихся диалоговых панелях
ответим на вопросы, касающиеся
устанавливаемого компонента. Можно также
просто перетащить имя файла компонента COM+
в Component Services Explorer.

После этого возможно найти и приложение, и сам компонент в Component Services
Explorer (рис. 4).

Создав
простейший компонент COM+
и зарегистрировав его в Component
Services,
мы можем приступить к созданию клиента.

Тестирование объекта COM+ для доступа к данным

Клиент
Component Services будет
представлять собой обычное Windows-приложение
(в общем случае это может быть и Web-приложение,
но мы здесь не будем его рассматривать).
Создадим новый проект, поместим на его
форму компоненты TRDSConnection
и TADODataSet. Свойство ServerName
компонента RDSConnection1
установим равным программному
идентификатору (ProgID) созданного
ранее объекта COM+
(в данном случае stock.Stock_Data), а свойство ComputerName
должно быть равно имени серверного
компьютера. Как уже говорилось выше, для
соединения с удаленным компонентом в этой
ситуации используется DCOM.
Никаких свойств компонента ADODataSet1
в процессе разработки устанавливать не
нужно — он просто получит набор данных на
этапе выполнения. Однако
нам следует продемонстрировать полученный
набор данных пользователю, поэтому
поместим на форму компоненты TDataSource,
TDBGrid и TDBNavigator и сошлемся в них на компонент ADODataSet1. Наконец, поместим компонент  TEdit для
ввода числа единиц заказанного товара и две
кнопки, с помощью которых мы будем вызывать
методы объекта COM+.

Следующий
шаг — создание обработчиков события 
OnClick этих кнопок.
Первый из них будет
получать от объекта COM+
набор данных и
отображать их:

procedure TForm1.Button1Click(Sender: TObject);  
begin  
 try  
  //Создаем контекст объекта Stock_Data  
  RDSConnection1.Connected := True;  
  //Получаем набор данных у объекта Stock_Data  
  RS := RDSConnection1.GetRecordset('ProductList','');  
  ADODataSet1.Recordset := RS;  
  //Показываем его пользователю  
  ADODataSet1.Open;  
  //Теперь можно вызывать другие методы этого объекта  
  Button2.Enabled := True;  
 except  
  //Объект не может вернуть данные  
  ShowMessage('Список товаров недоступен');  
 //Тогда мы не можем вызывать его методы  
  Button2.Enabled := False;  
 end;  
 //Освобождаем контекст объекта  
 RDSConnection1.Connected := False;  
end;  

Обработчик
события OnClick другой кнопки эмулирует
обработку заказа, вызывая два других метода
нашего объекта:

procedure TForm1.Button2Click(Sender: TObject);  
var   
 PID, Quantity : Integer;  
begin  
 //Идентифицируем товар по значению поля ProductID  
 PID := ADODataSet1.FieldByName('ProductID').AsInteger;  
 //Определяем, сколько единиц товара мы хотим заказать  
 Quantity := StrToInt(Edit1.Text);  
 try  
  //Создаем контекст объекта Stock_Data  
  RDSConnection1.Connected := True;  
  //Вычитаем значение Quantity из значения  
  //поля UnitsOnOrder   
  RDSConnection1.AppServer.Dec_UnitsInStock(PID, Quantity);  
  //Добавляем Quantity к значению поля  UnitsOnOrder  
  RDSConnection1.AppServer.Inc_UnitsOnOrder(PID, Quantity);  
  Button1Click(self);  
 except  
  //В объекте возникло исключение  
  Showmessage('Заказ не принят');  
 end;  
 //Освобождаем контекст объекта  
 RDSConnection1.Connected := False;  
end;  

Нам
следует также описать переменную RS :

var  
  Form1 : TForm1;  
  RS    : _Recordset;  

Теперь мы можем скомпилировать и сохранить клиентское приложение, а затем скопировать
его на клиентский компьютер. Запустим клиентское приложение и нажмем первую
кнопку. Мы должны получить набор данных, который будет отображен в компоненте
TDBGrid (рис. 5). Если при этом открыт и Component Services
Explorer, можно наблюдать анимацию значка компонента, к которому происходит
обращение. Как только закончится пересылка данных, анимация должна прекратиться,
поскольку свидетельствует о том, что объект находится в активном состоянии.

Теперь
можно выбрать одну из записей полученного
набора данных, ввести целое число 
(например, 1) в
компонент Edit1 и
нажать вторую кнопку. После этого набор
данных должен обновиться, и в выбранной
записи значение поля UnitsInStock
должно уменьшиться, а значение поля
UnitsOnOrder –
увеличиться на введенную в компонент Edit1
величину. Однако если мы попытаемся ввести
в компонент Edit1
число, превышающее значение UnitsInStock,
то объект COM+, выполняя
запрошенный метод с этим параметром,
инициирует нарушение ограничения на
значение этого поля, содержащееся
в базе данных, и, следовательно,
возникновение исключения в самом объекте COM+.
После этого все манипуляции с данными
прекратятся, а исключение будет передано
вызывающему приложению, которым
в данном случае является
наше клиентское приложение. В нем-то мы
и увидим сообщение об ошибке: «Заказ не
принят».

Обратите внимание на то, что сведения о количестве  завершенных и отмененных
транзакций можно найти в разделе Distributed Transaction Coordinator | Transaction
Statistics приложения Component Services Explorer (рис. 6).

Таким
образом, вы научились создавать простейшие
объекты COM+,
регистрировать и тестировать их. Следующим
шагом будет реализация транзакции,
состоящей из нескольких частей и
реализованной в разных объектах.
Этому будет посвящена вторая часть
данной статьи.

КомпьютерПресс 4’2002

Здравствуйте!

Отдел маркетинга — это “кулак ярости”, который способен разнести Ваших конкурентов на миллион маленьких конкурентиков и запустить маховик развития.

Ну что, Вы уже мечтаете о своем собственном отделе? Тогда добро пожаловать в статью, разберем этот отдел по косточкам.

Кому нужен отдел маркетинга

Если Вы не можете определиться, то мы Вам поможем. У меня есть собственные варианты, которые определяют, кому нужен отдел маркетинга, а кому нет (о них ниже).

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

Не нужен

Один знакомый бизнесмен, проектировщик концертных залов сказал: “Мой отдел маркетинга — это я и пара часов в сауне с нужными людьми”.

Отчасти, мы с ним согласны, да и он был влиятельным человеком в узких кругах (это мы сейчас о личном бренде).

И у него точно нет проблем с заказчиками. В этой ситуации и без отдела маркетинга все относительно неплохо.

Теперь приведу другой пример. Как-то раз владелец бизнеса по розничной торговле строительными материалами спросил у нас: “Как построить отдел маркетинга?”.

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

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

Нужен

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

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

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

Плюсы и минусы

Без сомнения, маркетинговый отдел может принести как пользу, так и вред. Это не так страшно, как прозвучало, но…

Чтобы отдел был для Вас эффективным, с ним придется повозиться и обеспечить комфортную среду. Поэтому важно понимать его плюсы и минусы и так как их сотни, то мы перечислим основные.

Плюсы:

  • Возможность развития компании;
  • Отстройка от конкурентов;
  • Выявление скрытых проблем;
  • Определение направления развития;
  • Улучшения качества обслуживания;

Минусы:

  • Увеличение зарплатного фонда;
  • Отсутствие 100% гарантии результата;
  • Неквалифицированный персонал.

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

Чем занимается отдел маркетинга

Тайна египетских пирамид — загадка для детского сада по сравнению с тайной маркетингового отдела, а точнее с его функциями, целями и задачами. 

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

Цели

Цели отдела могут быть совершенно разные. И все, как обычно, зависит от конкретных ситуаций.

Например, может быть краткосрочная цель — провести мероприятие по стимулированию сбыта. А может и долгосрочная — выход на новый рынок.

И если упростить, то вот самые основные цели отдела:

  1. Увеличение доли рынка;
  2. Развитие имиджа компании;
  3. Повышение дохода;
  4. Отстранение от конкурентов;
  5. Вывод нового продукта;
  6. Рост объема продаж.

Хотя, если глобально говорить, то все цели маркетингового отдела, как и компании в общем, сводятся к одной — увеличение прибыли. Как не крути, а делается все ради денег.

Функции

Мы не знаем, какую цель преследуют начальники-маркетологи, когда используют профессиональные термины при разговоре и отчетах с руководством?

Мне кажется, что благодаря таким ситуациям отдел маркетинга получает статус “бездельников”.

Мы не переносим у заумные слова, поэтому вот функции отдела человеческим языком:

  1. Составление маркетингового плана;
  2. Исследования рынка;
  3. Позиционирование бренда компании;
  4. Продвижение компании;
  5. Ценообразование;
  6. Ассортиментная политика компании;
  7. Генерация новых идей и путей развития;
  8. Анализ маркетинговой деятельности.

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

Задачи

Все очень просто. Если функции — это стратегические решения, то задачи — это локальные, то есть обязанности отдела маркетинга.

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

Поэтому можно выделить 12 основных задач отдела:

  1. Сбор и анализ данных;
  2. Изучение и анализ целевой аудитории;
  3. Составление планов и отчетов;
  4. Разработка стратегий продвижения и развития;
  5. Аудит продаж и каналов сбыта;
  6. Разработка маркетинговых и PR коммуникаций;
  7. Мониторинг ценовой политики сферы деятельности;
  8. Анализ продукции и составление продуктовой матрицы;
  9. Поиск новых рынков сбыта;
  10. Соблюдение и ведение маркетингового плана;
  11. Корректировки планов и продаж;
  12. Взаимодействие со всеми подразделениями компании.

И далее, далее, далее.. Самые основные моменты деятельности маркетингового отдела мы разобрали. Теперь осталось внести корректировки согласно Вашей сфере бизнеса.

Место в структуре

Как Вы думаете, от кого зависит позиция отдела маркетинга в организационной структуре предприятия?

Правильно, от руководителя. Так как он составляет или принимает регламент структуры. То есть, кто кому подчиняется, кто с кем и что согласовывает. Маркетинговый отдел стоит в одном ряду с такими составляющими организационной структуры компании, как производство, финансы и кадры.

Хотя, кто-то ставит производство главным элементом в системе управления компанией, кто-то финансы. Бывает даже такое, что и маркетинг становится основным элементом, но это в редких случаях.

Даже при “равных правах” в оргструктуре, отдел маркетинга всегда получает меньше всего внимания к себе.

При этом взаимодействовать сотрудники отдела маркетинга должны со всеми другими подразделениями. И часто структура имеет такой вид:

Место в структуре

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

Поскольку это будет похоже на ситуацию с трехместной лавочкой, на которую должны усадить четыре человека.

Кадровая структура

Это тот случай, когда кадры действительно решают. И в настоящий момент, самая обычная кадровая структура на предприятиях сейчас выглядит так:

Кадровая структура

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

Должности

Преподаватель маркетинга в ВУЗе спустил бы меня с лестницы прямиком в “буханку” психиатрической больницы, расскажи мы ему десять лет назад, из каких профессий будет состоять отдел маркетинга в 2018 году.

Но… Таков маркетинг.

Должность некоторых специалистов может быть неизменной, меняются только инструменты и каналы. А вот появление новых профессий — это факт.

Естественно, все может зависеть от специфики бизнеса, но знание интернет-маркетинга — это обязательное требование каждого сотрудника отдела. Рассмотрим самые популярные должности, которые могут из Вашего бизнеса сделать “ракету”.

1. Начальник отдела

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

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

На эту должность подойдет маркетолог, у которого стаж не менее 3-х лет. И наличие диплома по маркетингу здесь не обязательно.

2. Менеджер по маркетингу и рекламе

На профессиональном языке их можно назвать маркетеры — те, кто воплощает в жизнь стратегию маркетинга компании.

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

3. Аналитик / Вэб-аналитик

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

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

4. Специалист по контекстной рекламе

Сейчас это неотъемлемая должность в отделе.

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

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

5. СЕО специалист

Разные слухи ходят об этой должности. Например, что они пользуются тем, что в СЕО никто ничего не понимает, а на самом деле там все просто, и они только делают вид, что работают.

Однако, без такого специалиста отдела маркетинга Вам не удастся снижать расходы на рекламный бюджет и продвинуть сайт в поисковых системах. Поэтому он идет в пару к контекстологу.

6. Программист

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

7. СММщик / Таргетолог

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

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

8. Копирайтер

На самом деле этот специалист нужен там, где требуется побуждать людей совершать, какие-либо действия и продавать по средствам текста.

Например, речи для политиков, сценарии для видео, коммерческие предложения, скрипты продаж, e-mail рассылки, рекламные слоганы и т.д. пишут копирайтеры. Опыт работы такого специалиста должен быть не менее двух лет.

9. Дизайнер

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

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

Количество специалистов

Количество человек зависит от Ваших целей, ресурсов и величины бизнеса. Где-то достаточно одного, с узкой специализацией, а где-то и 15 специалистов будет недостаточно. Рассмотрим основные ситуации и критерии определения количества человек:

1. Отдел из одного специалиста

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

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

Но они не понимают, что даже если этот “супер-мен” будет компетентен в 20 должностях, его не хватит просто физически на всё. И никакая ЗП в этом не поможет.

2. Отдел и из двух специалистов

Этот вариант самый популярный среди предпринимателей. Один занимается продвижением, а другой аналитикой и исследованиями.

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

3. Полноценный отдел (3 — 8 специалистов)

Эти ребята могут серьезно “пошуметь” на рынке Вашей сферы. В таком случае отдел маркетинга состоит из специалиста по продвижению, маркетолога-аналитика, PRщика, и пр., в зависимости от целей, которые могут запустить маховик развития.

Часть работы они могут выполнять как сами, так и посредством подрядчиков (удаленных специалистов). Строить такой отдел имеет смысл, если обороты Вашей компании десятки-сотни миллионов.

4. Департаменты

Полноценные отделы для каждого из направлений маркетинга. Это те компании, которые Вы все знаете.

У них большая история и рекордные показатели. Их обороты, естественно, уже, не в миллионах, а в миллиардах… И даже не рублей.

Штат или аутсорсинг

“Дилемма” — слово, которое возникает в голове при вопросе: взять в штат или лучше на аутсорсе найти?

Даже идут дискуссии и споры по этому поводу. Но… Одно не может быть лучше или хуже другого. Главное понимать, что для каждого существует свой вариант и свои возможности.

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

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

Аутсорсинг

Основополагающий момент выбора сторонних организаций для бизнес процессов — финансовый.

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

Если Вы стартап или малый бизнес, то, скорее всего, Вы придете к решению обзавестись отделом маркетинга на аутсорсинге. Также этот результат Вас ждет в том случае, если Вы строите бизнес по типу: “Получится — хорошо. Не получится, ну и черт с ним”.

Штат

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

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

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

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

Эффективность отдела

KPI отдела маркетинга (показатели эффективности) — это заранее прописанные показатели, которые должны быть достигнуты за определенный период времени и направлены на достижение целей компании.

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

Если говорить вкратце, то Вам будут важны следующие показатели:

  1. Увеличение новых обращений;
  2. Влияние на продажи;
  3. Рентабельность маркетинговых инвестиций;
  4. Узнаваемость бренда;
  5. Увеличение количества повторных покупок;
  6. Повышение лояльности к бренду;
  7. Выполнение маркетингового плана.

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

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

А вот и пример KPI для отдельного сотрудника:

  1. Эффективность проведенных акций;
  2. Цена за клик и CTR в контекстной рекламе;
  3. Повышение сайта в органической выдаче;
  4. Повышение конверсии сайта;
  5. Цена подписчика в группе;
  6. Готовый скрипт продаж;
  7. Утвержденный контент-план;
  8. LTV;
  9. NPS. 

Если Вы хотите более подробно прочитать о показателях эффективности, то рекомендуем нашу статью.

Как построить маркетинговый отдел

Непростая задача. Если говорить честно, то поиск кандидатов через объявления на различных ресурсах — это не волшебная таблетка.

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

К тому же, поиск кандидатов это не первостепенная задача, как считают многие предприниматели. Поэтому сейчас разберем основные шаги построения отдела маркетинга.

Шаг 1. Цели и задачи

“Нам нужен отдел маркетинга. Начинайте искать” — стандартная фраза владельцев бизнеса. А зачем он нужен или нужен ли он вообще? Непонятно.

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

В нем должны быть прописаны долгосрочные цели бизнеса и процессы, которыми будут достигаться эти цели. 

Еще план должен содержать четкое понимание финансовой ситуации, динамику и прогнозы развития бизнеса. Это Вам нужно для того, чтобы определить кадровый состав будущего отдела.

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

Здесь полезным будет хороший трейд-маркетолог. Подробно писать не буду, суть и так понятна.

Шаг 2. Оргструктура и состав

Вы уже знаете, какие должности самые распространенные, на данный момент, в отделе маркетинга.

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

Орг.структура

Часто начальники делят отдел на подразделения. Например, менеджер по маркетингу, аналитик и начальник отдела в подразделении “стратегического планирования”. Специалист по контекстной рекламе, СЕОшник и программист в подразделении “Производство сайта” и т.д.

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

Шаг 3. Расчеты затрат

Самый животрепещущий этап — создание отдела и дальнейшее его содержание. Вы должны определить зарплатный фонд, найти помещение и обеспечить рабочие места всем необходимым.

А также определить бюджет отдела маркетинга. Сами же понимаете, реклама, POS материалы, специальные сервисы и т.д.

Затраты

При расчете заработной платы необходимо исходить из опыта кандидатов и Вашего региона. Если говорить о Москве, то увеличивайте все на 40%.

К тому же, размеры ЗП будут зависеть от системы найма (об этом поговорим ниже). Данную таблицу лучше проработать с бухгалтером.

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

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

Шаг 4. Требования

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

  1. Опыт. Будет большим преимуществом. Впрочем, можно рассмотреть кандидата и без стажа, но тогда Вам придется его самостоятельно обучать;
  2. Достижения. Те самые кейсы — наличие практических примеров на предыдущих местах работы. Причем наличие неудачного опыта — это не минус, а плюс;
  3. Мотивы. Заниматься какой-либо деятельностью без мотивов — странная позиция. Просто задайте вопрос: “Почему Вы этим занимаетесь?”;
  4. Чистота. Естественно, Вам не подойдет кандидат, у которого будут проблемы с законом. И не удивляйтесь, мы все-таки в России находимся;
  5. Ценностей компании. Кандидат должен знать и принять Ваши ценности. Однако, хороший спец готов предлагать свое мнение без фанатической одержимости;
  6. Интервью. Оценка кандидата на рубеже огня. Его одежда, поведение, умение отвечать на вопросы, импровизировать и действовать в нестандартных ситуациях.

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

Шаг 5. Найм

С задачей найма лучше всего справится HR-специалист или рекрутинговое агентство.

Но, если Вы хотите принимать непосредственное участие в формировании отдела, то придется “прокачиваться” в этом деле. И чтобы начать “операцию Найм” необходима следующая схема:

1. Поиск кандидатов

Для поиска рекомендую разместить объявления на площадках Вашего города (Head Hunter, Авито и т.д.), создать посты в социальных сетях (в собственных сообществах и у местных блогеров).

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

2. Последовательность

Естественно, сначала необходимо “обзавестись” начальником отдела. Он сможет правильно проводить собеседования, да и вообще, может сам заняться построением отдела.

Но помните, что такие специалисты редко ищут работодателей. В основном, работодатели их ищут.

3. Интервью

Составьте вопросы для каждой должности, которые Вы будете задавать на интервью. Определите критерии опыта, портфолио и мышления кандидатов.

Да, именно мышления. Это мы считаем основным критерием. Как человек говорит о своей профессии, какая у него поза, как реагирует на вопросы и как размышляет.

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

4. Отбор

Как в природе — естественный отбор. Рынок труда такой же, как и все другие рынки. Если кандидат не соответствует Вашим критериям…

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

Коротко о главном

Построение отдела маркетинга — непростая задача, но это не значит, что она невыполнимая.

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

Кроме этого необходимо осознавать, что обратную сторону медали никто не отменял. И напомню, что 100% гарантию результата от работы этого отдела Вам не даст никто.

До новых встреч!

Понравилась статья? Поделить с друзьями:
  • Отривин с ментолом инструкция для детей
  • Дентин герметизирующий ликвид инструкция по применению
  • Газовый счетчик вектор т g4 инструкция
  • Должностная инструкция менеджера пункта выдачи заказов вайлдберриз
  • Куклы мартинички своими руками пошаговая инструкция для начинающих