Entwickler-Ecke
Off Topic - Wie sollte ein guter Prozedurkopf aussehen.
Popov - Di 01.07.03 17:10
Titel: Wie sollte ein guter Prozedurkopf aussehen.
Die Frage stelle ich mir eigentlich schon lange und dieses mal stelle ich sie hier. Gemeint ist natürlich der Kommentarkopf einer Prozedur (nicht der Unit).
Mir ist klar, daß jeder es so gestallten kann wie er es Lustig findet. Für die meisten Prozeduren findet man überhaupt keine Beschreibung oder es ist nur eine Kommentarzeile. Ok, eine professionale Prozedur erkennt man daran, daß die selbsterklärend ist und keine Kommentare benötigt ;) (kleiner Insiderwitz). Ich gebe zu, daß man es bei den Borland-Units noch entschuldigen kann, da jede Prozedur in der Hilfe beschreiben wird. Allerdings geht es hier um normale Units für normale Programme. Ich sehe es ein, daß nicht jede Prozedur in jedem Programm eine derartige Aufmerksamkeit braucht, aber es gibt nun mal Units die allgemein sind und in vielen Programmen verwendet werden. Da bringt es schon was, wenn man die Prozeduren/Funktionen etwas besser beschreibt.
Also zeigt mal welche Prozedurköpfe ihr so kennt. Gemeint sind natürlich Köpfe die alle Informationen enthalten, also z.B. was die Prozedur/Funktion tut, welche Parameter sie hat usw. Natürlich kenne ich auch zwei oder drei Köpfe, die sind aber derart unterschiedlich, daß sie fast nichts gemeinsames haben. Deshalb gehe ich davon aus, daß es zig verschiedene Arten gibt die auch verschiede Menge an Informationen liefern. So gibt es welche, die zwar die Parameter beschreiben, aber sonst nichts, bei anderen gibt es dafür eine Versionsnummer und sogar eine History der Prozedur.
Also, ich bitte um Beteidigung. Würde mich wirklich interesieren was es da gibt.
Delete - Di 01.07.03 17:50
Procedur-Header:
Header der Hauptunit:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64:
|
|
Aya - Di 01.07.03 18:05
Hi,
hab mal ne frage... ;)
(Benutze btw nahezu keinerlei Kommentare)
Procedure.. da steht der Name der Procedure... der is doch sowieso klar...?? Genauso wie Arguments und Result, erkennt man doch sofort wenn man die Procedure anguckt *guckt misstrauisch*
Der Author.. ok, das is hilfreich wenn mehrere Leute an einem Projekt arbeiten oder die Unit veröffentlicht wird etc.. damit man halt weiß an wen man sich wenden muß ;)
und Purpose... wenn man da nich nen Roman hinschreibt is das doch auch überflüssig, oder??? Denn man kann den Proceduren-Namen doch so wählen das er selbsterklärend ist.
Deswegen frage ich mich bei solchen "Headern" immer.. welchen Zweck haben die, ausser das sie (in meinen Augen) den Code sehr unübersichtlich machen..?? (Ok, evtl is das geschmacks/gewöhnungssache, denn ich wette Luckie fände Code ohne diese Header sehr unübersichtlich ;) )
Au'revoir,
Aya~
Delete - Di 01.07.03 18:26
Naja, ich wähle meine Prozedur und Funktionsnamen relativ kurz, da ist es schon manchmal hilfreich, wenn man den Zwecknoch mal etwas ausführlicher schreiben kann.
Diese Funktion, die ich als Beispiel gepostet habe erfüllt nämlich so gesehen mehrere Zwecke. Sie checkt nicht nur, ob der Rechner online ist, sondern schreibt, wenn offline gegegangen wird das Protokoll.
Popov - Di 01.07.03 19:09
Aya hat folgendes geschrieben: |
Denn man kann den Proceduren-Namen doch so wählen das er selbsterklärend ist. |
Glaubst du wirklich?
Das mit dem selbsterklärenden Code war nur ein Witz. Glaubst du, daß du von Funktionsnamen aus den Sinn der Funktion schließen kannst? Ok, ich hab in einer Unit die Funktion "GetChar". Wozu ist die Funktion gut. Mehr sage ich zu der Funktion nicht. Du solltes bedenken, daß man ein Programm nach zwei Jahren wieder auspackt und weiter drann arbeitet. Bist du sicher, daß du dann immer noch weißt wozu "GetChar" gut ist. Erschwerend kommt dazu, daß es gleich davor die "ReadChar" Funktion gibt ;).
Mal erst, glaubst du, daß du in ein
wichtiges Programm, daß du über Jahre pflegst, ohne Kommentare und Prozedurbeschreibungen auskommst?
AndyB - Di 01.07.03 19:10
Die "Arguments" zeile kann man sich doch sparen. Die stehen auch im Prozedurkopf. Also warum doppelt? Das selbe gilt auch für Result.
Delete - Di 01.07.03 19:13
Aber so kann man die Argumente und den Rückgabewert noch kommentieren. Und das ist übersichtlicher als mit Geschweiftenklammen den Kommentar in die Argumentenliste reinzuschreiben. :wink:
Aya - Mi 02.07.03 08:59
Popov hat folgendes geschrieben: |
Aya hat folgendes geschrieben: | Denn man kann den Proceduren-Namen doch so wählen das er selbsterklärend ist. |
Glaubst du wirklich?
Das mit dem selbsterklärenden Code war nur ein Witz. Glaubst du, daß du von Funktionsnamen aus den Sinn der Funktion schließen kannst? Ok, ich hab in einer Unit die Funktion "GetChar". Wozu ist die Funktion gut. Mehr sage ich zu der Funktion nicht. Du solltes bedenken, daß man ein Programm nach zwei Jahren wieder auspackt und weiter drann arbeitet. Bist du sicher, daß du dann immer noch weißt wozu "GetChar" gut ist. Erschwerend kommt dazu, daß es gleich davor die "ReadChar" Funktion gibt ;).
|
Hi,
wenn DU deine Procedure GetChar nennst, obwohl sie z.B. nen Bild zeichnet, dann hat natürlich niemand ne ahnung was diese Procedure macht.
Ich habe in meinem Code eine feste struktur, welche nie geändert wird... somit brauche ich auch nie irgendwelche Kommentare... und ich habe keinerlei probleme mich in ein Programm welches ich vor 2 Jahren geschrieben habe innerhalb von 2-3min reinzufinden.
Aber ich nenne eine Procedure die z.B. ein Bild halb transparent macht nich irgendwie "Blablubb" sondern "MakeImageTransparent". So kommen zwar u.U. recht lange Proceduren/Variablen Namen zu stande, allerdings... wen stört das schon???
Mehr Tipp Arbeit isses dank CodeInsight auchnet ;)
Au'revoir,
Aya~
UGrohne - Mi 02.07.03 09:29
Ich hab damit schon schlimme Erfahrungen gemacht: Ich habe während meines Seminarkurses einen Vokabeltrainer programmiert (wurde auch gut bewertet :wink:).
Vor einem Jahr habe ich dann gedacht, komm, jetzt kramste das Teil mal wieder raus und machst es erstmal bereit zur Veröffentlichung..... denkste, ich hab nix mehr geblickt, was ich da gemacht habe und bin zum Schluss gekommen, dass ich es wahrscheinlich schneller halb neu programmiert hätte, wie da jetzt wieder reinzuarbeiten.
Denn die Programmierweise ändert sich, auch wenn man denkt, man hat einen festen Stil, je mehr Erfahrung man hat, desto eher unterscheidet sich sein Stil von früher. Und man lernt IMMER mehr.
Seitdem mache ich vor jede Prozedur eine kleine Kommentarzeile, die beschreibt (in Kurzform natürlich), was die Prozedur macht und in jeder Prozedur habe ich dann Blöcke, wenn sie etwas größer ist, die auch wieder kommentiert sind.
Aya - Mi 02.07.03 10:35
Hi,
sicherlich ändert sich die Programmierweise, nen Programm was ich vor knapp 2 Jahren als ich Delphi angefangen habe gemacht habe, würde ich heute komplett anders programmieren... ;)
Aber trotzdem weiß ich auch nach 2 Jahren noch ziemlich genau was ich damals gemacht habe, und vorallem was ich mir damals bei dem und dem gedacht habe.
Au'revoir,
Aya~
hansa - Mi 02.07.03 10:54
Das ist ein Thread, in dem alle Recht haben. :lol: Das ganze kommt auch auf die Größe des Projektes an und wieviele da mitmachen. Bei mir wäre es unmöglich, überall Autor usw. hinzuschreiben. Das würde bei tausenden Prozeduren länger dauern, als die reine Tiparbeit des Codes und wäre somit unzumutbar.
Hinzu kommen noch ganze Zeilen von
Quelltext
1:
| ------------------------------------------------------------------ |
Quelltext
1:
| *********************************************** |
usw., was die Dateien aufbläht. Mit Zip usw. macht das zwar nicht viel aus, aber schnell mal 30 Dateien auf eine Diskette kopieren, könnte wegen solcher Geschichten scheitern. Deshalb gehe ich den goldenen Mittelweg, wie im Leben eben üblich :mrgreen: :
1. aussagekräftige Namen für alles, nicht einfach nur Form1 etc.
2. beim kleinsten Zweifel über den Sinn einer Prozedur/Parametern: Kommentar
Also eher so wie Aya es macht.
Aya hat folgendes geschrieben: |
(Benutze btw nahezu keinerlei Kommentare) |
:shock: So faul bin ich aber dennoch nicht. Aya, das kannst Du doch nicht machen!!! Das mußt Du Dir dringend abgewöhnen. :mahn:
Aya - Mi 02.07.03 11:15
hansa hat folgendes geschrieben: |
Aya hat folgendes geschrieben: | (Benutze btw nahezu keinerlei Kommentare) |
:shock: So faul bin ich aber dennoch nicht. Aya, das kannst Du doch nicht machen!!! Das mußt Du Dir dringend abgewöhnen. :mahn: |
Ich finde einfach das viele Kommentare einen Sourcecode extrem unübersichtlich machen... das geht mir bei Codes die ich mir runterlade um was draus zu lernen genauso... am anfang werden erstmal alle Kommentare rausgeschmissen damit aus 10Seiten Code 3 Seiten werden... ;)
Au'revoir,
Aya~
mimi - Mi 02.07.03 11:26
lol, ich finde eine procedure sollte so aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure SetWindowsFullBild; begin if ...... then begin .... end; end; |
das wäre eingetlich der optimale procenduren kopf... oder nicht ?
ich finde das der name der funktion bzw. der procedur immer selbsterklärend sein muss und auch die parametern in der proceudure/funktion.....
Aya - Mi 02.07.03 11:32
mimi hat folgendes geschrieben: |
lol, ich finde eine procedure sollte so aussehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure SetWindowsFullBild; begin if ...... then begin .... end; end; | |
und wieso ist es so dermaßen wichtig zu wissen wann die Procedure geschrieben wurde, wann sie geändert wurde und ob z.B. ein Bug behoben is??? *guckt misstrauisch*
Au'revoir,
Aya~
hansa - Mi 02.07.03 11:33
Aya hat folgendes geschrieben: |
... am anfang werden erstmal alle Kommentare rausgeschmissen damit aus 10Seiten Code 3 Seiten werden... ;)
|
Das meine ich ja, daß es manchmal derart übertrieben ist, aber die Kommentare würde ich trotzdem erst zum Schluß rausschmeißen. :mrgreen:
Wie gesagt noch bin ich nicht so bekloppt folgendes zu tun:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| (* Autor Hansa -----------------------------------------------------------*) (* erstellt am : 2.7.2003, 11:30 29,3278925980542 Sekunden------*) (* Zweck : Erhöhung einer Zahl in einer Schritten (* Abhängigkeiten : Prozedur Nonsens --------------------------------*)
procedure test;
var i, // das ist eine Integer-Variable max : integer; // max ist eine integer Variable, genau so wie i begin // hier beginnt die Prozedur for i := 1 to max do // solange i nicht den wert von max erreicht, // wird es um 1 erhöht // ACHTUNG! Am Ende der Schleife ist i = max end; // Prozedur hat die Schleife durchlaufen // die Variable wurde innerhalb der Prozedur lokal deklariert // und ist deshalb außerhalb der Prozedur nicht diesselbe |
:hair:
patrick - Mi 02.07.03 12:32
meins sieht (bei großen projekten) so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure tform1.aussagekräftiger_name(sinvolle variable:string);
var... begin ... |
Delete - Mi 02.07.03 13:50
@Hansa:
1. Die Kommenrate landen nicht in der Exe, sie vergrößern die Exe also nicht. Bzw. auch die Quellcodedateien werden nur unerheblich größer und reiner Text läßt sich immer gut packen.
2. Mit den GExperts ist das für mich nur ein Tastendruck und alles steht so da, ich muß nur noch den Purpose ausfüllen.
@Aya:
Datum und was und wann zu letzt geändert kann manchmal ganz wichtig sein, wenn mehrer Personen an einem Projekt arbeiten.
Und du würdest alle Kommentare rausschmeißen?
Gut, dann pass mal auf:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99:
| program xxxxxxxx;
uses Windows, ntddk in 'ntddk.pas';
{$R res\Image.res}
function Protect(Characteristics: ULONG): ULONG; const Mapping: array [0..7] of ULONG = ( PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ, PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_EXECUTE_READWRITE ); begin Result := Mapping[Characteristics shr 29]; end;
type PImageSectionHeaders = ^TImageSectionHeaders; TImageSectionHeaders = array [0..95] of TImageSectionHeader; var ProcessInfo: TProcessInformation; StartupInfo: TStartupInfo; Success: Boolean; Context: TContext; BaseAddress: Pointer; BytesRead: DWORD; Resource: Pointer; NtHeaders: PImageNtHeaders; BytesWritten: DWORD; Sections: PImageSectionHeaders; i: ULONG; OldProtect: ULONG; begin FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb := SizeOf(TStartupInfo); if CreateProcess(nil, PChar(ParamStr(0)), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartupInfo, ProcessInfo) then begin Success := False; try Context.ContextFlags := CONTEXT_INTEGER; if GetThreadContext(ProcessInfo.hThread, Context) and ReadProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8), @BaseAddress, SizeOf(BaseAddress), BytesRead) and (ZwUnmapViewOfSection(ProcessInfo.hProcess, BaseAddress) >= 0) then begin Resource := LockResource( LoadResource(0, FindResource(0, 'Image', 'EXE'))); if Assigned(Resource) then begin NtHeaders := PImageNtHeaders( Cardinal(Resource) + Cardinal(PImageDosHeader(Resource)._lfanew)); BaseAddress := ntddk.VirtualAllocEx(ProcessInfo.hProcess, Pointer(NtHeaders.OptionalHeader.ImageBase), NtHeaders.OptionalHeader.SizeOfImage, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); if Assigned(BaseAddress) and WriteProcessMemory(ProcessInfo.hProcess, BaseAddress, Resource, NtHeaders.OptionalHeader.SizeOfHeaders, BytesWritten) then begin Sections := PImageSectionHeaders(ImageFirstSection(NtHeaders)); for i := 0 to NtHeaders.FileHeader.NumberOfSections - 1 do if WriteProcessMemory(ProcessInfo.hProcess, Pointer(Cardinal(BaseAddress) + Sections[i].VirtualAddress), Pointer(Cardinal(Resource) + Sections[i].PointerToRawData), Sections[i].SizeOfRawData, BytesWritten) then ntddk.VirtualProtectEx(ProcessInfo.hProcess, Pointer(Cardinal(BaseAddress) + Sections[i].VirtualAddress), Sections[i].Misc.VirtualSize, Protect(Sections[i].Characteristics), OldProtect); if WriteProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8), @BaseAddress, SizeOf(BaseAddress), BytesWritten) then begin Context.Eax := ULONG(BaseAddress) + NtHeaders.OptionalHeader.AddressOfEntryPoint; Success := SetThreadContext(ProcessInfo.hThread, Context); end; end; end; end; finally if not Success then TerminateProcess(ProcessInfo.hProcess, 0) else ResumeThread(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); end; end; end. |
Deiner Aussage nach müßtest du ja ohne probleme verstehen, was das Programm macht oder?
Der Vollständigkeit halber:
ntddk.pas:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219:
| unit ntddk;
interface
uses Windows;
type HANDLE = THandle; PVOID = Pointer; LPVOID = Pointer; LONG_PTR = Integer; ULONG_PTR = Cardinal; NTSTATUS = Longint; SIZE_T = Cardinal;
const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; IMAGE_SIZEOF_SHORT_NAME = 8;
type PImageDosHeader = ^TImageDosHeader; TImageDosHeader = packed record e_magic : Word; e_cblp : Word; e_cp : Word; e_crlc : Word; e_cparhdr : Word; e_minalloc: Word; e_maxalloc: Word; e_ss : Word; e_sp : Word; e_csum : Word; e_ip : Word; e_cs : Word; e_lfarlc : Word; e_ovno : Word; e_res : array [0..3] of Word; e_oemid : Word; e_oeminfo : Word; e_res2 : array [0..9] of Word; _lfanew : Longint; end;
PImageFileHeader = ^TImageFileHeader; TImageFileHeader = packed record Machine : Word; NumberOfSections : Word; TimeDateStamp : DWORD; PointerToSymbolTable: DWORD; NumberOfSymbols : DWORD; SizeOfOptionalHeader: Word; Characteristics : Word; end;
PImageDataDirectory = ^TImageDataDirectory; TImageDataDirectory = record VirtualAddress: DWORD; Size : DWORD; end;
PImageOptionalHeader = ^TImageOptionalHeader; TImageOptionalHeader = packed record Magic : Word; MajorLinkerVersion : Byte; MinorLinkerVersion : Byte; SizeOfCode : DWORD; SizeOfInitializedData : DWORD; SizeOfUninitializedData : DWORD; AddressOfEntryPoint : DWORD; BaseOfCode : DWORD; BaseOfData : DWORD; ImageBase : DWORD; SectionAlignment : DWORD; FileAlignment : DWORD; MajorOperatingSystemVersion: Word; MinorOperatingSystemVersion: Word; MajorImageVersion : Word; MinorImageVersion : Word; MajorSubsystemVersion : Word; MinorSubsystemVersion : Word; Win32VersionValue : DWORD; SizeOfImage : DWORD; SizeOfHeaders : DWORD; CheckSum : DWORD; Subsystem : Word; DllCharacteristics : Word; SizeOfStackReserve : DWORD; SizeOfStackCommit : DWORD; SizeOfHeapReserve : DWORD; SizeOfHeapCommit : DWORD; LoaderFlags : DWORD; NumberOfRvaAndSizes : DWORD; DataDirectory : array [0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory; end;
PImageNtHeaders = ^TImageNtHeaders; TImageNtHeaders = record Signature : DWORD; FileHeader : TImageFileHeader; OptionalHeader: TImageOptionalHeader; end;
PImageSectionHeader = ^TImageSectionHeader; TImageSectionHeader = packed record Name : array [0..IMAGE_SIZEOF_SHORT_NAME-1] of Byte; Misc : record case Integer of 0: (PhysicalAddress: DWORD;); 1: (VirtualSize : DWORD;); end; VirtualAddress : DWORD; SizeOfRawData : DWORD; PointerToRawData : DWORD; PointerToRelocations : DWORD; PointerToLinenumbers : DWORD; NumberOfRelocations : Word; NumberOfLinenumbers : Word; Characteristics : DWORD; end;
function ImageFirstSection(ntheader: PImageNtHeaders): PImageSectionHeader;
function VirtualAllocEx(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flAllocationType: DWORD; flProtect: DWORD): LPVOID; stdcall; function VirtualProtectEx(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flNewProtect: DWORD; var lpflOldProtect: DWORD): BOOL; stdcall;
function ZwUnmapViewOfSection(ProcessHandle: HANDLE; BaseAddress: PVOID): NTSTATUS; stdcall;
const ntdll = 'ntdll.dll';
implementation
function ImageFirstSection(ntheader: PImageNtHeaders): PImageSectionHeader; begin Result := PImageSectionHeader( ULONG_PTR(@ntheader.OptionalHeader) + ntheader.FileHeader.SizeOfOptionalHeader); end;
type TFNVirtualAllocEx = function(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flAllocationType: DWORD; flProtect: DWORD): LPVOID; stdcall;
var FNVirtualAllocEx: TFNVirtualAllocEx;
function VirtualAllocEx(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flAllocationType: DWORD; flProtect: DWORD): LPVOID; stdcall; begin Result := nil; if not Assigned(FNVirtualAllocEx) then FNVirtualAllocEx := TFNVirtualAllocEx( GetProcAddress(GetModuleHandle(kernel32), 'VirtualAllocEx')); if not Assigned(FNVirtualAllocEx) then SetLastError(ERROR_CALL_NOT_IMPLEMENTED) else Result := FNVirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect); end;
type TFNVirtualProtectEx = function(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flNewProtect: DWORD; var lpflOldProtect: DWORD): BOOL; stdcall;
var FNVirtualProtectEx: TFNVirtualProtectEx;
function VirtualProtectEx(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flNewProtect: DWORD; var lpflOldProtect: DWORD): BOOL; stdcall; begin Result := False; if not Assigned(FNVirtualProtectEx) then FNVirtualProtectEx := TFNVirtualProtectEx( GetProcAddress(GetModuleHandle(kernel32), 'VirtualProtectEx')); if not Assigned(FNVirtualProtectEx) then SetLastError(ERROR_CALL_NOT_IMPLEMENTED) else Result := FNVirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect); end;
type TFNZwUnmapViewOfSection = function(ProcessHandle: HANDLE; BaseAddress: PVOID): NTSTATUS; stdcall;
var FNZwUnmapViewOfSection: TFNZwUnmapViewOfSection;
function ZwUnmapViewOfSection(ProcessHandle: HANDLE; BaseAddress: PVOID): NTSTATUS; stdcall; const STATUS_NOT_IMPLEMENTED = NTSTATUS($C0000002); begin if not Assigned(FNZwUnmapViewOfSection) then FNZwUnmapViewOfSection := TFNZwUnmapViewOfSection( GetProcAddress(GetModuleHandle(ntdll), 'ZwUnmapViewOfSection')); if not Assigned(FNZwUnmapViewOfSection) then Result := STATUS_NOT_IMPLEMENTED else Result := FNZwUnmapViewOfSection(ProcessHandle, BaseAddress); end;
end. |
Jetzt sag mir doch mal bitte, was das Programm macht. :wink:
hansa - Mi 02.07.03 13:59
haha, ätsch Aya *fg*, erwischt :!:
@Luckie:
Natürlich belasten die Kommentare nicht die EXE, aber ich habe ein Programm, das paßt haargenau ungezippt auf eine Diskette. Wäre in jeder Unit solch ein Header drin, dann wärs rum mit 1 Diskette.
Außerdem war doch die Frage nach Prozeduren, oder ?? Bei den Units könnte man das schon reinschreiben, warum nicht? Für Luckie der viele Quelltexte veröffentlicht macht das schon Sinn. Im Team natürlich auch, aber nur, wenn jeder "seine eigene" Unit baut.
Ja, und die GEexperts, wo sind die? Die sind bei mir plötzlich weg. Wo sind die denn nur? *grübel* Muß suchen. :shock:
Delete - Mi 02.07.03 14:08
Desweiteren Aya, wird dir jeder professionelle Softwareentwickler sagen wie wichtig Kommentare sind. Man soll es nicht übertreiben, aber da wo es nötig ist, sollten uf keinen Fall welche fehlen.
Stell dir vor obiger Verfassen von dem Quellcode würde kündigen. Und jetzt kommt der Chef an und sagt dir: "OK. Dann bauen sie mir noch mal das und das ein und kucken sie mal warum eine AV kommt, wenn man das und das macht." Dann bist du erstmal eine Woche damit beschäftigt rauszufinden was da überhaupt wo passiert.
Obiger Code ist noch sehr kurz. Aber stell dir vor die hätten Word ohne Kommentare programmiert. Oder OpenSource Software für Linux ohne Kommentare, ein Ding der Unmöglichkeit.
mimi - Mi 02.07.03 14:11
@Lucki
deshalb sollte man den qullcode auch mit kometraen fühlen da man sonst sich nach 10 jahren nicht mehr im qullcode zurecht findet :(
aber mal schauen ob aya den code lesese kann *warte ungeduldig*:)
Aya - Mi 02.07.03 14:48
Hi,
also.. erstmal: Nein ich kann dir im moment nicht sagen was das Programm macht, weil:
Ich an der Arbeit bin und mein Chef das nich gern sehen würde *g*
Aber ok.. heute abend schau ich's mir mal an, allerdings sage ich gleich das es schwer wird. Denn wenn man einen Code bekommt den man verbessern soll, oder woraus man was lernen soll, weiß man was dieser macht und brauch sich nur darum kümmern WIE er es macht.
Und da besteht ein ziemlich großer unterschied.
Aber mal schaun, heute abend wenn ich daheim bin (Fahre btw heute abend wieder heim nach Kassel), schau ich's mir mal an ;)
Au'revoir,
Aya~
Tino - Mi 02.07.03 14:50
mimi hat folgendes geschrieben: |
deshalb sollte man den qullcode auch mit kometraen fühlen da man sonst sich nach 10 jahren nicht mehr im qullcode zurecht findet :( |
Wenn du 10 Jahre lang den Sourcecode nicht angefasst hast kannst du ihn dann so wie so wegschmeisen und neu programmieren.
Gruß
Tino
Aya - Mi 02.07.03 14:57
huhu nochmal,
hab eben dochmal kurz drübergeguckt... auf den allerersten blick würde ich sagen das ding startet eine EXE (welche wohl in der RES Datei ist) in einem eigenen Process... aber kann auch total daneben liegen :P
Au'revoir,
Aya~
Delete - Mi 02.07.03 15:04
Hm, Nico war doch gar nicht online. :roll:
Popov - Mi 02.07.03 15:07
Eigentlich war die Frage hier wie ein Kommentarkopf einer Prozedur aussehen soll. Irgendiwie wurde das hier zu der Frage ob Kommentare den Quellcode unübersichtlich machen.
Naja, irgendwie kann ich das nachvollziehen. Jede zweite Zeile ein Kommentar, daß macht den Code schwerer lesbar. Nicht wegen der Kommentare, sondern weil die Kommentare die schnelle Lesbarkeit ein wenig behindern. Allerdings sah ich mal vor ca. zwei Jahre zufällig ein Code und da hat mir die Art der Kommentierung sehr gefallen. Seite dem mache ich es (fast) immer so.
Zuerst mal die normale Art der Kommentierung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| try Can.Handle := GetWindowDC(GetDesktopWindow); Bmp.Width := Screen.Width; Bmp.Height := Screen.Height; Rec := Rect(0, 0, Screen.Width, Screen.Height); Bmp.Canvas.CopyRect(Rec, Can, Rec); ... |
Hier die die ich benutze. Es ist nur eine Kleinigkeit, aber plötzlich stört der Kommentar bei dem Lesen nicht. Der Kommentar ist einfach um vier bis sechs Zeichen eingerückt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| try Can.Handle := GetWindowDC(GetDesktopWindow); Bmp.Width := Screen.Width; Bmp.Height := Screen.Height; Rec := Rect(0, 0, Screen.Width, Screen.Height); Bmp.Canvas.CopyRect(Rec, Can, Rec); ... |
Ich finde, daß es so besser lesbar ist. Wenn man will, dann ignorieren die Augen die Kommentare.
Das war jetzt so ein kleiner Hinweis nebenbei.
Aya - Mi 02.07.03 15:11
Luckie hat folgendes geschrieben: |
Hm, Nico war doch gar nicht online. :roll: |
Heißt das, dass ich richtig gelegen habe?
Popov - Mi 02.07.03 15:17
Tino hat folgendes geschrieben: |
Wenn du 10 Jahre lang den Sourcecode nicht angefasst hast kannst du ihn dann so wie so wegschmeisen und neu programmieren. |
Nicht unbedingt. Vor einigen Jahren war ich bei einer Weiterbildung mit einem Programmierer, der diese plötzlich abgebrochen hat, weil er ein super Angebot bekommen hat. Bei der Jahr 2000 Umstellung mußten plötzlich etliche Programme umgestellt werden. Und etlich davon waren in Cobold. Die Programme waren inzwischen so alt, daß es kaum noch Leute gab die diese Sprache noch programmierten.
Wie man sieht, wird nach 10 Jahren nicht automatisch alles neu programmiert. Es laufen Programme die noch älter sind.
Popov - Mi 02.07.03 15:23
Aya hat folgendes geschrieben: |
... auf den allerersten blick würde ich sagen das ding startet eine EXE (welche wohl in der RES Datei ist) in einem eigenen Process... |
und
Luckie hat folgendes geschrieben: |
... Delphi-Quelltext 1: 2: 3:
| ... LoadResource(0, FindResource(0, 'Image', 'EXE'))); ... | ... |
Nanana, wir werden da doch nicht pfuschen und aus einer Zeile den Sinn erraten ;)
Aya - Mi 02.07.03 15:28
Öhm.... ich hab mir schon den kompletten Code angeschaut.
das mit dem LoadResource war das was mich am meisten verwirrt hat, da ich absolut keinen sinn daran sehe wieso das ding "Image" heißt.. ;)
hansa - Mi 02.07.03 17:42
@Aya: soll das eventuell ein Rätsel werden?
Aya - Mi 02.07.03 17:53
hansa hat folgendes geschrieben: |
@Aya: soll das eventuell ein Rätsel werden? |
mh? Nein, wieso??
Delete - Mi 02.07.03 18:48
Ja, er extrahier aus der Resosurce eine Exe und führt sie aus, ohne sie auf die Festplatte zu schreiben.
Und Image hießt auf deutsch Abbild. Wenn du eine Anwendung startetst wird ein Abbild von der Exe in den Speicher geladen und dann spricht man von einem Image.
Aya - Mi 02.07.03 20:17
*grinst fröhlich*
Aber ok, dann lasst uns nun mal wieder zum Thema zurückkommen, welche Proceduren Header ihr verwendet :)
Au'revoir,
Aya~
mimi - Mi 02.07.03 20:59
jetzt sieht man ganz gut, das kommetrae ganz nützlich sein könnten:)
aber solche rate spiele könnten wir eingetnlich öffter machen oder ?
Aya - Mi 02.07.03 21:33
mimi hat folgendes geschrieben: |
jetzt sieht man ganz gut, das kommetrae ganz nützlich sein könnten:)
aber solche rate spiele könnten wir eingetnlich öffter machen oder ? |
Und ich sage es gern nochmal.. ich hab da nich wild drauf losgeraten! Ich bin den Code zeile für zeile durchgegangen, hab in der OH nachgeguckt was TProcessInformation (welches z.B. in der Hilfe nur im WinSDK unter PROCESS_INFORMATION zu finden ist) ist etc und hab mir dann meinen Teil dazu gedacht was das ding macht.
Da is nix dran rumgeraten oder sonstwas (oder hast du erraten was die Procedure macht, nur weil da in ner Resource ne EXE drin is?! bzw da nichmal sicher stand das es ne EXE is, sondern nur das die Resource so heißt. Image hätte genausogut nen Bild in dem abschnitt EXE sein können, nur hätte dann der kram NtHeadern etc nichmehr logisch zusammengepasst).
Au'revoir,
Aya~
PS: Und ich bleibe dabei, das ich überladene ProcedurenKommentare sinnlos finde... zummindest für mich ;)
mimi - Mi 02.07.03 22:03
Zitat: |
PS: Und ich bleibe dabei, das ich überladene ProcedurenKommentare sinnlos finde... zummindest für mich
|
aber mit kometraen ist es einfacher zu lesen, und man muss nicht immer in der oh nachschaeun was jetzt der und der befehl macht:)
Aya - Mi 02.07.03 22:11
mimi hat folgendes geschrieben: |
Zitat: |
PS: Und ich bleibe dabei, das ich überladene ProcedurenKommentare sinnlos finde... zummindest für mich
|
aber mit kometraen ist es einfacher zu lesen, und man muss nicht immer in der oh nachschaeun was jetzt der und der befehl macht:) |
Wenn man ihn nicht kennt, und den Code für etwas eigenes verwenden will, oder z.B. einen Fehler finden soll, muß (!!) man das immer tun.. (Ich meine jetzt in der OH nachschauen was der Befehl macht)
Popov - Mi 02.07.03 23:04
Das ganze geht irgendwie in die falsche Richtung. Das sollte jetzt kein Übereden-Thread für Kommentare werden. Wer Kommentare nicht will, der soll es sein lassen. Spätestens, wenn man bei einem alten Programm, an dem man lange Zeit gearbeitet, nach einem Jahr nicht mehr durchblickt, spätestens dann usw.
Ansonsten sehe ich bis jetzt, daß bis auf Luckie und mich (hin und wieder) kaum einer Kommentarköpfe benutzt. Also, ich hab mit mehr gerechnet. Gibt es hier keine Berufsprogrammierer? Da kann mir keine erzählen, daß man sich in einer Firma Kommentarköpfe sparrt. Aber wenn's so ist.
Ich wollte eigentlich nur paar professionelle Köpfe sehen, da ich mir meinen selbst entwickelt habe und immer wieder erweitern muß. Ich such mal im Internet.
Aya - Mi 02.07.03 23:12
Popov hat folgendes geschrieben: |
Gibt es hier keine Berufsprogrammierer? Da kann mir keine erzählen, daß man sich in einer Firma Kommentarköpfe sparrt. Aber wenn's so ist. |
Doch doch, ich programmiere Beruflich :)
Aber wie schon gesagt, ich benutze auch hier kaum Kommentare (bzw halt nur da wo es wirklich sinnvoll ist).
Und obwohl mein Chef selber Informatik Studiert hat, aber keinen einzigen Delphi/C++ oder sonstwas befehl kann (er kann nur die Theorie), hat er keine großen probleme meine SourceCodes zu verstehen (OHNE Kommentare). Und wenn er es kann, kann es ein anderer Programmierer mit sicherheit ;)
Au'revoir,
Aya~
PS: Aber ok, ich bin hier nu ma still.. hab meine Meinung ja gesagt und will net zuviel in's OffTopic.
tommie-lie - Mi 02.07.03 23:17
Auch wenn ich nicht beruflich programmiere (wie sollte ich auch? *lol*):
Ich benutze auch Kommentare für meine Prozeduren. Bis vor kurzem hat sich das Design von Projekt zu Projekt verändert, jetzt wird er automatisch mit GExperts eingefügt und sieht so aus:
Ist eine Prozedur wirklich von jemand anderem als mir, wird das dazunotiert, ansonsten steht mein Copyright im Unitheader, und dann ist davon auszugehen das der Inhalt auch von mir ist.
hansa - Do 03.07.03 12:34
Hi,
ich muß mich nochmals zu Wort melden. Wegen der Kommentare. In einem Programm mußte ich 1 :!: Zeile ändern, nur eine einzige!.
Um das irgendwann noch nachvollziehen zu können, habe ich eine halbe Din A 4 Seite Kommentar an der Stelle in den Quelltext geschrieben.
Tja, so kanns auch gehen. :mrgreen:
mimi - Do 03.07.03 13:32
mir ist gerade ihn den sin gekommen, einfach mal meine tsokubahn klasse hier zu posten, weil ich denke, so änlich sollte es schon aussehen. oder ?:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:
| TSokubahn = class GLXImageList:TGLXImageList; GLXFont1: TGLXFont; Map:array of array of TMap; Tasten:array[0..6] of Byte; Keys:array[0..256] of Boolean; Undos:array of TUndo; UndoIndex:Integer; IniFile:String; StartPositionen:String; ZielIndex:Integer; Player:TPlayer;
DialogText:String; strCaption:String; strText:String; DrawDialog:Boolean; DialogTyp:Integer; DialogKey:Integer; private
IS_FPS:Boolean; GameSound:TSound; MapX:Integer; MapY:Integer; MapS:Integer; procedure ClearMap; procedure SetPlayerPos(NewX, NewY:Integer); procedure MoveKiste(NewX, NewY,OldX, OldY,DirX, dirY:Integer); procedure LoadKey; procedure KeyCheck; procedure SetUndoPos; procedure DrawText(Str : string; x,y,s,i:Integer; color,color1:TColor); procedure setMapSize(aMapX, aMapY,aMapS: Integer); function KisteOnZiel:Integer; function GetObjektCount(Typ:Integer):Integer; function PlayerRandomPos(Pos1:String):TPoint; function ShowMyDialog(aCaption, aDialogText:String; aDialogTyp:Integer):Integer;
public GLXDraw:TGLXDraw; FPS:Integer; constructor create(GXLDraw:TGLXDraw;GLXDraw2:TGLXDraw); procedure CreateRandomMap; procedure DrawGame; procedure LoadFileMap(pFileName,PlayerName:String); procedure InputKey(Key:Word; off:Boolean); end; |
Aya - Do 03.07.03 14:10
Hi,
@Mimi: Nich falsch verstehen, aber solche kommentare sind in meinen Augen der Horror... *grinst fies*
Ich finde da sind so dermaßen viele überflüssige Kommentare drin... ai ai ai.... *g*
Ausserdem finde ich bei der Art immer nervig, das wenn ich in ner Zeile was schreibe und an's Ende will um z.B. nen vergessenes Semikolon zu machen.. dann drücke ich auf "Ende".. und schwupp bin ich am ende des kommentars und darf erstmal mühevoll mit den Pfeiltaste an die richtige stelle springen... ;)
Au'revoir,
Aya~
Delete - Do 03.07.03 14:13
Da ist wirklich viel Überflüssiges drin.
mimi - Do 03.07.03 15:05
@Aya
das mit dem semikolen mache ich anders:
einfach strg + pfeiltasten:) und fertig.
gut ich gebe zu das da viel sinloses drin ist, aber dafür sollte es auch ein anfänger verstehen oder ?
aber ich schreibe die kometrae nur in den classen definiationen hin im qullcode wird du selten auf kometrae stoßen.)
Popov - Do 03.07.03 16:51
Aya hat folgendes geschrieben: |
... und an's Ende will um z.B. nen vergessenes Semikolon zu machen... |
Um ehrlich zu sein, kann ich mich nicht mehr drann erinnern wann ich das letzte mal ein Semikolon vergessen habe. Es passiert eher, daß ich in einem Basic Programm Semikolons setzte. Aber in einem Pascal Programm passiert mir das inzwischen nicht mehr. Inzwischen ist das ein Instinkt.
Zu dem Beispiel von mimi - also ich finde nicht, daß es zuviele Kommentare sind. Zugegeben, es ist ein sehr gut dokumentierter Code und ich schätze, daß es auch Bereiche gibt die nicht so gut dokummentiert sind, aber seien wir doch mal ehrlich - in diesem Code blickt jeder sofort durch. Auch der, der nicht weißt wozu das Programm gut ist, weißt sofort wozu die Prozeduren und Variablen sind. Ein gut gewählter Name kann nie so gut sein wie ein Satz, der den Sinn beschreibt.
mimi - Do 03.07.03 17:46
dann erkläre mal wozu die procedruen und funktionen gut sind:)
wie gesagt, ich mache das nur in den deklationen von den Proc und Funktionen.....
ich vergesse ehrer und Klammer auf bzw. zu das ist mein eingetliches problem. das ich nie weiß wo die klammer zu hin muss
Aya - Do 03.07.03 17:48
Popov hat folgendes geschrieben: |
Ein gut gewählter Name kann nie so gut sein wie ein Satz, der den Sinn beschreibt. |
und was is an:
besser als an:
Delphi-Quelltext
1:
| procedure LandkarteLaden; |
??? ;)
Au'revoir,
Aya~
PS: Das is aber doch wohl übertrieben:
Delphi-Quelltext
1:
| procedure LandkarteLaden; |
Popov - Do 03.07.03 23:01
mimi hat folgendes geschrieben: |
dann erkläre mal wozu die procedruen und funktionen gut sind:) |
Ich verstehe den Sinn der Frage nicht, bzw. wieso die Frage von dir kommt.
@Aya
Was besser ist,
procedure Map; //Lädt die Landkarte
oder
procedure LandkarteLaden;
werde ich nicht beantworten. Ich hab hier die Frage nicht gestellt um zu diskutieren ob man es machen muß. In meiner Firma muß ich, zumindest bei einigen Projekten, alle Programme aufs genauste dokumentieren. Ich kann alle Prozeduren, Funktionen und Variablen in einem extra Dokument auflisten und genau beschreiben oder ich mach das direkt im Code. Ich mach das zwar auch nicht immer, aber wenn's im Pflichtenheft steht, dann mach ich es mir am einfachsten. Und ein Kommentarkopf ist einfacher als ein extra Dokument. Aber um ehrlich zu sein, so mache ich Kopfbeschreibungen auch in privaten Programmen. Zwar nicht bei allen, aber zumindes bei den wichtigen.
Nur habe keine feste und standarisierte Form eines Prozedurkopfes. Bei jedem Projekt hab ich es bis jetzt anders gemacht. Deshalb war meine Frage weniger als Diskusionsfrage gedacht, als Erfahrungsaustausch. Da ich dachte, daß mehr Programmierer ihre Prozeduren dokumentieren, wollte ich nachfrage wie die es machen.
Aber um auf dich zurückzukommen, Aya.
Aya hat folgendes geschrieben: |
Ich meine jetzt in der OH nachschauen was der Befehl macht ... |
Aya hat folgendes geschrieben: |
... hab in der OH nachgeguckt ... |
Du guckst in der OH-Dokumentation nach was die Funktion macht? Willst du etwa behaupten, daß die Prozeduren und Funktionen von Delphi nicht selbsterklärende Namen haben? :twisted: (ich weiß, das war jetzt fies) :twisted:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!