Mal eine Frage zu Binary Serialization

KonradN

Super-Moderator
Mitarbeiter
Hallo zusammen,

jetzt muss ich doch einmal hier einmal nach euren Meinungen fragen, denn ich scheine einen wichtigen Punkt zu übersehen.

Die Kernproblematik ist folgende:
  • Es wird eine ArrayList<Entity> per ObjectOutputStream geschrieben.
  • Dann wird diese zurück gelesen. Man bekommt ein Object. Jetzt könnte man einfach einen Cast machen a.la.:
ArrayList<Entity> entities = (ArrayList<Entity>) objectInputStream.readObject();

Da gibt es dann aber natürlich eine Warnung, denn das ist ein unsafe cast.

Daher war die Überlegung von mir, dass man hier ja sehr wohl einfach den Typ prüfen kann. Das Problem ist jedoch: Generic type erasure. Wenn ich also die Typen prüfen will, dann muss ich im Code nicht nur auf ArrayList prüfen sondern auch die Elemente. Das kann man natürlich einfach in Code schreiben - das würde dann so in der Art aussehen:
Java:
    ArrayList<Employee> employeesList = new ArrayList<>();

    try (FileInputStream fis = new FileInputStream("employeeData");
         ObjectInputStream ois = new ObjectInputStream(fis);) {

        Object readObject = ois.readObject();
        if (readObject instanceof ArrayList readArray) {
            for (Object element: readArray) {
                if (element instanceof Employee employee) {
                    employeesList.add(employee);
                } else {
                    // Handle here, that your are loading a file that is not what expected, e.g. throw an exception.
                }
            }
        } else {
            // Handle here, that your are loading a file that is not what expected, e.g. throw an exception.
        }
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } catch (ClassNotFoundException c) {
        System.out.println("Class not found");
        c.printStackTrace();
    }

Und dann ist natürlich wichtig: Wenn man das in einer eigenen Klasse kapseln würde, wäre es einfacher. Denn dann würde lediglich die erste Prüfung notwendig sein und die Elemente wären nicht mehr zu prüfen.

Habe ich hier wichtige Punkte übersehen? Sehe ich da etwas falsch?
Irgend etwas muss ich übersehen, denn das alles hat auf SO stattgefunden und ich habe downvotes bekommen. Ein Kommentar "Those warnings are unavoidable" bekam upvotes ...

In RuntimeExceptions zu laufen (ClassCastException) ist ein schlechter Stil, daher würde ich immer die aktive Prüfung vorziehen. Alleine schon um so Warnungen zu vermeiden...

Was Downvotes begründen könnte, wären:
  • die schlechten catches - die ich von der Fragestellung übernommen hatte ... war evtl. ein Fehler ...
  • die else nach den if sind erst mit dem Edit eben rein gekommen - da gab es vorab nur einen Kommentar, das ich das halt erst einmal weggelassen habe.

Ich wäre hier also wirklich interessiert an Meinungen, was ich hier bei der Antwort falsch gemacht habe. Es geht nicht um irgend eine Rechtfertigung oder so. Aber es schockt mich halt schon etwas, denn man kann ja Kommentare schreiben und dann würde man ggf. nachbessern oder so... Im Augenblick bin ich da etwas geschockt - nachdem ich da ein Jahr nichts mehr gemacht habe ...
 
Ich kann beide Standpunkte nachvollziehen. Ob ein Downvote angemessen ist oder nicht, ist etwas Geschmackssache und hängt auch von den Kenntnissen des Fragestellers ab - konnte dieser das richtig einschätzen/bewerten? Ich denke eher nicht. Ein Downvote ist natürlich ärgerlich für die Reputation aber ich würde es einfach abhaken. Für manche Nutzer ist es einfach geil, wenn sie so etwas tun und sich somit selbst bestätigen können. Der wichtigste Hinweis ist imho die Nutzung von XML/JSON mithilfe einer Lib.
 
Ich denke, ein großer Teil des Problems ist SO selber. Ich finde zwar durchaus auch manchmal gute Antworten beim Suchen von Problemen, aber die sind in aller Regel ziemlich alt.

Ich habe da nur eine einzige Frage reingestellt, und danach nie wieder. Die Antworten kaum brauchbar, und der Moderator der da meine Typos korrigiert hat, hat für mich dann den Vogel abgeschossen. Ich bin zwar wirklich relativ talentfrei wenn es um Fremdsprachen geht, aber so mies war es dann sicher doch nicht. Für mich sieht das so aus, als wäre SO von lauter Boomern aufgebaut worden – aus dieser Zeit kommen noch die guten und hilfreichen Antworten die ich heute noch finde – und danach haben die Idioten übernommen.

Auf mikrocontroller.net gibt es auch so ein Bewertungssystem (lesenswert/nicht lesenswert), das sieht man aber nur wenn man dort angemeldet ist. Mit ein Grund, warum ich dort nie angemeldet war und nicht mehr schreibe, seitdem es den Gastzugang nicht mehr gibt. Dort hast du auch Spaßvögel, die negativ bewerten, selbst wenn das der beste Beitrag im ganzen Thread war. Manche haben da auch echte Fans, die grundsätzlich jeden Beitrag ihres "Lieblings" negativ bewerten den sie finden können.

Einfach nichts draus machen. Man muß nicht von allen gemocht werden und um der eigenen Gesundheit willen sollte man auch nicht danach streben, jedenfalls nicht im Internet.

Und, ohne mir den SO-Thread jetzt angetan zu haben: Ich denke auch nicht, daß Downvotes von einer allzu schlechten Frage kommen. Wieviele Anfänger haben wir hier, warum sollte man ihre Frage als schlecht bewerten? Die speziellen Übungsthreads "Könnt ihr meine Aufgaben machen, ich muß in den Urlaub" sind da vielleicht eine Ausnahme, aber da werde ich persönlich lieber direkt pampig als nur eine Bewertung abzugeben.

Und ich denke auch nicht, daß Downvotes von schlechtem Beispielcode kommen. Guter Beispielcode ist nicht der, der in einem normalen Programm perfekt ist und alle Fehler abfängt, sondern der, der das konkrete Problem direkt veranschaulicht, ohne überflüssigen Ballast.
Wer schon nicht imstande ist die Anforderungen an dreieinhalb Codezeilen im jeweils passenden Kontext zu sehen, ist zu einer qualifizierten Antwort ganz sicher auch nicht in der Lage.
 
Danke euch für eure Meinung. Vor allem: Das was ich bisher erst vermutet hatte, habe ich jetzt ausgetestet:

Dieses "Ich caste einfach eine ArrayList" birgt die Gefahr einer ClassCastException beim Zugriff auf die Daten!

Dazu habe ich jetzt schnell mal einen UnitTest geschrieben, der das einfach mal zeigt:
Java:
package de.kneitzel.so;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;

import static org.junit.jupiter.api.Assertions.*;

public class BinarySerializationFailure {

    @Test
    public void testBinarySerialization() {
        ArrayList<String> objects = new ArrayList<>();
        objects.add("Some String");

        try ( FileOutputStream fileOut = new FileOutputStream("account.ser");
                ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(objects);
        } catch (Exception ex) {
            fail("Exception!", ex);
        }

        ArrayList<Point> loadedList = null;
        try (
                FileInputStream fileIn = new FileInputStream("account.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn)) {
            loadedList = (ArrayList<Point>) in.readObject();
        } catch (Exception ex) {
            fail("Exception!", ex);
        }

        // Assert, that we was able to load the data.
        assertEquals(1, loadedList.size());

        // So whenever we try to access, we get an exception:
        ArrayList<Point> finalLoadedList = loadedList;
        assertThrows(ClassCastException.class, () -> {
            Point point = finalLoadedList.get(0);
        });
    }
}

Aber ein Punkt ist richtig: Ich bringe erst den Code und die Anmerkungen danach. Die werden dann einfach übersehen. Das kann die Downvotes erklären. Aber das zeigt, das die Leute sich einfach zu wenig Zeit nehmen ....
 
Binary Serialization ist ein zweischneidiges Schwert. Einerseits sehr einfach andererseits auch sehr fehleranfällig. Ich denke für viele Nutzer ist auch verlockend, dass der Dateiinhalt nicht direkt menschenlesbar ist. Es wäre aber möglich auch dieses Format weitgehend resistent gegen unwillkürliche Laufzeitfehler durch falsche Inhalte zu machen. Eine Möglichkeit wäre Magic Numbers einzubauen oder immer konkrete Typen statt generischen zu verwenden. Trotzdem bleibt eigentlich immer ein Restrisiko, dass bspw. durch Änderungen oder ein anderes JDK bzw. JDK-Version das Dateiformat unbrauchbar wird. Serialisierung macht nur Sinn, wenn man die Daten auch irgendwie weitergeben möchte. Andernfalls könnte man einfach eine Datenbank verwenden. Auf diesem Gebiet gibt es auch genügend leichtgewichtige Ansätze, bis hin zu NoSQL. Den Vorgang der Weitergabe kann man separat immer entsprechend schützen, etwa durch Verschlüsselung. Es gilt die Regel, immer etwas erledigen zu lassen, durch den, der es am besten kann (etwa Download/Upload über HTTPS/SSL). Wenn man das beachtet, dann machen Formate wie XML oder JSON viel mehr Sinn. Denn selbst wenn alle XML- und JSON-Parser auf der ganzen Welt plötzlich verschwunden wären, könnte immer noch einfach ein Mensch diese Textdateien interpretieren und auch relativ einfach neue Parser programmieren.
Binary Serialization ist einfach etwas, das man kennen sollte und mit dem man sich einmal, im Rahmen des Lernfortschrittes, beschäftigen muss. Dann sollte man das weitgehend abhaken.
 
Ja, das ist auch meine Sichtweise zu Binary Serialization. Ich bin halt über die Frage gestolpert und da war halt direkt ein Kommentar
Those warnings are unavoidable
Und das ist halt mit der größte Schwachsinn ... und der bekam Upvotes?

Generell spricht nichts dagegen zu sagen: Ich mache einfach den Cast. Und dann fliegt halt eine Exception.
Ich muss mich ja eh um Exceptions kümmern, also alles ist gut.

So gesehen habe ich jetzt tatsächlich Gründe für die Downvotes gefunden, die ich auch akzeptieren kann:
a) In dem ersten Post habe ich halt die wichtigen zusätzlichen Informationen erst hinter den Code gepackt. Das ist für den 08/15 SO Deppen zu viel. So Code würde er nie schreiben (ich auch nicht, da hat er Recht!) und daher Downvote als Quatsch.
b) Es geht da ja weniger um die Fragestellung als eben um den Kommentar. Dafür verdiene ich auch Downvotes.

Daher habe ich - auch danke diverser zusätzlicher Kommentare - die Downvotes (ehrlich und mit harter Arbeit) verdient.

Aber das ändert dennoch nichts an gewissen Clean Code bedenken:
  • Eine Runtime Exception ist leicht vergessen. Vor allem, wenn man es nicht direkt vor Ort erledigt.
  • Ist es wirklich "exceptional" - das hängt an den Umständen. Bei einem Transfer, auf den der User keinen Zugriff hat: Ja. Aber wenn es z.B. ein Laden ist und der User wählt aus (und wählt dann statt Employees.dat eben Customers.dat aus), dann geht es in Richtung Exception nutzen zur Steuerung des Ablaufs.
  • Und ein Punkt, den ich sehe: Eine so dumme Sache kann so einfach zu Fehlern an ganz anderer Stelle führen. Du schreibst irgend welchen Code, der mit einer List<Employee> arbeitet und da bekommst Du eine ClassCastException wenn Du einen Employee aus der Liste nimmst?

Für mich war halt wichtig, dass ich die Downvotes verstehen konnte. Die Beweggründe konnte ich jetzt wohl tatsächlich nachvollziehen. Verständnis für diese Leute habe ich nicht wirklich, den ich glaube, die haben deutlich weniger über die Problematik nachgedacht als ich und haben teilweise die Probleme nicht wirklich verstanden. Das ist aber jetzt natürlich nur eine Unterstellung - und das ist vermutlich sogar ein Zeichen, dass ich eben die Ansprüche von SO zu sehr auf die leichte Schulter nehme, da ich ja Punkte für Downvotes eingestehe!

Aber ich denke, man ist sich doch direkt einig: Ich mach SO nicht und da sind welche, die mich nicht mögen 🙂 Und ich habe genug andere Möglichkeiten, meine Zeit zu nutzen. (SO ist da eh suboptimal. Da sind "schnelle Antworten" nicht gut - was diese Antwort von mir aber explizit nicht war! Aber in der Regel investiere ich nicht ganz so viel Zeit - auch wenn. meine Posts oft viel Text haben. Ich bin halt durchaus schnell beim Tippen.)

Auf jeden Fall vielen herzlichen Dank für eure Beiträge. Ihr habt mir bei der Sicht auf diese Thematik sehr geholfen.
 
Oh, gestern nicht mehr abgesendet:

Zunächst einmal sehe ich es wie @Oneixee5 - allerdings halte ich die Argumentation des Users, "but those if-else, just to throw another type of exception are redundant", für falsch, da ein unchecked cast durchgeführt wird, egal, was in der Liste steckt und die RuntimeException möglicherweise erst sehr viel später an ganz anderer Stelle auftritt. Daran ändert auch ein Unit-Test nichts, denn wie soll denn mit einem Unit-Test festgestellt werden, dass das "correct thing" geladen wird, wenn dieses von außen übergeben wird? Das war zwar im Thread nicht gefordert, aber auch nichts Gegenteiliges.

Aber dann kann ich ja gleich noch was ergänzen, was SO und den Kommentar dazu betrifft: eine Begründung für den Downvote war, dass der Code nicht für Copy & Paste geeignet ist. Das geht mir doch entschieden zu weit.

Inhaltlich kann man sicher darüber diskutieren, ob es sinnvoll ist, für jeden Eintrag eine Typprüfung vorzunehmen, und ja, sicher gibt es komplexere Strukturen, wo es dann wirklich unschön wird. Diesbezüglich ist der Kommentar nachvollziehbar, aber deswegen muss man doch kein Downvote geben. Noch dazu war die Frage explizit für eine ArrayList gestellt.
 
Aber dann kann ich ja gleich noch was ergänzen, was SO und den Kommentar dazu betrifft: eine Begründung für den Downvote war, dass der Code nicht für Copy & Paste geeignet ist. Das geht mir doch entschieden zu weit.
Oh, habe ich da einen Kommentar übersehen? Hat SO den Anspruch, eine Copy & Paste Quelle zu sein? Es geht doch um das Verständnis... Aber ok, das wäre dann der dritte Grund für einen möglichen Downvote, den ich sehe (und den ich auch akzeptieren kann - so das halt der Anspruch von SO ist)

Inhaltlich kann man sicher darüber diskutieren, ob es sinnvoll ist, für jeden Eintrag eine Typprüfung vorzunehmen, und ja, sicher gibt es komplexere Strukturen, wo es dann wirklich unschön wird.
Ja, das ist aber doch auch abgehandelt, weil doch da meine Aussage ist, dass man seine Daten kapseln soll. Dann habe ich meine Klasse Employees oder EmployeeManagement oder wie man die Klasse nennen will. Die hat dann von mir aus die List<Employee> und dann wird Employee serialisiert. Damit hätte ich
  • entweder die ClassCastException direkt beim Laden
  • eben nur ein einzelnes instanceof, das ich prüfen müsste.

Aber ok, ich habe damit abgeschlossen (mit der Frage aber auch SO generell. Wieso bin ich da nach so vielen Monaten wieder online gegangen UND habe auch noch Zeit verschwendet für so ein Thema? Das waren ja jetzt doch einige Stunden meiner Zeit...).
 
Ich frage mich sowieso immer, wo du die viele Zeit und Geduld, für die vielen und ausführlichen Beiträge im Forum, her nimmst?
Die Fragestellung gab es glaube ich schon einmal. Ich denke, das ist vergleichbar mit Anderen Hobbies:
  • Irgendwelche Spieler. Da wird dann massiv gespielt ... Das sind dann jeden Tag mehrere Stunden ...
  • Social Media: Ich lasse es mal unter diesem Namen ... Ich kenne gerade mal FB und YT... Aber Menschen kommen ja teilweise auf zig Onlinestunden auf dem Smartphone ....

Unter dem Strich wird es auf etwas in der Art hinaus laufen. Eine Gewöhnung / Prägung (um nicht gar zu sagen Sucht?) die viel Zeit kostet und nicht positiv ist. Meine Frau würde sich bestimmt freuen, wenn ich weniger Zeit am Computer wäre und mehr Zeit in andere Aktivitäten stecken würde .... Ist etwas, das mir auch körperlich gut tun würde - mehr Bewegung statt so viel vor dem Rechner zu sitzen ...

Ich kann hier nur schwer Wertungen vornehmen. Aber das dürfte so der Sachverhalt sein - zusammen natürlich mit der Tatsache, dass Beruf und Hobby doch recht nah beieinander liegen bei mir und das Hobby den Beruf somit etwas ergänzt.
 
Ich kenne gerade mal FB
Ich kenne FB auch - aber nur vom Namen 🤣
Oh, habe ich da einen Kommentar übersehen?
Vielleicht habe das auch falsch verstanden: "People tend to just copy/paste code, and while I firmly believe that it's their responsibility to check the code and read carefully what is written, they don't do it mostly. The answer should be written in a way that the pitfalls are clear to see (if there are any). For me that's enough of a reason to downvote."
 
Ok, das hatte ich so etwas überlesen oder auf die Schnelle mit abgehakt über die bessere Positionierung von Hinweisen (vor dem Code) und dem Hinzufügen der else Parts.

Aber da steckt noch mehr drin - da hätte vermutlich eine Generics Methode raus kommen müssen die eine eigene Exception wirft, wenn das Lesen fehlgeschlagen ist.
Und auch Verbesserungen wie try with resources.

Also sind die Downvotes verständlich, das andere Aussagen upvotes bekommen haben ist evtl. ärgerlich (aber halt nicht das Problem der Downvoter) und ich hätte mir noch viel mehr Mühe geben müssen. Aber dazu bin ich nicht bereit, daher lasse ich SO so lange wieder weg, bis ich Lust habe, Studienarbeiten zu schreiben 🙂
 
Betreffend Stack Overflow, die Frage ist schon schlecht. Deine Antwort ist schon gut, aber ich an deiner Stelle wuerde noch deine zweite Antwort in die erste einarbeiten und die zweite dann loeschen (ich hab ehrlich gesagt die zweite Antwort uebersehen, hatte nicht damit gerechnet dass da noch eine ist, huestel). Damit gibst du einen groszen Gesameindruck der Situation (wieso es so ist wie es ist), was es zu beachten gibt und was moegliche Loesungstrategien sind. Es macht keinen Sinn dass auf zwei Antworten aufgeteilt zu haben.

Dass es Runterwaehlis gab, ist so eine Sache. Zu einem bestimmten Grad haben deine Antworten die Frage verfehlt, aber das liegt halt einfach daran weil die Frage schon schlecht gestellt ist im Kontext von Stack Overflow. Aber das ist mehr ein Problem mit dem wie Stack Overflow von den meisten Leuten verwendet wird, als von deinen Antworten.
 
Danke auch für Deine Einschätzung und auch Danke für Deinen Vorschlag. Die Idee ist gut, aber das Thema ist für mich abgeschlossen und ich werde da nicht mehr Zeit investieren. Ich werde auf SO bis auf weiteres nicht mehr aktiv sein, da der Aufwand in meinen Augen zu groß ist und ich da nichts außer gewissen Frust habe.

Aber evtl. überlege ich es mir morgen noch - jetzt ist erst einmal ein langer Tag (03:30-jetzt) vorbei und ich werde erst mal drüber schlafen 🙂
 
Ok, Tobias hat einen weiteren Punkt für ein Downvote: Ich habe das Exception Handling vom TE übernommen, was nicht gut ist.
(Er hat da etwas zu dem Thread beigetragen, danke dafür. Aber wie üblich ist der Account dann erst einmal weg.)
 

Zurück
Oben