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

Вниз

Архитектура приложения   Найти похожие ветки 

 
Timego   (2004-03-04 16:58) [0]

Уважаемые мастера!
Знаю, что вопрос молй описывается во многих книгах и статьях, к которым меня непременно отправят ;) Пишу здесь, потому как хочется узнать живое мнение живых людей, создающих реальные приложения.

В моем приложении есть около десятка глобальных объектов, класс каждого из которых описан в своем модуле. Объекты предназначены для решения конкретных задач, но иногда некоторые объекты "прибегает к услугам" других объектов, то есть обращаются к их свойствам и методам. Например, объект Protocol, инкапсулирующий протокол взаимодействий с сервером, обращается к объектам Log (лог, журнал) и Config (конфигурация). Объект Connector (cоединение) обращается к журналу и протоколу. Единственной проблемой оказывается повторное использование отдельных модулей (классов) в других приложениях, функциональность которых не требует полного набора используемых объектов.
Возможно ли разработать классы таким образом, чтобы степень их связи с другими классами был минимальным, но при этом использование их было таким же простым как и в моем случае?
Чтобы можно было взять класс as is и перенести его в другое приложение.


 
Тимохов ©   (2004-03-04 17:05) [1]

Если связь есть (например protocol обращается к log) то от этого никуда не дется. Если нужно перенести protocol, то нужно перенести и log или отказаться от его использования, например, через условную компиляцию.


 
Тимохов ©   (2004-03-04 17:09) [2]

Т.е. одна сущьность полагается на другую сущьность, то в новом проекте первая сущность должна получить адекватную замену. НАпример, может быть такая ситуация:
Проект 1
protocol использует log

Проект 2
есть protocol из проекта 1. Т.к. данный класс в проекте 1 использует log, то и в проекте 2 он также должен иметь адекватную замену. Возможно, что в проекте 2 вы захотите функции ложира переложить на другой класс. В этом случае надо в обоих проетах работать с классом log через интерфейсы, например, создать интерфейс ILog, который по-разному реализовать в проекте 1 и проекте 2.


 
Никто   (2004-03-04 17:11) [3]

Вариант 1:
type
 TLog = class
 public
   procedure DoIt;
 end;

 TConfig = class
 public
   procedure DoIt;
 end;

 TProtocol = class
 private
   m_Config: TConfig;
   m_Log: TLog;
   procedure DoWithLog;
   procedure DoWithConfig;
 published
   property Log: TLog read m_Log write m_Log;
   property Config: TConfig read m_Config write m_Config;
 end;

procedure TProtocol.DoWithLog;
begin
 if Assigned(Log) then
   Log.DoIt;
end;

procedure TProtocol.DoWithConfig;
begin
 if Assigned(Config) then
   Config.DoIt;
end;


Вариант 2:
const
 MM_DOIT = WM_USER + $01;

type
 TLog = class
 private
   procedure WMDoIt(var Msg: TMessage); message WM_DOIT;
 end;

 TConfig = class
 private
   procedure WMDoIt(var Msg: TMessage); message WM_DOIT;
 end;

 TProtocol = class
 private
   m_Config: TObject;
   m_Log: TObject;
   procedure DoWithLog;
   procedure DoWithConfig;
 public
   property Log: TObject read m_Log write m_Log;
   property Config: TObject read m_Config write m_Config;
 end;

procedure TProtocol.DoWithLog;
var
 Msg: TMessage;
begin
 if Assigned(Log) then
 begin
   ...
   Log.Dispath(Msg);
 end;
end;

procedure TProtocol.DoWithConfig;
var
 Msg: TMessage;
begin
 if Assigned(Config) then
 begin
   ...
   Config.Dispath(Msg);
 end;
end;


 
Тимохов ©   (2004-03-04 17:19) [4]


> Никто   (04.03.04 17:11) [3]

Имхо вариант 2 это синтаксический обман дельфи.
Т.е. обманываем синтаксис дельфи так, чтобы он не ругался при переносе TProtocol в новый проект на отсутствие в нем TConfig. Но если подумать, то это не отвечает на суть вопроса. А что если в TConfig лежат важные параметры, без которых TProtocol работать не может. При этом в новом проекте TConfing не реализован.

Т.о. в данном случае есть потеря функциональности TProtocol.

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

Хотя, это уже идеологический вопрос...


 
Polevi ©   (2004-03-04 17:20) [5]

интерфейсы


 
Timego   (2004-03-04 17:40) [6]


> интерфейсы


Интерфейсы - это здорово, спасибо.
Спасибо и Тимохов, особенно за "создать интерфейс ILog, который по-разному реализовать в проекте 1 и проекте 2".
Только вот получается, что во второй проект должны потянуться ВСЕ без исключения первого проекта. И все методы должны быть перекрыты, даже, если они вообще не нужны во втором приложении.


 
Timego   (2004-03-04 17:39) [7]


> интерфейсы


Интерфейсы - это здорово, спасибо.
Спасибо и Тимохов, особенно за "создать интерфейс ILog, который по-разному реализовать в проекте 1 и проекте 2".
Только вот получается, что во второй проект должны потянуться ВСЕ без исключения первого проекта. И все методы должны быть перекрыты, даже, если они вообще не нужны во втором приложении.


 
WebErr ©   (2004-03-04 17:45) [8]


> Timego   (04.03.04 17:39) [7]
>
> > интерфейсы
>
>
> Интерфейсы - это здорово, спасибо.
> Спасибо и Тимохов, особенно за "создать интерфейс ILog,
> который по-разному реализовать в проекте 1 и проекте 2".
> Только вот получается, что во второй проект должны потянуться
> ВСЕ без исключения первого проекта. И все методы должны
> быть перекрыты, даже, если они вообще не нужны во втором
> приложении.

Создай общего предка, используй мощь ООП, если не нужны методы, не используй их, просто поднимись к пра-правнуку и заставь его родить ишо што-небуть! :))))


 
Тимохов ©   (2004-03-04 17:47) [9]


> Timego   (04.03.04 17:40) [6]

Конечно, придется тянуть в другой проект.
Сами подумайте, если protocol полагается на config как он может обойтись без него в новом проекте! Другой вопрос, что можно пересмотреть архитектуру в первом проекте, чтобы "полагание" не было очень сильным. Т.е. есть config хорошо, нет - ну и фиг с ним, обойдемся без него.


 
Никто   (2004-03-04 17:59) [10]


> А что если в TConfig лежат важные параметры, без которых
> TProtocol работать не может. При этом в новом проекте TConfing
> не реализован.

1. Если в TConfig лежат параметры, без которых TProtocol работать не может, то тогда нужно использовать TConfig (или его потомков). (Хотя, функциональность которых не требует полного набора используемых объектов (в вопросе))

2. Или как вариант:
procedure TProtocol.DoWithConfig;
begin
if Assigned(Config) then
  Param := Config.Param
else
  Param := DefaultParam;  
end;


3. Или WebErr ©   (04.03.04 17:45) [8] - использовать абстрактного предка (например, TAbstractConfig).

4. Или интерфейсы, хотя внутри Delphi можно обойтись и без них (см. п. 3).


 
WebErr ©   (2004-03-04 18:06) [11]


> 3. Или WebErr ©   (04.03.04 17:45) [8] - использовать абстрактного
> предка (например, TAbstractConfig).

А чо я в самом конце? :))))


 
Defunct ©   (2004-03-04 18:34) [12]

Зы, а почему бы как сказал WebErr ©   (04.03.04 17:45) [8] не использовать вообще общего предка для всех объектов:

Unit BasicClass;

Const ciBasicPrimitive = 0; { ci = ClassID }
     ...
...
Type
 TBasicPrimitive = Class(_)
 Private
   FClassID  : Cardinal;
 Public
   Constructor Create;Virtual;
   Procedure Configure;Virtual;Abstract;
   Procedure Load;Virtual;Abstract;
   Procedure Save;Virtual;Abstract;
   Procedure Tune;Virtual;Abstract;
   Procedure Work;Virtual;Abstract;
   Procedure LinkWith(Primitive:TBasicPrimitive);Virtual;abstract;
   ... // Какие-то заранее общие процедуры и функции для всех объект
   // По сути это и есть Интрефес

   Property ClassID:Cardinal; Read FClassID;
 End;

....
Constructor TBasicPrimitive.Create;
Begin
 ClassID := ciBasicPrimitive;
End;

End.


Далее все объекты прямым или косвенных образом наследовать от него.

А в вашем объекте протокол использовать не TConfig и TLog а именно, TBasicPrimitive.

Unit Unit99;
....
Const ciProtocol = 99;

 TProtocol = Class(TBasicPrimitive {или любой другой наследник})
 Private
   FConfig : TBasicPrimitive;
   FLog    : TBasicPrimitive;

 Public
   Constructor Create;Override;
   Procedure LinkWith(Primitive:TBasicPrimitive);Override;
 End;

Constructor TProtocol.Create;
Begin
 Inherited;
 ClassID := ciProtocol;
End;

Procedure TProtocol.LinkWith;
Begin
 Case Primitive.ClassId Of
  ciLog      : FLog := Primitive;
  ciConfig   : FConfig := Primitive;
  ciProtocol : FProtocol := Primitive;
 End;
End;

....


 
Defunct ©   (2004-03-04 18:47) [13]

Defunct ©   (04.03.04 18:34) [12]

Таким образом, при пререносе в другой проект класса TProtocol, Вам будет достаточно перенести вместе с ним только один модуль, в котором описан TBasicPrimitive. Все константы отвечающие за СlassID можно разместить в том же модуле с TBasicPrimitive.

Да ну и я там допустил небольшую ошибку, в кострукторах инициализируется поле FClassID, а не read-only property.



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

Форум: "Основная";
Текущий архив: 2004.03.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.034 c
14-1078405998
Multy
2004-03-04 16:13
2004.03.28
Нашёл тут класный анекдот


1-1078488826
MetalFan
2004-03-05 15:13
2004.03.28
показ Popup menu в нужную сторону


4-1074046926
EcoloRa
2004-01-14 05:22
2004.03.28
Работа с заголовком окна


1-1078325312
able
2004-03-03 17:48
2004.03.28
HTML - подсветка синтаксиса в TRichEdit, оптимизация.


1-1078658419
Fess
2004-03-07 14:20
2004.03.28
Работа с файлами





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский