Unhandled exception error bei Arrays umleiten?
Übersicht![](/themes/Standard/arrow.png)
![](/themes/Standard/arrow.png)
sinjinBetreff: Unhandled exception error bei Arrays umleiten? |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Gleich zum Beispiel. Ich habe ein Array von 10. Nun kann es vorkommen das ich z.B. das 11. Element abfrage, was ja logischerweise zur Exception führt. Kann ich es so machen das mein Programm dafür einfach 0 wiedergibt ohne dafür eine Abfrage für jede einzelne Stelle im Programm zu schreiben? | ||
ohaz |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Sorry dass ich deine Frage jetzt nicht direkt beantworte, aber du hast innerhalb von wenigen Tagen zwei Fragen dieser Art gestellt. Vor kurzem wolltest du, dass bei x/0 = 0 rauskommt, jetzt, dass arrays dir 0 zurück geben, wenn du out of bounds Zugriffe machst.
Beides deutet krass darauf hin, dass du vor hast, super schlechten Code zu schreiben. Niemand wird den Code jemals verstehen, er wird extrem schwer zu warten sein und vermutlich tausend Bugs beinhalten. Als jemand der jetzt schon viele Jahre (professionell) programmiert, lass mich dir einen Tipp geben: Mach es ordentlich. Bau deine Abfragen ein, oder kümmere dich konzeptionell schon darum, dass du nicht an falsche Stellen im Array zugreifst. Mach deine Divisionen ordentlich. Dein Zukunfts-Ich wird dir danken. Und falls du noch jung bist und in Zukunft als Programmierer arbeiten willst, halte dich erst recht an ordentlichen Code-Stil. Dich wird jede Firma raus schmeißen, wenn sie sieht, dass du solche Sachen machst. |
||
sinjin |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Was heisst "solche" Sachen, wenn es geht ist das ein unbenutztes Feature für mich und keine zufällige Erscheinung. Und wenn es geht warum sollte ich es doppelt programmieren und auf irdendwelche Boundaries achten? Wenn mein Programm evtl erwartet, das 0 rauskommt, dann habe ich mir wohl dabei was gedacht, bzw ich würde sowas mit Absicht machen, nicht weil ich ein solch schlechter Programmierer bin ![]() |
||
ohaz |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Der wichtige Unterschied ist hier, dass du versuchst es global für Arrayzugriffe umzustellen. Niemand ist böse, wenn du an den elementaren Stellen die boundary Checks machst. Was aber definitiv falsch ist, ist es für viele Stellen automatisch zu machen. Das sorgt, wie gesagt, für Code, den man später nicht mehr verstehen kann. Und kein Code ist schlechter als der, der unverständlich ist. Im Allgemeinen wird sehr oft auf "unbenutzte Features" verzichtet, wenn sie zu schlechtem Code führen. Bestes Beispiel dafür ist "goto". Oder Pointerarithmetik. Oder casts auf (void *). | ||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Es ist und bleibt einfach unsauberer, fehleranfälliger und daher zu vermeidender Codestil. Was dir bei deiner ersten Anfrage auch schon so beantwortet wurde. | ||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem, weswegen man sowas nicht machen sollte, ist, dass du nachher nicht mehr unterscheiden kannst, ob die 0 im Array war oder du aus dem Array rausgerutscht bist.
Im Endeffekt nimmst du einen Zustand, der vorher out-of-band ausgegeben wurde (über die Exception) und gibst ihr stattdessen einen in-band Wert. Das gleiche Problem gab es z.B. in BlitzBasic wenn man einen String auf Integer gecastet hat. War der String nämlich nicht als Zahl parsbar (z.B. weil nur Buchstaben oder gar nichts drin war), dann hat die Funktion 0 zurück gegeben, statt irgendeiner Art Fehler. Das heißt, wenn ich den User Folgendes frage: Code: [AUSKLAPPEN] Gib die Zahl des Menüpunktes ein, um zu tun was hinter der Zahl steht: 0: Lösche die ganze Festplatte 1: Fahre normal fort Und der User bleibt an der Taste neben der 1 hängen und gibt "^1" ein, dann interpretiert das Programm es als 0 und löscht die Festplatte. In vielen Sprachen gibt es bestimmte Befehle mit Defaultwerten. So z.B. bei Maps in Python. Dort schaut es dann so aus: Code: [AUSKLAPPEN] map = {"a": 1} map["b"] # -> Wirft eine Exception weil der Key "b" nicht in der Map ist. map.get("b", 0) # -> Returned eine 0, da "b" nicht in der Map ist und deswegen 0 als Defaultwert zurückgegeben wird. Das ist hat Anwendungsfälle, ist aber absichtlich nicht der Default-Fall, weil man es nur verwenden soll, wenn man sich im Klaren ist, was das tut. Sonst macht man Code, der Fehler produziert, die man nie wieder findet. In deinem Fall kannst du dir locker einfach so eine Funktion schreiben, die den Default-Wert returned wenn der Index nicht im Array ist. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
sinjin |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Sowas ähnliches ist mir mal passiert, aber das war FDISK.EXE? War früher noch bei XP dabei...da wusste man nicht welche Partition er meint...allerdings war das kein Array/Null Problem, er hat mir einfach den Laufwerksbuchstaben nicht genannt...schwupp war alles weg. Ich mache manchmal, nicht regelmäßig, natürlich nen Backup ![]() ![]() ![]() |
||
sinjin |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Und auch, lieber OHAZ, nach 10-15 verschaltelungen, hab glaube kein Code wo es vor kommt, aber fast..dann möchte man ein GOTO haben!!!! weil ohne wird es nämlich wirklich unansehnlich!Code: [AUSKLAPPEN] while a local b% while b local c% while c local d%... ;du siehst es schon oder? ein einfacher GOTO "end"...(ein Return ist manchmal nicht die Lösung weil man nach Sachen sucht die zwar verschaltelt sind, aber dann doch fragt: ob if a=0 ist)... ist manchmal schon sinnvoll! auch wie ich mal sagte, der assembler kennt NUR goto's! (jumps) Da gibt es KEINE verschachtlungen wie du es meinst. Es ist Sinnvoll, in Sachen die man machen möchte!! wend wend wend wend |
||
sinjin |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich sehe was ihr meint...aber Programm-Technisch....wieviele "Indents brauche ich? lol wie gesagt, es kommt kaum vor in meinem Code...wenn, dann würde ich es selber verschachteln:
Code: [AUSKLAPPEN] local a% while a<aha.length local b% while b<aha.sub.length local d% while d<aha[a].sub[b].length ;go out!...schon bin ich raus... der rest ist falsch! if c[aha[b][d]]=not like expected... d:+1 wend if c[aha[b][d]]=not like expected... go out! b:+1 wend a:+1 wend :out 'solche sachen sind in asslembler sogar einfacher :D oder können einfacher sein! weil ma da nur einen loop hat, hast du da auch, aber ich finde es schwierig es zu sehen print "nope, its not the case" sry, dann sind es halt nur meine augen lool, nach 2 verschachtelungen, verstehst du deinen eigenen code nicht mehr...es ist sinnvoll! in machen situationen Ich habe sowas wie: global test%[][]...schupp die wupp, schon kann es probleme geben. das handelt man noch aber danach.. sense wenn du aha%[][][][] hast...dann ist es echt besser assembler zu beherrschen! halt je nachdem was man erreichen will. und es ist dann auch angebracht nen GOTO oder jmp to end (wie gesagt, der assembler macht eh jumps die ganze zeit!) zu benutzen...finde ich. Ein GOTO ist ähnlich wie nen CONTINUE oder? lol |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Die Antwort hier bezieht sich sowohl auf deine Posts hier als auch auf die im anderen Thread, da sich beides ein bisschen annähert, hat keinen Sinn die Diskussion auf beide Threads aufgeteilt weiter zu führen ![]() Das Ganze kommt, wie fast alles in der modernen Programmierung, auf die Softwarekrise zurück. Ich bin mir nicht sicher ob die dir was sagt, aber das ist eines der Grundthemen, das beinflusst, wie wir Programmiersprachen, Programmbibliotheken und Frameworks bauen. Die Softwarekrise war der Punkt, an dem die Kosten für Software zum ersten Mal die Kosten der Hardware überstiegen haben. Je nach Geräteklasse (Mainframe, Großcomputer, Kleincomputer, Handheld, ...) hat sich das Thema zwischen den 1960ern und 1980ern abgespielt. Mit anderen Worten kann man sagen, dass die Softwarekrise der Punkt war, wo die Hardware so stark und kompliziert geworden ist, dass es sich nicht mehr auszahlt, (performancemäßig) absolut perfekt zu programmieren. Das war dann auch der Punkt, an dem für den Großteil der Entwicklung nicht mehr auf perfekten, handoptimierten Assemblercode zurückgegriffen wurde, sondern man lieber Hochsprachen verwendet hat, die Performance zugunsten von besserer Programmierbarkeit geopfert haben. Und zwar deswegen, weil die Zeit des Programmierers plötzlich teurer war, als die Rechenzeit des Computers. Man muss sich das vor Augen halten, dass zu Beginn der Computerzeit ein Rechner oft von mehreren Dutzend Programmierern gefüttert wurde, und die Rechenzeit des Computers trotzdem teurer war als das Gehalt des Programmierers. Inzwischen kann man sich für das Monatsgehalt eines Programmierers locker ein bis zwei echt tolle Server leisten. Speicher und Rechnenleistung sind billig und werden immer billiger, während Programmierer eher teurer werden und ihre Effizienz nicht annähernd so stark steigt, wie die Rechenleistung der Computer. Jetzt ist es auch noch so, dass beim Programmieren Tippen nur einen Bruchteil der Arbeitszeit einnimmt. Im Durchschnitt erzeugt ein professioneller Programmierer rund 50 Zeilen Programmcode pro Tag. Bei neuen und kleinen Projekten sind es mehr Zeilen, aber je älter und größer das Projekt wird, desto weniger Zeilen schafft man pro Tag. Ein wichtiger Grund dafür ist, dass man sich in Code, den man länger nicht angefasst hat (oder der gar nicht von einem Selbst ist, sondern von einem Teamkollegen), erst einarbeiten muss um ihn passend verändern zu können. Ein anderer Grund ist, dass es zwar sehr leicht ist, einen Fehler in 20 Zeilen Code zu finden, aber je größer das Projekt wird, desto weniger offensichtlich sind die Fehlerquellen. Bei einem mittelgroßen Projekt mir und 50k Zeilen Code muss man schnell mal einen Fehler über 5 Files und 10 Funktionen hinweg verfolgen. Und das ist nicht selten, das passiert ganz oft. Da hat man z.B. im Frontend einen Fehler, der über das REST-Interface vom Backend übermittelt wurde. Von dort aus verfolgt man den Fehler über ein paar Business Logic-Funktionen zur Datenbank und findet, dass dort ein Wert im falschen Format abgespeichert wurde. Also schaut man von wo der Wert abgespeichert wurde und findet heraus, wieder über den Umweg von mehreren Business Logic-Funktionen und das REST-Backend, dass der Fehler eigentlich von einem falsch abgespeicherten Wert im Frontend kommt. Und schon hat man für zwei Zeichen an Änderung mehrere Stunden verschmissen. Unter diesen Prämissen (Tippen nimmt nur einen Bruchteil der Arbeitszeit ein, planen, suchen und verstehen benötigt viel mehr Arbeitszeit) werden also die meisten Programmiersprachen, die im professionellen Umfeld verwendet werden, designt. Man nimmt also etwas verbosität (viel Text zum Tippen) in Kauf um dafür den Code so lesbar und verständlich zu machen wie es geht. Man wirft lieber harte Exceptions damit Programmierer die Fehler leichter finden, als dass man Fehler versteckt und einfach weiter macht. GOTO so wie das Verstecken von Fehlern (Array Index Out Of Bounds, Null-Pointer, Division by Zero, ...) sind zwar nette Kleinigkeiten um einem tippen zu sparen, aber sie haben das fatale Problem, dass sie den Code weniger offensichtlich machen und seine Funktionsweise dem Programmierer verstecken. Das heißt, sie sorgen dafür, dass das Programmieren in der einfachen Phase (dem Anfang des Projekts) etwas einfacher wird, dafür wird es in der schwierigen Phase (wenn das Projekt größer wird) ein Graus. Das originale BlitzBasic ist voll von solchen Sachen. Deswegen eignet es sich sehr gut für winzige Projekte (quasi was auch immer man einem BCC abgeben würde) ist aber völlig ungeeignet für alles Größere. Deswegen gab es ja auch selbst zur Hochzeit von BB nur eine Handvoll professioneller Spiele die in BB gemacht wurden, obwohl die Sprache eigentlich irrsinnig populär war. Sie eignet sich einfach nicht für große Projekte. An dieser Stelle würde ich noch gern auf das "Zen of Python" verweisen: Zitat: Beautiful is better than ugly.
Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! Besonders hervorgehoben:
Das heißt, es ist besser genau zu sagen was du willst, als den Computer raten zu lassen.
Besser mehr Text der eindeutig ist, als viel Bedeuting in zu wenige Zeichen zu packen.
Unless explicitly silenced. Jeder Fehler sollte dem Programmierer vom Programm bekannt gemacht werden. Denn nur wenn der Programmierer von dem Fehler weiß kann er entscheiden, was er damit machen will.
Wie zuvor, wenn unklar ist was gefordert ist, soll das Programm nicht raten, sondern den Programmierer fragen (in Form z.B. einer Exception), so dass der Programmierer entscheiden kann, was zu tun ist. Natürlich hindert dich keiner daran, in einem Stil zu programmieren, in dem du Fehler versteckst. Die Idee war gerade um das Jahr 2000 sehr verbreitet und viele Programmiersprachen haben immer noch Reste dieser Ideologie eingebaut, sehr zum Leidwesen der Programmierer die damit arbeiten müssen. Sprachen die viel in die Richtung haben sind z.B. Visual Basic, JavaScript und HTML. HTML ist hier vielleicht sogar eines der schlimmsten Beispiele. HTML z.B. macht immer weiter, egal was. Closing Tags sind größtenteils optional, die richtigen Tag-Typen muss man auch nicht verwenden und auch sonst kann man auch Code reinfüttern, der mit HTML eigentlich gar nichts zutun hat. Aber statt dass sich der Parser dann aufregt, macht er stattdessen einfach irgendwas. Und je nach Parser/Render Engine ist das Ergebnis dann teils was ganz was Anderes. Wir haben es in der Arbeit schon öfters gehabt, dass die Seite in Chrome und Firefox völlig anders ausgeschaut hat, und der Grund dann war, dass ein Tippfehler am komplett anderen Ende des Source-Files den Parser geschmissen hat, und er trotzdem irgendwie weiter gemacht hat. Allerdings ist die Industrie zum größten Teil (also in quasi allem Neuentwickelten) von diesem Stil weggegangen. Weil es Code einfach unwartbar macht. That said, wenn du nur vor hast, Programme mit <100 Zeilen zu machen, an denen nur du arbeitest, dann wird es dich wahrscheinlich nicht so arg in den Hintern beißen. Ich hoffe, das macht jetzt mehr Sinn, warum dir alle sagen, dass es eine schlechte Idee ist ![]() PS: Du arbeitest nicht in meinem Team und ich muss mit deinem Code nichts zu tun haben, also arbeite wie du willst, erwarte nur nicht, dass man es für eine gute Idee hält^^ |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
sinjin |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Also so Jung bin ich auch nicht, bin zwar in den 70ern geboren, und hab nie gearbeitet(auch kein Geld verdient...hab persönliche Probleme...dafür hab ich schon bevor es DOS gab, programmiert), hab mir alles von A-Z selber beigebracht, Internet habe ich auch erst seit 2011. Dafür bin ich, ich beurteile mich ungern selbst, ich glaube dafür bin ich nicht schlecht. Ich war immer der Typ der Funktionen und Prozeduren schreibt, und die will man ja schnell und sauber haben. Wie andere damit, oder ob andere was damit anfangen können, weiß ich nicht. Was du sagst verstehe ich, aber bin nicht einverstanden, wie kann man einfach alles "hinklatschen", "der Prozessor ist schon schnell genug", gut, verstehe ich auch, Geld halt bzw Arbeit. Ich will meinen Code so schnell wie möglich haben, auch wenns nicht nötig ist ![]() Ein Nebenwort: Ich hoffe alle sind und bleiben gesund! Und auch, ich will hier ja keinen Stress machen, auch wenn es manchmal so ausieht...Sonst würde ich ja nicht Fragen, sondern Stress machen haha ![]() Mein Hauptpunkt ist halt: Warum ein dickes Fenster ausgeben, und das halbe Betriebssystem aktivieren, wenn man selber bestimmen kann was passiert nach einer Exception? Und, ich hatte es schon mal geschrieben, ich glaube kaum, das eine AI bzw ein Compiler besser ist als ein Mensch! Zumindest auf nem PC kann ich ja so spezifisch sein, ohne etwas durch sich selbst zu teilen (weil das andere Prozessoren machen, bzw den Platz brauchen würden). Jep, ich debugge manchmal, da sehe ich Code der totalen Non-Sense ergibt! Da soll der Compiler besser sein als ich???? Sry, der Mensch ist und bleibt noch länger besser als JEDER Compiler und auch besser als JEDE AI!!!!! Ich weiß, und verstehe ja auch, das einige Programme etwas beweisen können, aber ja nur weil ein Mensch der AI etwas beigebracht hat, den Code, nicht eine Frage, das kann Alexa dir auch nicht beantworten. Z.B. das Karten-Problem, das man nur 4 Farben braucht um die Grenzen auf jeder Karte, Land oder andere 2D-Karten, abzugrenzen. Das hat das Programm gemacht, nicht Alexa lol Wenn es so wäre, wo ist das Problem das Alexa nicht programmiert? Ist halt so! Wenn es kein Mensch weiß, weiß es Alexa auch nicht. Ist kein vernünftiger Grund, logisch, aber versuche mal Alexa etwas beizubringen! Im Moment will ich alles über Audio wissen, das sieht so aus: Code: [AUSKLAPPEN] function audiomaxvol(s:taudiosample)
local chn%=channelspersample[s.format] local bits%=bitspersample[s.format] shr 4 local mx# local a%=s.length*chn while a a:-chn for local c%=0 until chn if bits then local b%=short ptr(s.samples)[a+c] if (b&$8000) then b=$ffff-b 'abs if (mx<b) then mx=b else local b%=s.samples[a+c] if (b&$80) then b=$ff-b 'abs if (mx<b) then mx=b endif next wend if bits then mx=$7fff/mx else mx=$7f/mx a=s.length*chn while a a:-chn for local c%=0 until chn if bits then local b%=short ptr(s.samples)[a+c] if (b&$8000) then b=-$ffff+b b:*mx short ptr(s.samples)[a+c]=b else local b%=s.samples[a+c] if (b&$80) then b=-$ff+b b:*mx s.samples[a+c]=b endif next wend endfunction function audiosine(s:taudiosample) local chn%=channelspersample[s.format] local bits%=bitspersample[s.format] shr 4 local mx# local a%=s.length*chn while a a:-chn for local c%=0 until chn if bits then local b%=sin(360.0/200*a)*$7fff '440 hz short ptr(s.samples)[a+c]=b else local b%=sin(360.0/200*a)*$7f '440 hz s.samples[a+c]=b endif next wend endfunction function audiozigzag(s:taudiosample) local chn%=channelspersample[s.format] local bits%=bitspersample[s.format] shr 4 local mx# local a%=s.length*chn while a a:-chn for local c%=0 until chn if bits then local b%=(pingpongmod(a+50,100)-50)*$ffff/100 '440 hz short ptr(s.samples)[a+c]=b else local b%=(pingpongmod(a+50,100)-50)*$ff/100 '440 hz s.samples[a+c]=b endif next wend endfunction function converthertz:taudiosample(s:taudiosample,hz#,del%=false) if (hz=s.hertz) then return s local factor#=hz/s.hertz local nl%=s.length*factor local chn%=channelspersample[s.format] local bits%=bitspersample[s.format] shr 4 local t:taudiosample=taudiosample.create(nl,hz,s.format) local a%,a1%=nl*chn',ao%=1,bo%[chn] while (a<a1) local a2%=int(a/factor)&$fffffffe'(int(a/factor)|$1)-1 for local c%=0 until chn if bits then local b%=short ptr(s.samples)[a2+c] short ptr(t.samples)[a+c]=b'+(bo[c]-b)'*factor else local b%=s.samples[a2+c] t.samples[a+c]=b endif next a:+chn wend if del and s.capacity then memfree s.samples return t endfunction Bin am überlegen wie ich es bei "converthertz" am Besten interpoliere... Ich habe viele Baustellen im Code, ist normal oder? Kein Compiler macht das für dich ![]() Um noch einmal auf deinen ersten Satz zu kommen DAK, ich bin halt mehr der Function/Prozeduren-Typ, und die will ich so schnell und so effizient wie möglich haben. Ist das ein Problem? lol Eine Software-Krise oder eine "Singularität" sozusagen, wo der Computer schneller wird als der Mensch...wo ist das Problem so effizient wie möglich zu bleiben? ![]() |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich glaub, du hast mich ein wenig missverstanden.
Erstmal, ich diskutiere hier mit dir, weil es Spaß macht, also keine Sorge ![]() Du sagst, der Computer ist nicht besser als ein Mensch. Und in manchen Belangen stimmt das, in anderen nicht. Ein Computer ist, allem voran, ein Werkzeug. Das heißt, ohne Mensch ist er nichts (da ihn wer bauen und programmieren muss), aber er wurde geschaffen, nur weil er manche Sachen besser macht als ein Mensch. Wir brauchen ja z.B. auch nicht diskutieren, dass ein Schraubenzieher Schrauben wesentlich besser drehen kann, als ein Mensch mit bloßen Fingern. Macht das den Schraubenzieher besser als den Mensch? In einer spezifischen Aufgabe ja. Im Gegensatz zum Schraubenzieher kann der Computer mehr oder weniger selbstständig Aufgaben erledigen, nachdem er programmiert und gestartet wurde, damit braucht er im Betrieb nicht immer einen Menschen dabei. Computer sind z.B. wesentlich besser als Menschen, wenn es um Rechengeschwindigkeit geht. Berechnungen, für die früher ein Fußballstadion voller Menschen nötig war, macht jetzt ein Handy. Gute Wettervorhersagen gibt es z.B. nur weil es Computer gibt. Auch sind sie besser, Listen von tausenden Details exakt abzuarbeiten, egal wie langweilig und repetitiv die Arbeit ist. Im Gegenteil, langweilig und repetitiv können sie viel besser. Deswegen hat man in der professionellen Softwareentwicklung auch z.B. automatisierte Tests. Die ersetzen die manuellen Tests nicht, da sie nur das testen, woran schon mal wer gedacht hat, aber das machen sie viel besser. Wir haben bei unseren Projekten in der Arbeit inzwischen recht große Test Suits, die alles mögliche abdecken. Das macht es viel einfacher, zu schauen, ob die aktuelle Änderung was kaputt gemacht hat. Statt dass ein menschlicher Tester tausende Schritte manuell durchgehen muss, macht das der Computer innerhalb von Minuten. Und so muss man den Computer sehen, als ein Werkzeug, nicht als einen Konkurrenten. Und das ist auch, was ich mit der Software-Krise gemeint hab. In den 60ern hat ein Programmierer alles wissen können, was in einem Computer abgeht. Der hat ohne größere Schwierigkeiten jedes Bit im Hauptspeicher manuell setzen können, und das wurde auch regelmäßig so gemacht. Der Programmierer hat auch über jeden einzelnen Bug in der Hardware perfekt bescheid wissen können, und es waren immer noch so wenige und überschaubare Details, dass er damit perfekten Code hat schreiben können. Würde ich bei meinem Laptop den gesamten Hauptspeicher manuell auch nur mit 0en füllen, und dabei rasante 10 Byte pro Sekunde eintippen könnte, dann wurde es mich über 27 Jahre brauchen. Dazu kommt, dass ich dutzende Schichten zwischen meinem Code und der CPU sind, von denen ich kaum oder keine Implementationsdetails kenne. Wusstest du z.B. dass moderne x86-CPUs gar keine x86-CPUs sind? Stattdessen verwenden die meisten einen custom RISK-Kern, der dann im Microcode einen x86-Emulator laufen lässt, weil das schneller ist. Also selbst wenn du Assembler schreibst, schreibst du nicht mehr den Code der dann auf der CPU rennt. Und das führt dazu, dass z.B. immer wieder Bugs in CPUs gefunden werden, weil die CPUs allein inzwischen um mehrere Größenordungen komplexer sind, als es in den 90ern die ganzen PCs inklusive OS und Software waren. Auf deinem Computer rennt auch nicht ein Betriebssystem, sondern einige. So haben z.B. Intel-Netzwerkkarten ein eigenes auf Minix basieriendes Betriebssystem drauf, dass nichts macht als sich um deine Netzwerkverbindung zu kümmern. Und ja, das heißt, deine Netzwerkkarte hat eine CPU, RAM und Flashspeicher drin. Du schreibst Code: [AUSKLAPPEN] OpenTCPStream()
und stößt damit ein paar tausend Zeilen Code verteilt über mehrere CPUs mit mehreren völlig unterschiedlichen Betriebssystemen an, geschrieben verteilt über Jahrzehnte von mehreren hundert verschiedenen Programmieren die bei einigen völlig unterschiedlichen Firmen gearbeitet haben. Und das Gleiche passiert bei quasi jedem Befehl den du ausführst. Das ist die Software-Krise: Du als Programmierer kannst gar nicht mehr wissen, was alles passiert, wenn du Code schreibst. Aus diesen Umständen hat sich auch die Art, wie wir programmieren, gewandelt. Man ist, zum Beispiel, stark von Mikrooptimierungen weg und zu Algorithmischen Optimierungen hin gegangen. Ein Beispiel dazu: bei einem unserer Projekte hatten wir eine Liste mit mehreren zehntausend Datensätzen, die innerhalb kürzererster Zeit auf einer sehr schwachen Embedded-CPU durchgegangen und änliche zusammengefasst werden mussten. Dazu mussten jeweils zwei Einträge mit einander verglichen werden, ob sie ähnlich genug waren, um zusammengefasst zu werden. Die erste Implementierung ist für jedes Element der Liste jedes andere Element der Liste durchgegangen und hat sie verglichen. Bei 100 Elementen wären das also 100*100=10 000 Vergleiche. Überschaubar. Bei 1 000 Elementen wären das schon 1 000 000 Vergleiche, und bei 10 000 Elementen sind es 100 000 000 Vergleiche. Wie du siehst, gibt es hier ein exponentielles Wachstum. Mit Mikrooptimierungen (Einsparen von unnötigen Befehlen) hätte man das vielleicht um 10-20% schneller machen können. Aber das bringt nicht viel, weil nur ein paar weitere Elemente in der Liste diesen Performance-Boost schon wieder kaputt machen. Also sind wir auf die Idee gekommen, die Liste sortiert zu halten. Ähnliche Einträge waren damit nebeneinander. Man muss also nur mehr die nächsten Paar Einträge nach jedem Eintrag überprüfen, bis man auf einen gleichen stößt. Das waren rund 5 Vergleiche pro Element. Plötztlich waren für 10 000 Elemente nur mehr 50 000 Vergleiche nötig. Eine Verbesserung von 2 000 000%! Das ist die Art von Optimiertung, für die es Menschen braucht, und die nicht einfach ein Computer übernehmen kann. Mikrooptimierungen sind so simpel, dass jeder halbwegs sinnvolle Compiler die eh schon übernimmt. Auf der anderen Seite führen Mikrooptimierungen oft dazu, dass der Code schlechter lesbar und damit schlechter wartbar ist. Ich hab früher auch viel auf Mikrooptimierungen gesetzt. Aber dann hab ich studiert und ein paar Jahre (sind inzwischen auch schon wieder 8 Jahre) als Programmierer gearbeitet. Da kriegt man dann hald einen anderen Blick auf Sachen und lernt, was man sonst nie gelernt hätte. That said, für kleinere Hobbyprojekte, die man nur selber anfasst, da hat man üblicherweise so viel Rechenpower und RAM zur Verfügung im Vergleich zu dem was man braucht, dass es fast wurscht ist, wie man programmiert ![]() |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
Übersicht
![](/themes/Standard/arrow.png)
![](/themes/Standard/arrow.png)
Powered by phpBB © 2001 - 2006, phpBB Group