Simplificando a utilização do ModularBr com o aplicações desktop através de middleware.
O ModularBr é um framework versátil, além de sua integração com o frameworks Rest para construção de APIs RESTful, o ModularBr também é adequado para o desenvolvimento de projetos client/server (desktop). Com suas funcionalidades de injeção de dependência e exportação de binds, o ModularBr oferece uma abordagem modular para o desenvolvimento de aplicações em Delphi. Essa abordagem pode ser aplicada a projetos que envolvem a comunicação entre cliente e servidor, permitindo que o desenvolvedor se beneficie da modularidade, reutilização de código e gerenciamento de dependências oferecidos pelo ModularBr. Ao adotar o ModularBr em projetos client/server, os desenvolvedores podem melhorar a organização do código, facilitar a manutenção e promover a escalabilidade das aplicações desktop.
Assim como ocorre nas aplicações RESTful, nas aplicações desktop, o AppModule também desempenha um papel fundamental como ponto de entrada para a utilização do ModularBr.
uses
dmfbr.modular,
...
procedure TFormPing.PingClick(Sender: TObject);
var
LRouteHandler: TPingRouteHandler;
begin
LRouteHandler := TPingRouteHandler.Create;
try
ShowMessage(LRouteHandler.Ping);
finally
LRouteHandler.Free;
end;
end;
procedure TFormPing.FormCreate(Sender: TObject);
begin
Modular.Start(TAppModule.Create);
end;
No AppModule, definimos as rotas iniciais.
...
function TAppModule.Routes: TRoutes;
begin
Result := [RouteModule('/ping', TPingModule)];
end;
Definimos então o modulo da rota mapeada '/ping'
unit ping.module;
interface
uses
ping.controller,
ping.service,
dmfbr.module;
type
TPingModule = class(TModule)
public
function Imports: TImports; override;
function Binds: TBinds; override;
function Routes: TRoutes; override;
function RouteHandlers: TRouteHandlers; override;
function ExportedBinds: TExportedBinds; override;
end;
implementation
{ TPingModule }
function TPingModule.Binds: TBinds;
begin
Result := [Bind<TPingService>.Factory,
Bind<TPingController>.Singleton];
end;
function TPingModule.ExportedBinds: TExportedBinds;
begin
Result := [];
end;
function TPingModule.Imports: TImports;
begin
Result := [];
end;
function TPingModule.RouteHandlers: TRouteHandlers;
begin
Result := [];
end;
function TPingModule.Routes: TRoutes;
begin
Result := [];
end;
end.
Os Route Handlers, ou manipuladores de rotas, são responsáveis por invocar os módulos desejados, de acordo com as rotas definidas no AppModule.
unit ping.route.handler;
interface
uses
SysUtils,
result.pair,
dmfbr.modular,
ping.controller,
dmfbr.route.handler;
type
TPingRouteHandler = class(TRouteHandler)
protected
procedure RegisterRoutes; override;
public
function Ping: string;
end;
implementation
uses
dmfbr.route.abstract;
{ TPingRouteHandler }
procedure TPingRouteHandler.RegisterRoutes;
begin
end;
function TPingRouteHandler.Ping: string;
var
LResultPing: string;
LResultRoute: TResultPair<Exception, TRouteAbstract>;
begin
LResultPing := '';
LResultRoute := Modular.LoadRouteModule('/ping');
try
LResultRoute.TryException(
procedure (Error: Exception)
begin
// Failure
LResultPing := Error.Message;
Error.Free;
end,
procedure (Route: TRouteAbstract)
begin
// Success
LResultPing := Modular.Get<TPingController>.Ping;
end);
finally
Modular.DisposeRouteModule('/ping');
end;
Result := LResultPing;
end;
end.
A partir deste ponto em diante, a escolha do padrão a ser adotado é completamente sua. O ModularBr proporciona total liberdade e flexibilidade para que você decida qual padrão deseja utilizar. Nesta documentação, apresentaremos um exemplo utilizando os conceitos de controller e service, seguindo o princípio de responsabilidade única, com o intuito de ilustrar a implementação. Contudo, é importante ressaltar que você tem a opção de escolher outros padrões, de acordo com suas necessidades e preferências individuais.
O Controller
unit ping.controller;
interface
uses
ping.service;
type
TPingController = class
private
FService: TPingService;
public
constructor Create(const AService: TPingService);
destructor Destroy; override;
function Ping: string;
end;
implementation
{ TPingController }
constructor TPingController.Create(const AService: TPingService);
begin
FService := AService;
end;
destructor TPingController.Destroy;
begin
FService.Free;
inherited;
end;
function TPingController.Ping: String;
begin
Result := FService.Ping;
end;
end.
O Service
unit ping.service;
interface
type
TPingService = class
public
function Ping: string;
end;
implementation
{ TPingService }
function TPingService.Ping: string;
begin
Result := 'Pong';
end;
end.