Projektvorstellung: Minesweeper für die CMD.EXE

Robocopy

Cadet 4th Year
Registriert
Dez. 2021
Beiträge
95
Hallo Freunde!

Ich habe mein erstes, größeres Projekt, die Entwicklung eines Minesweeper-Klons, fertiggestellt.

Projekt im Browser ausführen

Hier könnte man es direkt ausführen:

Minesweeper-Klon über Repl.it im Browser ausführen

Kurze Projektvorstellung

Ich bin ein Programmier-Anfänger, der nach langer Zeit des Lernens und mit-Code-Herumspielens mal ein erstes, kleines Projekt realisieren und so richtig profi-mäßig mit Git und Github, und Lizenz etc. ausstatten wollte.

Und so ist mein erster, eigener, hunderttausendster Minesweeper-Klon für die Kommandozeile entstanden - wobei er aber in mancherlei Hinsicht doch Alleinstellungsmerkmale hat. Denn ich musste feststellen, dass die meisten CMD-Klone schnell hingeklatscht wurden, und bei kleinen Fehleingaben mit Hardcrashes reagieren und über keine Highscore-Verwaltung verfügen, keine Schwierigkeitsmodi haben etc.

Ich dagegen habe versucht, ein bisschen auf Form-Vollendung und auch auf Code-Qualität zu achten, möchte jetzt als Anfänger aber auch nicht zu sehr auf den Putz hauen in dem ich behaupte, es sei mir Großartiges gelungen.

Meine Fragen an euch

Da dies zu meinen ersten Projekten gehört, die über Hello-Word und Primzahlenberechnung leicht hinausgehen, habe ich ein paar kleine Fragen:

  • Schätzt ihr mein Github-Repository als "vernünftig gepflegt" ein? Oder hätte man da etwas schöner machen können?
  • Wie fühlt sich das Programm-Handling für euch an? Ist es okay? Oder sollte man was verbessern?
  • Und die wichtigste Frage: Wie bewertet ihr den Quelltext? Ist er noch arg hässlich, oder schon annehmbar? Was kann man besser machen?

Zur letzten Frage will gesagt sein, dass ich eine eigene, kleine Bibliothek entwickelt habe, die dem Projekt als .jar-Datei beigefügt ist. Im obigen direkt ausführbaren Code-Repl sind aber alle Klassen auf einem Haufen.

Der Vollständigkeit halber also auch nochmal der Link zu meiner Bibo, sofern diese auch begutachtet werden will:

Github LittleLib

Das Github-Repository

Und hier haben wir dann das eigentliche Github-Repository

Minesweeper CMD Github

Ich bin sehr gespannt zu hören, wie ihr mein Projekt bewertet und einschätzt! :-)
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: BeBur
Wurde hier nicht x/y vertauscht? Bei dieser Eingabe hätte ich horizontal 3, vertikal 5 erwartet, also relativ zu den schon aufgedeckten Feldern links unten.
Zusätzlich würde ich die horizontale Nummerierung am unteren Rand bevorzugen, das wäre wohl übersichtlicher bei der Eingabe der Koordinaten.
1640851338263.png


Zu deinen Fragen:
Die Repos wirken dem Projekt entsprechend sauber, keine erzwungen Bürokratie die bei so einem Kleinprojekt nicht notwendig wäre.
Einzig das .jar bei den Source-Files fällt auf: https://github.com/hweinert/Bash-Minesweeper/blob/master/src/LittleLib.jar
Solche Dinge sollten nicht unbedingt im Repository eingecheckt werden. Wenn man anfängt mit größeren Libraries oder Frameworks zu arbeiten, treibt das die Größe sehr schnell in unhandliche Bereiche. Es gibt in der Java-Welt unzählige Tools um solche Dependencies zu managen, die aber nicht unbedingt anfängerfreundlich sind.
Sollte man sich im Sinne der Einfachheit bei so einem Projekt und einer so kleinen Library trotzdem dafür entscheiden es im git-Repo einzuchecken, würde ich es zumindest in ein anderes Directory schieben (libs statt src o.ä.), damit eigener Code und "fremde" Binaries sauber getrennt sind.

Für den Code möchte ich ein Lob aussprechen, insgesamt ist das gut lesbar, funktioniert und sinnvoll aufgebaut. Da du dich ja verbessern möchtest, trotzdem ein paar Tipps/Anregungen zum weiteren Selbststudium:
  • final Keyword, Immutability - Sollten Properties unveränderbar sein, z.B. in der Entry-Klasse, kann dies mit final bestimmt werden. Positiv fällt trotzdem auf, dass nicht blind alle getter und setter auto-generiert wurden.
  • Java Object Serialization: dies wird zum Schreiben der Highscores verwendet. Ich würde wenn möglich die Java Serialization vermeiden und auf robustere Lösungen setzen, sei es ein selbst gebastelter .csv Writer o.ä. oder Standardlösungen wie JSON-Serialisierung mit Libraries wie Gson. Ein Thema mit dem man sich durchaus länger beschäftigen kann...
  • Das Highscore-Handling würde ich generell in ein separates Objekt auslagern, damit kann die Game-Klasse kompakt gehalten werden und sich nur auf eine Aufgabe konzentrieren: den Gameablauf kontrollieren. Das File-Handling, Serialisieren o.ä. kann dann wo anders passieren. Solltest du dann mal die Datenquelle austauschen oder die Serialisierung ändern, muss die Game-Klasse nicht geändert werden.
    Stichwörter zum Nachlesen: SOLID, separation of concerns, und trotz der ganzen theoretischen Designaspekte: KISS!
Natürlich gibt es jetzt je nach Interessen viele Möglichkeiten sich weiterzuentwickeln, auch dazu ein paar Anregungen, weniger zum Programmieren selbst (dafür dürftest du ja bereits Resourcen haben) als zum Rundherum:
  • Unit-Tests: sollte mal professionell entwickelt werden eigentlich unvermeidbar, sehr nützlich und hilft auch beim Softwaredesign
  • Build Tools, Dependency Management: um wie angesprochen Libraries nicht manuell managen zu müssen und die Software unkompliziert bauen zu können. Im Optimalfall lassen sich dann auch die Unittest einfach ausführen, damit bei jedem commit die Tests automatisch ausgeführt werden (Stichwort CI). Bekannt Tools sind in der Java-Welt z.B. Gradle und Maven, aber mit diesen Tools kann man sehr viel Zeit versenken...
Fürs Minesweeper wäre noch eine interaktivere Lösung nett, wo mit den Pfeiltasten eine Position ausgewählt werden kann - dann fällt auch das x/y-Problem weg :)
 
  • Gefällt mir
Reaktionen: Robocopy
Sehr gut für ein erstes Projekt!
Jede Stelle, wo du erklärende Kommentare hast "// display all lines" gehört in eine sprechende eigene Method ausgegliedert.

Die Aufteilung der wichtigen Funktionalitäten ist etwas unübersichtlich. Du hast eine mainLoop Methode die aber gar nicht deine mainloop ist, stattdessen ist die in der Mitte von play versteckt und da ist dann ein Aufruf zu getUserInput, welche aber noch viel mehr macht als das was sie behauptet, nämlich das 'heavy lifting' deiner Spiel-Logik beinhaltet. Du vermischst u.a. dadurch auch Spiel-Logik mit der visuellen Darstellung des Spiels.
 
  • Gefällt mir
Reaktionen: andy_m4, Drexel und Robocopy
Du könntest noch ein Bild einfügen oder ein GIF. Das beschreibt immer ganz gut was das Programm macht
 
  • Gefällt mir
Reaktionen: Robocopy und BeBur
Ganz herzlichen Dank für eure Antworten! Ich habe viele Ratschläge berücksichtigt, und andere, die etwas Mehraufwand erfordern, wie z. B. die Verwendung eines Build-Tools, werde ich in meinen kommenden Projekten berücksichtigen. Da gibts um sowas dann auch eh kein Drum-Herum mehr.

Folgendes habe ich Dank eurer Ratschläge noch verbessern können:
  • Unnötigen Code entfernt (Game.java muss nicht serialisierbar sein)
  • LittleLib.jar in Ordner "libs" ausgelagert und eine Open-Source-Notiz hinzugefügt
  • Bild hinzugefügt und Readme aktualisiert
  • x und y werden jetzt richtig gesetzt
  • Anzahl der Highscore-Einträge vergrößert

Vielen Dank nochmal für eure Unterstützung!
 
  • Gefällt mir
Reaktionen: konkretor
Servus,

zunächst mal das obligatorische "Kudos" für den Mut und die Bereitschaft, den fabrizierten Code nicht nur zu basteln, sondern auch noch anderen zugänglich zu machen. :-)

Da um Review gebeten wurde, hier ein paar Anmerkungen, und ich möchte eingehend gleich aus dem Weg räumen: Ja, ich kreide eher negativ auffallende Dinge an als positive; das soll aber nicht heißen, daß der beanstandete Bockmist auch wirklich "Bockmist" wäre. Wäre er das, dann würde ich mir nicht die Mühe eines Reviews machen. :Daumen:
Außerdem hab ich irgendwie Autocorrect an. Sorry, ich gehe davon aus, daß ein paar Fehler automatisch reimkorrigiert wurden und ich das nicht bemerkt hab vor dem Abschicken. hust

Ich will mich mal zunächst auf die Library beschränken, die (im Normalfall) ja den relevanten Code beinhalten sollte. Je nach Lust und Zeit (immer zuwenig) alles andere eventuell später.

= stopwatch:
Der Code ist schön strukturiert und, sowie ich das auf den ersten Überflieger mitnehme, wurde auch darauf geachtet, nicht unnötig zu duplizieren.

So richtig gefällt mir die null als Initialwert für Start- und Endzeit nicht recht. Aber das kann man sich sicherlich überlegen und jeder beliebige Start(End)wert hat sicherlich das Problem, zumindest potentiell ein "echtes" Ergebnis sein zu wollen.

Start() als Methode fehlt das Exceptionhandling. Wenn ich start() aufrufe und das Ding läuft schon? Keine Möglichkeit, das abzufangen, weil keine Ausnahme generiert wird. this.startTime == null ? Instant.now() : throw new StopwatchStartException() oder dergleichen teilt der aufrufenden Methode mit, daß der Versuch nicht funktioniert hat wie erwartet. Diese aufrufende Methode kann(muß) jene Ausnahme dann behandeln - oder ignorieren, was den bisherigen Programmfluß abbilden würde.

Für Stop() (und alle anderen Methoden) wäre mein impulsiver Vorschlag, dem Objekt Stopwatch eine Eigenschaft bool isRunning zu verpassen, gerne public. Kann aber auch ein Getter sein, der die Prozeßlogik hinter "woher weiß ich ob die Stoppuhr läuft" kapselt. Das macht zB die Methode stop() zu einem simplen isRunning() ? stopTime = instant.now() ? throw new StopWatchNotRunningException(); oder dergleichen und Du mußt nicht immer und überall auf die Werte von Start- und Endzeit prüfen.
Anders gesagt: Du hast hier momentan ein paar unschöne Spuren von prozeduraler Programmierung, wo die Implementierung bekannt sein muß; bei OO ist das anders, da ist oder sollte das alles gekapselt sein und wenn Du wissen willst "läuft die Stoppuhr", dann fragst Du "läuft die Stoppuhr" und gräbst keine Interna aus. Plus auf dem Weg kannst Du die Prozeßlogik komplett über den Haufen werfen und die API bleibt erhalten, grad für Libs ist das wichtig.

Ein Ausnahmemodell wäre natürlich zu entwerfen. Im einfachsten Fall reicht eine simple Klasse StopWatchexception() als Ableitung von Exception mit Angabe der erforderlichen Informationen über den Nachrichtentext. Als abgeleitete Klasse können aber auch eigene Eigenschaften und Konstruktoren definiert werden, je nach Bedarf.

Allgemein in Stopwatch: Versuche (a) Returns ganz zu vermeiden oder (b) wenn das nicht geht, nur ein (1) Return pro Methode zu haben. Ansonsten fällt Dir das beim Review auf die Füße. Es passiert nicht was es soll und dann bist Du gezwungen, alle returns abzufressen. "Besser": Eine "Ergebnisvariable" haben, die dann je nach Bedarf gesetzt wird und die dann am Ende der Methode zurückgegeben wird.
Noch besser: Eine Klasse StopwatchResult erfinden und der Stopwatch-Klasse ein readonly Stopwatchresult result mitgeben.
Dann kannst Du dessen Eigenschaften setzen, (so gut wie) alle returns fallen weg und Du bist ein bißchen implementierungsunabhängiger, weil dann nur noch die Implementierung der Stopwatchresult-Klasse geändert werden muß und die API trotzdem stabil bleibt. Und das Beste, Tonnen Definitionen von getX oder getY oder getZ oder was weiß ich fallen pauschal weg, wenn das StopwatchResult-Objekt das als Methoden oder Eigenschaften bereits einmal implementiert hat. Das vereinfacht die Arbeit mit der Stopwatch auf Frontend-Seite erheblich.


= Tools
Da würde ich gerne mehr zu sagen, komme aber nicht ernsthaft über "while true" hinaus.
Neu implementieren. OHNE Endlosschleife. JAVA kennt Events; nutze sie. Das kommt Dir auch später sehr zugute, wenn Du mehr oder weniger eine Vorstellung von event raising and consuming hast.
Ansonsten wurde ja bereits erwähnt, daß hier womöglich ein bißchen zuviel Programmlogik ins Backend ausgelagert wird.
Plus.... gerade hier fällt mir auf, daß Du versuchst, OO in Prozedur zu pressen. Bitte NICHT machen und, soweit es geht, auch wieder abgewöhnen. Sowas wie, wenn es ein Problem gab: neu versuchen: das ist Programmlogik. Die Library muß hier eine Ausnahme werfen und es der Anwendung überlassen, was diese damit machen will.
Vorsicht auch bei (zu) spezifischen Methodensignaturen und bedenken, daß weitere Signaturen derselben Methode durchaus möglich sind.

Protip: Wenn es um Booleans geht, dann ist in 11 von 10 Fällen ein Großteil des Programmcodes redundant und kann ersatzlos gestrichen werden. True und false als Schlüsselwörter braucht man nur in wenigen Fällen.

Beispiel: If a < b then return true else return false? Blödsinn. Return a < b.
Wenn Du ein Konstrukt hast wie A = 0; if B < C then A = 1
dann ist es meist übersichtlicher (und schneller) einfach A = B < C ? 1 : 0 zu schreiben.

= Entry
Seh ich auf den ersten Blick nichts, steht aber auch nicht viel drin. ;-) Mich persönlich stört der ganze Overhead für die getter, aber gut, ist JAVA.
Den Namen überdenken. Entry ist zu allgemein, wenn du oder irgendwer das verwenden will mit anderen Klassen, wo auch fünf Entry definiert sind, dann wird's interessant. An der Stelle vielleicht HighscoreEntry. Oder sowas.

= Highscorelist
Würde ich persönlich wegwerfen wollen. Sorry. List<Entry> ist der richtige Ansatz, ja. Aber das Ganze ist zu abhängig von Entry.
Highscorelist selber hat mit (einem) Entry nix zu tun, das ist eine leere Liste aus Entries wo dann die einzelnen Entry-Objekte reingeslottet werden können.
Sowas wie "lowestisbest" oder "checkworthy" ist Programmlogik, das hat auf dem HS-Board nix zu suchen. Das ist einfach das Brett. Wie es ausgewertet werden muß, dh. was ich rauslesen will, wenn ich es angucke: Das ist Anwendungssache.

Measurementunit könntest Du als enum definieren. Oder als eigene Klasse. String ist eher schlecht - mit string darf jeder "irgendwas" da hinschreiben und das ist dann eben die Maßeinheit; und wenn Du irgendwann mal hergehen willst und measurementUnit auch verwenden möchtest, dann ist das als String eben aus diesem Grund entweder unmöglich oder erfordert haufenweise switches. Mit Enum hast Du stattdessen klar definierte Werte, die übergeben werden müssen, und dann ist eben MeasurementUnit.KM ein Kilometer, wenn Du das als Maßeinheit brauchen solltest => das erledigt auch gleich "Kimloometer" als mögliche Falscheingabe.



Ansonsten sieht das definitiv gut und vielversprechend aus. Wichtig erachte ich momentan nur, daß Du bedenkst: OO ist OO und Prozedur ist Prozedur; und das eine hat mit dem anderen nichts zu tun.
Und: Wenn meine Funktion insbesondere in einer Bibliothek nicht exakt das tut, was zu erwarten wäre, dann ist eine Ausnahme zu generieren, und zwar so, daß "klar" wird, exakt WAS schiefgegangen ist. Sonst gibt es echte Probleme beim Debugging der abhängigen Anwendung(en). HighscoreList.Restore("/home/ralphs/hsbackup.txt") liefert null oder setzt meine Highscoreliste nicht? Schön, aber warum? Datei nicht da, nicht lesbar, falsches Format, oder Fehler im Programmcode? Keine Ahnung, wenn es keine sinnvollen Ausnahmen gibt, und zur Laufzeit nicht verarbeitbar.
 
  • Gefällt mir
Reaktionen: andy_m4 und Robocopy
RalphS schrieb:
So richtig gefällt mir die null als Initialwert für Start- und Endzeit nicht recht. Aber das kann man sich sicherlich überlegen und jeder beliebige Start(End)wert hat sicherlich das Problem, zumindest potentiell ein "echtes" Ergebnis sein zu wollen.
Lieber null und im schlimmsten Fall eine NPE als Ergebnisse die richtig aussehen es aber nicht sind, weil man mit irgendwelchen defaults rumrechnet nur weil jemand erzählt dass null böse ist.
RalphS schrieb:
Allgemein in Stopwatch: Versuche (a) Returns ganz zu vermeiden oder (b) wenn das nicht geht, nur ein (1) Return pro Methode zu haben.
Das ist meiner Meinung nach absolut Blödsinn. Wird oft verbreitet, gern auch aus dem akademischen Bereich, macht den Code aber oft viel komplizierter als notwendig. Immer situationsbezogen zu entscheiden, wie es lesbarer ist.
RalphS schrieb:
= Entry
Seh ich auf den ersten Blick nichts, steht aber auch nicht viel drin. ;-) Mich persönlich stört der ganze Overhead für die getter, aber gut, ist JAVA.
So sind nun mal POJOs. Wenn man das nicht will, hilft nur auf alle Konventionen verzichten oder weg von Java...
RalphS schrieb:
Den Namen überdenken. Entry ist zu allgemein, wenn du oder irgendwer das verwenden will mit anderen Klassen, wo auch fünf Entry definiert sind, dann wird's interessant. An der Stelle vielleicht HighscoreEntry. Oder sowas.
Stickwort packages, das gibt dem Namen gleich ein wenig Kontext. Nicht jeder Klassenname muss ein Roman sein, nur weils Java ist.


Das zeigt nun auch, dass es in der Softwareentwicklung oft nicht nur die eine richtige Lösung gibt und manche gutgemeinte Tipps für andere eher kontraproduktiv wirken. Zu beachten ist, dass man sich nicht in Detaildiskussionen verläuft, denn damit kann man jeden Fortschritt sehr gut bremsen.
 
  • Gefällt mir
Reaktionen: mental.dIseASe, ###Zaunpfahl###, KitKat::new() und 2 andere
Vielen Dank für die Anregungen!

Ich persönlich glaube, dass die Sprache Java und das OO-Konzept schöne Dinge sind, und verwende auch vorwiegend OO-Konzepte, aber nicht nur. Gewisse Funktionalitäten lassen sich meiner Meinung nach am sinnvollsten prozedural implementieren, was wohl auch die Meinung der Bibliotheks-Architekten von Java war, als sie diverse Utilities-Klassen, wie man sie wohl nennt, schufen.

Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function.” - John Carmack

Ich bin auch kein großer OO-Versteher, gebe ich ehrlich zu. Mein OO-Horizont geht so weit, dass ich weiß, dass manche Programm-Probleme sinnvoll als Datenstrukturen (structs) zu modellieren sind, und es Funktionen geben sollte, die angepasst sind für eben diese structs. Und Java gibt mir die Möglichkeit das schön auszudrücken. Das darüber hinausgehende - Verebung und so weiter - habe ich nur selten gebraucht.

while-true-Konstrukte erlauben es mir, Werte solange zu bearbeiten, bis sie in der gewünschten Form vorliegen, so dass dann die Ausführung mit break oder return beendet werden kann. Event Raising und Consuming sind interessante Stichworte - Das schaue ich mir mal an!

Als Anfänger habe ich mich für OO-Software-Architektur interessiert und war erschrocken, was zu gutem OO-Code wohl alles scheinbar dazugehört. Es hat mich regelrecht in der Entwicklung gehemmt: "So kann ich das nicht schreiben, da würde mich Professor xy mit seinen Publikationen so lange besprengen, bis der Dämon ausfährt", waren so meine Gedanken.

Aber mittlerweile denke ich mir: Ich bau erstmal meine ersten Häuser und Gebäudekomplexe, bevor ich mich mit Stadt- und Staatsplanung herumärgere. Und selbst wenn ich bei letzterem ankomme: Ganz idealtypisch wird es wohl nie. Das sah ich auch, als ich größere Projekte ein wenig studierte. Höchstens ideologisch verkorkst, wenn ich einen Idealtypus zu sehr forciere.

Aber ich hör jetzt mit meiner Schwafelei auf und schaue, dass ich fleißig weiterwachse in der Software-Entwicklung :D
 
  • Gefällt mir
Reaktionen: BeBur
1pressaltf4 schrieb:
Das zeigt nun auch, dass es in der Softwareentwicklung oft nicht nur die eine richtige Lösung gibt und manche gutgemeinte Tipps für andere eher kontraproduktiv wirken.
Natürlich nicht, das sollte von Anfang an klar sein. jede Anregung ist genau das, eine Anregung. Nicht mehr. Nicht weniger. Wenn einer hergeht und sagt, ich sag’s so also ist das so und du machst das so, dann ist in jedem Fall was schiefgelaufen und als „Reviewempfänger“ darf man das dann gerne als Anregung reinterpretieren. Auch und sogar dann, wenn es gute Gründe gab. Jedenfalls dann, wenn man lernen will. Bei einer Anregung muß ich natürlich entscheiden: gefällt mir das, kann ich was anfangen damit? und dann berücksichtigen oder sein lassen.

Ansonsten sind wir denk ich derselben Meinung, jedenfalls im Hinblick auf deine Zitate, auch wenn ich das nicht überall ausformuliert hatte. „Niemals Werte als ungültig verwenden, die durchaus gültige Werte sein können“ sollte zB auf der Hand liegen.
Nur ist eine Stoppuhr normalerweise auf 0 und nicht auf „keine Ahnung“ initialisiert. Konkret da kann man also abwägen. Oder hat Bool isReset als Eigenschaft und spart sich die null-Frage ganz. Es gibt so viele Möglichkeiten, die man aber zu Anfang noch nicht kennt. Da sag ich, lieber ein Hinweis mehr. Und zb ich will in meiner Klasse keine unerwartete Exception mehr sehen, sondern nur noch die eigenen implementierungsunabhängigen. NPE in einer Stoppuhr? 🤔

Klar kommt auch ein bisschen Akademik dazu. Anderseits ist es imo etwas hypocritical erst zu sagen, is halt Java, halt dich an die Konvention; und dann rumzudrehen mit „naja die Konvention gefällt mir aber nicht“. Nein, grad java möchte eben keine Methoden-Rückgabewerte haben, ebensowenig wie direkt zugreifbare Eigenschaften. Exakt deswegen GIBT es getter und setter. Muß man nicht mögen, muß man sich auch nicht stur dran halten (mach ich auch nicht), aber man muß es mal gehört haben um sich evtl damit befassen zu können. Mehrere returns geht natürlich, klar, aber nicht „weil ich es kann“ sondern weil spezifische Umstände vorlagen. Ansonsten gibts Spaghetticode. Viel Spaß bei der Fehlersuche.


Andere Sprache laß ich aber nicht gelten. Da verschiebt man nur die Torpfosten. Klar ginge C#. Und dann? „Mit C# wäre dieser Ansatz falsch oder besser lösbar“? Tolle Wurst. Keine Ahnung, warum sich @Robocopy für Java und nicht zB für c#/net6 entschieden hat. Interessiert mich an der Stelle auch nicht. Er hat und das reicht.
 
  • Gefällt mir
Reaktionen: Robocopy
RalphS schrieb:
Keine Ahnung, warum sich @Robocopy für Java und nicht zB für c#/net6 entschieden hat. Interessiert mich an der Stelle auch nicht. Er hat und das reicht.
C# mag ich aus vielerlei Gründen nicht. Java merkt man an, dass sie (vom damaligen, kleinen Oak-Team) ursprünglich mal mit Liebe und Leidenschaft gemacht wurde. Die Sprache wirkt formvollendet, die Bibliotheken sind gut durchdacht und das Gesamtpaket stimmig.

.NET dagegen ist so ein typisches Microsoft Monstrum nach dem Motto: Wir nehmen Java, blähen Sprache und Bibos bis ins unermessliche auf und bewerben es dann indirekt als "fortgeschritteneres Java".

Ich bin von Arbeit wegen mit VB u. .NET unterwegs, und ja, es funktioniert alles. Aber manchmal hab ich auch so meine Krämpfe mit diesem Microsoft-Zeug. Man merkt einfach, dass das ganze Dingens nicht wirklich mit Liebe gemacht wurde.
 
.NET dagegen ist so ein typisches Microsoft Monstrum nach dem Motto: Wir nehmen Java, blähen Sprache und Bibos bis ins unermessliche auf und bewerben es dann indirekt als "fortgeschritteneres Java".
@Robocopy das ist aber grundlegend dein persönliches Problem. Nicht jeder wird deine Meinung teilen. Genauso lässt sich über Java schimpfen, siehe geringe Leistung, Echtzeitfähigkeit, Event-Programmierung, usw.? Wo fangen wir an, wo hören wir auf?

Jede Sprache hat seine Vor- und Nachteile. Die Sprache sollte für das jeweilige Projekt richtig gewählt sein, um nicht eine überdimensionierte Sprache für eine einfache Textausgabe zu nutzen. Hierbei muss jeder auf sein eigenes empfinden Rücksicht nehmen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Robocopy und BeBur
Da hast du natürlich recht - meine Meinung über MS und .NET ist höchst subjektiv. Zumal ich als Anfänger auch nicht in der Lage bin, ein umfängliches, objektives Urteil über .NET zu fällen. Das wäre auch mehr als vermessen.
 
  • Gefällt mir
Reaktionen: cfHxqA und BeBur
Robocopy schrieb:
Da hast du natürlich recht - meine Meinung über MS und .NET ist höchst subjektiv. Zumal ich als Anfänger auch nicht in der Lage bin, ein umfängliches, objektives Urteil über .NET zu fällen. Das wäre auch mehr als vermessen.
Du kannst deine persönliche Meinung zu MS haben, wie das Wetter ändert. Es ändert nichts an der Tatsache, dass es dein persönliches empfinden ist. 😉

Hat sich den Java in Leistung und Event-Programmierung überhaupt verbessern können? 😚 🤔
 
Zurück
Oben