Ich dachte schon. Ich meine er hat auch irgendwo davon gesprochen als Werkstudent nebenbei wo in der Software Entwicklung zu beginnen. Tut mir leid, falls ich das falsch in Erinnerung habe.
Prinzipiell hast du recht und es sollte uns egal sein, durch diesen Thread ist es mir das aber nicht. Wenn ich mir vorstelle, dass er mein Kollege ist kommt mir das Grauen.
Ach du scheisse ... jetzt bekomme ich Alpträume: Ich werde jetzt bestimmt träumen, dass mein Chef zu mir kommt um mir den neuen Werkstudenten vorzustellen....
Also kann gut sein, dass ich da etwas verpasst habe ... aber die Leistungen hier würden dazu nicht wirklich passen....
Ich dachte schon. Ich meine er hat auch irgendwo davon gesprochen als Werkstudent nebenbei wo in der Software Entwicklung zu beginnen. Tut mir leid, falls ich das falsch in Erinnerung habe.
Prinzipiell hast du recht und es sollte uns egal sein, durch diesen Thread ist es mir das aber nicht. Wenn ich mir vorstelle, dass er mein Kollege ist kommt mir das Grauen.
Ich bin hier nur zur Unterhaltung. Ihre Energie verschwenden hier nur die Leute die dir helfen wollen, da du einfach nichts von den Ratschlägen umsetzen kannst/willst.
Ich bin hier nur zur Unterhaltung. Ihre Energie verschwenden hier nur die Leute die dir helfen wollen, da du einfach nichts von den Ratschlägen umsetzen kannst/willst.
Ich habe es ja bereits erwähnt: Antworten wie z.B.: "Try catch" auf die ausführliche Antwort von @kneitzel sind eine Frechheit gegenüber jenen, die dir hier ihre Hilfe anbieten. Dies ist ja nicht das erste Mal, sondern zieht sich konsequent durch den Thread: Dir gibt jemand eine gute Hilfestellung, deine Antwort ist ein simples "i". Was soll sowas? Das ist einfach an Dreistigkeit nicht zu überbieten. Wenn du genauso kommunizierst wird dich keine Firma je länger als die Probezeit behalten.
Ich habe es ja bereits erwähnt: Antworten wie z.B.: "Try catch" auf die ausführliche Antwort von @kneitzel sind eine Frechheit gegenüber jenen, die dir hier ihre Hilfe anbieten. Dies ist ja nicht das erste Mal, sondern zieht sich konsequent durch den Thread: Dir gibt jemand eine gute Hilfestellung, deine Antwort ist ein simples "i". Was soll sowas? Das ist einfach an Dreistigkeit nicht zu überbieten. Wenn du genauso kommunizierst wird dich keine Firma je länger als die Probezeit behalten.
Solche Antworten sind respektloser. Keiner ist dir böse wenn du nicht sofort antwortest, deine Antwort sollte aber auf das Vorherige eingehen, zeigen, dass du dich damit beschäftigt hast, eine konkrete Frage zu dem stellen was du nicht verstehst oder etwas sein wie "Danke, das hat mir geholfen. Es funktioniert jetzt, das ist der neue Code: //Code einfügen"
Sinnlose Antworten spare dir bitte.
Solche Antworten sind respektloser. Keiner ist dir böse wenn du nicht sofort antwortest, deine Antwort sollte aber auf das Vorherige eingehen, zeigen, dass du dich damit beschäftigt hast, eine konkrete Frage zu dem stellen was du nicht verstehst oder etwas sein wie "Danke, das hat mir geholfen. Es funktioniert jetzt, das ist der neue Code: //Code einfügen"
Sinnlose Antworten spare dir bitte.
dann hast du meinen Standpunkt gehört dann hoffe ich dass wir auf einen Nenner kommen werden.
Es war nicht meine Absicht
Ich werde sem
Kollegen schreiben direkt wenn ich daran sitze.
Aber nicht wegen der Aufgabe aondern wie man Debuggen.
Außerdem sollte alles hier nicht persönlich genommen werden!
Wenn ich respektlos wäre hätte ich längst beleidigt....
Ich habe weiter oben ganz konkret eine Codezeile zitiert, in der ein Fehler auftritt. Du musst diese Zeile umschreiben, auch das wurde hier schon sehr oft erwähnt. Nur so kannst du genau feststellen, wo der Fehler liegt.
Übrigens muss das Debuggen nicht extra gelehrt werden, da jeder, der schon mal programmiert hat, weiß, dass die Fehlersuche eine wichtige Arbeit dabei ist. Das Debuggen usw. lernt man mit dem Programmieren parallel.
Hmm ... noch keine 500 Posts und schon Ende? Das ist jetzt aber sehr enttäuschend. Aber das Thema ist damit wohl für den TE erledigt und es ist Zeit, ein paar Dinge bezüglich Clean Code zu bringen.
Also paar Dinge sind tabu in Clean Code. Ein wichtiger Punkt ist etwas, das oft als "Magic Numbers" bezeichnet wird (Etwas irritierend, denn es betrifft nicht nur Zahlen):
Direkt im Code-Verlauf darf es keine Konstanten geben. Konstanten müssen immer in entsprechenden Konstrukten definiert werden.
Hier gibt es dann mehrere Arten von Lösungen:
a) Verwendung von Konstanten. Also statt ein Byte Array mit Größe 1024 zu definieren, definiert man an eine Konstante BUFFER_SIZE oder so und erstellt dann ein Byte Array it der Größe BUFFER_SIZE. Das hat den Vorteil, dass der Code lesbar ist. Und ein Refactoring ist einfacher, denn mal angenommen, das soll von 1024 auf 4096 erhöht werden. Nun muss man nach allen 1024 suchen, entscheiden, ob das eine Stelle ist, die geändert werden muss um dann ggf. die Stelle zu ändern oder nicht... Mit Konstanten ändert man dann einfach die Konstante an einer Stelle.
b) Oft gibt es Konstanten, die zusammen gehören. Ein Beispiel dafür ist z.B. die Liste der Befehle, die möglich sind. ('f','b','l' und 'r') oder aber auch die Feldinhalte die möglich sind ('#', 'v', '<', ....)
Hier kann man dann eine Enum verwenden. Der große Vorteil dabei ist dann auch, dass man damit teilweise switch Statements / if ketten und so vermeiden kann. Hintergrund ist dabei, dass man Enum Werten auch weitere Werte geben kann. Also bei den Beispielen bedeutet das, dass man jedem Befehl (FORWARD, LEFT, RIGHT, ...) auch die Befehl-Zeichen mitgeben kann ('f', 'l', 'r', ...) Und dann kann man z.B. zu einem Befehl einfach das Befehlszeichen bekommen oder eben in einer kleinen Schleife vom Befehlszeichen zu dem Befehl kommen...
c) Der letzte wichtige Part sind Ausgaben. Diese gehören auch nicht in den Code. Statt dessen sollten Ausgaben immer aus einer Ressource Datei kommen. Dies hat den großen Vorteil, dass die Ausgabe schnell angepasst werden kann. So können die Ressource-Dateien z.B. an einen Übersetzer gehen, der von Software Entwicklung keine Ahnung haben muss. Und Übersetzungen sollten sich ohne komplette Neuübersetzung einpflegen lassen.
Speziell zu b) sähe der Code für Befehle und FeldInhalte dann z.B. so aus:
Java:
package rover;/**
* Commands the rover understands
*/publicenumCommand{/**
* Move rover forward.
*/FORWARD('f'),/**
* Move rover backwards.
*/BACKWARD('b'),/**
* Turn rover right.
*/TURN_RIGHT('r'),/**
* Turn rover left.
*/TURN_LEFT('l');/**
* Command character used when submitting a command.
*/privatechar commandChar;/**
* Create a new instance of Command.
* @param commandChar Character to use to transfer the command.
*/Command(char commandChar){this.commandChar = commandChar;}/**
* Gets the command character ot the command.
* @return Character used to transfer command.
*/publicchargetCommandChar(){return commandChar;}/**
* Get a Command instance from a command character.
* @param commandChar Command character
* @return Command instance.
* @throws IllegalArgumentException if character is not a valid command chaarcter.
*/publicstaticCommandfromChar(char commandChar){for(Command command:Command.values()){if(command.getCommandChar()== commandChar)return command;}thrownewIllegalArgumentException("commandChar");}}
Und das kann dann auch entsprechend genutzt werden. Also um Befehle aus den Zeichen zu bekommen, könnte man in der main Methode folgenden Code verwenden:
Dann sollte eine Aufgabe in Java Objektorientiert aufgebaut werden. Und bei der Aufgabe sieht man direkt mehrere Dinge.
Zum einen die Position, welche einfach über ein int Array abgebildet wurde. Also ideal, um es als Klasse abzubilden:
Java:
package rover;/**
* Position inside the map
*/publicclassPosition{privateint x;privateint y;publicPosition(int x,int y){this.x = x;this.y = y;}publicbooleanvalidate(int maxX,int maxY){return(maxX > x)&&(maxY > y)&&(x>=0)&&(y>=0);}publicintgetX(){return x;}publicintgetY(){return y;}@OverridepublicinthashCode(){return x +(y<<16);}@Overridepublicbooleanequals(Object obj){// Check if same referenceif(obj ==this)returntrue;if(obj instanceofPosition){Position other =(Position) obj;return
other.x == x &&
other.y == y;}returnfalse;}}
Das die Position auch als Key verwendet werden soll, ist natürlich klar, dass ein equals (und damit natürlich auch der hashCode) überschrieben werden muss. Ein Verändern eines Keys ist aber kritisch, so auch der Hashcode verwendet wird, daher wurden Setter explizit weggelassen. (Das Thema hatte ich ja schon vorab angesprochen....)
Und dann hat man natürlich eine Karte. Die kann man dann auch mit entsprechenden Funktionen implementieren. Hier kann man überlegen, ob man generics verwenden möchte, aber dann läuft es schnell auf eine schon vorhandene Klasse heraus. Somit kann man überlegen, ob diese Klasse notwendig ist. Aber ohne Generics ist das eine recht schöne Kapselung:
Java:
package rover;importjava.util.LinkedHashMap;/**
* ItemMap for rover solution
*/publicclassItemMap{privateint height;privateint width;privateLinkedHashMap<Position,FieldContent> map;publicItemMap(int width,int height){
map =newLinkedHashMap<>();this.height = height;this.width = width;}publicFieldContentget(Position position){// Get result.FieldContent result = map.get(position);// return EMPTY when field is empty.if(result ==null)returnFieldContent.EMPTY;// return resultreturn result;}publicvoidput(Position position,FieldContent content){// Validateif(!position.validate(width, height))thrownewIllegalArgumentException("position");
map.put(position, content);}publicFieldContentremove(Position position){// Validateif(!position.validate(width, height))thrownewIllegalArgumentException("position");return map.remove(position);}publicvoidmove(Position oldPosition,Position newPosition){// Validateif(!oldPosition.validate(width, height))thrownewIllegalArgumentException("oldPosition");if(!newPosition.validate(width, height))thrownewIllegalArgumentException("newPosition");FieldContent content =remove(oldPosition);if(content !=null)put(newPosition, content);}publicbooleanisBlocked(Position position){returnget(position)!=FieldContent.EMPTY;}}
Dabei ist ein Punkt wichtig, ob den man in der Aufgabe auch mehrfach gestolpert ist: Rückgabe von NULL Werten! Das ist etwas, das leicht Probleme mit sich bringt. Es gibt hier ein paar Ansätze bei Java mit Annotations zu arbeiten (@null, @NotNull), aber andere Sprachen gehen hier noch deutlich weiter (z.B. Kotlin). Aber man kann hier sauber bleiben und z.B. bei get auf eine Rückgabe von null verzichten und da dann statt dessen ein EMPTY zurück geben.
Und dann hat man schon eine Grundlage für leserlichen Code, den man direkt nutzen kann. Die Funktionen könnten dann z.B. in der Form aufgebaut sein:
Java:
/**
* Initialization of map.
*/publicstaticvoidnewInit(){
map =newItemMap(mapWidth, mapHeight);
roverPosition =newPosition(
mapWidth /2,
mapHeight /2);for(int x =0; x < mapWidth; x++){for(int y =0; y < mapHeight; y++){Position p =newPosition(x, y);if(r.nextDouble()<0.25&&!(roverPosition.getX()== x && roverPosition.getY()== y))
map.put(p,FieldContent.BLOCKED);}}
map.put(roverPosition,FieldContent.ROVER_NORTH);}/**
* Turn right from a given direction.
* @param direction Current direction as FieldContent
* @return New direction as FieldContent
*/publicstaticFieldContentturnRight(FieldContent direction){switch(direction){case ROVER_NORTH:returnFieldContent.ROVER_EAST;case ROVER_EAST:returnFieldContent.ROVER_SOUTH;case ROVER_SOUTH:returnFieldContent.ROVER_WEST;case ROVER_WEST:returnFieldContent.ROVER_NORTH;default:thrownewIllegalArgumentException("direction");}}/**
* Turn left from a given direction.
* @param direction Current direction as FieldContent
* @return New direction as FieldContent
*/publicstaticFieldContentturnLeft(FieldContent direction){switch(direction){case ROVER_NORTH:returnFieldContent.ROVER_WEST;case ROVER_EAST:returnFieldContent.ROVER_NORTH;case ROVER_SOUTH:returnFieldContent.ROVER_EAST;case ROVER_WEST:returnFieldContent.ROVER_SOUTH;default:thrownewIllegalArgumentException("direction");}}/**
* Moves an object that is at the given position. Must be a rover at the location.
*
* Checks that the map is not left and does not move on not empty fields.
* @param position Position to check.
* @param forward Should the rover move forward (true) or backwards (false)
* @return New Position or ld position if new position was invalid (blocked, outside map)
*/publicstaticPositionmove(Position position,boolean forward){// Get new position when moving.Position newPosition =getNewPosition(position, forward);// Validate new positionif(!newPosition.validate(mapWidth, mapHeight))return position;// Check if new position is blockedif(map.isBlocked(newPosition))return position;// Do move
map.move(position, newPosition);// Return new positionreturn newPosition;}/**
* Gets a new position when moving into a direction.
* @param position Current position
* @param forward Moving forward or backwards
* @return new Position.
*/privatestaticPositiongetNewPosition(Position position,boolean forward){FieldContent direction = map.get(position);switch(direction){case ROVER_NORTH:returnnewPosition(
position.getX(),
forward ? position.getY()-1: position.getY()+1);case ROVER_EAST:returnnewPosition(
forward ? position.getX()+1: position.getX()-1,
position.getY());case ROVER_SOUTH:returnnewPosition(
position.getX(),
forward ? position.getY()+1: position.getY()-1);case ROVER_WEST:returnnewPosition(
forward ? position.getX()-1: position.getX()+1,
position.getY());default:thrownewIllegalArgumentException("direction");}}/**
* Handles a given command.
* @param command to handle.
*/publicstaticvoidhandleCommand(Command command){FieldContent roverDirection = map.get(roverPosition);switch(command){case FORWARD:
roverPosition =move(roverPosition,true);break;case BACKWARD:
roverPosition =move(roverPosition,false);break;case TURN_LEFT:
roverDirection =turnLeft(roverDirection);
map.put(roverPosition, roverDirection);break;case TURN_RIGHT:
roverDirection =turnRight(roverDirection);
map.put(roverPosition, roverDirection);break;default:System.out.println("Unknown command: "+ command);}}/**
* Print out the map.
*/publicstaticvoidprintMap(){for(int y =0; y < mapHeight; y++){for(int x =0; x < mapWidth; x++){FieldContent content = map.get(newPosition(x, y));System.out.print(content.getPrintChar());}System.out.println();}for(int x =0; x < mapWidth; x++){System.out.print("=");}System.out.println();}
Generell sollte man alle Funktionen und so dokumentieren. JavaDoc ist da die Lösung, die in erster Linie verwendet wird.
Bei dem letzten Code sieht man das relativ gut. Bei den vorherigen Code-Postings sind diese auch noch weggelassen.
Und natürlich sollten so Funktionen nicht statisch sein. Statt dessen sollte es auch noch eine Klasse geben, von der dann eine Instanz erstellt wird. Aus der init Funktion wird dann ein Konstruktor und so ....
Und noch eine Anmerkung: In meinem Code hatte ich den alten Code parallel in der Klasse behalten. Daher so Namen wie "newInit". Das ist natürlich auch schlecht. Code, den man nicht braucht, löscht man. Eine Source Verwaltung wie git sorgt dafür, dass man an den alten Stand auch wieder ran kommen kann. Und dann sind die Namen natürlich auch sauber und es gibt nur ein "init" oder so.
@kneitzel ich habe mir jetzt nicht alles im Detail durchgelesen (bin mir aber sicher, dass das passt) und wollte mal meine Anerkennung für die ganze Arbeit zum Ausdruck bringen. Das kann man einfach nicht unkommentiert stehen lassen.
Bleibt noch eine Frage: was machen wir jetzt mit den verbleibenden 37 Kommentaren?
@kneitzel ich habe mir jetzt nicht alles im Detail durchgelesen (bin mir aber sicher, dass das passt) und wollte mal meine Anerkennung für die ganze Arbeit zum Ausdruck bringen. Das kann man einfach nicht unkommentiert stehen lassen.
Bleibt noch eine Frage: was machen wir jetzt mit den verbleibenden 37 Kommentaren?
Also wir könnten den Thread für ein neues Thema entführen ...
Also mein Vorschlag für ein Thema wäre:
Da ein unter 18 Jähriger bestimmt nicht die Geduld hat, den Thread bis hier hin zu lesen, haben wir einen effektiven Jugendschutz.
So in den nächsten paar Antworten alle zustimmen, haben wir evtl. noch Platz für paar nicht Jugendfreie Witze?
Ich habe da jetzt vor kurzem erst einen Witz gehört bezüglich Punktrechnung vor Strichrechnung
Also wir könnten den Thread für ein neues Thema entführen ...
Also mein Vorschlag für ein Thema wäre:
Da ein unter 18 Jähriger bestimmt nicht die Geduld hat, den Thread bis hier hin zu lesen, haben wir einen effektiven Jugendschutz.
So in den nächsten paar Antworten alle zustimmen, haben wir evtl. noch Platz für paar nicht Jugendfreie Witze?
Ich habe da jetzt vor kurzem erst einen Witz gehört bezüglich Punktrechnung vor Strichrechnung
Du bekommst ein Bußgeld wegen zu schnellem Fahren .... 3 Punkte und 250€.
Und vom letzten Besuch eines Freudenhauses kommt auch noch eine Rechnung mit der Post: ebenfalls 250€!
kann mir einer helfen ahahahich, ich weiß nicht wie ich die if bedinung machen soll also ich muss wissen was frößer ist aber bei generischen klassen ist das bischen komplizierter.
Java:
publicvoidsorting(){ListNode current = head;ListNode currentvor = current.next;for(int i=1; i <size(); i++){for(int j =0; i <size(); i++){if(current.value.compareTo(currentvor.value)<0){}}}}
das buggt auch nicht merh aber leider fehlt mir den programmier ansatz wie ich die beiden listnodes vergleichen kann mit der compare methode.
kann mir einer helfen ahahahich, ich weiß nicht wie ich die if bedinung machen soll also ich muss wissen was frößer ist aber bei generischen klassen ist das bischen komplizierter.
Java:
publicvoidsorting(){ListNode current = head;ListNode currentvor = current.next;for(int i=1; i <size(); i++){for(int j =0; i <size(); i++){if(current.value.compareTo(currentvor.value)<0){}}}}
das buggt auch nicht merh aber leider fehlt mir den programmier ansatz wie ich die beiden listnodes vergleichen kann mit der compare methode.
Hmm, den Witz habe ich jetzt nicht verstanden. Aber evtl. kannst Du den Witz ja für mich kurz erläutern.
Ansonsten hast Du ja einen Thread, in dem das Thema behandelt wird. Und da hattest Du ja auch schon eine erste Erwiederung bekommen.... Und nein, auch mit Generics wird das nicht wirklich komplizierter.
Ja, wo Du Recht hast, hast Du durchaus Recht. Peinlich wird es dadurch, dass ich es am Computer geschrieben habe und der eine automatische Rechtschreibkontrolle drin hat. Da ist das Wort sogar rot unterstrichen....
Natürliche Zahlen ist halt auch nicht eindeutig! Gehört da die 0 mit dazu, oder eben nicht?
Es gibt hier zwei Definitionen, einmal mit 0 und einmal ohne. Früher war es immer ohne 0, da war es also eindeutig. Ein Hr. Fermat oder Hr. Euler wird damit also keine Schmerzen gehabt haben. Aber gerade wir Informatiker haben es ja mit dem Herrn Neumann ... und dann gehört die Null auf jeden Fall mit dazu.....
Es gibt hier zwei Definitionen, einmal mit 0 und einmal ohne. Früher war es immer ohne 0, da war es also eindeutig. Ein Hr. Fermat oder Hr. Euler wird damit also keine Schmerzen gehabt haben. Aber gerade wir Informatiker haben es ja mit dem Herrn Neumann ... und dann gehört die Null auf jeden Fall mit dazu.....
Ich will euch ja nicht den Spaß verderben, aber es is nicht abhängig von Mathe- oder Informatik-Vorlesungen, sondern von der Präferenz des Dozierenden, ob und wenn ja wie 0 dabei ist.
Ich will euch ja nicht den Spaß verderben, aber es is nicht abhängig von Mathe- oder Informatik-Vorlesungen, sondern von der Präferenz des Dozierenden, ob und wenn ja wie 0 dabei ist.