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

Давайте сравним близкий к реальному псевдокод на сторонах клиента в рамках CORBA с псевдокодом в среде веб-служб. При поддержке сессии все достаточно прозрачно и не нуждается в комментариях.

Псевдокод транзакции в среде CORBA

CosTransactions.Current current = CosTransactions.CurrentHelper.Narrow(

orb.ResolveInitialReferences("TransactionCurrent"));

current.Begin();

try

{

store1.Remove(product, quantity);

store2.Append(product, quantity);

current.Commit();

}

catch (Exception e)

{

current.Rollback();

ShowError("Ошибка выполнения операции: " + e.toString());

}

В среде веб-служб в программе-клиенте приходится надстраивать абстракции DTO[81]. А в серверном приложении, где используются соединения, например, с СУБД или монитором транзакций, необходимо фактически дублировать предыдущий код с раскруткой объекта – единицы работы (unit of work) в реальную транзакцию.

Псевдокод транзакции в среде веб-служб

StoreServiceClient storeServiceClient = new StoreServiceClient(url);

StoreOperationDTO operation1 = storeServiceClient.CreateOperation(store1.Id);

operation1.Type = StoreOperations.Remove;

operation1.ProductId = product.Id;

operation1.Quantity = quantity;

StoreOperationDTO operation2 = storeServiceClient.CreateOperation(store2.Id);

operation2.Type = StoreOperations.Append;

operation2.ProductId = product.Id;

operation2.Quantity = quantity;

UnitOfWork uow = new UnitOfWork();

uof.RegisterDirty(operation1);

uof.RegisterDirty(operation2);

try

{

storeServiceClient.ProcessOperations(uow);

}

catch (Exception e)

{

ShowError("Ошибка выполнения операции: " + e.toString());

}

Вторым «упрощением» стал переход от понятных прикладному программисту деклараций интерфейсов объектов и служб на языке IDL[82] к WSDL[83] – описаниям, ориентированным, прежде всего, на обработку компьютером. Сравним декларации складской службы, возвращающей по запросу текущее количество товарных позиций.

Декларация службы в CORBA IDL

module StockServices

{

typedef float CurrentQuantity;

struct QuantityRequest

{

string stockSymbol;

};

interface StockInventoryService

{

CurrentQuantity getCurrent(in QuantityRequest request);

};

};

Декларация службы в WSDL

version="1.0" encoding="utf-8"?>

name="StockInventoryService"

xmlns: sqs="http://mycompany.com/stockinventoryservice.wsdl"

xmlns: sqsxsd="http://mycompany.com/stockinventoryservice.xsd"

xmlns: soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns: wsdl="http://schemas.xmlsoap.org/wsdl/"

xmlns: xsd="http://www.w3.org/2000/10/XMLSchema">

name="CurrentQuantity">

name="stockSymbol" type="string"/>

name="CurrentQuantity">

name="quantity" type="float"/>

name="CurrentQuantity">

name="quantity" type="float"/>

name="getCurrentInput">

name="body" element="sqsxsd: CurrentQuantity"/>

name="getCurrentOutput">

name="body" element="sqsxsd: CurrentQuantity"/>

name="StockInventoryServicePortType">

name="getCurrent">

message="sqs: getCurrentInput"/>

message="sqs: getCurrentOutput"/>

name="StockInventoryServiceSoapBinding"

type="sqs: StockInventoryServicePortType">

style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

name="getCurrent">

soapAction="http://mycompany.com/getCurrent"/>

use="literal"/>

use="literal"/>

name="StockInventoryService">

name="StockInventoryServicePort"

binding="sqs: StockInventoryServiceBinding">

location="http://mycompany.com/StockInventoryService"/>

Третьим «усовершенствованием» стал отказ от автоматической подгрузки связанных объектов[84] в пользу исключительно ручного управления процессом.

Перейти на страницу:

Все книги серии Библиотека программиста

Похожие книги