Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Softwaredesign - Modularisierung (https://www.delphipraxis.net/133772-softwaredesign-modularisierung.html)

I.A 8. Mai 2009 11:30


Softwaredesign - Modularisierung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich habe folgenden Entwurf für einen Quelltexteditor:

Delphi-Quellcode:
  TEditorPage = class(TTabSheet)
  private
    FEditor: TSynEdit;
    FExtension: ShortString;
    FFilename: ShortString; //Name der Editordatei
    FHighlighter: TSynCustomHighlighter;
    FHighlighters: THighlighters;
    FEmptyFileNames: TStringList;
    FHighlighterIX: Integer;
    {$ifdef fpc}
    FProcess: TProcess; //nur FPC Version
    {$endif}
    function HighlighterEquivalentToFileExt(AFileExt: ShortString): Integer;
    function GetHighlighter: Integer;
    procedure SetFilename(AFilename: ShortString);
    procedure SetHighlighter(AHighlighter: Integer);
  public
    //Compiler ist individuell für die Editordatei
    procedure Compile;
    procedure CompileSource(AFilename: ShortString);
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure LoadFromFile(AFilename: ShortString);
    procedure Save;
    procedure SaveAs(AFilename: ShortString);

    property Editor: TSynEdit read FEditor;
    property FileExt: ShortString read FExtension write FExtension;
    property Filename: ShortString read FFilename write SetFilename;
    property Highlighter: Integer read GetHighlighter write SetHighlighter;
  end;

  TEditorsList = class(TObjectList)
  private
    function GetEditors(Index: Integer): TEditorPage;
  public
    function AddEditor(AEditor: TEditorPage): Integer;
    property Editors[Index: Integer]: TEditorPage read GetEditors; default;
  end;

(*
  Here the Editor-PageControl follows
*)

  { TEditorPages }

  TEditorPages = class(TPageControl)
  private
    FFilename: ShortString; //Name des Projektes
    {$ifdef fpc}
    FProcess: TProcess; //nur FPC Version
    {$endif}
  public
    //Compiler ist derjenige der das Projekt überstzt
    //Compiler des einzelnen Editors kann dagegen eine andere Programmiersprache
    //übersetzen und den Bin-code in den Code des Projektes linken
    procedure Compile;
    procedure CompileProject(AProject: ShortString);
    procedure Debug;
    procedure DebugProject(AProjectName: ShortString);
  end;

  { TEditorPagesContainer }

  TEditorPagesContainer = class(TPanel)
  private
    FEditorPage: TEditorsList;
    FEditorPages: TEditorPages;
    function GetPageCount: Integer;
  public
    procedure OpenEditor(AFilename: ShortString);
    procedure CloseCurrentEditor;
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure Save;
    procedure SaveAs(AFilename: ShortString);
    procedure SaveAll;
    property Editors: TEditorPages read FEditorPages;
    property PageCount: Integer read GetPageCount;
  end;

  { TEditorWindow }

  TEditorWindow = class(TForm)
  private
    FEditor: TSynEdit;
    FExtension: ShortString;
    FFilename: ShortString;
    FHighlighter: TSynCustomHighlighter;
    FHighlighters: THighlighters;
    FEmptyFileNames: TStringList;
    FHighlighterIX: Integer;
    {$ifdef fpc}
    FProcess: TProcess; //nur FPC Version
    {$endif}
    FStatusBar: TStatusBar;
    function HighlighterEquivalentToFileExt(AFileExt: ShortString): Integer;
    function GetHighlighter: Integer;
    procedure SetFilename(AFilename: ShortString);
    procedure SetHighlighter(AHighlighter: Integer);
  public
    procedure Compile;
    procedure CompileSource(AFilename: ShortString);
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure NewFile;
    procedure LoadFromFile(AFilename: ShortString);
    procedure Save;
    procedure SaveAs(AFilename: ShortString);
    property FileExt: ShortString read FExtension write FExtension;
    property Filename: ShortString read FFilename write SetFilename;
    property Highlighter: Integer read GetHighlighter write SetHighlighter;
  end;
Das TEditorWindow dient als Editor, wenn ich eine MDI Anwendung bauen will. Soll der Editor in Registerkarten erscheinen, wie in der Delphi IDE, dann kommt die Version mit EditorPage und Co. zum Einsatz.

Den EditorPagesContainer habe ich hinzugefügt, um die Editorseiten einfacher in das PageControl, hier TEditorPages, einfügen zu können. Leider wird aber nur eine Registerseite erzeugt.

Gibt es eine Möglichkeit, das Design übersichtlicher zu gestalten?

Ich will erreichen, das alle Funktionen eines Quelltexteditors (auch mit mehrereren Editoren pro Sitzung, siehe Delphi IDE) in einem Modul Vereint sind und ich spter, wenn ich in den Tiefen des Internets einen KommandozeilenCompiler finde, für eine Programmiersprache, die ich mir aneignen will, problemlos eine IDE für diesen Compiler bauen kann.

Mir gefllt jedoch mein aktuelles Design noch nicht wirklich. Wie kann ich es übersichtlicher machen?

Außerdem wird, wie gesagt immer nur eine Registerseite erzeugt. Wenn ich eine neue Datei öffne, wird der Text in der Registerseite ersetzt, whrend Delphi dann eine neue Editorseite erzeugt, was auch ich beabsichtige.

Im Anhang ist mein gesamter Quellcode. Hier nur noch zum schnelleren Finden die Methode OpenEditor von TEditorPagesContainer:

Delphi-Quellcode:
procedure TEditorPagesContainer.OpenEditor(AFilename: ShortString);
var Editor: TEditorPage; Extension: ShortString; Index: Integer;
begin
  {
  So hatte ich es zuerst gemacht
  Editor := TEditorPage.Create(self);
  Editor.PageControl := FEditorPages;
  Editor.LoadFromFile(AFilename);
  }
 
  //FEditorPage ist eine erweiterte TObjectList. Ich habe die Methode AddEditor und eine
  //Eigenschaft Editors als Default hinzugefügt und will die einzelnen Editoren hier speichern,
  //da die obige Version immer nur einen Einzigen Editor öffnet.
 
  Index := FEditorPage.AddEditor(TEditorPage.Create(self));
  FEditorPage[Index].PageControl := FEditorPages;
  FEditorPage[Index].LoadFromFile(AFilename);
end;

Tyrael Y. 8. Mai 2009 12:10

Re: Softwaredesign - Modularisierung
 
Ein Konzept zum Refaktoren und damit erzeugen von vielen kleinen Klassen aus einer großen ist folgender.

1. man versucht möglichst wenig Paramter zu übergeben
2. gleiche Parameter die in vielen verschiedenen Methoden vorkommen, macht man zu Feldvariablen
3. jede Feldvariable sollte von möglichst allen Methoden seiner Klasse benutzt werden, ist dies nicht der Fall, dann gehört diese Feldvariable mit seinen Methoden höchstwahrscheinlcih in eine neue Klasse

(4. Jede Methode, die sehr lang ist, ist aller wahrscheinlich nach besser als eine neue Klasse zu implementieren)
Edit: den Punkt 4. könnte man so geschrieben falsch verstehen

4. Aus jeder Methode, die sehr lang ist, kann man wahrscheinlich eine eigene Klasse machen

Luckie 8. Mai 2009 12:12

Re: Softwaredesign - Modularisierung
 
5. Jede Klasse sollet möglichst eine eng umrissene Aufgabe erfüllen.

I.A 8. Mai 2009 22:17

Re: Softwaredesign - Modularisierung
 
Hallo Luckie + Tyrael Y.!

Danach waere ja mein Entwurf schon mal nicht der schlechteste. Danke so weit für die theoretischen Hinweise. :cheers:

Ich sehe allerdings in der TEditorpage die Methoden LoadFromFile,Save und SaveAs doppelt gemoppelt also redundant, weil diese Methoden eh im TEditorcontainer stehen. Da könnte ich auch das Feld Filename als Property bestehen lassen und von den Methoden des EditorContainers aus beeinflussen.

Außerdem könnte ich statt den Syntaxhighlighter als Eigenschaft rauszuführen, eine Eigenschaft Programmiersprache definieren und den Syntaxhighlighter abhngig vom Wert dieser Eigenschaft an den Syntaxeditor zuweisen.

Ich werd also weiter dran arbeiten.

Das immer nur eine Registerseite erzeugt wurde lag daran das ich den Editorcontainer nicht im Konstruktor meiner Anwendung, sondern in der LoadFile Methode meines Hauptformulars erzeugt hatte.
wall:


Das Erzeugen dieses Editorcontainers gehört aber in den Konstruktor der Anwendung. :warn:

Dann wird auch für jede Datei ein neuer Editor erzeugt, wie ich das haben will. bounce2:



P.S: Ich habe in meinem Profil Smileys aktiviert. Warum sind die Bilder hier nicht zu sehen?

Schönes WE und Grüße

alzaimar 9. Mai 2009 07:32

Re: Softwaredesign - Modularisierung
 
6. Trenne Funktion und Darstellung.
7. Erstelle unabhängige Klassen.

Ich würde die Liste der zu editierenden Dateien sowie die Funktionen, die Du auf diesen Dateien ausführen willst in eine eigene (Funktions-)Klasse auslagern. Diese übernimmt die Arbeit. Für die Darstellung sind dann andere Klassen zuständig, die jedoch über einen Controller gefüttert werden (MVC-Paradigma)

So eine 'TEditFile'-Klasse sollte mit einer TStrings-Eigenschaft arbeiten, die Du nach belieben zuweisen kannst. Die Klasse instantiiert also keine eigene Stringliste sondern verwendet die, die ihr 'von Außen' zur Verfügung gestellt wurde. So kannst Du diese TEditFile-Klasse auch in einem Konsolenprojekt verwenden. Gut, ist jetzt nicht so der Hit, aber es ginge (und darum geht es wg. Punkt 7). Der große Vorteil wäre eben, das Du völlig unabhängig von den verwendeten Darstellungskomponenten bist.

ich verwende z.B. gar kein TPageControl, sondern ein ähnliches Teil von einer Fremdfirma. Das sieht besser aus und man hat mehr Möglichkeiten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz