Interface, aber die Methoden bleiben teilweise gleich

DaBe1812

Bekanntes Mitglied
Hi,
ich versuche mir gerade ein wenig Schreibarbeit zu ersparen, damit den Code zu verkleinern und am Ende des Tages den Wartungsaufwand zu minimieren.

Also, ich habe eine Maske, auf der man nach Datensätzen suchen kann. Dazu wählt man erst den Typ Datensatz aus (also die tatsächliche Entität/Klasse) und dann die Suchfelder.
Dazu brauchen die Klassen aber ein Interface -> SearchableEntity.
Hier müssen Funktionen zur Verfügung stehen, damit der SuchHandler mit allen Klassen kommunizieren kann. Soweit, so Standard.
Hier mal das Interface:
Java:
public interface SearchableEntityFactoryInterface {

    String getEntityDisplayName();
    List<SearchableEntity> searchEntity(List<SearchTerm> searchTerms);
    List<String> getAvailableSearchFields();
    
    List<SearchResultField> getDefaultResultFields();
    List<String> getDefaultResultFieldsString();

    List<SearchResultField> getResultFields();
    List<SelectItem> getEntityStates();

    List<String> getPossibleResultFields();
    List<String> getUserResultFields();
    
    void saveRecord(SearchableEntity entity);
    void createRecord(SearchableEntity entity);
    void saveColumnOrder(List<String> pickedStrings);

    SearchableEntity newRecord();
}

Eine Methode, wie getEntityStates muss ich überschreiben, weil das ist meiner Meinung nach zu kompliziert, um es der Maschine in generell zu erklären. Aber z.B. die Methoden getPossibleResultFields und getUserResultFields sehen in der Implementierung immer gleich aus:
Java:
@Override
public List<String> getPossibleResultFields() {
    List<String> possibleResultFieldsString = new ArrayList<>();
    possibleResultFieldsString = POSSIBLE_RESULT_FIELDS.stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
    return possibleResultFieldsString;
}

@Override
public List<String> getUserResultFields() {
    String user = session.getUser().getUserName();
    List<String> userResultList = userParameterInterface.getProIpsColumnOrder(user, USER_TABLE_ENTITY_STRING);
    if(userResultList != null) {
        List<SearchResultField> userSearchResultFields = SearchResultField.getSearchResultFieldListByString(userResultList, POSSIBLE_RESULT_FIELDS);
        return userSearchResultFields.stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
    }
    return null;
}
Es dreht sich immer um, in dem Fall, zwei Konstanten in der Klasse. War für mich einfacher, so konnte ich die Funktionen einfach aus einer anderen Implementierung kopieren und muss immer nur die Konstanten anpassen.
Jetzt begab es sich aber, dass ich im Laufe der Entwicklung schwächen an den Methoden gefunden hatte, also musste ich jetzt jede Implementierung öffnen, um die Methode an zu passen.

Gibt es da keine elegantere Möglichkeit?
Irgendwie glaube ich, dass ich gerade in einer Box sitze und nicht sehe, welche Alternative es gibt.
 

CSHW89

Bekanntes Mitglied
Da gibt es mehrere Möglichkeiten. Die einfachste ist eine abstrakte Klasse. Wenn die Erbhierarchie schon gesetzt ist, wäre auch ein (weiteres) Interface mit default-Methoden möglich. Die zwei Konstanten könnte man dann in der abstrakten Klasse definieren, und in der speziellen Klasse befüllen. Alternativ könnten die beiden Konstanten auch durch "protected abstract" Methoden ersetzt werden:
Java:
abstract class AbstractSearchableEntityFactory : SearchableEntityFactoryInterface {
    
    protected abstract List<SearchResultField> specialPossibleResultFields();
    protected abstract String userTableEntityString();
   
    @Override
    public List<String> getPossibleResultFields() {
        List<String> possibleResultFieldsString = new ArrayList<>();
        possibleResultFieldsString = specialPossibleResultFields().stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
        return possibleResultFieldsString;
    }
   
    @Override
    public List<String> getUserResultFields() {
        String user = session.getUser().getUserName();
        List<String> userResultList = userParameterInterface.getProIpsColumnOrder(user, userTableEntityString());
        if(userResultList != null) {
            List<SearchResultField> userSearchResultFields = SearchResultField.getSearchResultFieldListByString(userResultList, specialPossibleResultFields());
            return userSearchResultFields.stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
        }
        return null;
    }
}
 

Barista

Top Contributor
Hier müssen Funktionen zur Verfügung stehen, damit der SuchHandler mit allen Klassen kommunizieren kann.
Ich würde es folgendermaßen machen und glaube auch, dass meine Lösung in einigen ORM-Mappern so oder ähnlich verwendet wird.

Ich würde eine Klasse/Interface Criteria/Predicate machen, die eine Klausel ( <Feldname> <Operator> <Wert> ) enthält.

Da es mehrere sein können, eine Liste davon.

Damit könnte man später auch so Sachen wie FeldA = FeldB codieren.

Über Generics könnte man noch absichern, dass ein bestimmtes Prädikat zur entsprechenden Tabelle passt.

JOOQ hat so etwas, glaube ich.

Ist aber eventuell übertrieben und wenn es um Joins geht, kommt man dann auch nicht weiter.

Ich sehe Deine Methoden-Namen etwas kritisch:

getPossibleResultFields

Darin versteckt sich

SearchResultField::getDisplayName

Nach meiner Meinung wäre ein Methodenname besser, der die Info DisplayName enthält.

Da der Rückgabetyp List of String ist, muss es sich sicher um feld-Namen, nicht um Feld-Objekte handeln.
Ich bin da eventuell ein bisschen kleinlich, aber Code wird öfter gelesen als geschrieben, der Aufwand es hier genau zu nehmen lohnt sich.
 

DaBe1812

Bekanntes Mitglied
Das ist komplett richtig.
Ich habe schon eine Klasse vom Typ SearchResultField, welche genau dafür da sein soll, diese möchte ich aber noch ein wenig aufbohren, weil sie mir zu wenig kann.
Eigentlich sollte diese Klasse quasi eine Metadaten-Klasse zur Entität sein, mit Eigenschaften wie:
  • Wie heißt das Attribut der Entität
  • Wie soll der Name auf der Oberfläche sein
  • Welcher Felddatentyp auf der Oberfläche wird verwendet
  • Kann nach dem Feld gesucht werden
  • Kann das Feld als Ergebnis-Ausgabefeld verwendet werden
  • Ist das Feld ein default Tabellen-Ausgabefeld
Damit könnte ich mir dann statische Listen sparen und diese dynamisch über die Metadaten erzeugen lassen. Dann bräuchte jede Entität eine Metadaten-Entität, aus der dann die Suchmaske gefüllt werden kann.

Ich habe nur auf der Oberfläche irgendwie ein Problem mit SearchResultField als Objekt im DropDown Menü. Er zeigt es zwar richtig an, aber nachher behauptet er der gewählte Wert wäre ein String und kein Objekt vom Typ SearchResultField.
 

DaBe1812

Bekanntes Mitglied
Ich hab mich auch echt blöde gesucht.
Macht es das so wirklich einfacher?
Also alternativ wäre ja sämtliche Methoden, die so abstrakt sind in die abstrakte Klasse zu schieben und im Interface nur das zu lassen, was wirklich implementiert werden muss und dann der Implementierung beides zuzuordnen.
Ich hab jetzt meinen Branch mal so weit frei geschaufelt, dass ich das jetzt aber mal ausprobieren will.
 

DaBe1812

Bekanntes Mitglied
Okay, ich bin jetzt mit dem Refactoring durch. Streicht meine Frage. Also der Weg über die abstract class war einfach so richtig.
Meine Abstrakte Klasse sieht jetzt so aus:
Java:
public abstract class AbstractSearchableEntityFaktory implements SearchableEntityFactoryInterface {

    protected abstract String getUserTableEntitySring();
    protected abstract List<SearchResultField> getPossibleResultFields();
    public abstract List<SearchResultField> getDefaultResultFields();

    @Inject    private AtcUserParameterInterface userParameterInterface;
    @Inject    private SessionHandler session;

    public List<String> getDefaultResultFieldsString() {
        List<String> defaultResultFieldsString = new ArrayList<>();
        defaultResultFieldsString = getDefaultResultFields().stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
        return defaultResultFieldsString;
    }

    @Override
    public List<SearchResultField> getResultFields() {
        String user = session.getUser().getUserName();
        List<String> userResultList = userParameterInterface.getProIpsColumnOrder(user, getUserTableEntitySring());
        if(userResultList != null) return SearchResultField.getSearchResultFieldListByString(userResultList, getPossibleResultFields());
        return getDefaultResultFields();
    }

    @Override
    public List<String> getPossibleResultFieldsDisplayname() {
        List<String> possibleResultFieldsString = new ArrayList<>();
        possibleResultFieldsString = getPossibleResultFields().stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
        return possibleResultFieldsString;
    }

    @Override
    public List<String> getUserResultFields() {
        String user = session.getUser().getUserName();
        List<String> userResultList = userParameterInterface.getProIpsColumnOrder(user, getUserTableEntitySring());
        if(userResultList != null) {
            List<SearchResultField> userSearchResultFields = SearchResultField.getSearchResultFieldListByString(userResultList, getPossibleResultFields());
            return userSearchResultFields.stream().map(SearchResultField::getDisplayName).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public void saveColumnOrder(List<String> pickedStrings) {
        String user = session.getUser().getUserName();
        List<String> pickedStringsRep = SearchResultField.getInternalStringListByStringList(pickedStrings, getPossibleResultFields());
        userParameterInterface.saveProIpsColumnOrder(user, pickedStringsRep, getUserTableEntitySring());       
    }
}
Das einzige, was ich schade finde ist, dass es keine abstrakten Parameter gibt. D.h. ich musste jetzt Funktionen aufnehmen für z.B. getUserTableEntitySring(), damit ich das in der Methode verwenden kann.
Aber den ersten Test heute hat die Anwendung überlebt. Cool fand ich auch, dass wieder zwei Injects aus den Implementierungen rausgefallen sind, weil ich sie in der Abstrakten Klasse verwende.
 

mrBrown

Super-Moderator
Mitarbeiter
Das einzige, was ich schade finde ist, dass es keine abstrakten Parameter gibt. D.h. ich musste jetzt Funktionen aufnehmen für z.B. getUserTableEntitySring(), damit ich das in der Methode verwenden kann.
Was meinst du denn mit "abstrakten Parametern"? Was zB geht ist ein Feld + Konstruktor der es setzt, alle Unterklassen müssen den ja aufrufen und können dann das passende übergeben.
 

Barista

Top Contributor
Ich habe zwar auch schon ORM-Mapper selbst geschrieben, es ist aber sinnvoll, mal zu schauen, was andere so programmiert haben, zum Beispiel Hibernate Criteria Query.
 

Oneixee5

Top Contributor
Ich habe zwar auch schon ORM-Mapper selbst geschrieben,
Ich schreibe auch immer Framework's selbst, welche jahrelang mit viel Manpower und immensen Kosten von Anderen entwickelt wurden, außerdem gut dokumentiert und getestet wurden, und unter Open Source Lizenzen verfügbar sind. Man hat ja sonst nichts zu tun ... Das tue ich, weil ich glaube, dass ich viel besser bin, als alle Anderen. Dann verliere ich zwar irgendwann die Lust daran und lasse meine Kunden hängen - aber das ist ja deren Problem.
 

DaBe1812

Bekanntes Mitglied
Ich schreibe auch immer Framework's selbst, welche jahrelang mit viel Manpower und immensen Kosten von Anderen entwickelt wurden, außerdem gut dokumentiert und getestet wurden, und unter Open Source Lizenzen verfügbar sind. Man hat ja sonst nichts zu tun ... Das tue ich, weil ich glaube, dass ich viel besser bin, als alle Anderen. Dann verliere ich zwar irgendwann die Lust daran und lasse meine Kunden hängen - aber das ist ja deren Problem.
Es kann schon Sinn machen sich etwas, das es fertig gibt trotzdem selbst zu bauen. Ich wollte JobRunr in meinem Projekt verwenden, das kam aber mit der Konfiguration der Datenbank nicht klar. Bei QuartzTimer hatten Funktionen gefehlt und es hat Haufenweise Steuertabellen erstellt, die Daten gehalten haben, die ich nicht gebraucht habe. Also habe ich mir einen eigenen JobPlaner gebaut, der mit zwei Tabellen aus kommt und bisher recht zuverlässig läuft.
Ich hab hier im Forum auch schon Leute getroffen die vermeiden es Frameworks zu verwenden und bleiben lieber bei so wenig Abhängigkeiten im Projekt, wie möglich.

Die CriteriaApi von Hibernate verwende ich aktuell um mir dynamisch Suchen auf zu bauen, also mit dynamischem Where-Teil
 

mihe7

Top Contributor
Ich hab hier im Forum auch schon Leute getroffen die vermeiden es Frameworks zu verwenden und bleiben lieber bei so wenig Abhängigkeiten im Projekt, wie möglich.
Da ich diesbezüglich schon entsprechende Kommentare abgegeben habe, fühle ich mich mal angesprochen. Ich denke, da liegt ein kleines Missverständnis vor. Es geht darum, dass eine Abwägung stattfinden muss. Auch Open-Source-Bibliotheken sind nicht ohne Kosten/Risiko...

Am besten erkläre ich das anhand von CSV-Dateien. CSV kann sehr einfach aber auch sehr komplex sein. Nun ist es so, dass es in sehr vielen Fällen ausreicht, die Zeilen am Feldtrenner zu splitten. Dafür muss ich mir keine externe Abhängigkeit ins Projekt holen! Wenn das nicht mehr funktioniert, weil die CSV-Datei z. B. Texte in Anfürhungszeichen setzt, weil diese den Feldtrenner enthalten, dann kann man sich Gedanken machen, ob man das noch selber machen möchte. Wenn man richtig komplex aufgebaute CSV-Dateien hat, dann bietet sich der Einsatz einer fertigen Lösung geradezu an. Aber auch dann muss bei der Auswahl einer Lösung auf alles Mögliche geachtet werden.
 

Manul

Mitglied
Am besten erkläre ich das anhand von CSV-Dateien. CSV kann sehr einfach aber auch sehr komplex sein. Nun ist es so, dass es in sehr vielen Fällen ausreicht, die Zeilen am Feldtrenner zu splitten. Dafür muss ich mir keine externe Abhängigkeit ins Projekt holen! Wenn das nicht mehr funktioniert, weil die CSV-Datei z. B. Texte in Anfürhungszeichen setzt, weil diese den Feldtrenner enthalten, dann kann man sich Gedanken machen, ob man das noch selber machen möchte. Wenn man richtig komplex aufgebaute CSV-Dateien hat, dann bietet sich der Einsatz einer fertigen Lösung geradezu an. Aber auch dann muss bei der Auswahl einer Lösung auf alles Mögliche geachtet werden.
Diese "sehr vielen Fälle" sind aber nur die, in denen man hundertprozentige Kontrolle über das reingegebene CSV hat, und nie was anderes als irgendwelches genau definiertes Happy-Path-Minimalst-CSV reingegeben werden kann.
Ansonsten haben solche selbst gebauten Lösungen leider die ungute Tendenz früher oder später auseinander zu fliegen, wenn dann doch mal was anderes um die Ecke kommt. Was dann mal wieder für Bugs bis hin zu handfesten Sicherheitslücken (und mitunter angesäuerten Kunden) sorgen kann. Und nach denen man sich dann mal wieder fragt, warum man nicht doch gleich eine halbwegs bewährte Standardlibrary genommen hat, statt das Rad aus vermeintlicher Zeitersparnis neu zu erfunden.
 

LimDul

Top Contributor
Diese "sehr vielen Fälle" sind aber nur die, in denen man hundertprozentige Kontrolle über das reingegebene CSV hat, und nie was anderes als irgendwelches genau definiertes Happy-Path-Minimalst-CSV reingegeben werden kann.
Ansonsten haben solche selbst gebauten Lösungen leider die ungute Tendenz früher oder später auseinander zu fliegen, wenn dann doch mal was anderes um die Ecke kommt. Was dann mal wieder für Bugs bis hin zu handfesten Sicherheitslücken (und mitunter angesäuerten Kunden) sorgen kann. Und nach denen man sich dann mal wieder fragt, warum man nicht doch gleich eine halbwegs bewährte Standardlibrary genommen hat, statt das Rad aus vermeintlicher Zeitersparnis neu zu erfunden.
Es ist immer eine Risikoabwägung. Das NPM Package LPAD möchte ein Wörtchen da mitreden :)

 

mihe7

Top Contributor
Diese "sehr vielen Fälle" sind aber nur die, in denen man hundertprozentige Kontrolle über das reingegebene CSV hat, und nie was anderes als irgendwelches genau definiertes Happy-Path-Minimalst-CSV reingegeben werden kann.
Eine Lib, die das CSV-Format lesen kann, entbindet nicht von entsprechenden Prüfungen.

Ansonsten haben solche selbst gebauten Lösungen leider die ungute Tendenz früher oder später auseinander zu fliegen, wenn dann doch mal was anderes um die Ecke kommt.
Wenn sich Anforderungen ändern, muss man darauf reagieren. Das sehe ich nicht als "ungute Tendenz", sondern als einen völlig normalen Vorgang. Falls Du ein Auseinanderfliegen aufgrund von inhaltlichen Änderungen meinst: s. o.

statt das Rad aus vermeintlicher Zeitersparnis neu zu erfunden.
Es geht nicht nur um Zeitersparnis. Das fängt schon bei lizenzrechtlichen Überlegungen an, geht über den Support bzw. die Community, ggf. Kompatibilitätsprobleme und auch eine Abhängigkeit will gewartet werden usw.

Wie gesagt: eine Lib kann durchaus sinnvoll sein. Wenn aber jemand meint, er müsse knapp 700 KB Commons Lang einbinden, um mit StringUtils auf einen "leeren" String zu prüfen, dann hätte ich da meine Bedenken.
 

i. O.

Mitglied
in denen man hundertprozentige Kontrolle über das reingegebene CSV hat,
Könntest du das vielleicht etwas genauer begründen? Ich habe noch nie einen kompromittierten String in Java gesehen, wie es zum Beispiel bei php oder anderen Unrat gang und gäbe ist...

Wenn das CSV-Format ungültig ist, sollte man eigentlich die Ausnahmebehandlung(en) kennen.

Wie gesagt: eine Lib kann durchaus sinnvoll sein. Wenn aber jemand meint, er müsse knapp 700 KB Commons Lang einbinden, um mit StringUtils auf einen "leeren" String zu prüfen,
Das natürlich nicht. :D Aber manchmal binde ich pro forma gewisse Libs im Vorfeld ein (auch, wenn zunächst nicht benötigt). Das Dependency Management ist ja eh automatisch.
 

KonradN

Super-Moderator
Mitarbeiter
Also CSV Dateien können massiv problematisch sein. Das war halt viel zu lange etwas, das nicht standardisiert wurde und als dann nach Jahrzehnten ein Standard erstellt wurde, hat er keinerlei Aufmerksamkeit mehr bekommen...

Das fängt schon damit an, dass eine "comma separated list" eben nicht Werte mit Komma trennen muss. Man kann ja auch einfach ein Listen-Trennsymbol einführen und das abhängig von Region / Kultur machen.

Aber auch die Frage nach dem Encoding ist schon eine erste interessante Frage... Dann scant man halt eine Datei unter der Prämisse, dass die "falsche Darstellung einer üblichen Sonderzeichens" ein Sonderzeichen sein sollte... Das kann stimmen oder eben auch nicht - es ist also nur eine Option, die ein Mensch fachlich klären muss um es dann einzustellen.

Wie dann die Werte dargestellt werden, ist dann die nächste Frage. Ich habe da extrem viel gesehen von "Anführungszeichen? Was ist das?" bis hin zu: Wir packen jedes Feld in Anführungszeichen. Und sowohl ein "Wenn ein Anführungszeichen im Text vorkommt, dann wird es escaped zu völliger Ignoranz..

Highlight ist eine Aufzählung in einem Feld ohne Quotes. So das nur einmal vorkommt oder das Format klar und von Nachbarfeldern abweicht: Das kann man auch lesen :)

Und ein "Das Format ist falsch und kann nicht eingelesen werden" als Antwort ist nicht immer möglich. Wenn wichtige Daten in einem anderen System sind und es da keinen anderen Export gibt, dann heißt es Friss oder stirb. (Extrem, aber das hatte ich in der Vergangenheit schon.)

Und die Aussage von @mihe7 kann ich nur unterstreichen: Es muss ein aktiver Prozess sein, der Abhängigkeiten bewertet. Und da kommen Nutzen und Kosten auf den Tisch. Und zu den Kosten gehören dann auch Risiken. Und wenn es eine wichtige Abhängigkeit ist, dann darf das auch Geld kosten (So man sicher sein will, dass ein Support vorhanden ist und aktiv gekündigt werden muss so dass man gewisse Zeit hat zum reagieren).

Das ist aber auch keine Entscheidung eines einfachen Entwicklers. Mir ist bewusst, dass es genug Firmen gibt, die so arbeiten. Entwickler haben Narrenfreiheit und dann wird halt direkt in Produktion gepusht. Time to Market sind dann deutlich unter einen Tag: Was man heute gebaut hat, geht dann am Besten direkt in die Produktion. Und wenn es nicht geht: Heya - man macht einen Commit rückgängig und es geht wieder? Was für ein genialer Software-Entwickler. Problem in Minuten gelöst! :)
Mein Umfeld ist da vermutlich eher unüblich: Große Konzerne, existenzielle Systeme. Wenn die ausfallen, dann kommt das in der Tagesschau. Zerhaut man es komplett, dann geht es teilweise an die Existenz ...
 

mihe7

Top Contributor
Könntest du das vielleicht etwas genauer begründen? Ich habe noch nie einen kompromittierten String in Java gesehen, wie es zum Beispiel bei php oder anderen Unrat gang und gäbe ist...
Naja, die Strings werden verarbeitet und an jeder Stelle kann es theoretisch zu einem Problem kommen. Da reicht ja schon das Logging (s. log4j 🤣).

Bei uns ist das alles relativ unproblematisch. Nicht, dass sich die Dateien nicht urplötzlich und unerwartet ändern könnten (und würden...), sondern weil wir einen manuellen Import mit Fehlermeldung an den Anwender haben. Wenn Du aber vollautomatische Schnittstellen hast und die Daten dann auch noch in einem automatisierten Prozess weiterverarbeitet werden, dann kann das natürlich zu einem echten Problem werden. Im Fehlerfall steht der Laden oder - noch schlimmer - er arbeitet mit falschen Informationen weiter, durch die dann erheblicher Schaden entsteht. Das hat aber nur bedingt etwas mit CSV zu tun.

Wenn wichtige Daten in einem anderen System sind und es da keinen anderen Export gibt, dann heißt es Friss oder stirb. (Extrem, aber das hatte ich in der Vergangenheit schon.)
LOL, das ist für viele unserer Kunden der Normalzustand. Die können sich glücklich schätzen, wenn sie überhaupt irgendwas bekommen, was man noch irgendwie einlesen kann. Man möchte es nicht für möglich halten, wie das manchen Großunternehmen völlig am Allerwertesten vorbeigeht, ob die anderen zurecht kommen. Die haben ihren Prozess hart kodiert in ihrer Software - basta.
 

KonradN

Super-Moderator
Mitarbeiter
LOL, das ist für viele unserer Kunden der Normalzustand. Die können sich glücklich schätzen, wenn sie überhaupt irgendwas bekommen, was man noch irgendwie einlesen kann. Man möchte es nicht für möglich halten, wie das manchen Großunternehmen völlig am Allerwertesten vorbeigeht, ob die anderen zurecht kommen. Die haben ihren Prozess hart kodiert in ihrer Software - basta.
Das ist erst off topic, aber zur Richtigstellung: Das war keine Kritik an irgendwelchen Systemen. Die Kunden waren sehr gut organisiert. Und das Problem war nicht technischer Natur. Daten lagen oft in relationalen Datenbanken vor. Nur eben fehlte es zeitnah an dem KnowHow, das abzufragen und dann wurde auf Möglichkeiten zurückgegriffen, die für einen einfachen Anwender der Software zur Verfügung standen. Das sind also Probleme die nur auf Grund eines zeitkritischen Projekts aufgekommen sind und die wir dann auch gut und schnell lösen konnten. Das waren dann oft auch nur Workarounds um Daten schnell in unsere BI Workflows einzubinden.

Das war also mehr ein Schmankerl aus meinem Berufsleben das zeigen sollte, dass CSV eben sehr viele Überraschungen mit sich bringen kann (Und as war damals schon etwas extrem. Alleine schon, weil Daten aus der ganzen Welt gekommen sind. Also die unterschiedlichen Settings, Encodings, .... Aber auch Verzögerungen: Man hat halt keine gemeinsamen Arbeitszeiten ... also schwer, da dann mal eben in einer Telko etwas zu klären ...

Das war also einfach nur eine technische Herausforderung. Kein Hinweis auf irgend welche Probleme bei Kunden oder bei spezieller Software oder auf ein "lock in" oder so. Wobei das mit dem Lock In gefühlt ein größeres Thema war. Mit den REST Webservices hat sich da vieles geöffnet würde ich aus dem Bauchgefühl sagen. Wobei ich das nicht tiefer analysiert habe.
 

Manul

Mitglied
Könntest du das vielleicht etwas genauer begründen? Ich habe noch nie einen kompromittierten String in Java gesehen, wie es zum Beispiel bei php oder anderen Unrat gang und gäbe ist...
Das glaube ich dir gern. Wahrscheinlich weil du außer hier rumschlaumeiern noch nie in praxisrelevantem Umfang mit sowas bzw. an mitunter witzigen Bugs welche durch selbst zusammengebautes Parsing und etwas unerwarteten Input entstehen können gearbeitet hast.

Wenn das CSV-Format ungültig ist, sollte man eigentlich die Ausnahmebehandlung(en) kennen.
Aha. Dann kannst du Schlaumensch sicher auch erklären, wie man Input verlässlich als ungültig erkennt bzw. als gültig definiert, wenn wie bei CSV noch nicht mal ein wirklicher allgemeingültiger Standard existiert.
Aber ja, einfach ne Ausnahmebehandlung drumherum und alles läuft wie geschmiert ... du bist echt ein Experte, wie man merkt :rolleyes:
 
Zuletzt bearbeitet:

Manul

Mitglied
Da nur der Hinweis auf RFC 4180

Da hätte man einen Standard, an den man sich halten könnte und der mit die gängigen Implementierungen umfasst (nach eigenen Angaben, paar Referenzen werden genannt).

Das einfach nur als kleine Ergänzung.

Ach herrje ... :rolleyes:
Dass dieses RFC keinen Standard für CSV spezifiert steht sogar gleich am Anfang:
Status of This Memo

This memo provides information for the Internet community. It does
not specify an Internet standard of any kind.
Distribution of this
memo is unlimited.
Und auch später ist noch mal unmissverständlich erklärt, dass hier nur dokumentiert wurde wie es typischerweise aussieht / benutzt wird:
2. Definition of the CSV Format

While there are various specifications and implementations for the
CSV format (for ex. [4], [5], [6] and [7]), there is no formal
specification in existence, which allows for a wide variety of
interpretations of CSV files. This section documents the format that
seems to be followed by most implementations:
 

i. O.

Mitglied
Wahrscheinlich weil du außer hier rumschlaumeiern noch nie in praxisrelevantem Umfang mit sowas bzw. an mitunter witzigen Bugs welche durch selbst zusammengebautes Parsing und etwas unerwarteten Input entstehen können gearbeitet hast.
Ich glaube, du weißt nichts über meinen Werdegang.

Dann kannst du Schlaumensch sicher auch erklären, wie man Input verlässlich als ungültig erkennt bzw. als gültig definiert, wenn wie bei CSV noch nicht mal ein wirklicher allgemeingültiger Standard existiert.
Aber ja, einfach ne Ausnahmebehandlung drumherum und alles läuft wie geschmiert
Nö.

Wenn es nicht geparst werden kann, dann wird die weitere Verarbeitung abgebrochen, ganz einfach. Das hat nichts mit allen möglichen Szenarien beachten zu tun.

Was soll diese Unterstellung, dass ich so arbeiten würde?
Das war keine Unterstellung, das war eine Feststellung infolge deiner Antwort.
 

mihe7

Top Contributor
Dass dieses RFC keinen Standard für CSV spezifiert steht sogar gleich am Anfang:
Im Gegensatz zum deutschen Wort "Standard" hat "internet standard" im RFC eine ganz konkrete Bedeutung im Standardisierungsprozess der IETF. An der Stelle wird schlicht das Verhältnis zwischen diesem "Memo" und den Internetstandards klargestellt.

Wenn Dich "Standard" in der Antwort von @KonradN stört, ersetze es einfach durch "Spezifikation". Das RFC enthält eine formale Spezifikation des De-Facto-Standards für das CSV-Format, d. h. wie
es typischerweise aussieht / benutzt wird
 

KonradN

Super-Moderator
Mitarbeiter
Und auch später ist noch mal unmissverständlich erklärt, dass hier nur dokumentiert wurde wie es typischerweise aussieht / benutzt wird:
Was ich doch auch in eigenen Worten geschrieben habe:
Da hätte man einen Standard, an den man sich halten könnte und der mit die gängigen Implementierungen umfasst (nach eigenen Angaben, paar Referenzen werden genannt).

Aber gut, dass Du die Stelle auch gefunden hast und dann sogar aufgezeigt hast, dass es noch mehr Spezifikationen dazu gibt, so dass Deine Aussage, dass es sowas nicht gibt, schlicht Quatsch ist.

Ansonsten habe ich vorher schon genug geschrieben zu der CSV Thematik.

Wenn es nicht geparst werden kann, dann wird die weitere Verarbeitung abgebrochen, ganz einfach. Das hat nichts mit allen möglichen Szenarien beachten zu tun.
Das ist doch nur die einfache Sicht des aktuellen Programms: Wenn ich eine Eingabe nicht auswerten kann, dann kann ich mit der Eingabe nicht weiter arbeiten.

Aber aus Sicht des Prozesses geht es dann doch los. Dann muss die Situation bewertet werden und dann kommen natürlich Punkte auf wie:
  • Analyse: Was ist denn das eigentliche Problem?
  • Auf Basis der Analyse kann dann das weitere Vorgehen überlegt werden. Ein wichtiger Punkt wird dabei immer sein: Kann die Datenqualität verbessert werden? Sprich: Es wird nach anderen Formaten geschaut: Was ist sonst noch möglich? XML, JSON, Excel, ... Aber hier ist auch die Frage: Was ist der zeitliche Ablauf und was bedeutet es für ein Projekt?

Und in dem Projekt, in dem ich war, haben wir regelmäßig den Import-Code verbessert um noch mehr einlesen zu können:
  • Zum einen hat uns dies zeitnah die Daten (oder den größten Teil) gegeben und die weiteren Prozesse konnten fortgeführt werden.
  • Das gleiche Problem kann beim nächsten Kunden ebenso auftreten. Da ist es also super, wenn man mit der Eingabe umgehen kann.
Aber parallel wurde immer auch geschaut, ob und wie die Datenqualität doch noch verbessert werden kann.

Aber ist klar: Warum soll man mehrere Millionen € in einem Projekt riskieren, wenn da ein Entwickler mal ein paar Stunden Arbeit hinein stecken kann. Zumal man dann direkt an einem Tag weiter gekommen ist ohne Verzögerung.
 

Barista

Top Contributor
Ich bin der Meinung, dass der Ton in diesem Thread ziemlich unfreundlich geworden ist.

Und irgendwelche Aussagen: "Du weißt schon was ich meine...", sind sicher nicht hilfreich, der/die-jenige weiß es offensichtlich nicht oder wahrscheinlich nicht.

Außerdem ist es letztendlich jedem seine eigene Entscheidung, ob sie/er eine Lib bzw. ein Framework verwendet oder nicht.

Sicher kann man auf mögliche Probleme hinweisen, aber bitte sachlich und verständlich.
 

i. O.

Mitglied
Außerdem ist es letztendlich jedem seine eigene Entscheidung, ob sie/er eine Lib bzw. ein Framework verwendet oder nicht.
Nicht ganz. Na klar, wenn du der Chef bist, dann kannst du tun, was du willst, trägst aber, zumindest zum Teil, auch die Konsequenzen oder Verantwortung für deine Entscheidung.

Externe Libs müssen gepflegt werden, Updates erhalten, lizenztechnisch muss geschaut werden, sie dürfen ein Projekt nicht aufblähen, und zu guter Letzt dürfen sie ein System nicht schädigen oder zum Stillstand bringen.
 

Barista

Top Contributor
Ein Aspekt ist meiner Meinung auch, dass es sinnvoll sein kann, etwas selbst zu programmieren um dann andere Lösungen (Open Source oder nicht) einschätzen zu können.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Leere vererbte Interface-Methoden Allgemeine Java-Themen 8
OnDemand Interface imlementieren Allgemeine Java-Themen 4
Buroto Interface Allgemeine Java-Themen 2
T Komische Zeichen im Zusammenhang mit Serializable interface Allgemeine Java-Themen 13
M Kann man Annotationen auf Klassen einschränken die ein Interface implementieren? Allgemeine Java-Themen 1
H Kombination Interface und Abstrakte Klasse bei Generics Allgemeine Java-Themen 3
B JaxB und @XmlIDREF mit Interface Allgemeine Java-Themen 1
R Lambda Expression in einer Methode execute() aufrufen (execute() ist eine Methode aus dem funktionalen Interface Command) Allgemeine Java-Themen 5
P Abstrakte Klassen vs. Interface Allgemeine Java-Themen 4
Kirby.exe Autocloseable Interface Allgemeine Java-Themen 2
T Abgeleitetes Interface public ohne Schlüsselwort "interface"? Allgemeine Java-Themen 3
S static in Interface und Klasse Allgemeine Java-Themen 2
S static methode im Interface Allgemeine Java-Themen 1
S Interface, generischer Datentyp, Exception? Allgemeine Java-Themen 3
B Vererbung Interface und implementierende Klassen Allgemeine Java-Themen 8
A Anonyme Klassen - Interface Allgemeine Java-Themen 5
C Ein Iterator ist eine Implementierung des Interface Iterable? Allgemeine Java-Themen 2
J Generische Interface - Problem Allgemeine Java-Themen 3
mrBrown Namensfindung Fluent-Interface Allgemeine Java-Themen 0
J Logik in Interface Allgemeine Java-Themen 2
N Best Practice Allgemeines Verhalten für ein Interface implementieren? Allgemeine Java-Themen 7
B eigenes Consumer Interface Allgemeine Java-Themen 0
S 2 methoden mit gleichen namen und ein Interface Allgemeine Java-Themen 9
N GUI Interface, swing Allgemeine Java-Themen 7
Thallius Konzeptproblem User-Interface Allgemeine Java-Themen 5
T Interface vs abstract Allgemeine Java-Themen 2
S Klassen Abstract, Interface und ein Chat Tool Allgemeine Java-Themen 1
I Interface Interface / Klasse - wieso Abstract? Allgemeine Java-Themen 13
D generische Interface und konkrete Methode Allgemeine Java-Themen 3
C Klassen Problem mit Funktion einer Generischen Klasse die ein Interface implementiert Allgemeine Java-Themen 0
N Problem mit Generics und Interface Allgemeine Java-Themen 4
D Methode mit optionalen Parametern in Interface Allgemeine Java-Themen 3
T Interface mit generische Typen Allgemeine Java-Themen 5
M Interface einer Library implementieren Allgemeine Java-Themen 3
A Klassen ein Interface aufzwingen Allgemeine Java-Themen 4
Bananabert Interface Custom 'Event' mit Interface Allgemeine Java-Themen 10
J Interface Serializable Methodensignatur Allgemeine Java-Themen 2
J Interface Interface für Framework verwenden Allgemeine Java-Themen 4
F Interface IInterface oder Interface? Allgemeine Java-Themen 3
M Generics (bounded wildcards statt Interface Bezeichnern) -- Sinn oder Unsinn? Allgemeine Java-Themen 2
T Interface Probleme Allgemeine Java-Themen 8
M Queues und Queue Interface Allgemeine Java-Themen 3
I Mehrfaches Implementieren eines generischen Interface Allgemeine Java-Themen 9
W Java Native Interface und "mp3player" Allgemeine Java-Themen 3
M Über Liste verschiendene JComponents mit eigenem implementierten Interface ansprechen Allgemeine Java-Themen 7
P Eclipse Java Native Interface-Problem Allgemeine Java-Themen 8
Z Abstrakte Klassen /Interface Allgemeine Java-Themen 5
pg1337 Interface-Frage Allgemeine Java-Themen 24
S Interface Welchen Interface Stil favorisiert ihr? (usability) Allgemeine Java-Themen 17
faetzminator statische Variablen in Interface - Vererbung? Allgemeine Java-Themen 9
R Implementierung eines Interface durch 2 verschiedene Klassen Allgemeine Java-Themen 6
T OpenOffice Interface Elemente Ein/Ausblenden Allgemeine Java-Themen 5
K Interface Interface comparable machen Allgemeine Java-Themen 9
T Interface > Abstract > Class Allgemeine Java-Themen 11
N Trick für Compilerfehler bei fehlendem Interface Allgemeine Java-Themen 12
X Interface - Klasse einladen Allgemeine Java-Themen 6
G Interface -> InterfaceImplementierung Allgemeine Java-Themen 3
Ark Array durch Interface ersetzen Allgemeine Java-Themen 7
R Interface instanzieren Allgemeine Java-Themen 8
B Frage zu Interface und List Allgemeine Java-Themen 4
KrokoDiehl JNI: native im Interface Allgemeine Java-Themen 4
S normale vererbung als interface Allgemeine Java-Themen 2
E Beispiel für ein möglichst einfaches Interface Allgemeine Java-Themen 22
N Unterschied abstract interface und interface Allgemeine Java-Themen 4
S interface verbung problem Allgemeine Java-Themen 9
S problem programm mit interface: Allgemeine Java-Themen 3
R Vererbung mit Interface und Abstract Allgemeine Java-Themen 3
B Interface und von Thread ableiten Allgemeine Java-Themen 6
R Interface Serializable technische Begrenzung Allgemeine Java-Themen 2
T Interface-Referenz Allgemeine Java-Themen 2
L interface abstrakte klasse Allgemeine Java-Themen 21
S Interface Geschäftslokik & GUI Allgemeine Java-Themen 6
G Interface zwischen 2 Programmierern Allgemeine Java-Themen 10
C Schnittstellen(interface) Allgemeine Java-Themen 9
N List<? implements "Interface"> geht nicht Allgemeine Java-Themen 13
D javadoc interface + implementation + @overrides Allgemeine Java-Themen 16
G Interface oder abstrakte Klasse Allgemeine Java-Themen 4
T Parameter einer Klasse auf Interface prüfen Allgemeine Java-Themen 6
A feststellen, welche Klassen ein Interface implementieren Allgemeine Java-Themen 3
G class, interface, or enum exp? Allgemeine Java-Themen 2
S Interface Klasse überladen. Allgemeine Java-Themen 2
K Inneres Interface äußere Klasse Allgemeine Java-Themen 7
T Frage zu interface und "guter Programmierstil" Allgemeine Java-Themen 4
T Interface "on-the-fly" implementieren? Allgemeine Java-Themen 3
S Frage zu Interface Allgemeine Java-Themen 7
J Objektorientiert - Interface & Klassen Allgemeine Java-Themen 3
G Interface - Klassen implementieren das - Reflection ok? Allgemeine Java-Themen 4
T "Programming against the interface" sinnvoll? Allgemeine Java-Themen 18
G Interface mehrfach implementieren Allgemeine Java-Themen 5
@ zur Laufzeit Interface aus jar implementieren? Allgemeine Java-Themen 5
A Was ist der genau Sinn eines Interface? Allgemeine Java-Themen 13
E Oberbergriff für class und interface Allgemeine Java-Themen 20
D QuickSort, Interface Allgemeine Java-Themen 2
R Interface für Arithmethik? Allgemeine Java-Themen 3
MQue Interface implementieren Allgemeine Java-Themen 7
P Liste von Klassen die ein Interface implementieren speichern Allgemeine Java-Themen 12
L Interface Frage! Allgemeine Java-Themen 25
T Instanz einer Interface abgeleiteten Klasse erzeugen Allgemeine Java-Themen 3
F Ein interface und private Methoden? Allgemeine Java-Themen 13
G nichtabstrakte Funktion zu einer Interface hinzufügen Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben