Guten Abend RetroTown Mit diesem Thread möchte ich einen Guide veröffentlichen welcher euch allen helfen soll übersichtlicheren und effizienteren Code zu schreiben. Solltet ihr ein Thema haben was euch interessiert aber hier nicht angesprochen wird, lasst es mich als Antwort wissen und ich werde ein Kapital davon aufstellen und im Inhaltsverzeichnis verlinken! Vorschläge, Verbesserungen und Ideen sind erwünscht Im Moment sind es noch wenige Kapitel, es ist vorgesehen dass dieser Thread mit der Zeit wächst und von der Moderation unterstützt wird. Viel Spaß beim lesen, diskutieren und Feedback abgeben Vergisst nicht, habt ihr weitere Beispiele zu einem Kapital in einer anderen Sprache dann lasst es mich via Antwort wissen. Der Thread wird wahrscheinlich mehrfach umstrukturiert.
Inhaltsverzeichnis
- Copyright & Lizenzen
- Übersicht von Variablen
- Functions & Native Strings
-
Low Level I/O & Insights
- Architecture
- Threading
- Socket I/O
-
High Level Insights
- ~ Coming soon ~
1. Copyright & Lizenzen
Wenn du dich andauernd fragst wie du am besten in der neuen leeren Datei anfangen sollst, dann bist du beim Thema Copyright & Lizenz genau richtig. Stellen wir uns vor du willst einen seriösen Code veröffentlichen, z.B. um dein Können bei einer IT-Firma zu beweisen, so ist es wichtig ein Copyright zu setzen, falls du möchtest auch eine Lizenz wie BSD-2/3, Apache oder GPL anhängen. Dadurch machst du nicht nur den Eindruck dass der Code den du schreibst dein Können zeigen soll, sondern nebenbei zeigt es auch von Stil und gewisser Erfahrung in der Open-Source Welt.
Ein einfaches Copyright setzt du eigentlich schon so wie unten angedeutet:
Falls du dich für eine Lizenz entschieden hast, sei es mal die BSD-3 Klausel Lizenz als Beispiel, fügst du sie nicht anders wie oben ein:
Nachdem du dein Copyright oder gewählte Lizenz eingefügt hast, lässt du am besten 3. Zeilenbrüche aus, um die Lesbarkeit zu verbessern
2. Übersicht von Variablen
Deklariere Variablen am besten in den ersten Zeilen der Funktion, definiere sie niemals Kreuz und Quer, das gibt sonst ein Variablesalat Variablesalate werden die Lesbarkeit deines Codes erschweren, in einer Kooperation mit einem Team kann das negative folgen haben. Egal ob PHP, C, Javascript oder C++, vermeidet überall Code wie
Sondern deklariert, bzw. definiert die Variablen zuerst am "Kopf" der Funktion,
Es ist wichtig dass die Variablen am Kopf der Funktion deklariert werden, bzw. definiert je nach Sprache, da es die Lesbarkeit unterstützt. Außerdem erhältst du auch eine bessere Übersicht über die Aufgabe der Funktion, ob es sich um eine mathematische Berechnung oder nur um eine Ver- oder Entschlüsselung einer Nachricht handelt. Man sollte zuerst alle nötigen Variablen mit deren zugehörigen Typ deklarieren, dann erst die Tasks schreiben nach dem dies getan wurde, dadurch hast du die Variablen allesamt auch auf einem Blick
Salat Beispiel:
Die Instandhaltung oder Weiterentwicklung solch eines Salats ist recht schwierig, man muss überall den Array Index bearbeiten falls man z.B. $get['username'] in $get['user_name'] überarbeiten möchte. Deswegen lohnt es sich die Variablen am Kopf der Funktion zu deklarieren, siehe Beispiel drunter.
Übersichtlich:
Wenn man nun einen Array Index überarbeiten möchte muss man die Änderung nur noch am Kopf der Funktion übernehmen Schon hat man sich mehrere Strg+Fs $get[index] gespart
3. Functions & Native Strings
Was Funktionen sind sollte dir bekannt sein. Jeder kennt sie und hat mit Sicherheit schon einige geschrieben. Bei großen Funktionen ist es wichtig sie in kleineren, sogenannten helper-functions, aufzuteilen, damit verbesserst du nicht nur die Lesbarkeit deines Codes, sondern auch die Instandhaltung. Gebe den Funktionen einen angemessenen Namen welcher z.B. die Aufgabe der Funktion beschreibt. Der Zweck hierbei ist eine art Kommunikation zwischen Leser und Code aufzubauen, Lesbarkeit ist neben Effizienz absolut wichtig. Vermeide unnötige Parameter, halte Funktionen kurz und knapp, verbanne unnötige Operationen.
Wenn du im Low-Level Bereich programmierst, verlange immer die N bytes via Parameter! Ein klassisches C Beispiel:
Wer Erfahrung hat wird sehen das die Verwendung von strcat sehr gefährlich sein wird! Ein Buffer-Overflow kann hier ausgenutzt werden um Stack Informationen abzurufen oder gar den Instructionpointer zu manipulieren. Der Loop kann das Programm zu einer Termination führen lassen falls das Betriebssystem eingreift, gegeben ein Strack Protector existiert. Zwar hat der frühere Author strcat kurz und knapp gehalten, jedoch in einer negativen Art und Weise. Um sich gegen Buffer-Overflows zu schützen musst du deswegen immer auf Längen und n-bytes achten! Implementieren wir strncat kurz und knapp, a la positiven Art, aka. die sichere Variante von strcat:
Diese variante der Funktion verlangt einen dritten Parameter, welche die maximale Anzahl der zu anfügenden characters übergibt. Um den Code zu verstehen müssen wir erstmals schauen wie Strings eigentlich aufgebaut sind, dafür habe ich dir diese Grafik herausgesucht:
Was wir hier abgebildet sehen ist ein typischer nativer String mit Platz für 5 Elementen. Du als Neuling siehst hier ein in rot markiertes 6tes Element welches die Terminating Null 0x00 ('\0') beinhaltet. Doch in der Welt der Programmierung wird die 0 immer mit gezählt, bzw. es wird beim Zählen von 0 angefangen. 0, 1, 2, 3, 4, 5!
5 Elemente also. Vielleicht fragst du dich jetzt weshalb die Terminating Null gerade bei Strings so wichtig ist... Ein Computer kann nicht wissen wann der String endet, gäbe es keine Terminating Null würden bekannte Funktionen wie strlen() immer weiter und weiter ins unendliche zählen, quasi ein while(true) loop mit continue; Um das zu verhindern gibt es die Terminating Null, welche festlegt wo der String aufhört.
Neben 0x00 haben wir 4 weitere Elemente die als Unused markiert sind Wollen wir nun den buffer des Strings vollständig nutzen und "Hello" in "Hello You" abändern lassen, so brauchen wir die strncat() Funktionen die wir oben geschrieben haben. Was machen wir denn in strncat() genau?
Wir haben eine Variable namens d, welche ein Pointer ist. Pointer zeigen auf die Adresse der Memory Location in welcher sich der Wert dieser Variable befindet. Würde d also auf Memory Location 0x1000 zeigen, hätten wir solch ein Layout mit je 1 Byte Abstand:
Da wir mit strncat() einen weiteren String an das Ende des zu modifizierenden Strings anfügen wollen, müssen wir also zu Position d 0x1005, sprich *d Element 5.
Bedeutet so viel wie, Loope durch die Werte der Adressen bis die Terminating Null erreicht wurde, das Ende des Strings Übersetzt würde dann
heißen, wenn der Wert von d (*d) nicht 0 ist, dann inkrementiere die Adresse (d) um 1 Byte und prüfe erneut. Falls auf das Ende des Strings getroffen wurde, wird im nächsten Loop Character für Character an das Ende des Strings angefügt und erneut auf 0 geprüft, außerdem wird n dekrementiert um einen Buffer Overflow zu vermeiden Ich denke das nach den oberen Erklärungen die Funktion von strncat() selbst erklärend ist, versucht es!
4. Low Level I/O & Insights
I/O bedeutet Input/Output. Darunter versteht man im deutschen Eingabe und Ausgabe von Daten. Es gibt verschiedene Arten von I/O. Zu den bekanntesten zählen
- Memory I/O
- File I/O
- Socket I/O
- Port I/O
- Piped I/O
Zu den teuersten I/O Operationen zählen das lesen und schreiben von Dateien (Read/Writes). In der Regel hat ein Prozess kein Zugriff auf Dateien, ohne ein syscall, anfragen an den Kernel, kann kein File I/O stattfinden. Die sogenannten syscalls zählen zu den expensive calls, man muss sich also im klaren sein dass mehrfache Verwendung von syscalls zu einem Effizienzdefizit beitragen. Eine Socket Kommunikation ist ebenfalls nichts anderes als das Öffnen, Lesen, Schreiben und Schließen von Dateien auf dem Rechner. Man kann nicht sagen Unix Sockets seien besser als Windows oder POSIX Sockets, am Ende liegt es an deiner Implementierung der Kommunikation zwischen Server und Client(s) ~ Wie du solch eine Kommunikation am besten Implementierst erfährst du natürlich theoretisch, teilweise auch praktisch, in diesem Thread! Doch vorerst lass mich dir die Welt von I/O etwas genauer erläutern um dich auf ein gewissen Standpunkt zu informieren. Um einen Dienst aufzubauen, sei es Web Solutions, Streaming Service oder Social Media Plattform, musst du dir im klaren seien dass du eine riesige Verantwortung trägst gegenüber der Latenz und Qualität. Um die Latenz zu verbessern musst du Server Seitige grundlegende Entscheidungen treffen. Vergiss nicht, die Kommunikation zwischen Server und Client ist I/O, Input & Output - Neben der zur Verfügung stehenden Bandbreite, wird das Dateisystem des Servers eine entscheidende Rolle spielen, die Architektur deiner Anwendungen, alles muss geplant sein.
4.1 Architektur
Die Architektur und Struktur deines Server wird das Basement deines Resultats der Zufriedenheit pflastern. Du musst Planen aus welchen Komponenten du deine Server-Architektur aufbauen möchtest. Entscheide dich für das richtige Betriebssystem, empfehlen kann ich dir eine selbst angepasste Version des FreeBSD Systems. Wie du FreeBSD modifizieren und kompilieren kannst erfährst du auf deren offiziellen Seite! Neben dem Betriebssystem, welches nur ein Stück des Grundgerüsts ist, wird das Dateisystem eine entscheidende Rolle spielen, sei dir bewusst dass es mehrere davon gibt. Nennenswerte sind ZFS, EXT4 und BTRFS. Ohne das zu den Tasks ausgelegte Dateisystem wirst du früh oder später auf die ersten Mängel beim bearbeiten von Anfragen stoßen, falls du Streams anbietest wird sich das negativ auf das Buffering auslegen. Zu den besten Implementierungen von Streaming Services lohnt es sich auf ein Cache-friendly Dateisystem zu setzen. Das Internet bietet Webserver wie IIS8, NGINX und H2O an, gerne könnt ihr auch selbst einen Webserver schreiben. Das bringt den Vorteil dass man nicht auf Patchs angewiesen ist, verfügt bessere Kontrolle über Vorgängen und die Applikationen können jeder Zeit ausgebaut, verbessert und weiterentwickelt werden Da der Thread Programming Guide heißt nehme ich an du entscheidest dich für housemade Applications (eigenen Webserver, Content Management System, NoSQL Server, ...).
Es ist wichtig dass man sich eine saubere Ordner Struktur anlegt, du willst sicherlich nicht alleine am Projekt arbeiten wollen und stellst deswegen wahrscheinlich ein kleines Team auf. Einigt euch auf einen Coding Style, schreibt keinen Code der sich vom Geschmack der anderen unterscheidet. Die Lesbarkeit des Projekts ist entscheidend beim weiterentwickeln, solltet ihr trotzdem in Situationen kommen in denen es verständlich nicht geht, Kommentiert die Lines ausführlich!
Tut mir leid Leute, irgendwie gibt es kein "Temporär Speichern", deswegen Poste ich den Thread jetzt schon, er ist aber noch nicht fertig !!! Wenn ihr möchtet könnt ihr ja schon mal Themen die euch interessieren posten, gute Nacht wünsche Ich euch