JUnit und JavaDoc für Beispielklasse

Hey Community,
dann mache ich mal wieder einen Thread auf, mir wurde es ja gestattet für ‚Wehwehchen‘ :wink:
Vielleich wäre auch mal ein Thema gut „Fragen die keinen eigenen Thread verdient haben“

Also wie aus meinem anderen Thread bekannt habe ich eine Report-Klasse.
Jetzt wollte ich für diesen im Nachhinein (weil ich noch nicht so weit vorausplanen kann) einen JUnit Test schreiben
UND JavaDoc Kommentare setzen.
Da ich beides in Projekten bisher vernachlässigt habe, wollte ich mal, dass evtl. jemand drüberschauen kann, meine Fragen also:

Was ist überflüssig?
Was kann ich besser machen?
Wo bin ich nicht genau genug?
Was ist fehlerhaft?
Wie geht es besser?

Report
[spoiler]```
/**

  • The report class represents a complete report which was created by a user.

  • The report class is linked with a set of Keywords through the

  • {@link de.binarylogic.xyz.model.ReportKeywordEntry} class.

  • @author BinaryLogic

  • @version 1.0 :: 2014-12-15
    */
    public class Report implements Serializable {

    public final static String ID_FIELD_NAME = „report_id“;
    public final static String USER_ID_FIELD_NAME = „user_id“;
    private static final long serialVersionUID = 3329580979489979731L;

    @DatabaseField(generatedId = true, columnName = ID_FIELD_NAME)
    private int id;

    @DatabaseField(dataType = DataType.STRING, unique = true, canBeNull = false)
    private String title;

    @DatabaseField(dataType = DataType.STRING, canBeNull = true)
    private String content;

    @DatabaseField(dataType = DataType.STRING, canBeNull = true)
    private String note;

    /**

    • The user is the owner of the report. He creates and stores the report with the UI.
      */
      @DatabaseField(canBeNull = false, foreign = true, foreignColumnName = USER_ID_FIELD_NAME)
      private User user = null;

    /** Default constructor which should only be used by (and is necessary for) ORMLight **/
    public Report() { }

    /**

    • Default constructor which should be used by other classes.
    • @param user The owner of the report.
    • @param title The title e.g. a short description of the content.
    •          It is limited to 50 characters.
      
    • @param content The content of the report.
    • @param note Additional notes related to the content.
    • @throws IllegalArgumentException
      */
      public Report(User user, String title, String content, String note) throws IllegalArgumentException {
      setUser(user);
      setTitle(title);
      setContent(content);
      setNote(note);
      }

    /**

    • Sets the title of the report. It should descripes the content or
    • be an unique keyword or word group. It’s limited to 50 characters,
    • all above are cutt off by this method.
    • If the title is null an {@link java.lang.IllegalArgumentException}
    • will be thrown.
    • @param title
    • @throws IllegalArgumentException
      */
      public void setTitle(String title) throws IllegalArgumentException {
      if(title == null) {
      throw new IllegalArgumentException(„Report title can’t be null.“);
      }
      else if(title.length() > 50) {
      this.title = title.substring(0, 49);
      }
      else this.title = title;
      }

    /**

    • Returns the title of the report as {@link java.lang.String}
    • @return title
      */
      public String getTitle() {
      return title;
      }

    /**

    • Sets the user which is the owner of the report. It can’t
    • be null.
    • @param user
    • @throws IllegalArgumentException
      */
      public void setUser(User user) throws IllegalArgumentException {
      if(user == null) {
      throw new IllegalArgumentException(„User (and owner of the report) can’t be null.“);
      }
      else this.user = user;
      }

    /**

    • Returns the user as {@link de.binarylogic.xyz.model.User} object.
    • @return {@link de.binarylogic.xyz.model.User}
      */
      public User getUser() {
      return user;
      }

    /**

    • Sets the content of the report. If it’s null an
    • empty {@link java.lang.String} will be generated.
    • @param content
      */
      public void setContent(String content) {
      if(content == null) {
      this.content = new String();
      }
      else this.content = content;
      }

    /**

    • Return the content of the report as a {@link java.lang.String}
    • @return
      */
      public String getContent() {
      return content;
      }

    /**

    • Sets the note of the report. The note should descripes the
    • content with additional information.
    • @param note
      */
      public void setNote(String note) {
      if(note == null) {
      this.note = „“;
      }
      else this.note = note;
      }

    /**

    • Returns the note as a {@link java.lang.String}
    • @return
      */
      public String getNote() {
      return note;
      }

    /**

    • Returns the title, the user and the content in
    • a human readable form.
    • @return
      */
      public String toString() {
      return String.format(
      „Title: %s
      User: %s
      Content:
      %s“,
      title,
      user.getUsername(),
      getContent()
      );
      }

    /**

    • Returns the id. The ID will be generated through
    • the ORMLight framework.
    • @return
      */
      public int getId() {
      return id;
      }

    /**

    • Checks if all conditions are complied to store
    • this Report and link it with a Keyword through the
    • {@link de.binarylogic.xyz.model.ReportKeywordEntry} class.
    • @return
      */
      public boolean isValid() {
      if(user != null && title != null && !title.isEmpty()
      && content != null && note != null) {
      return true;
      }
      return false;
      }
      }```[/spoiler]

ReportTest
[spoiler]```
/**

  • A class testing the functionality of

  • the Report class in {@link de.binarylogic.xyz.model.Report.class}

  • @author BinaryLogic

  • @version 1.0 - 2014-12-17
    */
    public class ReportTest {

    private Report report;

    @Before
    public void initialize() {
    report = new Report();
    }

    /**

    • The tested constructor is for ORMLight only and it
    • should never used otherwise. So this is the only
    • way the title, the note, and the content can
    • be null.
      */
      @Test
      public void constructReport() {
      report = new Report();
      assertNull(report.getTitle());
      assertNull(report.getNote());
      assertNull(report.getContent());
      assertNull(report.getUser());
      }

    @Test(expected = IllegalArgumentException.class)
    public void constructParameterizedReportWithNullUser() throws IllegalArgumentException {
    report = new Report(null, „Title“, „Content“, „Note“);
    }

    @Test(expected = IllegalArgumentException.class)
    public void constructParameterizedReportWithNullTitle() throws IllegalArgumentException {
    User mockedUser = mock(User.class);
    report = new Report(mockedUser, null, „Content“, „Note“);
    }

    @Test
    public void constructParameterizedReportWithNullContent() {
    User mockedUser = mock(User.class);
    report = new Report(mockedUser, „Title“, null, „Note“);
    assertNotNull(report.getContent());
    }

    @Test
    public void constructParameterizedReportWithNullNote() {
    User mockedUser = mock(User.class);
    report = new Report(mockedUser, „Title“, „Content“, null);
    assertNotNull(report.getNote());
    }

    @Test
    public void constructParameterizedReport() {
    User mockedUser = mock(User.class);
    when(mockedUser.getUsername()).thenReturn(„User“);
    report = new Report(mockedUser, „Title“, „Content“, „Note“);
    assertEquals(„User“, report.getUser().getUsername());
    assertEquals(„Title“, report.getTitle());
    assertEquals(„Content“, report.getContent());
    assertEquals(„Note“, report.getNote());
    }

    @Test(expected = IllegalArgumentException.class)
    public void setNullTitle() throws IllegalArgumentException {
    report.setTitle(null);
    }

    /**

    • This method test for a too long title. This should not be able
    • in normal work - because the UI limits the title, so that the
    • user can’t type more as 50 characters. But for security the
    • title will be cutted off if anyone should pass a string with
    • more as 50 characters.
    • @throws IllegalArgumentException
      */
      @Test
      public void setTooLongTitle() throws IllegalArgumentException {
      String random = UUID.randomUUID().toString().concat(UUID.randomUUID().toString());
      report.setTitle(random);
      assertEquals(random.substring(0, 49), report.getTitle());
      }

    @Test
    public void setNormalTitle() throws IllegalArgumentException {
    String random = UUID.randomUUID().toString().substring(0, 30);
    report.setTitle(random);
    assertEquals(random, report.getTitle());
    }

    @Test(expected = IllegalArgumentException.class)
    public void setNullUser() throws IllegalArgumentException {
    report.setUser(null);
    }

    @Test
    public void setUser() {
    String result = „User #1“;
    User mockedUser = mock(User.class);
    when(mockedUser.getUsername()).thenReturn(result);
    report.setUser(mockedUser);
    assertEquals(result, report.getUser().getUsername());
    }

    @Test
    public void setNullContent() {
    report.setContent(null);
    assertNotNull(report.getContent());
    }

    @Test
    public void setContent() {
    String random = UUID.randomUUID().toString();
    report.setContent(random);
    assertEquals(random, report.getContent());
    }

    @Test
    public void setNote() {
    String random = UUID.randomUUID().toString();
    report.setNote(random);
    assertEquals(random, report.getNote());
    }

    @Test
    public void setNullNote() {
    report.setNote(null);
    assertNotNull(report.getNote());
    }

    @Test
    public void testToString() {
    User mockedUser = mock(User.class);
    when(mockedUser.getUsername()).thenReturn(„user“);
    report.setUser(mockedUser);
    report.setTitle(„This title“);
    report.setContent(„Important content“);
    String result = „Title: This title
    User: user
    Content:
    Important content“;
    assertEquals(result, report.toString());
    }

    @Test
    public void getId() throws NoSuchFieldException, IllegalAccessException {
    Field field = Report.class.getDeclaredField(„id“);
    field.setAccessible(true);
    field.set(report, 5);
    assertEquals(5, report.getId());
    }

    @Test
    public void isValid() {
    User mockedUser = mock(User.class);
    report = new Report(mockedUser, „Title“, „Content“, „Note“);
    assertTrue(report.isValid());
    }

    @Test
    public void isNotValid() throws NoSuchFieldException, IllegalAccessException {
    User mockedUser = mock(User.class);
    Field userField = Report.class.getDeclaredField(„user“);
    Field titleField = Report.class.getDeclaredField(„title“);
    Field contentField = Report.class.getDeclaredField(„content“);
    Field noteField = Report.class.getDeclaredField(„note“);

     userField.setAccessible(true);
     titleField.setAccessible(true);
     contentField.setAccessible(true);
     noteField.setAccessible(true);
    
     // create valid user
     report = new Report(mockedUser, "Title", "Content", "Note");
     userField.set(report, null);
     assertFalse(report.isValid());
     userField.set(report, mockedUser);
     titleField.set(report, null);
     assertFalse(report.isValid());
     titleField.set(report, "");
     assertFalse(report.isValid());
     titleField.set(report, "Title");
     contentField.set(report, null);
     assertFalse(report.isValid());
     contentField.set(report, "Content");
     noteField.set(report, null);
     assertFalse(report.isValid());
    

    }
    }



Mir ist bewusst, dass mein Englisch an einigen Stellen noch Macken hat. Ich hoffe es ist trotzdem verständlich.

Ich bin leider noch nicht ganz fertig mit Fragen:
Ist denn die `isNotValid()` soweit i.O. optisch ist sie ja ziemlich 'BLERGH!' - oder lieber aufspalten, oder ganz anders?
Ich habe versucht die setMethoden zu umgehen um in einem Getter o.ä. Test nicht eine Methode zu verwenden, die ich an anderer Stelle teste,
wie ist das so? Soll ich das mit Gettern auch so machen oder ganz anders?

Gibt es ein Framework, welches mich die JavaDoc-Kommentare irgendwie auslägern lässt in eine Config-File? Der ganze Code wirkt dadurch doch irgendwie unübersichtlich wie ich finde.

Ich hoffe der Präfix ist i.O. so und die Kategoriewahl auch, ansonsten wäre es nett, wenn das geändert werden könnte.

Danke schonmal für eure Antworten
BL

die ganze Idee für diesen Thread und die Umsetzung sind ziemlich bedenklich,
was wohl auch deine Fragen beantwortet und die Notwendigkeit dieses Threads unterstreicht (Dilemma…)

Dokumentation ist eine selbsterklärende Sache die sinnvolle Dinge tun soll, nicht unbekannten Fremd-Standards gefallen,

es gibt ein paar Standards an die man sich besser hält wie Einsatz von /** */ statt alternativ eh nur eine Möglichkeit // und Tags wie @param,
aber das hast du anscheinend alles drauf

schreibe rein was sinnvoll erscheint, vor allem dir selber etwas hilft und fertig, nichts nachzudenken, nicht groß nach Standards oder Wünsche von anderen zu richten,
von langen Märchen hat niemand was

@param content The content of the report. ist eine Beleidigung für jeden Leser, 1-3 sec aufgewandt und verarscht worden :wink:
der Kommantar sagt nix neues zum löblich bereits guten Parameter-Namen

/** Returns the title of the report as {@link java.lang.String} @return title */ treibt es in seiner Formalität auf die Spitze, ist auch nicht mehr als String getTitle() auch schon sagt

andere Meinungen wird es natürlich auch geben :wink:


new String()
ist übrigens etwas, was in exakt diesen Aufbau niemals im Code vorkommen sollte, „“ ist dasselbe, verwendest du in setNote() auch


beim Test ist die Ausführlichkeit (wie auch die Kommentare zuvor) vielleicht durch die Beispielhaftigkeit hier gegeben,

allgemein schadest du aber vor allem dich selber und auch den (vergleichsweise seltenen) Leser dieses Tests, wenn du jeden simplen Kram wie setNote() testest,
das kannst du in deinem Leben kaum durchhalten, vermute ist

ein paar komplizierte Regeln als nur get/set sind ja schon in der Klasse, ok…,


ich finde es übrigens komisch, dass ein neuer Report null-Variablen haben darf,
aber wenn man null im Konstruktor übergibt oder setContent(null) aufruft, dann ist es nicht mehr null, null auch nie wieder herzustellen,

hat seine Berechtigung als eine Variante, aber schwer von außen nachzuvollziehen,
wenn man nur 2 Parameter hat, dann vielleicht reine Schönheitsentscheidung, ob man Konstruktor mit zwei Parametern benutzt (+ Rest null) oder Default-Konstruktor und zwei set-Methoden,
Ergebnis sind aber zwei unterschiedliche Zustände…

Alternative wäre von Anfang an „“ zu setzen, in der DB auch not null

[QUOTE=SlaterB]die ganze Idee für diesen Thread und die Umsetzung sind ziemlich bedenklich,
was wohl auch deine Fragen beantwortet und die Notwendigkeit dieses Threads unterstreicht (Dilemma…)
[/quote]
Wie gesagt ein „Fragen die keinen Thread verdient haben“ gab es leider nicht.

Dokumentation ist […]

Ja, ich dachte mir schon, dass ich es in der Richtung etwas übertrieben habe.

@param content The content of the report. ist eine Beleidigung für jeden Leser, 1-3 sec aufgewandt und verarscht worden :wink:
der Kommantar sagt nix neues zum löblich bereits guten Parameter-Namen
/** Returns the title of the report as {@link java.lang.String} @return title */ treibt es in seiner Formalität auf die Spitze, ist auch nicht mehr als String getTitle() auch schon sagt

Es sieht halt schöner aus im JavaDoc, aber im Grunde schaut da am Ende wahrscheinlich eh keiner rüber, hast schon recht. Zudem bläht es einen
recht simplen Code nur unnötig auf.

new String()
ist übrigens etwas, was in exakt diesen Aufbau niemals im Code vorkommen sollte, „“ ist dasselbe, verwendest du in setNote() auch

Gibt es da bestimmte Gründe? Verstoße ich da gegen irgendwas?

allgemein schadest du aber vor allem dich selber und auch den (vergleichsweise seltenen) Leser dieses Tests, wenn du jeden simplen Kram wie setNote() testest,
das kannst du in deinem Leben kaum durchhalten, vermute ist

Dann werde ich das wohl noch etwas beschneiden. Die Test liest (dachte ich zumindest) eh keiner, bis mal 'ne rote Lampe leuchtet.

ich finde es übrigens komisch, dass ein neuer Report null-Variablen haben darf,
aber wenn man null im Konstruktor übergibt oder setContent(null) aufruft, dann ist es nicht mehr null, null auch nie wieder herzustellen,
[…]
Alternative wäre von Anfang an „“ zu setzen, in der DB auch not null

Hast recht, irgendwie verkompliziere ich manche Sachen gerne. Letztendlich, wenn ein Report gespeichert wird, wird durch das nicht durchführbare Ablegen
in der DB ein Indikator sein, dass was nicht stimmt.

Danke schonmal!

Machst dadurch die Compileroptierierungen kaputt, als Grundregel: new String(…) ist immer falsch.

Ansosnten sollte Doku(JavaDoc) eben schon gerechtfertigt sein und etwas hinzufuergen das ohne nicht gegeben waere.

[quote=BinaryLogic]

new String()
ist übrigens etwas, was in exakt diesen Aufbau niemals im Code vorkommen sollte, „“ ist dasselbe, verwendest du in setNote() auch

Gibt es da bestimmte Gründe? Verstoße ich da gegen irgendwas?[/quote]Der Grund ist, das new String() immer ein neues String-Objekt erzeugt (new String() != new String(), probier es aus!), mit "" bekommst Du immer das selbe leere String-Objekt aus dem StringPool.

bye
TT

*** Edit ***

[quote=BinaryLogic;107959]Jetzt wollte ich für diesen im Nachhinein (weil ich noch nicht so weit vorausplanen kann) einen JUnit Test schreiben[/quote]Du musstest Dir doch überlegen, was Deine Klasse tun soll. Wieso konntest Du das nicht in einem JuntTest formulieren?

Verabschiede Dich frühzeitig von der Vorstellung, das ein JUnitTest ein Test ist. Es ist vielmehr eine ausführbare Anforderung an deinen Produktiv-Code.

bye
TT

Ah, genau! Da war ja was. Jetzt fällts mir wieder ein. Danke!

Du musstest Dir doch überlegen, was Deine Klasse tun soll. Wieso konntest Du das nicht in einem JuntTest formulieren?

Weil…da müsste ich jetzt eine Ausrede stammeln. Im Grunde hätte ich das tun können.

Verabschiede Dich frühzeitig von der Vorstellung, das ein JUnitTest ein Test ist. Es ist vielmehr eine ausführbare Anforderung an deinen Produktiv-Code.

Also wäre es doch wie SlaterB sagte eigntl. auch übertrieben die Getter- und Setter-Methoden zu ‚tesen‘, schließlich beinhalten sie nicht wirklich eine Logik, die
man explizit als Anforderung definieren sollte/müsste.
Wobei so 100% Line Coverage auch ganz schön aussieht im IntelliJ, aber das kann wahrscheinlich auch etwas trügerisch sein.

zum Mini-Thema String immer noch:
selbst bei gleichen Aufwand und sonstigen Konsequenzen wäre “” einem new String() vorzuziehen, weil kürzer und klarer,
auf die Speicherzahlen soll man ja eh nicht schauen, also auch falls das Verhältnis andersrum wäre

verschärfend kommt hinzu dass new String(), obwohl legitimer Konstruktor einer der wichtigsten Klassen, praktisch nie benötigt wird,
das ist einfach unschön zu lesen in normalen Code,

Ausnahmen nur an dafür gedachten Stellen, beim Einlesen von Dateien (bytes in String, dann auch anderer Konstruktor),
beim Eintragen in einen komplizierten String-Cache wo es vielleicht unbedingt ein eigenes String-Objekt sein soll, oder was auch immer

[quote=BinaryLogic]Also wäre es doch wie SlaterB sagte eigntl. auch übertrieben die Getter- und Setter-Methoden zu ‘tesen’, schließlich beinhalten sie nicht wirklich eine Logik, die
man explizit als Anforderung definieren sollte/müsste.[/quote]Also ertmal sind Getter und Setter per see böse und eigentlich nur in “dummen” DTOs akzeptabel. Von daher komme ich nie in die Verlegenheit getter/setter testen zu müssen.

In Deinem Fall enthalten die Setter aber Geschäftslogik in dem sie die Gültigkeit der übergebenen Werte prüfen. Und diese Geschäftslogik benötigt sebst verständlich Tests. Wobei natürlich je Setter einmal der positiv-Fall und jeder mögliche Negativ-Fall getestet werden muss.

Und an dieser Stelle zeigt sich dann der Vorteil von TDD: Wenn ich die Test (also die ausführbareAnforderung) zuerst schreibe, gibt es keinen nicht getesteten Fehlerfall. So musst Du über die Coverage-Analyse ermitteln, welchen Fehlerfall Du noch nicht getestet hast…

bye
TT

bye
TT

Mit dem Design der Tests hast du recht, das werde ich bei zukünftigen Klassen einfach mal versuchen und sehen wie es funktioniert.
Nein, nicht versuchen ich werd’s so machen!

Jetzt habe ich folgendes geändert:

  • JavaDoc-Kommentare größtenteils raus (bei Gettern und Konstruktor). Bei den Settern habe ich nur eine Beschreibung hinzugefügt, wann die IllegalArgumentException fliegt
  • Der JavaDoc-Beschreibung zur Methode setTitle(String title) ist auch geblieben, die param-Beschreibung flog raus
  • Der JavaDoc-Kommentar zur Klasse ist geblieben
  • isValid() ist rausgeflogen. Ich denke, das ist nicht wirklich die Aufgabe des jew. Objekts sich selbst zu validieren. Einerseits werden durch die
    GUI mögliche Fehleingaben abgefangen und andererseits fliegt im Notfall ein Fehler beim Schreiben in die Datenbank.
  • der ReportTest wurde etwas gekürzt, der getId()-Test flog raus und natürlich die Tests zur isValid()-Methode

Sieht schon etwas sauberer aus.

Edit:
Achso und:

  • Instanzattribute haben jetzt den leeren String als Default-Wert und wurden auf ‘canBeNull = false’ gestellt.

gelesen, was gelernt, danke dafür,

Ecken und Kanten sind noch dran, die müssen ab,
wenn ‘null’ nicht permitted ist, dann darf in oder innerhalb der Geschäftslogik nicht mehr darauf geprf. werden, das ist (vorher) 'ne “Vorbedingung”

Grüßle, bis morgen,

[quote=BinaryLogic]Achso und:

  • Instanzattribute haben jetzt den leeren String als Default-Wert und wurden auf ‚canBeNull = false‘ gestellt.[/quote]
    Ueberleg dir mal, welche Instanzattribute aenderbar sein muessen.
    Die anderen, werden weder auf einen sinnfreien Wert initialisiert, sondern im Konstruktor, oder in der Factory gegen null geprueft, ggf. oder per JSR 303.
    Unveraenderbarkeit hat Vorteile, man braucht nicht immer Setter, wenn man nur gueltige Objekte zulaesst, hat man es einfacher, „“ ist selten sinnvoll, manchmal schon.

Wie sieht es denn zB. mit dem user aus, soll man den spaeter noch aendern koennen?
title, unique aber aenderbar, sicher ? :wink:

[QUOTE=BinaryLogic][…]

  • Der JavaDoc-Beschreibung zur Methode setTitle(String title) ist auch geblieben, die param-Beschreibung flog raus
    […][/QUOTE]
    Warum gibt es überhaupt einen Setter für einen Titel? Setter sprechen eigentlich immer für die Verletzung von OOP (wenn sich auch manchmal notwendig sind).

[quote=Sym]Warum gibt es überhaupt einen Setter für einen Titel?[/quote]Weil die wohl sein OR-Mapper braucht, stand doch als Kommentar im erste Code-Post

bye
TT

Hab ich wohl auch überlesen.
Finde da s Rückständig weil sehr invasiv, da gibts besseres.

Wozu eigentlich die SUID? IDE falsch konfiguriert?

[QUOTE=maki]

  1. Finde da s Rückständig weil sehr invasiv, da gibts besseres.

  2. Wozu eigentlich die SUID? IDE falsch konfiguriert?[/QUOTE]

  3. Haste ein Beispiel, bin neugierig.Framework oder vorgehensweise?

  4. Ist dies nicht die empfohlene Vorgehensweise?

[QUOTE=Unregistered]1. Haste ein Beispiel, bin neugierig.Framework oder vorgehensweise?

  1. Ist dies nicht die empfohlene Vorgehensweise?[/QUOTE]
    Hi :slight_smile:

Sowohl JDO als auch JPA und dessen Implementierungen unterstützen Field Access, da wird man nicht zu gettern/settern gezwungen.

SUIDs vergibt man, wenn man will das zwischen verschieden Versionen serialisiert wird, damit das richtig funktioniert braucht es mehr als nur die SUID, eine vom kompiler fenerirte stellt sicher das versehentlich unterschiedliche eingesetzte Versionenen schnell auffallen… leider hat zB. Eclipse eine andere default Einstellung was Warnungen und eine nicht explizit vergebene SUIDs betrifft.

Meine 50ct

Wenn du mal weiter bist, darfst du für so eine triviale Angelegenheit nicht so viel Aufwand treiben:

Die Validierung könnte in ein Validation-Framework ausgelagert werden und dann bleibt nur eine simple POJO übrig, die heute viele Tools automatisch erstellen können…

Ansonsten ist das ja gar nicht so schlimm, auch wenn ich

        if(note == null) {
            this.note = "";
        }
        else this.note = note;

durch

        this.note = (note == null) ? "" : note;

geschrieben hätte. Das alles wirkt so riesig, dabei ist in Wahrheit gar nicht so viel geboten…

Das einzig wirklich interessante ist der 50 Zeichen constraint, (setTooLongTitle, setNormalTitle) und den testest du mit etwas riesig großem und mit einem 30 Zeichen String. Das ist irgendwie lame, du musst schon Extremfälle testen

null oder die Länge 0,1,48,49,50,51, oder so

Ich würde mich da selber testen und der häufigste Fehler, der mir unterläuft ist das “falsch Zählen am Rand”

Und: musst du wirklich die toString()-Methode testen, also das Format der toString in einem Test NOCHMAL fixieren? Das hat nur dann Sinn, wenn toString irgendwo funktional wichtig ist (oder exakt so gefordert wird), ansonsten stört das nur beim Programmieren.

Ay ay ay, so viele Antworten. So falsch war der Thread dann wohl doch nicht.

[QUOTE=maki]Ueberleg dir mal, welche Instanzattribute aenderbar sein muessen.
Die anderen, werden weder auf einen sinnfreien Wert initialisiert, sondern im Konstruktor, oder in der Factory gegen null geprueft, ggf. oder per JSR 303.
Unveraenderbarkeit hat Vorteile, man braucht nicht immer Setter, wenn man nur gueltige Objekte zulaesst, hat man es einfacher, „“ ist selten sinnvoll, manchmal schon.
Wie sieht es denn zB. mit dem user aus, soll man den spaeter noch aendern koennen?
title, unique aber aenderbar, sicher ? ;)[/QUOTE]

In eine Factory kann ich das noch auslagern, JSR 303 müsste ich mir erst angucken, dass sagt mir jetzt kaum was.
Soweit sollen alle Instanzvariablen änderbar sein, gut der User wird wirklich nicht mehr geändert. Der Title, der Content und die Note aber schon. Der Titel ist
unique, weil er trotzdem nicht zweimal in der DB vorkommen soll. Änderbar soll er trotzdem sein, wenn der User das so machen möchte.

Der Report wird ja bei der Erstellung über die UI gefüllt (das übernimmt dann ein Controller oder sonst was, die Validierung findet ja eigntl. schon zum Größten Teil über
die UI statt, indem bestimmte Eingaben gar nicht möglich sind).
Allerdings wird der Report vom ORM beim Auslesen aus der DB ja wieder in ein Objekt geladen und wird dann über die UI wieder ausgelesen und bearbeitet, so auch der
Titel.
Ich habe jetzt wirklich schon einiges über OOP gelesen denke ich (angewendet eher weniger, merkt man denke auch). Das Setter gegen OOP sprechen wäre mir jetzt neu.
Objekt hat Attribute mit Attributwerten => Zustand; Operationen => Verhalten. Zustand kann über Operationen manipuliert werden.
Wie sieht das denn sonst aus? Ich kann mir doch nicht ausschließlich alles als final deklarieren und immer wieder neue Objekte erzeugen.
Kannst du da nochmal drauf eingehen, welches Prinzip da verletzt wird?

[QUOTE=maki;107995]Hab ich wohl auch überlesen.
Finde da s Rückständig weil sehr invasiv, da gibts besseres.

Wozu eigentlich die SUID? IDE falsch konfiguriert?[/QUOTE]
Wäre immer nett, mir das bessere zu nennen, noch ist das Ding nicht in Stein gemeißelt. Ich bin da immer offen was neues kennenzulernen.
Die SerialVersionUID? Also der Report implementiert ja Serializable und da habe ich mal aufgeschnappt, dass man dann SerialVersionUID verwenden
sollte wegen Versionierung. An die Klasse kommen ja noch Annotations für XML, falls ich das nicht irgendwie über eine Config umgehen kann.

Vielleicht kann das ORMLight auch, sehe mich mal nochmal genauer um.

[QUOTE=maki;108000]
SUIDs vergibt man, wenn man will das zwischen verschieden Versionen serialisiert wird, […][/QUOTE]
An genau sowas dachte ich sogar teilweise, weil es bestimmt am Anfang noch das ein oder andere Update oder Fix geben wird. Auch wenn es sehr wahrscheinlich
ist, dass am Report nichts mehr geändert wird. Die autom. Generierung habe ich sogar erzwungen (arbeit übrigens mit IntelliJ).

Okay, weniger Aufwand. Notiert! :smiley:

        if(note == null) {
            this.note = "";
        }
        else this.note = note;

durch

        this.note = (note == null) ? "" : note;

Okay, das Konstrukt der kurzen If habe ich noch nie gemocht und werde es auch nicht mögen. Daher bleib ich lieber bei dem klassichen „Monster“.

Das einzig wirklich interessante ist der 50 Zeichen constraint,[…]

Guter Einwand mit den ‚Grenzfällen‘. Gibt es da eigntl. schon ein fertiges Tool, welches einem String bestimmter Länge automatisch generiert - am Besten
mit Inhalt?

Und: musst du wirklich die toString()-Methode testen, also das Format der toString in einem Test NOCHMAL fixieren? Das hat nur dann Sinn, wenn toString irgendwo funktional wichtig ist (oder exakt so gefordert wird), ansonsten stört das nur beim Programmieren.

Nein, die gesamte toString() ist auch schon rausgeflogen, und der Test natürlich auch.

Danke für die vielen Antworten, finde das echt Klasse!
BL

Mal das richtige lesen :wink:
Google mal nach „getter setter evil“

Sorry, dachte du hast schonmal was von JPA, Hibernate, EclipseLink gehoert.

[quote=BinaryLogic;108012]Die SerialVersionUID? Also der Report implementiert ja Serializable und da habe ich mal aufgeschnappt, dass man dann SerialVersionUID verwenden
sollte wegen Versionierung.[/quote]
Soll man eben nicht, siehe meine letzte Antwort.

Die automatische Genriereung passiert wenn man keine SUID anlegt, vom Compiler.

Inzwischen nehme ich für sowas Guava: Strings (Guava: Google Core Libraries for Java 19.0-SNAPSHOT API)