![]() |
Aufbau logisch und korrekt?
Hallo
Ich habe vor eine Parser-Klasse zu schreiben, die verschiedene Dienste im Internet Parst und formatiert ausgibt. Meine Klasse soll vorerst Google, Milw0rm, Heise, Gulli, Tecchannel und Wikipedia unterstützen. Ich lese dabei den Titel und wenn verfügbar den Link der jeweiligen Seite aus. Bsp. Google: Benutzer gibt Query 'delphi forum' ein. Klasse gibt als Titel (in dem Fall der erste Googleeintrag) 'Delphi-PRAXIS - Hier werden sie geholfen' aus und als Link 'http://delphipraxis.net'. Die Klasse soll später in einen IRC Bot Integriert werden, also arbeitet sie Zeilenbasiert. (Das nur nebenbei, ist eher unwichtig. Mein Ziel ist es erstmal die Klasse zu schreiben). Nun möchte ich von euch Wissen, ob mein Aufbau logisch und strukturiert erscheint oder ob ich etwas verbessern kann. Das Programm ist noch nicht fertig, es ist lediglich der Ansatz da und möchte Wissen ob der Ansatz korrekt ist. Allgemeiner Aufbau: Rahmen-Klasse: TParseServices (wird aufgerufen)
Delphi-Quellcode:
...
PS.Service := svGoogle; PS.Query := 'delphi forum'; PS.Submit; {Submit liest den Service aus und übergibt dann den Query an die jeweilige UnterKlasse} Titel := PS.GetResult.Title.Strings[0]; // Gibt 'Delphi-PRAXIS - Hier werden sie geholfen' Link := PS.GetResult.Link.Strings[0]; // Gibt 'http://delphipraxis.net' uParseServices:
Delphi-Quellcode:
unit uParseServices;
interface uses IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, StrUtils, Classes; type TServices = (svGoogle, svMilw0rm, svHeise, svGulli, svTecchannel, svWikipedia); type TResult = record Title: TStrings; Link: TStrings; end; type TPattern = record FBegin: string; FEnd: string; end; type TGoogle = class private FPatternTitle: TPattern; FPatternLink: TPattern; FQueryURL: string; function Parse: TResult; end; type TMilw0rm = class private FPatternTitle: TPattern; FQueryURL: string; function Parse: TResult; end; type THeise = class private FQueryURL: string; function Parse: TResult; end; type TGulli = class private FQueryURL: string; function Parse: TResult; end; type TTecChannel = class private FQueryURL: string; function Parse: TResult; end; type TWikipedia = class private FPatternTitle: TPattern; FPatternArticle: TPattern; FQueryURL: string; function Parse: string; // Erster Artikel end; {(*}const GoogleURL = 'http://google.de/?q=[<QUERY>]'; Milw0rmURL = 'http://milw0rm.com/?q=[<QUERY>]'; HeiseURL = 'http://heise.de/?q=[<QUERY>]'; GulliURL = 'http://gulli.com/?q=[<QUERY>]'; TecChannelURL = '...[<QUERY>]'; WikipediaURL = 'http://wikipedia.de/go?q=[<QUERY>]&l=de&e=wikipedia&s=suchen&b=suchen'; {*)} type TParseServices = class private FResponse: string; FQuery: string; FService: TServices; FFilterdLinks: TStrings; FFilterdTitles: TStrings; Google: TGoogle; Milw0rm: TMilw0rm; Heise: THeise; Gulli: TGulli; TecChannel: TTecChannel; Wikipedia: TWikipedia; public property Service: TServices read FService write FService; property Query: string read FQuery write FQuery; procedure Submit; function Results: TResult; property GetResult: TResult read Results; // Gibt den Titel und die Links wieder property GetRawHTTPResponse: string read FResponse; // Gibt den kompletten HTTP Response zurück constructor Create; destructor Destroy; override; end; implementation constructor TParseServices.Create; begin inherited; Google := TGoogle.Create; Milw0rm := TMilw0rm.Create; Heise := THeise.Create; Gulli := TGulli.Create; TecChannel := TTecChannel.Create; Wikipedia := TWikipedia.Create; FFilterdLinks.Create; FFilterdTitles.Create; // [<QUERY>] als Platzhalter wird mit StringReplace ersetzt // Stimmen nicht alle, nur für Anschauung präsent Google.FQueryURL := GoogleURL; Milw0rm.FQueryURL := Milw0rmURL; Heise.FQueryURL := HeiseURL; Gulli.FQueryURL := GulliURL; TecChannel.FQueryURL := TecChannelURL; Wikipedia.FQueryURL := WikipediaURL; // Parst den Content with Google do begin FPatternTitle.FBegin := ''; // Pattern kommen noch :) FPatternTitle.FEnd := ''; FPatternLink.FBegin := ''; FPatternLink.FEnd := ''; end; with Milw0rm do begin FPatternTitle.FBegin := ''; FPatternTitle.FEnd := ''; end; with Heise do begin end; with Gulli do begin end; with TecChannel do begin end; with Wikipedia do begin FPatternTitle.FBegin := '<h1 id="firstHeading" class="firstHeading">'; // Titel <h1 id="firstHeading" class="firstHeading">Titel</h1> FPatternTitle.FEnd := '</h1>'; FPatternArticle.FBegin := ' '; // Content ...</p><table id="toc" class="toc"> FPatternArticle.FEnd := '</p><table id="toc" class="toc">'; end; end; destructor TParseServices.Destroy; begin Google.Free; Milw0rm.Free; Heise.Free; Gulli.Free; TecChannel.Free; Wikipedia.Free; FFilterdLinks.Free; FFilterdTitles.Free; inherited; end; procedure TParseServices.Submit; begin case Service of svGoogle: begin Google.Parse; end; svMilw0rm: begin end; svHeise: begin end; svGulli: begin end; svTecchannel: begin end; svWikipedia: begin end; end; end; function TGoogle.Parse: TResult; var Titles: TStrings; Links: TStrings; begin Titles := TStringList.Create; Links := TStringList.Create; // ToDo: FQueryURL wird aufgerufen und die Anwort in FResponse gespeichert // Dann wird mitPos, PosEx, Copy geparst bis Titel und Links gefiltert sind Titles.Add('ATitle'); Links.Add('ALink'); Parse.Title := Titles; Parse.Link := Links; Links.Free; Titles.Free; end; function TParseServices.Results: TResult; begin Results.Link := FFilterdLinks; Results.Title := FFilterdTitles; end; end. |
Re: Aufbau logisch und korrekt?
Ich würde es vermeiden, die Unterscheidung über case-Strukturen zu regeln. Das führt dazu, dass du an zig Stellen etwas verändern musst, sobald du eine weitere Seite hinzufügen willst, und führt zu unübersichtlichem Code. Leite stattdessen alle spezialisierten Seiten-Klassen von einer Basisklasse ab und biete die Methoden über ein einheitliches Interface an.
Das ![]() |
Re: Aufbau logisch und korrekt?
Danke für die Antwort.
Könntest du mir dazu ein Delphi Beispiel geben? Ich bin leider (noch) kein ausgebildeter Informatiker :) Edit: Wäre ![]() |
Re: Aufbau logisch und korrekt?
Zitat:
Aber ich habe mir jetzt deinen Quellcode noch einmal genauer angesehen, und dabei ist mir aufgefallen: Wozu brauchst du überhaupt TParseServices? Eine sinnvolle, logische Klassenstruktur sähe für mich so aus:
Delphi-Quellcode:
Eine konkrete Implementierung eines bestimmten Searchproviders könnte dann so aussehen:
uses
contnrs; // für TObjectList type TSearchResult = class private FTitle, FLink: string; public property Title: string read FTitle write FTitle; property Link: string read FLink write FLink; end; TSearchResultList = class(TObjectList) private function GetItem(Index: integer): TSearchResult; procedure SetItem(Index: integer; Item: TSearchResult); public property Items[index: integer]: TSearchResult read GetItem write SetItem; default; function Add(Item: TSearchResult): integer; override; { ... } end; TSearchProvider = class private FResults: TSearchResults; FQuery: string; protected function BuildRequestURL(Query: string): string; virtual; abstract; procedure Parse(Content: string); virtual; abstract; public property Results: TSearchResultList read FResults; property Query: string read FQuery write FQuery; procedure Submit; constructor Create; destructor Destroy; override; end; implementation { TSearchProvider } constructor TSearchProvider.Create; begin inherited; FResults := TSearchResultList.Create(True); end; constructor TSearchProvider.Destroy; begin FResults.Free; end; procedure TSearchProvider.Submit; var Content: string; begin Content := HTTP_GET(BuildRequestURL(FQuery)); // ausgedachte Funktion... konkrete umsetzung überlasse ich dir Results.Clear; Parse(Content); end; { TSearchResultList } function TSearchResultList.GetItem(index: integer): TSearchResult; begin Result := TSearchResult(inherited GetItem(index)); end; procedure TSearchResultList.SetItem(index: integer; Item: TSearchResult); begin inherited SetItem(index, Item); end; function TSearchResultList.Add(Item: TSearchResult); begin Result := inherited Add(Item); end;
Delphi-Quellcode:
Und ein Aufruf dann so:
type
TGoogle = class(TSearchProvider) protected function BuildRequestURL(Query: string): string; override; procedure Parse(Content: string); override; end; implementation function TGoogle.BuildRequestURL(Query: string): string; begin Result := Format('http://google.de/?q=%s', [Query]); end; procedure TGoogle.Parse(Content: string); override; var SearchResult: TSearchResult; begin // Suchergebnisse in Quellcode suchen... SearchResult := TSearchResult.Create; SearchResult.Title := '...'; SearchResult.Link := '...'; Results.Add(Searchresult); // ... end;
Delphi-Quellcode:
Nach dem Schema von TGoogle kannst du dir auch für alle anderen Seiten entsprechende Suchprovider erstellen.
var
SearchProvider: TSearchProvider; i: integer; begin SearchProvider := TGoogle.Create; // SearchProvider := THeise.Create; // SearchProvider := TGulli.Create; SearchProvider.Query := 'delphi forum'; SearchProvider.Submit; for i := 0 to SearchProvider.Results.Count -1 do begin WriteLn(Format('Titel: %s; Link: %s', [SearchProvider.Results[i].Title, SearchProvider.Results[i].Link])); end; SearchProvider.Free; end; Bitte beachte: Dieser Code wurde im Beitragseditor getippt und enthält sicher ein paar Fehlerchen - macht aber auch nix, schließlich geht es eher um die grobe Struktur. [edit] Zitat:
[/edit] |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:09 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