Wiki

Clone wiki

BibSonomy / development / Best Practices

Best Practices


Auf dieser Seite könnt Ihr Eure Regeln posten, mit denen man Eurer Meinung nach Probleme am elegantesten lösen kann. Da man Best Practices meist nur dann kennenlernt, wenn andere einen auf einen besseren Weg hinweisen, wäre es in gerade solchen Momenten gut, Eure gewonnen Erkenntnisse hier einzustellen.

Allgemein

Grundregeln

  • commit early and often - wenn man nicht gerade etwas größeres programmiert bzw. ändert, sollte man regelmäßig (am besten täglich) seine Änderungen ins CVS einchecken - sofern der Code compiliert und alle Tests durchlaufen! Ausnahme: ein Release steht bevor (und das wurde auch angekündigt).

  • code reuse - bevor man eine neue Funktionalität (Methode, CSS-Klasse, I18N-Message, etc.) erzeugt, zunächst nachschauen (bzw. nachfragen!), ob diese nicht schon an anderer Stelle bereitgestellt wird.

  • good names - Das Vergeben von Namen für Dateien, Methoden, Klassen, Variablen, URLs, etc. sollte mit Bedacht geschehen. Zunächst sollte man sich dabei an existierenden Konventionen orientieren und sich im Code umschauen, wie an anderer Stelle Namen vergeben wurden, denn es gilt: Einheitlichkeit geht vor! Je sichtbarer ein Name nach außen ist (URL, Datei, Klasse, ...), desto wichtiger sind gute Namen. Daher sollte im Zweifelsfall einer der Verantwortlichen gefragt werden.

  • use the source, luke! - Jeglicher Code (auch JSPs!) muss kommentiert werden! Bei öffentlichen Methoden und Attributen ist JavaDoc (/** ... */) zu verwenden. Nicht nur Methoden kommentieren, sondern auch einzelne Codeabschnitte.

  • If it is something you use often, be careful with it! Änderungen an Dateien, die oft im Betrieb von Bibsonomy genutzt werden, vorher mit den alten Hasen absprechen. Immer bedenken, daß Erweiterungen häufig aufgerufener Seiten eine relativ hohe Last verursacht.

    • (Java) Controller/Commands, die in der Ableitungshierarchie weit oben stehen. (Klassenname in
      Eclipse markieren und Hirarchy displayen)
    • (JSP/HTML) Vorsicht beim Aufbohren von häufig verwendeten Tags oder JSPs.

Bibsonomy-Database


##Grundlegenes## Eine content_id darf das Datenbankmodul nie verlassen. D.h. außerhalb dieses Moduls dürfen Content-IDs zur Identifizierung von Posts o.Ä. nicht verwendet werden. Ähnliches gilt für alle weiteren IDs (siehe "ids"-Tabelle)

##'Param'-Objekte##

Die Param-Objekte (UserParam, BookmarkParam, etc.) sollen nur zur Übergabe von Parametern an SQL-Statements verwendet werden und daher nur im jeweiligen DatabaseManager verwendet werden. Der UserParam darf also nicht in der DBLogic gefüllt werden, sondern erst in der entsprechenden Methode im UserDBManager, die das SQL-Statement aufruft.

Viele DBManager handhaben das leider noch nicht so.

##Methoden-Namen##

Die Methodennamen sollen den grundlegenden CRUD-Operationen entsprechen, d.h. mit

  • create (Beispiel: createUser)
  • read - Ausnahme: get! (Beispiel: getUser)
  • update (Beispiel: updateUser)
  • delete (Beispiel: deleteUser)

beginnen. Methoden, die einen Boolean zurückliefern und z.B. eine Eigenschaft prüfen, sollen mit is beginnen.

##DBLogic/LogicInterface##

Hinzufügen/Ändern von Methoden bitte mit einem der hauptamtlichen, 'älteren' Entwickler absprechen.

Bibsonomy-Webapp


##Controller/Command##

konkrete Typen von Commandattributen statt Strings

Die Attribute von Commands sollten konkrete Typen statt Strings sein. D.h. habt ihr ein url Attribut, das eine URL sein sollte, sollte der Typ URL und nicht String sein!

Bsp:

class SampleCommand extends BaseCommand {
    private URL url;
}

nicht:

class SampleCommand extends BaseCommand {
    private String url;
}

ggf. müsst ihr ein Converter<String, TARGETTYPE> schreiben, siehe Spring Doku

Typen können auch Enums sein und das Binding sollte out-of-the-box funktionieren.

##JSP##

###Grundlegendes###

  • Jegliche Variablen müssen escaped werden! Das geht mittels <c:out value="${variable}"/>. Für Werte in Parametern nimmt man stattdessen ${fn:escapeXml(variable)}. Werte in URLs müssen ggf. mittels ${mtl:encode(variable)} kodiert werden.

  • Bei wichtigen Transaktionen, sollten die Formen, die diese dann starten, ein hidden Feld ckey besitzen, welches automatisch befüllt wird (command.context.ckey). Dies verhindert, dass diese Transaktionen einfach so aufgerufen werden können, ohne, dass der User tatsächlich auf der Website ist. Die Cookie-Attack geht dann nicht.

  • avoid inline css

  • avoid inline javascript

  • use the url generator to generate link, not by hand

  • include extra javascript files in jspx files not in a tagx file

###Tags### * Der Name eines Formularfeldes wird mittels des Tags <label>Titel</label> neben das Formularfeld geschrieben

  • Die XML-konformen Java Server Pages (.JSPX) werden vom Tomcat-Modul Jasper auf ihre XML-Konformität geprüft und normalisiert. Das bedeutet insbesondere, dass leere Tags <tag></tag> durch <tag /> ersetzt werden. Im Fall der Textarea führt das zu Problemen, da <textarea ... />* nicht html-konform ist. Um also Probleme von fehlerhaften Tags zu umgehen, sind in leere Textareas Kommentare einzufügen, damit keine Normalisierung durchgeführt wird. Das Ganze sieht dann so aus.

    <textarea><!-- dont remove this --></textarea>
    
  • Das fmt:message-Tag erlaubt einem direkt, eine Variable anzugeben. D.h., statt

    <c:set var="expandBookmarks"><fmt:message key="list.expand.bookmarks"/></c:set>
    

    bitte

    <fmt:message var="expandBookmarks" key="list.expand.bookmarks"/>
    

    verwenden

  • JavaScript-Code bitte so einschließen:

    <script type="text/javascript">
    //<mtl:cdata>
    <![CDATA[
    
    ]]>
    //</mtl:cdata>
    </script>
    
  • Nur Code in eine Schleife packen, der auch in jedem Schleifendurchlauf ausgeführt werden muss!. Folgendes ist falsch:

    <c:forEach var="tag" items="${command.tags}">
      <fmt:message var="posts" key="posts"/>
      ...
    </c:forEach>
    

Javascript

do not include or submit minified JavaScript!

##Exceptions## Fehler des Users im Controller berücksichtigen. Wenn der Fehler vom User selber behebbar ist, dann mit Error-Nachricht auf die Seite lenken, von der er kommt. In solchen Fällen sollten keine Exceptions fliegen! Jegliche andere Art von erwartbarem Fehler sollte gecatcht und im Error-Objekt gespeichert werden. (Interface ErrorAware) * Der MinimalisticControllerSpringWrapper fängt alles übrige und leitet auf entsprechende Seiten weiter.

##Sprache/Übersetzung## siehe Sprache Übersetzung Schreibweisen

##Misc##

nicht eingeloggten Benutzer zur login-Seite redirecten

einfach im Controller eine AccessDeniedException (die aus org.springframework.security.access) werfen. Spring Security kümmert sich um das Speichern des ursprünglichen Requests und leitet nach erfolgreichem Login wieder zurück zum Controller.

Sonstige

Updated