Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Codedesign (https://www.delphipraxis.net/11629-codedesign.html)

Luckie 10. Nov 2003 20:48


Codedesign
 
Ich bekam jetzt mal Code zusehen, der meiner Meinung vom Design her schelcht war. Daraufhin habe ich ihn überarbeitet - eigentlich total omgekrempelt. Dabei habe ich mir einige Gedanken gemacht, was guten Code von schlechten unterscheidet. Als Essenz bin ich dabei auf folgende Regeln gekommen:
  • Trennung von Aufgabe / Funktion und der Benutzerschnittstelle,
  • erleichtert die Wiederverwendbarkeit von Codeteilen.
  • Aufteilung in Teilprobleme. Daraus resultiert:
  • Aufteilung in sinnvolle Abschnitte (Subroutinen).
  • Für sich sprechende Variablen- und Funktionsnamen
  • So wenig Kommentare wie möglich, so viele Kommentare wie nötig.
  • So wenig globale Variablen wie möglich.
  • Subroutinen sollten auf eine Bildschirmseite passen.
Jetzt würde ich von euch gerne wissen, ob ihr mit mit einer Meinung seit, ob ihr daran was auszustezten habt oder ob ihr aus eigenen erfahrungen noch was ergänzen würdet.

Anmerkunmg zum letzten Punkt: Diesen habe ich noch wie folgt erläuteret:
Zitat:

Über den letzten Punkt kann man geteilter Meinung sein. Was eigentlich schon damit anfängt, was eine Bildschirmseite denn ist. Bei einer Auflösung von 1280 x 1024 bekomme ich mehr auf eine Bildschirmseite als bei einer Auflösung von 800 x 600. Aber wie auch immer wir eine Bildschirmseite definieren, bin ich der Meinung, dass es das Lesen und Verstehen eines Quellcodes unheimlich erleichtert, wenn man die gesamte Subroutine mit einem Blick erfassen kann ohne großartig scrollen zu müssen. Hier zu kann man auch noch folgenden Punkt zu zählen: Zeilen sollten nicht länger als 80 Zeichen werden. Einmal, um horizontales Scrollen zu vermeiden, was erwiesenermaßen noch unbeliebter ist als vertikales, und zum Zweiten werden so meist, bei vernünftig gewählter Schriftgröße, hässliche Zeilenumbrüche beim Drucken vermieden.

SirThornberry 10. Nov 2003 21:14

Re: Codedesign
 
Grundsätzlich stimm ich den Punkten mal zu. Zum Thema subroutinen äußer ich mich lieber nich da ich sowas verabscheue, da sieht kein schwein mehr durch und in den meisten fällen würde es auch nicht schaden diese einfach in eine eigene funktion zu packen und diese dann in den privateteil zu packen.
Ich selbst programmier mehr nach dem Try and Error Prinzip und wenns dann bissl mehr source wird, wird umsortiert und zwischen den funktionen eine zeile {===} eingefügt damit man beim durchscrollen durch die unit schneller funktionsanfang und -ende findet... aber wer hier schonmal bissl source von mir runtergeladen hat der wird da in den seltensten fällen durchgesehen haben und wenns nach meinem scheff geht muss ich mich och mal dazu durchringen in der Zukunft kommentare im Source unterzubringen aber bins halt gewöhnt source von anderen durchzuwühlen um dann zu wissen wie was funktioniert...

So sind die Punkte eigentlich ne supi Grundlage für Open-Sourceprogrammierung und Projekte wo mehrere Leutz mitmachen

Chewie 10. Nov 2003 21:16

Re: Codedesign
 
Zitat:

Zitat von SirThornberry
Zum Thema subroutinen äußer ich mich lieber nich da ich sowas verabscheue, da sieht kein schwein mehr durch und in den meisten fällen würde es auch nicht schaden diese einfach in eine eigene funktion zu packen und diese dann in den privateteil zu packen.

Hä? Subroutinen = Funktionen/Prozeduren.

SirThornberry 10. Nov 2003 21:17

Re: Codedesign
 
Achso, dachte mit Subroutinen waren die Proceduren/Funktionen gemeint die innerhalb einer Funktion definiert sind

Daniel B 10. Nov 2003 21:21

Re: Codedesign
 
Zitat:

Zitat von SirThornberry
Achso, dachte mit Subroutinen waren die Proceduren/Funktionen gemeint die innerhalb einer Funktion definiert sind

Das sind eher Inlay-Prozeduren/Funktionen.

SirThornberry 10. Nov 2003 21:26

Re: Codedesign
 
ok, dann will ich mich halt zu den inlay-Prozeduren/Funktionen nicht weiter äußern (thx für die Theorie, war schon kurz davor nen thread dazu aufzumachen)

Der Punkt das "normale" proceduren und Funktionen nicht länger als eine Bildschirmseite sein sollten erscheint mir bissl unmöglich. Bei gewissen Projekten ist das einfach nicht möglich. Bsp.: 2D/3D-Move berechnungen. Außerdem kann man ja die übersichtlichkeit da waren in dem man wie schon erwähnt zwischen die Proceduren/Funktionen "{=======}" einfügt

choose 10. Nov 2003 21:40

Re: Codedesign
 
Hmmm. Jetzt wo ich das einmal runtergeschrieben habe, sind doch ein paar Fragen zum Design "dazwischengerutscht"... Trotzdem ist vieles zum Theme "Code" dabei. Was haltet ihr von dieser Ergänzung?

Klarer Entwurf
  • Abstrakten Entwurf des Systems anfertigen (Modellierungswerkzeuge und Karten)
  • Der Einsatz von DesignPatterns zahlt sich aus (auch ohne OOP lassen sich viele Ideen übertragen)
  • Den Entwurf mit dritten diskutieren

Nutzung der Typenstrenge in Pascal/Delphi Language
  • Typesierte Ordinalwerte, um "selbstüberprüfende" Routinen zu schreiben (unbedachte Fälle vom Compiler "aufspüren" lassen)
  • Arbeiten mit Klassen und Interfaces statt mit interpretierten Integers und Records (implementierung später ändern, bessere Integration)

Kapselung, Geheimnisprinzip
  • Wenn schon keine OOP, Funktionen nach Zuständigkeiten gliedern, nicht nach einfacherer Implementierung (UseCases)
  • Trampdaten vermeiden (Delegation ok, aber es muss Sinn machen, dass eine Methode/Funktion einen Parameter erhält)
  • Globale Variablen/Singeltons vermeiden (Probleme bei Nebenläufigkeit), stattdessen Kontexte verwenden

Vorbedingungen und Nachbedingungen
  • Konsequener und wohldurchdachter Einsatz von Exceptions (auch hier: Typen!)
  • Assertions, für Programmierung "By Contract"

Testen, Debugging, Profiling
  • Code für Regressionstests und Unittests vorbereiten
  • Logging nach Möglichkeit generieren und nicht implementieren (Konsistenz, Übersichtlichkeit)
  • Instrumentieren von Code ausschließlich über Generatoren vornehmen lassen (Übersichtlichkeit)!

Es ist nichts schlimmes, die Lösung in mehreren Iterationen zu verbessern. Auch hier ist die Hilfe dritter unbezahlbar!

phlux 10. Nov 2003 21:42

Re: Codedesign
 
Irgendwo habe ich mal gelesen das Sakura zitiert hat, dass Prozeduren mit cirka 70 Zeilen länge am wenigsten Fehler enthalten, deshalb versuche ich persönlich zusatzfunktionen nicht umfangreich zu gestalten und wenn auf mehrere Funktionen aufzuteilen.
Ansonsten empfehle ich den OP Style Guide (gibts bei Luckie auf der Page :mrgreen: ). Was ich ansonsten überhaupt nicht abkann (was man hier auch manchmal im Forum sieht) sind PERMANENTE GROSSSCHREIBUNG, so Spaghetticode, und nicht schön abgestufter Code :love: . Naja das wars von meiner Seite zu dem Thema ;)

mfg phlux :hi:

Chewie 10. Nov 2003 21:45

Re: Codedesign
 
Zitat:

Zitat von SirThornberry
Achso, dachte mit Subroutinen waren die Proceduren/Funktionen gemeint die innerhalb einer Funktion definiert sind

Man sieht, dass du nie ein Perl-Programm gesehen hast :mrgreen:

negaH 10. Nov 2003 23:14

Re: Codedesign
 
und das diese Inlay funktionen offiziell "nested" Funktionen heissen :)

Ich persönlich sehe nested Funktionen als guten OOP Stil an. Sie sind nämlich meistens nur 3-4 Zeilen lang und fassen Funktionalität zusammen die mehrmalig im übergeordneten Code benötigt wird, und zwar ausschließlich NUR im übergeordneten Code. Sobald diese Funktionalität interessant für andere Funktionen wird sollte man sie auslagern.

Nested Funktion sind deshalb auch übersichtlicher ! Denn man wird sie einmalig lesen und verstehen, und konzentiert sich dann auf den eigentlichen Code der natürlich nun viel kürzer und besser lesbar ist !

Wird nun die eigentliche Funktion kopiert, weil man sie eventuell wo anders einmalig benötigt, so kopiert man immer auch die neseted Funktionen mit. Somit verliert man nicht eventuell kurze Codestücken, oder muß diese aus anderen Units zusammen suchen.

Sie pauschal zu verdammen oder immer als gut zu heissen ist sehr schlechter "OOP/NOP" Stil !

Gruß Hagen

Robert Marquardt 11. Nov 2003 06:08

Re: Codedesign
 
Nested functions haben auch noch weitere Vorteile.
Erstens hat man eine Teilfunktionalitaet isoliert, die man bestimmt bald als lokale Funktion brauchen kann.
Ganz anders ist der Vorteil das man Zugriff auf uebergeordnete Variablen hat. Das muss man allerdings sorgfaeltig evaluieren, da es sehr unuebersichtlich werden kann.

Nimoee 11. Nov 2003 06:19

Re: Codedesign
 
Hallo choose,

wäre vielleicht mal ganz nett, wenn du deinen Beitrag ins Deutsch übersetzen könntest, ich als Hochschulabgänger und Softwareentwickler versteh ihn nämlich nicht!

Nimoee

choose 11. Nov 2003 07:14

Re: Codedesign
 
Hallo Nimoee,

ich bin den Text noch einmal durchgegangen, Du hast Recht: Obwohl ich mir Mühe gegeben habe, sind in der Tat noch einige englische Begriffe im Text vorhanden... Mit den folgenden Begriffen meinte ich das:
  • Code = Programmquelltext
  • DesignPatterns = Entwurfsmuster
  • Singelton = Hier konnte ich beim Buch der GoF nach der Übersetzung von D. Riehle keinen dt. Begriff finden.
    Zitat:

    Zitat von Entwurfsmuster, Gamma et. al., Übersetzung: D.Riehle
    Intention: Sichere ab, dass eine Klasse genau ein Exemplar besitzt, und stelle einen globalen Zugriffspunkt darauf bereit.

  • Exceptions = Ausnahmebedingungen
  • Assertinos = Zusicherungen
  • Programming by Contract(ing) = "Vertragsmodell" nach erstem Treffer bei Bei Google suchenprogramming by contract vertrag
  • Debugging = Entwanzen, umgangssprachlich. Meint Fehler im Code zu finden und zu entfernen.

Ich hoffe, dass ich Dir damit helfen konnte. Wie ich im letzten Posting schon erwähnte, es sind eher Entwurfsentscheidungen (und ein bisschen Vorgehensmodell), die ich hier aufgezählt habe. Trotzdem beeinflussen einige von ihnen stark die lesbarkeit des Codes.

Luckie 11. Nov 2003 09:10

Re: Codedesign
 
Zurück zum Thema, ihr meint also, dass ich die wichtigesten Regeln gefunden habe oder könnte man noch was ergänzen? Es soll eigentlich ein kleiner Artikel für Einsteiger werden. Und so tief wie choose wollte ich nicht in die Materie einsteigen, damit dürften Anfänger überfordert sein.

negaH 11. Nov 2003 09:53

Re: Codedesign
 
Naja, eines noch: man sollte wissen wie was wann der Compiler compiliert :-)
D.h. man sollte wissen was die einzelnen Aufruf Konventionen für direkte und indirekte Auswirkungen auf das beste Codedesign haben. Zb. arbeiten wir standardmäßig mit Register Aufrufkonvention. Beachtet man im Design das jede Funktion max. 3 Parameter ordinalen Types hat -> Integer/Pointer und Klassen Methoden max. 2 solcher Parameter, dann ist dies die optimale Vorgehensweise damit der Optimierer schnellen Code erzeugen kann. Man sollte dann auch bedenken das die Anzahl der lokalen Variablen in den Proceduren gering gehalten wird. Auch dies ermöglicht dem Optimierer die bestmögliche Arbeitsweise um mit den vorhandenen Registern jonglieren zu können. Auch deshalb sind nested Proceduren sinnvoll. Denn der Optimeirer optimiert jede Funktion für sich gesehen. Je einfacher und linear strukturiert eine Procedure ist je besser kann der Optimierer seine Arbeit machen. Es gibt also direkte Abhänigkeiten des erzeugten Codes durch den Compiler zum gewählten Design.

In kurz:
- 3 ordinale Paramter maximal für Proceduren
- 2 ordinale Paramter maximal für Methoden (Self ist der 3. unsichtbare Parameter)
- register Aufrufkonvention wenn möglich
- Result immer nur am Ende der Funktion belegen, oder vor einem Exit;
- möglichst wenige lokale unkomplizierte Variablen
- das Aufsplitten komplexer Funktionen auf mehrere weniger komplexe Funktion macht den Code meistens schneller, da der Optimierer besser arbeiten kann (gilt auch für nested Proceduren)

Mit dem Result hier ein Source:
Delphi-Quellcode:
function BadResultUsage: Integer;
var
  I: Integer;
begin
  Result := 1;
  for I := 0 to 1024 do
    Result := Result + Result;
end;

function GoodUsage: Integer;
var
  I,J: Integer;
begin
  J := 1;
  for I := 0 to 1024 do
    J := J + J;
  Result := J;
end;
In komplexeren Sources wird nämlich in BadResultUsage das Resultat im Stack zwischen gespeichert. In GoodUsage geben wir aber dem Optimierer in J die Berechnungsvariable vor, die der Optimierer innerhalb der Loop in ein Register optimieren kann. Erst am Ende der Funktion wird das Resultat belegt, was meistens durch den Optimierer einfach bedeutet das er das optimierte Register J ind Register EAX kopiert. In BadResultUsage wäre dies aber im Stack gespeichert.

Wohlgemerkt obige Beispiele sind zu einfach, das heist der Optimierer kann so wie sie sind beide optimal umsetzen. Würde man aber viel mehr Code drinnenstehen haben tritt diese Regel in Kraft.

Nochwas: man sollte nach Möglichkeit mit Funktionen mit ordinalen Rückgabewerten arbeiten. Proceduren mit Reückgabeparametern bei Referenzen sind ineffizienter.

Delphi-Quellcode:
procedure BadResultProc(var Result: Integer; Data: Integer);
begin
  Result := Result + Data;
end;

function GoodResultFunc(PrevResult, Data: Integer): Integer;
begin
  Result := PrevResult + Data;
end;
Gruß hagen

Luckie 11. Nov 2003 10:03

Re: Codedesign
 
Gute Tipps, wußte ich auch noch nicht. Aber ich weiß nicht, ob ich das noch einbaue, da der Artikel nicht compilerabhängig sein sollte. Mal sehen eventuell als anhang oder so. hast du dazu noch irgendwelche quellen im Internet oder so?

negaH 11. Nov 2003 10:04

Re: Codedesign
 
Bei Prozedure/Funktionen/Methoden die mit Interface/Floatingpoints/Variant/Strings Paramter arbeiten sollte man const Paramter benutzen.
const deklarierte Paramter verhindern das der Compiler das nötige Referenzecounting bei diesen komplexen Typen durchführt.

Delphi-Quellcode:
procedure BadRefCountedTypes(Data: String/Variant/Interface);
begin
  // _AddRef(Data); // intern durch Compiler erzeugt
  // try
 
  if Data <> ... then ;
   
  // finally
  //   _Release(Data)
end;

procedure GoodRefCountedTypes(const Data: String/Variant/Interface);
begin
  if Data <> ... then ;
end;
Im zweiten Falle weiß der Compiler durch die const Deklaration das sich nichts and den Daten ändern wird, es geht auch garnicht. Dadurch kann er sich die Einrichtung eines unsichtbaren try finally end Blockes und den Code für's Referenzecounting vollständig sparen.
Bei Interfaces zB. sind Parameter die nicht const deklariert wurden fast immer schlecht deklariert, da man sie eigentlich immer nur als const oder var benutzen kann.

Gruß Hagen

negaH 11. Nov 2003 10:07

Re: Codedesign
 
Zitat:

hast du dazu noch irgendwelche quellen im Internet oder so?
Eigentlich keine, die Tipps sind einfach Erfahrungswerte :)
Selbst in den Borland NewsGroups existieren darüber falsche Ansichten, auch bei TeamB Mitgliedern.

Gruß Hagen

PS: man kann sich die logischen Abhänigkeiten aus der Delphi Hilfe ableiten, mit ein wenig Geschick :)

Luckie 11. Nov 2003 10:09

Re: Codedesign
 
Hm, gut. Mal sehen, ob ich die gepordnet da unterbringen kann. Jetzt koche ich mir aber ertsmnal meine Eier.

choose 11. Nov 2003 10:13

Re: Codedesign
 
Zitat:

Zitat von Luckie
Es soll eigentlich ein kleiner Artikel für Einsteiger werden. Und so tief wie choose wollte ich nicht in die Materie einsteigen, damit dürften Anfänger überfordert sein.

Oh, dann bin ich wohl am Thema vorbei (nicht gerade selten, bisher diese Woche *grummel*)
Wo genau soll denn der Schwerpunkt Deines Artikels liegen? Deine bisherigen Vorschläge scheinen sich auf Wartbarkeit zu beziehen. Hagen schein die Erweiterbarkeit im Sinn zu haben
Zitat:

Zitat von negaH
Wird nun die [..] Funktion kopiert, [...] so kopiert man immer auch die neseted Funktionen mit. Somit verliert man nicht eventuell kurze Codestücken, oder muß diese aus anderen Units zusammen suchen.

und zeigt datüber hinaus Möglichkeiten auf, den Code performanter zu machen.

Was aber willst Du in Deinem Artikel darstellen?

Luckie 11. Nov 2003 10:19

Re: Codedesign
 
Liste der Anhänge anzeigen (Anzahl: 1)
ja Moment. Ich hänge ihn mal an.

negaH 11. Nov 2003 10:23

Re: Codedesign
 
Zitat:

Was aber willst Du in Deinem Artikel darstellen?
Ich nahm an das Luckie über praktisches und gutes Codedesign referieren will. Gutes Codedesign berücksichtigt immer Erfahrungen von anderen Programmierern, und es ist ein Mix aus technischen Gegebenheiten des Compilers/Source Editierung/der Sprache und aus philosophischen Erwägungen wie Wartbarkeit/OOP/Algorithmen/Lesbarkeit/Dokumentation.

Wichtig ist das das Vorurteil das ein Source subjektiv und Geschacksache ist aus der Welt zu schaffen. Denn Programmierung ist reinste Logik und da haben Gefühle wie Geschmack nichts zu suchen. Man kann also ein gutes Code Design absolut logisch und schlüssig erklären warum es so am besten ist.

Eine der wichtigsten Regel ist es:
Der Programmierer codiert NICHT aus Selbstzweck und schon garnicht so das er sich in seinem Stil von allen anderen Programmierern unterscheidet !! Dies ist dumm und arrogant.

Delphi-Quellcode:
PROCEDURE _Tue_was_schlechter_stIEL(var
  param_1: XType);
     BEGIN
          IF BooleanVariable = TRUE
              THEN BEGIN
                  Display;
              END
     END
Ist absolute Scheiße !

1.) Underline als Separator ist C/C++ Stil
2.) Underline am Anfang definiert virtuell einen Compiler Magic
3.) Compiler Tokens werden immer kleine geschrieben
4.) Blöcke werden niemals auseinander gerissen, wie beim obigen IF THEN
5.) begin end/try finally end/try except end definieren einen Block Anfang und End deshalb gehören sie auf selbe Einrückungsebene
6.) immer 2 Leerzeichen werden Blöcke eingerückt, nicht 3,4,5 oder 8 und schon garnicht Tabulatoren !! 2 Leerzeichen nichts anderes. Es kommt häufig vor das man einem PASCAL Source in anderen Editoren betrachten und Tabulatoren zerstören die Formatierungen.
7.) Hinter JEDEM end gehört ein Semikolon, auch wenn es nicht unbedingt notwendig ist
8.) if then erwartet eine Boolsche Abfrage, einen Boolean nochmals mit einer Boolschen Abfrage zu versehen deutet darauf hin das der Programmierer nicht rechnen kann und die Boolsche Algebra in der Schule verpennt hat.


Gruß Hagen

Luckie 11. Nov 2003 10:27

Re: Codedesign
 
Prima. :P Unterhaltet euch nur schön weiter so, ich mache mir Notizen. :wink: Der Artikel oben ist übrigens erst mal nur ein grober Entwurf. Da muss auch sprachlich noch gefeilt werden, damit er sich flüssig liest.

@Hagen: Das geht aber schon in Richtung Codeformatierung, darüber wollte ich mich weniger auslassen. Dazu gibt es ja schon den Style Guide von Calvert.

negaH 11. Nov 2003 10:32

Re: Codedesign
 
Ein gutes Beispiel für relativ schlechten Code findet man in der INDY Library.
Ein gutes Beispiel für relativ guten Code findet man in der JEDI Library.

Gruß Hagen

choose 11. Nov 2003 10:34

Re: Codedesign
 
Hallo Luckie,

ich habe Deinen Text einmal überflogen und finde ihn ziemlich gut aufgemacht. Ähnlichen Code konnte ich bei vielen Einsteigern, die sich den Problemen nicht bewusst waren, ebenfalls entdecken.
Du zeigst recht pragmatisch, wovon andere Autoren in abstrakten Texten mit Realitätsfremden Diagrammen berichtet wird (bitte nicht missverstehen, ich bin ein Fan des MVC-Paradigmas!).

Hauptaugenmerk richtest Du nach meinem Empfinden auf Lesbarkeit, Verständnis und Änderung des Codes.
Was hältst Du von einem Folgeartikel, der Konzepte der Wiederverwendbarkeit aufzeigt? Ich könnte mir zB vorstellen, dass eine Person, die ähnliche Problemstellungen zu lösen versucht, Schwierigkeiten mit der Pflege und Übersicht den vielen ähnlichen Validierungsfunktionen begekommt...

Luckie 11. Nov 2003 10:39

Re: Codedesign
 
Zitat:

Zitat von choose
ich habe Deinen Text einmal überflogen und finde ihn ziemlich gut aufgemacht.

:P
Zitat:

Ähnlichen Code konnte ich bei vielen Einsteigern, die sich den Problemen nicht bewusst waren, ebenfalls entdecken.
Genau das ist die Zielgruppe. Deswegen will ich auch gar nicht so tief in die Materie einsteigen. Anfänger wären da einfach überforderet. Desweiteren kenn ich solche theoretischen Abhandlungen nicht und habe mich auch nicht damit beschäftigt. Ich bin eher der Praktiker.
Zitat:

Hauptaugenmerk richtest Du nach meinem Empfinden auf Lesbarkeit, Verständnis und Änderung des Codes.
Genau.
Zitat:

Was hältst Du von einem Folgeartikel, der Konzepte der Wiederverwendbarkeit aufzeigt? Ich könnte mir zB vorstellen, dass eine Person, die ähnliche Problemstellungen zu lösen versucht, Schwierigkeiten mit der Pflege und Übersicht den vielen ähnlichen Validierungsfunktionen begekommt...
Hm. Muss ich mal sehen. Aber ich hätte kein Problem damit auch Co-Autoren zu haben, falls interesse besteht, da mit zu wirken. :wink:

negaH 11. Nov 2003 10:40

Re: Codedesign
 
Nun Klammersetzung. Es sollten niemals zu viele Klammern sein, sondern nur so viele wie nötig

Delphi-Quellcode:

  if ((Boolean) and (not (Value = 1))) then Bad;
  if Boolean and (Value <> 1) then Good;

  if (A = 0) and (B = 0) and (C = 0) then Bad;
  if A or B or C = 0 then Good;

  if (A <> 0) or (B <> 0) or (C <> 0) then Bad;
  if A or B or C <> 0 then Good; // auch wenn dieser Code ineffizienter ist !
 
  if ((Red in Set) or (Green in Set) or (Blue in Set) or (Set = [])) and not (Yellow in Set) then Bad;
  if Set * [Red, Green, Blue, Yellow] <> [Yellow] then Good;
D.h. Boolsche Algebra heist das man mit den Operatoren AND,OR,NOT,XOR rechnen kann.
D.h. das man mit Mengen rechnen kann wie mit Boolscher Algebra.

Gruß Hagen

Sharky 11. Nov 2003 10:47

Re: Codedesign
 
:cry:

Hai Hagen,

mache nur so weiter und zerstöre meine Illusion ist würde "gut" Coden ;-)

Ne, im Ernst: Wenn ich das hier mitlese wird mir bewusst auf was ich alles nicht geachtet habe.

Finde es allso Super! :thuimb:

Gerade die kurzen Beispiele zeigen sehr gut die Unterschiede zwichen gut und schlecht.

@Luckie: Auch das formatieren des Codes (inkl. der Namesvergabe von Methoden und Variablen) sollte nicht unerwähnt bleiben.

Luckie 11. Nov 2003 10:51

Re: Codedesign
 
Zitat:

Zitat von Sharky
@Luckie: Auch das formatieren des Codes (inkl. der Namesvergabe von Methoden und Variablen) sollte nicht unerwähnt bleiben.

Ich verweise da auf den Style Guide von Charels Calvert, wie ich schon sagte.

negaH 11. Nov 2003 10:56

Re: Codedesign
 
@Luckie:

In deinem Tut:

1.) die ShowMessage() sollte durch eine Excpetion ersetzt werden. Der Code als "Highlevel" Funktion sollte auch eine Fehlerüberprüfung haben. "Highlevel" Funktionen können demzufolge auch Exceptions auslösen. Paralell dazu könnte man die Funktion so umbasteln wie es in StrToIntDef() der Fall ist. Dies würde die Exceptions beseitigen und einen Default Wert zuweisen.
2.) ValidatDay() ist eine Schlampigkeit, denn das eine fehlende "e" für ValidateDay() hätte man auch noch schreiben können :) Es sei denn man würde IsValidDay() benutzen.
3.) Button1.Enabled := IsValidDay and IsValidMonth and IsvalidYear; stellt klip und klar eine Boolsche Berechnung dar. Man benötigt keinerlei if then else !
Selbiges in ValidatDay()
4.) ALLE Varibalen beginnen mit Großbuchstaben !
5.) ValidatDay(d: string): Boolean; ist inkonsitent -> IsValidDay(const Value: String): Boolean;
6.) edtDay.Text -> EditDay.Text oder EDay.Text
7.) Extended für die Berechnungen ist überdimensioniert, Default Floatingpoint sollte Double sein.
8.) CalcJulYear(Day, Month, Year: DWord): Extended -> CalcJulianYear(Year: Word; Month: Word = 1; Day: Word = 1): Word;
DWord ist ein Windows API Datentyp kein PASCAL Datentyp. In PASCAL wäre es Cardinal.

Gruß Hagen

choose 11. Nov 2003 10:58

Re: Codedesign
 
Zitat:

Zitat von Negah
Es sollten niemals zu viele Klammern sein, sondern nur so viele wie nötig

Hallo Negah,

ich empfehle Einsteigern meißt eher das Gegenteil, weil vielen die Prioritätsregeln nicht "im Blut stecken".
Es gibt zwei Prioritätsregeln:
  1. Punkt- vor Strichrechnung
  2. Klammer vor allem
Lieber eine Klammer mehr, als ein Bug, den man nicht findet, weil man glaubt, der Compier übersetzt es so, wie man meint:
Delphi-Quellcode:
var
  a, b: Integer;
begin
  a:= -1;
  b:= 2;
  if not a < b then
Und "Tricks mit binären Operatoren" in der Form
Zitat:

Zitat von Negah
Delphi-Quellcode:
  if A or B or C = 0 then Good;

würde ich als Einsteiger lesen als "Wenn eine der Variablen null ist, dann".

Ich hatte mal den folgenden Code gesehen:
Delphi-Quellcode:
  //its not a sony, its a trick
  a:= a xor b;
  b:= a xor b;
  a:= a xor b;
Sicher, er funktioniert, ist performat, braucht eine Variable weniger, aber: Wer, der nicht vorher ASM geschrieben hat, versteht ihn (und dann noch der Kommentar! Ich beziehe mich hier auf Negah: "Der Programmierer codiert NICHT aus Selbstzweck")?

Luckie 11. Nov 2003 11:03

Re: Codedesign
 
Schon verbessert. :thumb:

negaH 11. Nov 2003 11:05

Re: Codedesign
 
Delphi-Quellcode:
function IsValidDay(const Value: String): Boolean;
begin
  Result := StrToIntDef(Value, 0) in [1..31];
end;

function CalcJulianYear(Year: Word; Month: Word = 1; Day: Word = 1): Word;
begin
// falls CalcJulianYear eine "lowlevel" private Funktion ist
  Assert(Month in [1..12]);
  Assert(Day in [1..31]);
// falls CalcJulianYear eine "highlevel" globale Funktion ist
  if not (Month in [1..12]) then
    raise EConvertError.Create();
  if not (Day in [1..31]) then
    raise EConvertError.Create();
 
// hier die Berechnung aus der PDF, ich verstehe aber nicht was dort berechnet wird,
// da die wichtigen Remarks fehlen !!?? :-)
 
end;
Gruß hagen

choose 11. Nov 2003 11:13

Re: Codedesign
 
Hallo negaH,

Luckie hat bewusst darauf hingewiesen, dass der Article nicht in der finalen Version vorliegt.
Tippfehler, wie ein fehlender Buchstabe, sollten deshalb verziehen werden...


Zitat:

Zitat von negaH
die ShowMessage() sollte durch eine Excpetion ersetzt werden. Der Code als "Highlevel" Funktion sollte auch eine Fehlerüberprüfung haben. "Highlevel" Funktionen können demzufolge auch Exceptions auslösen. Paralell dazu könnte man die Funktion so umbasteln wie es in StrToIntDef() der Fall ist. Dies würde die Exceptions beseitigen und einen Default Wert zuweisen.

Assertion- und Exceptionhandling ist mehr als nur irgendeine Exception zu werfen. Weil die VCL es nur bedingt vorlebt und Delphi nicht das Konzept der Checked Exceptions unterstützt, sind sie dem Delphi-Einsteiger (Zielgruppe des Artikels) nicht vertraut. Richtig angewandt sind Exceptions sehr sinnvoll, aber auch aufwendig zu designen!

Zitat:

Zitat von negaH
4.) ALLE Varibalen beginnen mit Großbuchstaben !
5.) ValidatDay(d: string): Boolean; ist inkonsitent -> IsValidDay(const Value: String): Boolean;
6.) edtDay.Text -> EditDay.Text oder EDay.Text

Wenn Luckie sich auf den StyleGuide von Charles Calvert beruft, simmt das. Allerdings habe zu genau diesen Punkten schon häufiger Kritik vernommen...

Zitat:

Zitat von negaH
7.) Extended für die Berechnungen ist überdimensioniert, Default Floatingpoint sollte Double sein.

Auch hier würde ich lieber einen zu großen Datentyp (für einen Einsteiger) empfehlen als einen zu kleinen mit deaktivierte Bereichsüberprüfung (sonst sind 200d+100d plötzlich einmal 45d).

negaH 11. Nov 2003 11:17

Re: Codedesign
 
Zitat:

ich empfehle Einsteigern meißt eher das Gegenteil, weil vielen die Prioritätsregeln nicht "im Blut stecken".
Absolut falsch. Bei meinen Lehrlingen habe ich alle diese Regeln wieder und wieder in den Schädel gehämmert, denn wie soll man es richtig lernen wenn man es nicht richtig lernt ??
Jede Ausnahmeregel und Ausnahmevereinfachung führt dazu das man es so und nicht anders in Zukunft macht.

Einfach mal sagen das der Himmel Grün und die Wiese Blau ist, damit es ein Idiot versteht halte ich für falsch (überspitzt ausgedrückt :-) ) Dem Lernenden ist nicht geholfen dabei.

Delphi-Quellcode:
var
  a, b: Integer;
begin
  a:= -1;
  b:= 2;
  if not a < b then
Diese Abfrage muß logisch begriffen werden, man muß also Klamern setzen wenn man den Boolschen Vergleich if not (A < B) then erreichen will.
Wichtig ist es hier aber das man merkt das diese Abfrage absolut schlechter Stil ist und der Programmierer NICHT nachgedacht hat. Denn:

Delphi-Quellcode:
  if a >= b then ;
wäre die RICHTIGE Antwort !


Delphi-Quellcode:
  a:= a xor b;
  b:= a xor b;
  a:= a xor b;
Das sollte absolut vermieden werden, korrekt !
Eine zusätzliche Variable macht den Code lesbarer und ist unter umständen schneller.

Gruß Hagen

Luckie 11. Nov 2003 11:29

Re: Codedesign
 
So, das werde ich nachher mal alles zusammentragen und mit einfließen lassen.

choose 11. Nov 2003 11:42

Re: Codedesign
 
Cool. Postest Du hier noch einmal, wenn Du den Artikel fertig und auf Deiner Seite veröffentlicht hast?

Danke.

Luckie 11. Nov 2003 11:52

Re: Codedesign
 
Logisch, sonst macht es ja wenig Sinn. Ich muss mich nur irgendwie mit dem Autor für den schlechten Code einigen. Bis jetzt sperrt er sich noch. :cry:

neolithos 11. Nov 2003 12:20

Re: Codedesign
 
Zitat:

Zitat von Hagen
8.) if then erwartet eine Boolsche Abfrage, einen Boolean nochmals mit einer Boolschen Abfrage zu versehen deutet darauf hin das der Programmierer nicht rechnen kann und die Boolsche Algebra in der Schule verpennt hat.

Für komplizierte Ausdrücke verwende ich da meist ein Stück Papier und male ein KV-Tafel auf.
Damit kann man komplizierte abfragen vereinfachen!

Man sollte aber einen Kommentar mit der Problembeschreibung dazusetzen.


Was bei mir noch immer aufgefallen ist,

Ich schreibe eine Procedure zuerst logisch auf.
Was soll grob getan werden. ==> Kommentare

Bsp: TSR

Delphi-Quellcode:
// Sortiere Feld
// Gehe Alle Städte -> Rekursion
for I := 0 to Count - 1 do
    // Schranke prüfen
    ;
Das Symikolon hatte ich vor sehr langer Zeit hinter das do gesetzt und manchmal vergessen es wieder wegzulöschen oder man setzt einen leeren Block.

Diese Vorgehensweise macht es mir leicht möglich das komplexen Problem in viele Teilprobleme zu zerlegen.

Nennt man glaube ich Top-Down-Prinzip.

S - tefano 11. Nov 2003 12:26

Re: Codedesign
 
Gibt es nicht von Borland selbst einen seitenlangen Artikel mit Richtlinien, wie man Pascal Code schreiben sollte?
Ich bin mir sicher ich hab sowas schonmal gelesen, vielleicht weiß von euch ja einer wo es den gibt. Ich werd ihn mal suchen, den könnte man wenigstens noch als Vergleichsquelle benutzen, wenn man sich nicht komplett an ihn hält. Denn neben den Regeln die es schon gibt noch eigene Regeln aufzustellen die denen ähnlich sind die es schon gibt...
Da kann ich mir auch ne eigene StVO entwerfen, die sich von der normalen nur dadurch unterscheidet dass ich immer Vorfahrt habe ;-)
Nichts für ungut :-)

Ich finde eure Ansätze bislang richtig gut, die machen Sinn und umfassen schon viele "Bereiche". Wenn sich daran hier im Forum jeder hält, haben wir alle mehr Spaß.

Bis dann,

S - tefano


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:52 Uhr.
Seite 1 von 2  1 2      

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