![]() |
Programm richtig kommentieren
hallo erstmal,
also ich brauch unbedingt ein einfaches programm, dass richtig kommentiert wurde, da wir morgen eine klassenarbeit schreiben, würde mich sehr freuen, danke im voraus |
Re: Programm richtig kommentieren
Und wie hilft dir dann ein ein x-beliebiges Programm?
|
Re: Programm richtig kommentieren
Zitat:
|
Re: Programm richtig kommentieren
Ich denke, das macht jeder Programmierer anders ...
|
Re: Programm richtig kommentieren
Du willst es dann benutzen, um eine gute Note zu Schreiben?
|
Re: Programm richtig kommentieren
Zitat:
|
Re: Programm richtig kommentieren
Wenn du ein Programm selber schreibst, werden die die Kommentar des anderen Programms nicht helfen.
|
Re: Programm richtig kommentieren
Manche machen es so:
Delphi-Quellcode:
andere so:
x := x + 1; //x incrementieren
Delphi-Quellcode:
Wie gesagt, das macht eigentlich jeder, wie er will.
//x incrementieren
x := x + 1; |
Re: Programm richtig kommentieren
Guck doch einfach mal hier bzw. bei dsdt.info in die Tutorial-Sparte.
|
Re: Programm richtig kommentieren
Also, wen es darum geht ein Programm richtig zu kommentieren, dann wird es schwer, weil jeder Programmierer einen eigenen Stil hat. Sollte es prüfungrelevant sein, dann habt ihr das betsimmt durchgesprochen. Guck also in deine Unterlagen.
Ich kommentiere immer so wenig wie möglich, so viel wie nötig. Und das:
Delphi-Quellcode:
würde ich nicht kommentieren. Wozu? Was bringt e, Leser der Kommentar an zusätzlichen Informationen? Nichts. Man sollte nicht kommentieren wa sman macht, das sehe ich selber am Code, sondern warum man etwas macht. Aktuelles Beispiel aus meinen String-DLL Artikel:
//x incrementieren
x := x + 1;
Delphi-Quellcode:
48, 55
(******************************************************************************
* * * DLLProg * * Demo-Programm Strings und DLLs * * * * Copyright (c) 2006 Michael Puff [url]http://www.michael-puff.de[/url] * * * ******************************************************************************) program DLLProg; {$APPTYPE CONSOLE} uses windows; type Tfunc1 = function(s: PChar; Buffer: PChar; lenBuffer: Integer): Integer; stdcall; var hLib: THandle; s: String; func1: Tfunc1; len: Integer; Buffer: PChar; begin Buffer := nil; hLib := LoadLibrary('StringDLL.dll'); if hLib = 0 then begin Str(GetLastError, s); Writeln(s); readln; exit; end; Str(hLib, s); Writeln('hlib: ' + s); @func1 := GetProcAddress(hLib, 'func1'); if (not Assigned(func1)) then begin Str(GetLastError, s); Writeln(s); readln; exit; end; Str(Integer(@func1), s); Writeln('@func1: ' + s); // Funktion aufrufen, um Größe des Buffers zu ermitteln len := func1('bar', nil, 0); Str(len, s); Writeln('len: ' + s); try // Speicher anfordern GetMem(Buffer, len + 1); // Funktion mit Buffer aufrufen len := func1('bar', Buffer, len + 1); Str(len, s); writeln(String(Buffer)+ ' [' + s + ']'); finally // Speicher wieder freigeben FreeMem(Buffer); end; readln; end. Der ertse Teil bis zeile 47 ist gänzlich unkommentiert, weil man da sieht, was passiert: DLL laden (LoadLibrary) Funktionsadresse holen (GetProcaddress) mit Fehlerbehandlung. Interessant ist der Funktionsaufruf in Zeile 49. Der Kommentar in Zeile 48 sagt warum ich dort diese Funktion aufrufe. Aus der Dokumentation würde hervorgehen, dass der Funktion im zweiten Parameter ein Buffer übergeben wird, in dem das Ergebnis landet. Und im Kommentar erkläre ich warum ich die Funktion erstmal mit nil aufrufe. Damit wird dann auch der Rest des Codes klar. Die Kommentar in Zeile 55 und 60 sind eigentlich auch überflüssig, weil man an den Funktionen sieht, was da passiert. Sind aber dort drinne, weil sich der Code an jemanden richtet, der diese Vorgehensweise nicht kannte und somit sollte dort deutlich werden was da passiert. Diese Kommentare sind also quasi nur eine Hervorhebung. Der Kommentar in Zeile 60 ist dann wieder im Zuammenhang mit den Kommentar in Zeile 48 zu sehen. Mit diesen zwei Kommentaren wird deutlich, was in diesem Block passiert und wichtiger, warum es so passiert. |
Re: Programm richtig kommentieren
Luckie hat vollkommen recht. Nicht kommentieren was man macht, sondern warum und immer abwägen, ob ein Kommentar an dieser oder jener Stelle erforderlich ist oder nicht. Durch einen übersichtlichen Code und eine gute Namensgebung kann man sich aber schon ein paar Kommentare ersparen.
@Luckie: Zitat:
Delphi-Quellcode:
:mrgreen:
// Speicher wieder freigeben
FreeMem(Buffer); |
Re: Programm richtig kommentieren
Ich habe doch erklärt, warum ich diese Zeilen kommentiert habe. :roll:
|
Re: Programm richtig kommentieren
Zitat:
Hättest du die Funktion nicht zu einer nichtssagend benannten eierlegenden Wollmilchsau gemacht, wäre klar gewesen was passiert. Du hättest dann nämlcih einen Funktionszeiger namens getBufferSize und einen namens fillBuffer gehabt. Natürlich sind auch andere Namen möglich, aber IMO wäre dann in dem Code nicht ein Kommentar nötig. Es gibt einfach keine Fallstricke. Naja bis auf die Tatsache, dass man in Delphi nicht sehen kann wann ein Parameter ein var-Parameter ist (bei dir nicht der Fall). |
Re: Programm richtig kommentieren
Ich kommentiere eigentlich nie einzelne Befehl (höchstens selbst geschriebene Funktion)
Was ich eher komentiere sind bereiche also z.b.
Delphi-Quellcode:
{Berechnungen beginnen}
x := y+1; .. .. y := x; {Ergebniss ausgeben} Label1.Caption := inttostr(x); Label2.Caption := inttostr(y); Label3.Caption := inttostr(z); |
Re: Programm richtig kommentieren
Nein, wenn dann hätte die Funktion ConCatString heißen müssen oder so. Und da wäre der Kommentar auch gerechtfertigt gewesen.
|
Re: Programm richtig kommentieren
Lieber ein Kommentar zu viel, als einen zu wenig.
|
Re: Programm richtig kommentieren
Zitat:
|
Re: Programm richtig kommentieren
Richtig oder falsch kommentieren ist auf jeden Fall auch relativ. Und wer jemals einen Quellcode von jemand anderem weiterentwickeln "musste", ist für jeden noch so kleinen Kommentar dankbar.
|
Re: Programm richtig kommentieren
Lieber einen Kommentar einsparen weil der Source sich absolut selbst erklärt !
Frage: Worin besteht eigentlich der Unterschied zwischen einem Sourcecode und einem Kommentar ? wenn wir davon ausgehen können das wir heute Sourcecode schreiben können der sich vollkommen selbst erklärt ? Ein Kommentar soll garnichts zum Source direkt erklären sondern höchstens 1. Referenzen zum verwendeten Algorithmus im Source liefern, wie Links, Bücher etc.pp. 2. wichtiges und eventuell fehlendes Background Wissen das nicht im Source ersichtlich ist nachliefern Ein Kommentar wird damit zu inaktivem Source = Quelle, weil wir mit der heutigen Programmierspache dieses Wissen nicht direkt als aktiven Source ausdrücken können. Wobei ja exakt das in neueren Sprachen, zb. eben aus dem Konzept der VCL mit ihren Komponneten und dem visuellen RAD ja schon verbessert hat. Just my 2 cent ;) Gruß Hagen |
Re: Programm richtig kommentieren
Zitat:
In Luckies Beispiel wird eine Funktion zum Konkatinieren zweier Strings benutzt, die auch noch die resultierende Länge zurückgibt. Sie wurde a)nur nichtssagend "func1" genannt und b) 2-mal mit komplett unterschiedlichen Absichten benutzt. Einmal um die Länge zu bekommen, ein anderes mal um tatsächlich mit den Strings zu arbeiten. Sowas ist schon vom Prinzip her etwas schief und erfordert deshalb Kommentare. Code, der keine Fallstricke hat braucht keine Kommentare, da dadurch die schnelle Lesbarkeit einfach sinkt. Aber Methoden selbst sollten immer eine Summary im Header haben, zumindest wenn sie nix triviales machen. Nachtrag:@Hagen, jennau! :) |
Re: Programm richtig kommentieren
Moin Luckie,
etwas OT: Das try gehört hinter das Getmem ;-) |
Re: Programm richtig kommentieren
Ups. :oops:
Genau genommen müsste es so aussehen:
Delphi-Quellcode:
Da habe ich wohl etwas durcheinander geworfen. ;)
try
GetMem; try finally FreeMem; end; except On E: Exception Do ShowMessage(E.Message); end; |
Re: Programm richtig kommentieren
Hi,
also bei öffentlichen Code Kommentiere ich immer ausführlich z.B. so:
Delphi-Quellcode:
{-----------------------------------------------------------------------------
Unit Name: uSimpleTrustCheck Author: ACE-ppc Date: 04-Apr-2005 Purpose: Unit for simple check if a file is Trusted History: V1.0: Erste Version v1.1: Speicher Leaks beseitigt, WINTRUST_DATA Struktur angepasst -----------------------------------------------------------------------------} unit uSimpleTrustCheck; interface function CheckFileTrust(const sFilename: string): Boolean; implementation uses Windows, SysUtils; const //Kostanten für die dwUnionChoice in WINTRUST_DATA WTD_CHOICE_FILE = 1; WTD_CHOICE_CATALOG = 2; //Konstanten für dwStateAction WTD_STATEACTION_IGNORE = 0; WTD_STATEACTION_VERIFY = 1; //UI Konstanten für WINTRUST_DATA WTD_UI_NONE = 2; //kein UI anzeigen //Konstanten zur Prüfung auf zurückgezogene Zertifikate WTD_REVOKE_NONE = 0; // keine zusätzliche Prüfun //Konstanten für TrustProvider WTD_SAFER_FLAG = 256; // für Winxp Sp2 benötigt //Wintrust Action GUID´s WINTRUST_ACTION_GENERIC_VERIFY_V2: TGUID = '{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}'; type CATALOG_INFO = record cbStruct: DWORD; // = sizeof(WINTRUST_CATALOG_INFO) sCatalogFile: array[0..MAX_PATH] of WCHAR; // Dateiname incl. Pfad zur CAT Datei end; PCATALOG_INFO = ^CATALOG_INFO; WINTRUST_CATALOG_INFO = record cbStruct: DWORD; // = sizeof(WINTRUST_CATALOG_INFO) dwCatalogVersion: DWORD; // optional pcwszCatalogFilePath: LPCWSTR; // benötigt, Dateiname incl. Pfad zur CAT Datei pcwszMemberTag: LPCWSTR; // benötigt, tag zum Mitglied im Katalog pcwszMemberFilePath: LPCWSTR; // benötigt, Dateiname incl. Pfad hMemberFile: THANDLE; // optional end; PWINTRUST_CATALOG_INFO = ^WINTRUST_CATALOG_INFO; WINTRUST_FILE_INFO = record cbStruct: DWORD; // = sizeof(WINTRUST_FILE_INFO) pcwszFilePath: LPCWSTR; // benötigt, Dateiname incl. Pfad pgKnownSubject: PGUID; // optional hFile: THANDLE; // optional end; PWINTRUST_FILE_INFO = ^WINTRUST_FILE_INFO; WINTRUST_DATA = packed record cbStruct: DWORD; // = sizeof(WINTRUST_DATA) pPolicyCallbackData: pointer; // optional - auf 0 setzen pSIPClientData: pointer; // optional - auf 0 setzen dwUIChoice: DWORD; // benötigt, UI auswahl fdwRevocationChecks: DWORD; // benötigt, auf zurückgezogene Zertifikate prüfen (online ben.) dwUnionChoice: DWORD; // benötigt, welche Datenstruktur soll verwendet werden pWTDINFO: pointer; // Pointer zu einer der Wintrust_X_Info Strukturen pFake: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird pFake1: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird pFake2: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird pFake3: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird dwStateAction: DWORD; hWVTStateData: THANDLE; pwszURLReference: PWChar; dwProvFlags: DWORD; dwUIContext: DWORD; end; PWINTRUST_DATA = ^WINTRUST_DATA; //Handle und Pointer auf KatalogAdminKontext HCatAdmin = THANDLE; PHCatAdmin = ^HCatAdmin; var hLibWintrust : THANDLE; //dynamische Dll Aufrufe - keine Statische einbindung möglich CryptCATAdminAcquireContext : function(PHCatAdmin: PHCatAdmin; pgSubsystem: PGUID; dwFlags: DWORD): BOOL; stdcall; CryptCATAdminReleaseContext : function(HCatAdmin: HCatAdmin; dwFlags: DWORD): BOOL; stdcall; CryptCATAdminCalcHashFromFileHandle: function(hFile: THANDLE; pHashSize: PDWORD; pbHash: PByteArray; dwFlags: DWORD): BOOL; stdcall; CryptCATAdminEnumCatalogFromHash: function(HCatAdmin: HCatAdmin; pbHash: PByteArray; pHashSize: DWORD; dwFlags: DWORD; phPrevCatInfo: PHandle): THANDLE; stdcall; CryptCATCatalogInfoFromContext: function(hCatInfo: THANDLE; psCatInfo: PCATALOG_INFO; dwFlags: DWORD): BOOL; stdcall; CryptCATAdminReleaseCatalogContext: function(HCatAdmin: HCatAdmin; hCatInfo: THANDLE; dwFlags: DWORD): BOOL; stdcall; WinVerifyTrust : function(hwnd: THANDLE; pgActionID: PGUID; pWintrustData: PWINTRUST_DATA): Longint; stdcall; {----------------------------------------------------------------------------- Funcktion: CheckFileTrust Date: 02-Mrz-2005 Arguments: const sFilename: string Result: Boolean Description: Prüft ob die angegebene Datei Trusted ist -----------------------------------------------------------------------------} function CheckFileTrust(const sFilename: string): Boolean; var //Byte Array und Counter aByteHash : array[0..255] of Byte; iByteCount : Integer; hCatAdminContext : HCatAdmin; WTrustData : WINTRUST_DATA; WTDCatalogInfo : WINTRUST_CATALOG_INFO; WTDFileInfo : WINTRUST_FILE_INFO; CatalogInfo : CATALOG_INFO; hFile : THANDLE; hCatalogContext : THANDLE; swFilename : WideString; swMemberTag : WideString; ilRet : Longint; x : Integer; begin //Standard Result setzen Result := False; //Sicherheitsabfrage ob Datei existiert if FileExists(sFilename) = False then Exit; //String in Widestring wandeln swFilename := sFilename; ZeroMemory(@CatalogInfo, SizeOf(CatalogInfo)); ZeroMemory(@WTDFileInfo, SizeOf(WTDFileInfo)); ZeroMemory(@WTDCatalogInfo, SizeOf(WTDCatalogInfo)); ZeroMemory(@WTrustData, SizeOf(WTrustData)); //Catalog Admin Kontext öffnen und falls nicht möglich Prozedur verlassen if CryptCATAdminAcquireContext(@hCatAdminContext, nil, 0) = False then Exit; //Filehandle auf die zu prüfende Datei holen hFile := CreateFile(PChar(string(sFilename)), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Wenn das Handle nicht erhalten wurde Prozedur verlassen if hFile = INVALID_HANDLE_VALUE then Exit; //iaBytescount nach größe des Arrays setzen iByteCount := SizeOf(aByteHash); //ByteArray mit Hash füllen lassen und die Größe in iByteCount bekommen CryptCATAdminCalcHashFromFileHandle(hFile, @iByteCount, @aByteHash, 0); // MemberTag brechnen (vom ByteArray auf HEX) for x := 0 to iByteCount - 1 do begin swMemberTag := swMemberTag + IntToHex(aByteHash[x], 2); end; //FileHandle schließen - wird nicht mehr gebraucht CloseHandle(hFile); //Erste Prüfung erfolgt mit WINTRUST_DATA.dwUnionChoice := WTD_CHOICE_CATALOG; //also muss WINTRUST_CATALOG_INFO gefüllt werden // //Handle auf den Katalog Kontext holen hCatalogContext := CryptCATAdminEnumCatalogFromHash(hCatAdminContext, @aByteHash, iByteCount, 0, nil); //Wenn das Handle 0 ist muss die Prüfung mit der //WINTRUST_DATA.dwUnionChoice := WTD_CHOICE_FILE; Struktur durchgeführt werden if hCatalogContext = 0 then begin //CatalogContext = 0 also // //WINTRUST_FILE_INFO Struktur initialisieren und füllen WTDFileInfo.cbStruct := SizeOf(WTDFileInfo); WTDFileInfo.pcwszFilePath := PWideChar(swFilename); WTDFileInfo.pgKnownSubject := nil; WTDFileInfo.hFile := 0; //WINTRUST_DATA Struktur initialisieren und füllen WTrustData.cbStruct := SizeOf(WTrustData); WTrustData.dwUnionChoice := WTD_CHOICE_FILE; //WINTRUST_FILE_INFO Struktur wählen WTrustData.pWTDINFO := @WTDFileInfo; //Pointer zu WINTRUST_FILE_INFO WTrustData.dwUIChoice := WTD_UI_NONE; WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE; WTrustData.dwStateAction := WTD_STATEACTION_IGNORE; WTrustData.dwProvFlags := WTD_SAFER_FLAG; //UI bei XP SP2 unterbinden WTrustData.hWVTStateData := 0; WTrustData.pwszURLReference := nil; end else begin //CatalogContext <> 0 also CATALOG_INFO benutzen // //CATALOG_INFO Struktur füllen CryptCATCatalogInfoFromContext(hCatalogContext, @CatalogInfo, 0); //WINTRUST_CATALOG_INFO Struktur initialisieren und füllen WTDCatalogInfo.cbStruct := SizeOf(WTDCatalogInfo); WTDCatalogInfo.pcwszCatalogFilePath := CatalogInfo.sCatalogFile; WTDCatalogInfo.pcwszMemberFilePath := PWideChar(swFilename); WTDCatalogInfo.pcwszMemberTag := PWideChar(swMemberTag); //WINTRUST_DATA Struktur initialisieren und füllen WTrustData.cbStruct := SizeOf(WTrustData); WTrustData.dwUnionChoice := WTD_CHOICE_CATALOG; //WINTRUST_CATALOG_INFO Struktur wählen WTrustData.pWTDINFO := @WTDCatalogInfo; //Pointer zu WINTRUST_CATALOG_INFO WTrustData.dwUIChoice := WTD_UI_NONE; WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE; WTrustData.pPolicyCallbackData := nil; WTrustData.pSIPClientData := nil; WTrustData.dwStateAction := WTD_STATEACTION_VERIFY; WTrustData.dwProvFlags := 0; //WTD_SAFER_FLAG; //UI bei XP SP2 unterbinden WTrustData.hWVTStateData := 0; WTrustData.pwszURLReference := nil; end; //WinVerifyTrust aufrufen um die Prüfung durchzuführen ilRet := WinVerifyTrust(INVALID_HANDLE_VALUE, @WINTRUST_ACTION_GENERIC_VERIFY_V2, @WTrustData); //Wenn Erg. 0 ist dann ist das File Trusted - alle anderen Werte sind Fehlercodes if ilRet = 0 then begin Result := True end else Result := False; //Handle zum Catalogfile schließen CryptCATAdminReleaseCatalogContext(hCatAdminContext, hCatalogContext, 0); //Catalog Admin Kontext schließen CryptCATAdminReleaseContext(hCatAdminContext, 0); end; initialization //Dynamisches laden der Dll und deren Funktionen hLibWintrust := LoadLibrary('wintrust.dll'); if hLibWintrust >= 32 then { success } begin CryptCATAdminAcquireContext := GetProcAddress(hLibWintrust, 'CryptCATAdminAcquireContext'); CryptCATAdminReleaseContext := GetProcAddress(hLibWintrust, 'CryptCATAdminReleaseContext'); CryptCATAdminCalcHashFromFileHandle := GetProcAddress(hLibWintrust, 'CryptCATAdminCalcHashFromFileHandle'); CryptCATAdminEnumCatalogFromHash := GetProcAddress(hLibWintrust, 'CryptCATAdminEnumCatalogFromHash'); CryptCATCatalogInfoFromContext := GetProcAddress(hLibWintrust, 'CryptCATCatalogInfoFromContext'); CryptCATAdminReleaseCatalogContext := GetProcAddress(hLibWintrust, 'CryptCATAdminReleaseCatalogContext'); WinVerifyTrust := GetProcAddress(hLibWintrust, 'WinVerifyTrust'); end; finalization FreeLibrary(hLibWintrust); end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:24 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