Я программист на Delphi Pascal, я использую последнюю версию Embarcadero Delphi XE, и я хотел бы воспользоваться преимуществами шаблонов проектирования, таких как контроллер представления модели и представление представления модели.
Тем не менее, в Интернете, кажется, не так много о лучших методах сделать это на паскале. Большинство примеров, которые я могу найти, находятся на C #, а некоторые языковые функции отсутствуют на паскале, что означает, что мне, возможно, придется искать способы реализации этих функций.
Я пытаюсь адаптировать код из этой статьи здесь
Я перечислю проблемы, с которыми я сталкиваюсь
- Обнуляемые типы
В Паскале нет обнуляемых типов, как в C #, поэтому я создал свой собственный.
TNullable<T> = record
strict private
fHasValue : boolean;
fValue : T;
function GetValue:T;
procedure SetValue(newValue : T);
public
property HasValue : boolean read fHasValue;
property Value : T read GetValue write SetValue;
procedure SetToNull;
end;
в разделе реализации
function TNullable<T>.GetValue:T;
begin
if fHasValue then
begin
Result := fValue;
end
else raise Exception.Create('Value Not Set');
end;
procedure TNullable<T>.SetValue(newValue : T);
begin
fValue := newValue;
fHasValue := true;
end;
procedure TNullable<T>.SetToNull;
begin
fHasValue := false;
end;
- Получить / установить свойства
Теперь, когда у меня есть обнуляемый тип, я могу создавать обнуляемые свойства. Однако он имеет некоторые запахи кода.
например, если я создаю
TFoo = class
private
function GetBar:TNullable<Integer>;
procedure SetBar(x:TNullable<Integer>);
public
property Bar : TNullable<Integer> read GetBar write SetBar;
в разделе реализации
function TFoo.GetBar:TNullable<Integer>;
begin
if **valueExists** then
begin
Result.Value := **the value**
end else
begin
Result.SetToNull;
end;
end;
procedure TFoo.SetBar(x:TNullable<Integer>);
begin
if X.hasValue then
begin
//Store/show value here
end else
begin
//handle null assignment here
end;
end;
Это хорошо, но когда дело доходит до использования этих свойств, я не могу просто использовать
myFoo.Bar.Value: = 1;
Я должен использовать
var
myBar : TNullable<Integer>;
begin
myBar.Value := 1;
myFoo.Bar := myBar;
end;
Что немного сложнее. Я полагаю, что я ничего не могу с этим поделать.
- Циркулярные ссылки
Мне нравится разделять классы на разные единицы.
то есть:
поддержание интерфейса пользователя отдельно от логики управления и уровня логики модели и данных.
У меня может быть ситуация, когда 2 класса могут ссылаться друг на друга. Хотя в большинстве случаев я хотел бы избежать этой ситуации, бывают случаи, когда это необходимо.
например
unit u_A;
interface
uses
u_B
;
type
TA = class
public
Foo : TB;
end;
implementation
end;
и другой блок
unit u_B;
interface
uses
u_A
;
type
TB = class
public
Foo : TA;
end;
implementation
end;
Этот код не работает, потому что два класса включают друг друга, и это не может быть сделано на паскале. Это не такая проблема в C #. Решения, которые я могу придумать: 1. включить оба класса в один и тот же модуль, хотя это проблема, если я не думаю, что это соответствует дизайну. 2. Создайте другой родительский интерфейс для B и унаследуйте B от этого, тогда это обойдется. Хотя это грязно для такой простой задачи.
- Статические классы
В Delphi нет статических классов, они полезны для управляющих классов.
- Лучшие классы контейнеров для использования в Delphi
В настоящее время я использую TList и TObjectList в Generics.Collections. Они были представлены в Delphi XE. Я надеюсь, что они лучше всего подходят, поскольку Delphi 7, похоже, не имеет хороших вариантов.
Я все еще думаю о обработчиках событий и любых проблемах, которые могут там возникнуть. Возможно, есть некоторые другие вопросы, о которых я еще не задумывался.
Спасибо за любой совет.
Ответы:
Вы должны взглянуть на Spring4D, так как он уже содержит обнуляемые типы (аналогичная реализация, как у вас, с небольшой дополнительной перегрузкой операторов) и гораздо более мощные типы коллекций, чем в RTL. Они также основаны на интерфейсе, что очень удобно, потому что вам не нужно беспокоиться об управлении жизненным циклом, особенно при их передаче.
Для проблем перекрестных ссылок я предлагаю кодирование для интерфейсов и использовать их в качестве ссылки в другой реализации, а не в двух реализациях, знающих друг друга.
Что касается части MVVM, вы можете взглянуть на DSharp, который имеет первую версию порта Caliburn Micro для Delphi. Это очень ранняя стадия и вряд ли документирована, но вы можете получить некоторые идеи о том, как создать MVVM в Delphi, используя слабосвязанный графический интерфейс и бизнес-логику, связанную с привязками данных. В журнале «Блез Паскаль» было две статьи на этот счет, если вам больше интересно.
PS Я думаю, вы имеете в виду, что вы используете XE6, так как это последняя версия.
источник