![]() |
Designfrage für eine kleine CRUD (REST) Webanwendung
Als kleines Anwendungsbeispiel erstelle ich gerade eine CRUD Anwendung, die eine Weboberfläche zur Verwaltung einer Liste von 'TPerson' erzeugt. Im Hintergrund arbeitet Indy TIdHTTPServer sowie ein von mir erstelltes kleines Framework.
Die erste Version hat aber noch Designschwächen - abesehen davon dass sie nicht threadsicher programmiert ist. Ich überlege daher sie noch einmal zu überarbeiten, um sie möglichst klein und kompakt zu halten, aber das Softwaredesign zu verbessern. Wenn mit dem Browser die Adresse ![]()
Delphi-Quellcode:
Die Funktion TCRUDModule.GetPersons iteriert über ein TDictionary<string, TPerson> und erstellt eine HTML Seite:
// GET http://localhost/rest/persons
// list all persons Path('persons'); Produces('text/html'); GET(procedure(Request: TRequest; Response: TResponse) begin Response.ContentText := CRUDModule.GetPersons; Response.CharSet := 'UTF-8'; end);
Delphi-Quellcode:
Der HTML Code der TPerson-Liste enthält dabei auch einen Hyperlink auf die Resource http://localhost/rest/persons/<id> wobei id jeweils der Key des Objekts im Dictionary ist.
function TCRUDModule.GetPersons: string;
var P: TPair<string, TPerson>; begin Result := '<html>'; for P in Persons do begin Result := Result + ' <p>' + P.Value.Name + ' - ' + Format('<a href="persons/%s">show</a>', [P.Key]) + ' </p>'; end; Result := Result + '</html>'; end; Der Code der durch den Hyperlink-Klick ausgeführt wird, liest das id Attribut aus dem GET Request, und erzeugt über die Funktion CRUDModule.GetPerson HTML Code zur Darstellung des TPerson Objekts:
Delphi-Quellcode:
Im nächsten Schritt könnte ich (über TCriticalSection) den Code threadsicher zu machen.
// GET http://localhost/rest/persons/
// get person information Path('persons/{id}'); Produces('text/html'); GET(procedure(Request: TRequest; Response: TResponse) var ID: string; begin ID := Request.Params.Values['id']; Response.ContentText := CRUDModule.GetPerson(ID); Response.CharSet := 'UTF-8'; end); Dabei gibt es die Wahl zwischen zwei Orten: entweder im Requesthandler:
Delphi-Quellcode:
oder im Datenmodul:
// GET http://localhost/rest/persons
// list all persons Path('persons'); Produces('text/html'); GET(procedure(Request: TRequest; Response: TResponse) begin CS.Enter; try Response.ContentText := CRUDModule.GetPersons; finally CS.Leave; end; Response.CharSet := 'UTF-8'; end);
Delphi-Quellcode:
Die zweite Variante hat den Vorteil, dass die Zeit der Sperrung des TDictionary minimiert wird. Die Critical Section soll ja nicht länger als notwendig den Zugriff anderer Threads auf die Daten blockieren.
function TCRUDModule.GetPersons: string;
var P: TPair<string, TPerson>; begin Result := '<html>'; CS.Enter; try for P in Persons do begin Result := Result + ' <p>' + P.Value.Name + ' - ' + Format('<a href="persons/%s">show</a>', [P.Key]) + ' </p>'; end; finally CS.Leave; end; Result := Result + '</html>'; end; Hat jemand noch andere Empfehlungen, umd das Design auf den "Stand der Technik" zu bringen? In einer 'richtigen' Anwendung (das Programm ist nur ein "Anwendungsbeispiel") würde ich zum Beispiel auch seitenweise Darstellung der Daten (Pagination) vorsehen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz