Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2014.06.15;
Скачать: [xml.tar.bz2];

Вниз

ООП   Найти похожие ветки 

 
RWolf ©   (2013-12-05 12:00) [0]

Задумался, как было бы правильнее всего построить программную модель для вот какого случая. Есть устройство, управляемое командами и присылающее ответы на них (синхронно). В коде ему соответствует, скажем, класс TDevice с каким-то сложным внутренним состоянием. Чтобы обновить своё состояние, TDevice вызывает функцию «обмен с устройством», та возвращает ответ в виде объекта-потомка TResponse.

[code]TResponse = class;
TResponseA = class(TResponse)
...данные из ответа А...
end;
TResponseB = class(TResponse)
...данные из ответа В...
end;
...

function QueryDevice(request: TRequest): TResponse;
[/code]

Теперь ТДевайсу нужно модифицировать свои приватные данные, причём разным способом для каждого класса ответа. Можно было бы вынести код модификации в виртуальный метод TResponse.UpdateDeviceState(device: TDevice):

[code]procedure TResponseA.UpdateDeviceState(device: TDevice);
begin
  device.UpdateInnerStateAfterReceiveResponseA(this);
end;

procedure TResponseB.UpdateDeviceState(device: TDevice);
begin
  device.UpdateInnerStateAfterReceiveResponseB(this);
end;[/code]

но тогда от ТДевайса потребуется выносить в публичный доступ массу приватных данных или одноразовых методов наподобие вышеуказанных UpdateInnerStateXXX(response: TResponseXXX). Этого можно избежать, разместив оба класса в одном модуле, но хотелось бы структурировать код так, чтобы: а) ТДевайс работал со своим состоянием самостоятельно, а не разбрасывать модификацию его состояния по посторонним классам, б) не выносить лишних методов в public TDevice.

Пока не придумал ничего лучше, чем набор ветвлений по типу ответа:

procedure TDevice.Process;
begin
 ...
 response := QueryDevice(request);
 if response is TResponseA then
    UpdateInnerStateAfterReceiveResponseA(response as TResponseA)
 else if response is TResponseB then
    UpdateInnerStateAfterReceiveResponseB(response as TResponseB)
 else if ...
   ...
 else
   raise EParameterError.Create("Unsupported response type");
end;[/code]

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


 
jumping jack   (2013-12-05 12:21) [1]

исходя из описанного, ваши TDevice и TResponce зависят друг от друга,  связаны сильно и неразрывно по самой сути их функций, а желание их во что бы то ни стало изолировать друг от друга - симптом "ООП головного мозга"


 
Ega23 ©   (2013-12-05 12:21) [2]

type
 TCustomDevice = class
 protected
   function ValidateResponse(Value: TResponse): Boolean; virtual; abstract;
   procedure ProcessResponse(Value: TResponse); virtual; abstract;
   function DoQueryDevice(Request: TRequest): TResponse; virtual; abstract;
 public
   function QueryDevice(Request: TRequest): Boolean;
 end;

function TCustomDevice.QueryDevice(Request: TRequest): Boolean;
var
 resp: TResponse;
begin
 resp := DoQueryDevice(Request);
 Result := ValidateResponse(resp);
 if Result then
   ProcessResponse(reps);
end;


 
Ega23 ©   (2013-12-05 12:22) [3]


> - симптом "ООП головного мозга"


С чего это? Всё отлично по полочкам раскладывается.


 
Медвешоног Порожог   (2013-12-05 12:31) [4]

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

по моему респонс должен быть тупыми данными


 
jumping jack   (2013-12-05 12:41) [5]

Ega23> С чего это?

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

то есть, либо треспонс должен знать все "интимные подробности" о тдевайсе, либо наоборот - тесная зависимость налицо
можно разве что только сделать ее односторонней

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


 
картман ©   (2013-12-05 12:53) [6]


>
> RWolf ©   (05.12.13 12:00)  

Четверг, а уже лень что-то делать - отмазки ищем?))


 
Ega23 ©   (2013-12-05 13:08) [7]


> то есть, либо треспонс должен знать все "интимные подробности"
> о тдевайсе, либо наоборот - тесная зависимость налицо
> можно разве что только сделать ее односторонней


Нет. Если все девайсы отвечают одинаково, то один класс респонса на всех, а у каждого класса устройств уже свой обработчик респонса.
Если респонсы и реквесты у всех разные, то также создаём предок, а у конкретного устройства - конкретные потомки. Там же и валидацию проходим, что тот класс респонса, который нужно подсунули.

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


 
RWolf ©   (2013-12-05 13:22) [8]


> картман ©   (05.12.13 12:53) [6]
> Четверг, а уже лень что-то делать - отмазки ищем?))


Просто релиз задерживается, появилось свободное время, можно заняться отвлечёнными вещами — пообсуждать архитектуру, например.


> Медвешоног Порожог   (05.12.13 12:31) [4]
> а зачем вообще респонс сделан объектом?

Объектами в дельфях (7) удобнее манипулировать — можно передавать в функции по значению, можно сложить в объектлист, а тот память сам почистит при освобождении, можно метод прикрутить при надобности. А так-то да, plain old data.


 
RWolf ©   (2013-12-05 13:37) [9]


> jumping jack   (05.12.13 12:41) [5]


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

Склонен согласиться, жаль только, что из-за дельфового правила «один файл — один модуль» такой подход порождает файлы по много тысяч строк.


 
Kerk ©   (2013-12-05 13:58) [10]

http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%81%D0%B5%D1%82%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29

?


 
jumping jack   (2013-12-05 14:02) [11]

RWolf> из-за дельфового правила «один файл — один модуль»...
инклюд никто не отменял - {$I FileName}


 
jumping jack   (2013-12-05 14:10) [12]

а если разделять по модулям связанные классы - работают ведь и перекрестные uses (в одном из interface, во втором - из implementatiob)


 
ТимоховД   (2013-12-05 15:32) [13]

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

и вообще, сделай, а там видно будет. возможно, вообще больше никогда не залезешь в этот модуль.

многое зависит от потенциальных перспектив расширения запросов.


 
ТимоховД   (2013-12-05 15:32) [14]

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

и вообще, сделай, а там видно будет. возможно, вообще больше никогда не залезешь в этот модуль.

многое зависит от потенциальных перспектив расширения запросов.


 
RWolf ©   (2013-12-05 15:50) [15]


> ТимоховД   (05.12.13 15:32) [14]

если сделать так, получится, что код, создающий экземпляры класса TResponse (т.е. по сути занимающийся десериализацией полученных от устройства данных), должен будет знать о существовании класса TDevice, хотя бы потому, что объявление класса TResponse будет содержать
procedure UpdateDeviceState(device: TDevice); virtual; abstract;
то есть имеем ситуацию, когда код нижележащего уровня зависит от вышележащего.


 
RWolf ©   (2013-12-05 16:25) [16]


> Kerk ©   (05.12.13 13:58) [10]

Под Посетителем здесь понимается TDevice? да, выделение методов в интерфейс позволит спрятать их в приват и отвязать код-создатель экземпляров TResponse от TDevice. Неудобство в том, что в Delphi нельзя просто так взять и заставить существующий класс реализовать интерфейс  — сначала надо унаследовать его от TInterfacedObject, а если он уже в иерархии, придётся наследовать её всю, множественного наследования тут нет. Значит, придётся делать специальный класс-прокси, снабжённый интерфейсом и имеющий доступ к приватным данным TDevice.


 
Ega23 ©   (2013-12-05 16:53) [17]


> Неудобство в том, что в Delphi нельзя просто так взять и
> заставить существующий класс реализовать интерфейс  — сначала
> надо унаследовать его от TInterfacedObject


TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)


 
RWolf ©   (2013-12-05 16:58) [18]


> Ega23 ©   (05.12.13 16:53) [17]

это в нынешних релизах от эмбаркадеро так можно делать? обязательное наследование от TInterfacedObject отменили?
//сижу на D7


 
vuk ©   (2013-12-05 17:05) [19]

to RWolf ©   (05.12.13 16:58) [18]:

> обязательное наследование от TInterfacedObject отменили?

Его никогда и не было. ;)


 
Ega23 ©   (2013-12-05 17:06) [20]


> обязательное наследование от TInterfacedObject отменили?


Так и раньше, вроде как, было совершенно необязательно.

У тебя должны быть реализованы

   function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
   function _AddRef: Integer; stdcall;
   function _Release: Integer; stdcall;


За 5 не скажу, а в семёрке можно было.
Дык раз ты на семёрке сидишь - посмотри как у тебя TComponent объявлен


 
Ega23 ©   (2013-12-05 17:08) [21]

Собственно, вся фишка TInterfaceObject - в сделанной реализации этих трёх методов, только и всего.


 
RWolf ©   (2013-12-05 17:17) [22]

> [19] [20]
а, ну да, теперь сам вспомнил, что уже делал такое, но привычка наследовать прижилась.


 
Kerk ©   (2013-12-05 17:46) [23]

Паттерн Visitor не про интерфейсы. Но я перечитал вопрос, похоже [2] надо делать.


 
Kerk ©   (2013-12-05 17:48) [24]

Или все-таки Visitor. Позже, может, идею распишу.


 
Kerk ©   (2013-12-05 18:06) [25]

В общем, как я понимаю, класс девайсов у тебя один, а респонсов много. Тогда можно сделать такую штуку.


type
 TDevice = class
   procedure Accept(Response: TCustomResponse);

   procedure AcceptResponse1(Response: TResponse1);
   procedure AcceptResponse2(Response: TResponse2);
 end;

procedure TDevice.Accept(Response: TCustomResponse);
begin
 Response.Apply(self);
end;

...
type
 TCustomResponse = class
 public
   procedure Apply(Device: TDevice); virtual; abstract;
 end;

 TResponse1 = class(TCustomResponse)
 public
   procedure Apply(Device: TDevice); override;
 end;

 TResponse2 = class(TCustomResponse)
 public
   procedure Apply(Device: TDevice); override;
 end;

procedure TResponse1.Apply(Device: TDevice);
begin
 Device.AcceptResponse1(self);
end;

procedure TResponse2.Apply(Device: TDevice);
begin
 Device.AcceptReponse2(self);
end;


Надеюсь, идея ясна. Писал с мобилки, возможны опечатки.


 
Kerk ©   (2013-12-05 18:15) [26]

Или это тоже самое, что у тебя и так есть.


 
Kerk ©   (2013-12-05 18:20) [27]

Можно еще вместо пачки методов с разными именами сделать пачку overload-методов с одинаковым именем и тем самым переложить вопросы диспетчеризации по типу респонса на компилятор.


 
Юрий Зотов ©   (2013-12-05 19:13) [28]

> хотелось бы структурировать код так, чтобы: а) ТДевайс работал
> со своим состоянием самостоятельно, а не разбрасывать модификацию
> его состояния по посторонним классам, б) не выносить лишних
> методов в public TDevice.


unit unit1;

uses unit2;

type
 TDevice = class(...)
 private
   ...
   procedure UpdateState(Response: TResponse);
 public
   procedure QueryDevice(Request: TRequest); // Публикуется только это
 end;

procedure TDevice.UpdateState(Response: TResponse);
begin
 case Response.Tag of
 1: ...
 2: ...
 ...
end;

procedure TDevice.QueryDevice(Request: TRequest);
var
 Response: TResponse;
begin
 // В зависимости от того, какой Request, создаем нужный Response.
 // Например:
 if Request.Что-то then
   Response := TResponseA.Create
 else
   Response := TResponseB.Create;
 try
   ... // Здесь посылаем запрос и заполняем ответ
   UpdateState(Response) // Обновляем состояние
 finally
   Response.Free;
 end
end;

// --------------------------------

unit unit2;

type
 TResponse = class(...)
 private
   FTag: integer;  
 public
   constructor Create; virtual;
   property Tag: integer read FTag;
 end;

 TResponseA = class(TResponse)
 public
   constructor Create; override;
 end;

 TResponseB = class(TResponse)
 public
   constructor Create; override;
 end;

...
constructor TResponse.Create;
begin
 inherited;
end;

constructor TResponseA.Create;
begin
 inherited;
 FTag := 1;
end;

constructor TResponseB.Create;
begin
 inherited;
 FTag := 2;
end;

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


 
Юрий Зотов ©   (2013-12-05 19:28) [29]

> Kerk

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

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


 
Rouse_ ©   (2013-12-05 19:49) [30]


>  if Request.Что-то then
>    Response := TResponseA.Create
>  else
>    Response := TResponseB.Create;


ИМХО лучше тогда:

Response := Request.GetResponseType.Create;


 
Медвешоног Порошог   (2013-12-05 20:42) [31]

Объектами в дельфях (7) удобнее манипулировать — можно передавать в функции по значению, можно сложить в объектлист, а тот память сам почистит при освобождении, можно метод прикрутить при надобности. А так-то да, plain old data.

отдавай респонс в виде xml.
а в параметры его обработчиков передавай ixmldomnode или весь документ.
и версионность формата будет искаропки и объекты будут и по значению и по сцылке и как хошь

а респонс как наследник тобджект - это перебор и изврат


 
Kerk ©   (2013-12-05 20:43) [32]


> Юрий Зотов ©   (05.12.13 19:13) [28]
>
> procedure TDevice.UpdateState(Response: TResponse);
> begin
>  case Response.Tag of
>  1: ...
>  2: ...
>  ...
> end;
>

Ну так ведь это ничем не отличается от (разве что требует чуть больше кода) этого:

if Response is TResponse1 then
  ...
else if Response is TResponse2 then
...


Введение свойства Tag могло бы помочь избавиться от связей между TDevice и TResponse1/TResponse2, но на практике врядли TDevice сможет нормально обработать response, если его настоящий класс неизвестен. Так что связи никуда не денутся. То есть реально отличий от "if Response is TResponse1..." никаких.


 
Медвешоног Порошог   (2013-12-05 20:59) [33]

procedure TDevice.UpdateState(Response: TResponse);

ну вот зачем респонс делать объектом? чтобы вот такие корявости потом выправлять?

а почему тогда не
procedure TResponse.UpdateState(Device: TDevice);

респонс устройства в реальном мире - это тупые данные
и в программе он должны быть тупыми данными а не объектом


 
Rouse_ ©   (2013-12-05 21:19) [34]


> респонс устройства в реальном мире - это тупые данные
> и в программе он должны быть тупыми данными а не объектом

Любые данные - суть есть буфер.
Правильно, зачем работать с объектами - только хардкор, только натив (машкоды рулят) :)


 
Rouse_ ©   (2013-12-05 21:24) [35]

ЗЫ: открою тайну великую, респонз устройства как правило представляет из себя регламентированную структуру данных, а не "тупые данные" :)


 
Kerk ©   (2013-12-05 21:34) [36]


> Rouse_ ©   (05.12.13 21:19) [34]

Это давний холивар. "Rich-модель" vs "Анемичная модель". В первом случае данные и поведение инкапсулируются внутрь объектов, во втором - делается четкое разделение между объектами данных и объектами-сервисами. Этот спор ведется на уровне всяких Фаулеров и Макконнеллов, мы за битвами богов можем только наблюдать да выбирать какую занять сторону :)

Правда, в контексте данной ветки вопрос скорее поставлен как "XML - основа всего", что уже давно перестало быть интересным.

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


 
Rouse_ ©   (2013-12-05 21:37) [37]


> Kerk ©   (05.12.13 21:34) [36]
> Это давний холивар. "Rich-модель" vs "Анемичная модель".
>  В первом случае данные и поведение инкапсулируются внутрь
> объектов, во втором - делается четкое разделение между объектами
> данных и объектами-сервисами. Этот спор ведется на уровне
> всяких Фаулеров и Макконнеллов, мы за битвами богов можем
> только наблюдать да выбирать какую занять сторону :)

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


 
Медвешоног Порошог   (2013-12-05 21:38) [38]

Объектами в дельфях (7) удобнее манипулировать — можно передавать в функции

так вот если кому-то удобно респонс передавать по ссылке одним параметром ,  он может передать ixmldomnode


 
Медвешоног Порошог   (2013-12-05 21:42) [39]

: открою тайну великую, респонз устройства как правило представляет из себя регламентированную структуру данных, а не "тупые данные" :)

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


 
Rouse_ ©   (2013-12-05 21:48) [40]


> а я почему-то думал, что респонс это биты и байты.

Ну так и думай так дальше - никто-ж не запрещает :)


 
Медвешоног Порошог   (2013-12-05 21:54) [41]

а что, у тебя есть пример реального респонса который есть не биты и не байты?
может покажешь?


 
Медвешоног Порошог   (2013-12-05 22:03) [42]

Вот вся причина почему респонс у автора стал объектом:

Объектами в дельфях (7) удобнее манипулировать — можно передавать в функции по значению, можно сложить в объектлист, а тот память сам почистит при освобождении, можно метод прикрутить при надобности. А так-то да, plain old data.

что реально мы видим:
1. автор хочет иметь мало параметров в процедурах обработки. в идеале один параметр.

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

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

4. если бы у него была подходящая структура для хранения данных респонса то необходимость в объекте была бы лишняя. и это сразу было бы видно.

а вместо этого в ветке сейчас трут (и еще долго будут тереть) про то с какого конца разбивать яйцо.


 
Rouse_ ©   (2013-12-05 22:08) [43]


> Медвешоног Порошог   (05.12.13 21:54) [41]
> а что, у тебя есть пример реального респонса который есть
> не биты и не байты?
> может покажешь?

Не поток сырых данных, а структура? Та лехко, четай :)
http://msdn.microsoft.com/en-us/library/aa363216(VS.85).aspx


 
имя   (2013-12-05 22:13) [44]

Удалено модератором


 
Rouse_ ©   (2013-12-05 22:16) [45]

Удалено модератором


 
Дмитрий Белькевич   (2013-12-05 22:57) [46]

>то есть имеем ситуацию, когда код нижележащего уровня зависит от вышележащего.

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

>procedure UpdateDeviceState(device: TDevice); virtual; abstract;

А если так: procedure UpdateDeviceState(device: TObject); virtual; abstract; ?

Я особенно не вчитывался. Обязательно туда именно определенный класс передавать?


 
Дмитрий Белькевич   (2013-12-05 23:09) [47]


> Вот вся причина почему респонс у автора стал объектом:Объектами
> в дельфях (7) удобнее манипулировать — можно передавать
> в функции по значению, можно сложить в объектлист, а тот
> память сам почистит при освобождении, можно метод прикрутить
> при надобности. А так-то да, plain old data.что реально
> мы видим:1. автор хочет иметь мало параметров в процедурах
> обработки. в идеале один параметр.2. у объекта респонса
> ничего кроме полей и свойств не используется. возможная
> прикрутка методов в перспективе не в счет.3. так как респонсы
> разные он поимел иерархию то ли классов то ли интерфейсов
> и ломает голову как же красиво и удобно писать обработчики
> на основе ртти.4. если бы у него была подходящая структура
> для хранения данных респонса то необходимость в объекте
> была бы лишняя. и это сразу было бы видно.а вместо этого
> в ветке сейчас трут (и еще долго будут тереть) про то с
> какого конца разбивать яйцо.


Всё таки, почему не record? Мало параметров в процедурах, в идеале - один, можно (уже) прикрутить методы, передавать по значению, если не использовать динамические массивы внутри - сами разрушаться. Только что их иерархию не сделать. Но можно какой-то один (пусть избыточный) record придумать, что бы для всех девайсов сразу. Ну а если нужно внутри класса-обработчки специальным образом обрабатывать разные респонс-рекорды, сделать поле - DeviceID и обрабатывать по-разному. ИМХО, конечно, мот задачу не понял до конца.


 
имя   (2013-12-05 23:09) [48]

Удалено модератором


 
Юрий Зотов ©   (2013-12-05 23:24) [49]

> Rouse_ ©   (05.12.13 19:49) [30]

Это же всего лишь пример. В реальности все определяется тем, как выполняется реквест. Например, если респонс создается при выполнении реквеста, то вызов конструктора ЗДЕСЬ вообще не нужен. Да и вызов Free - под вопросом (уничтожать респонс или нет - зависит от задачи).

> Kerk ©   (05.12.13 20:43) [32]

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

А вот связь становится односторонней - девайс знает все респонсы, но ни один респонс не знает ни о каком девайсе. Здесь четкое разделение функционала: каждый класс изменяет лишь свои данные.

> All

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


 
Kerk ©   (2013-12-05 23:51) [50]


> Юрий Зотов ©   (05.12.13 23:24) [49]
> Естественно, case от if мало чем отличается. Просто код
> становится более читабельным, особенно в случае многоэтажного
> if при большом количестве разных респонсов.

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


 
Kerk ©   (2013-12-05 23:58) [51]

Ну и по второй обсуждаемой теме...
Если респонс - это биты и байты, то непременно надо их в XML запихать. Это наиболее оптимальный вариант :)


 
Юрий Зотов ©   (2013-12-06 00:02) [52]


> Kerk ©   (05.12.13 23:51) [50]

Естественно. Но это уже вопрос реализации.


 
Юрий Зотов ©   (2013-12-06 00:08) [53]

> Kerk ©   (05.12.13 23:58) [51]

Ну, ты и язва...
:o)


 
имя   (2013-12-06 08:39) [54]

Удалено модератором


 
имя   (2013-12-06 08:47) [55]

Удалено модератором


 
имя   (2013-12-06 10:07) [56]

Удалено модератором


 
имя   (2013-12-06 11:06) [57]

Удалено модератором


 
имя   (2013-12-06 11:18) [58]

Удалено модератором



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2014.06.15;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.63 MB
Время: 0.003 c
15-1386249858
SKIPtr
2013-12-05 17:24
2014.06.15
поиск в яндекс браузере


15-1385757002
Юрий
2013-11-30 00:30
2014.06.15
С днем рождения ! 30 ноября 2013 суббота


15-1386016202
Юрий
2013-12-03 00:30
2014.06.15
С днем рождения ! 3 декабря 2013 вторник


3-1297844761
leonidus
2011-02-16 11:26
2014.06.15
ADO и ошибка "Класс не зарегистрирован"


2-1377332433
Jimmy
2013-08-24 12:20
2014.06.15
Анимационный Gif с помощью RX





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский