2022-01-25 Die Extensions halten Einzug

Diese Woche gibt es gar nicht so viel Neues zu zeigen. Wir haben uns hauptsächlich mit Refactoring beschäftigt, da die Methodennamen teilweise von der Länge her ausgeartet sind. Es sind DataObjectMeta-Klassen entstanden, auf die direkt durch das DataObject zugegriffen werden kann. Somit wurde z.B. aus Folgendem in den AttributeProperties:

SP.fetch<IDataObjectMetaRepository>().fetch(dataObject::class)
dataObjectMeta.findAttributePropertyNameByDataObject(dataObject, this)

eine lesbarere Schreibweise:

dataObject.meta.instanceProperties.findAttributePropertyName(this)

Außerdem machen wir immer mehr von den Kotlin-Features Gebrauch und legen Extensions an, was das Coding nochmal etwas lesbarer macht, z.B.:

val KClass<out IDataObject>.properties: List<KMutableProperty<Any>>
    get() {
        return SP.fetch<IDataObjectMetaRepository>().fetch(this).properties
    }

fun List<AttributeProperty<out Any>>.createColumnValues(): ColumnValues {
    return SP.fetch<IColumnValueFactory>().createFromAttributeProperties(this)
}

Ansonsten unterstützt der QueryGenerator ein paar mehr Funktionen wie limit, offset, min und max und ist komplett unitgetestet und das war es diese Woche auch schon wieder mit unserem Fortschritt.

2022-01-18 Zweite Runde des Jahres

Der nächste Sprint 2022 ist abgeschlossen. Wie auch in den letzten Monaten des vergangenen Jahres, ist unsere Sprint-Planung einer beliebigen Abarbeitung von Aufgaben gewichen.

Trotz fehlender Planung bleibt unser Fokus auf dem Backend. Zum einen beschäftigen wir uns mit unserem Service Provider, dessen Funktionsumfang und Funktionsweise immer runder wird. Zum anderen geht es mit unserem Persistenz-Framework vorwärts, in dem der Service Provider immerhin schon in seiner 15. Version und mit einer überaus sehenswerten Testabdeckung zum Einsatz kommt. Außerdem wächst unsere Gradle-API zum Einbinden unserer Git-Bibliotheken in Umfang und Stabilität.

Was außerdem hervorgehoben werden muss ist unsere Lernkurve bzgl. Kotlin. Denn durch unsere hohe Programmiertätigkeit gepaart mit viel Recherche, dem Lesen der Kotlin-Doku und dem Austausch zwischeneinander merken wir, wie wir immer mehr von Kotlin’s-Sprachumfang nutzen. Immer weniger If-Bedingungen sind zu finden, die wir durch bestehende Extensions ersetzen. Null-Prüfungen weichen Kotlin’s Elvis-Operator, statt separate Interfaces nutzen wir immer mehr Lambda-Implementierungen. Wir finden Kotlin ist eine tolle Sprache.

… Folglich gibt es gar nicht viel zu zeigen. Über das Persistenz-Framework gibt es aber Folgendes zu sagen:
– Beim Starten einer Anwendung können Tabellen automatisch gedroppt und neu aufgebaut werden. D.h. Änderungen am Model werden in die DataSource wie bspw. eine Datenbank gepusht.
– Unsere bestehenden Singletons und Services, die von außen überschrieben werden können sollen, wurden auf das Service-Provider Framework umgestellt.
– Vor der Generierung von Tabellen werden die Felder sortiert. So werden alle AutoIncremented Schlüsselfelder, Schlüsselfelder, Datenfelder und Modifizierungs-Timestamps gruppiert.
– Transaktionen werden durch ein ChangeLog unterstützt, das Änderungen an Daten-Objekten aufzeichnet.
Allerdings ist die Liste mit den Anforderungen noch immer lang. Viel Zeit haben wir auch in das Refactoring gesteckt, um Coding zu Vereinfachen.

2022-01-11 Erster!

Erster! Erster Eintrag 2022. Neues Jahr, neues Glück. Der faule Monat ist vorbei. Weihnachten ist vorbei. Neujahr ist vorbei. Das neue Jahr ist in vollem Gang.

Diese Woche und auch im Weihnachtsurlaub haben wir bereits an der App gearbeitet. Mal wieder sind wir dabei alles von rechts auf links zu drehen. An der App an sich haben wir immer noch nichts gemacht. Noch immer sind wir dabei das Backend auf Kotlin umzustellen. Einerseits sind wir dabei Gradle uns gefügig zu machen, anderseits arbeiten wir an unserem Persistenz-Framework.

Für Gradle haben wir weiter an der Variante zur vereinfachten Verwendung gearbeitet und diese auch im Persistenz-Framework eingebaut.

Das Persistenz-Framework, das eine Mischung aus Spring Boot Data, Jetbrains Exposed und simples DAO ist, haben wir weiter ergänzt. Und so langsam hat es den Stand, den wir bereits vorher bei unserem DAO-Framework hatten.

Außerdem haben wir uns in den Feiertagen wieder mehr mit Kotlin beschäftigt. Die Möglichkeiten von Kotlin sind im Vergleich zu ABAP einfach Hammer. Reflection ist so mächtig und Coding zu schreiben so viel kürzer, als wir es aus unserer Arbeitswelt gewohnt sind. Mittlerweile haben wir ein separates Projekt angelegt, um spez. Sprachkonstrukte zu verewigen … und um sie dort immer wieder nachschlagen zu können.

Was steht für dieses Jahr an? Die App veröffentlichen :P.

2021-12-07 Kotlin in Gradle

Letzte Woche haben wir dem ersten Schnee gewidmet, sind dafür aber diese Woche wieder etwas weiter gekommen. Wir haben uns eine Struktur für die DB-Library überlegt und ziehen langsam alles aus unserem Backend-Demo-Projekt um.

Außerdem haben wir uns ein bisschen in Gradle weitergebildet. In einem Artikel sind wir auf die Info gestoßen, dass die Intellij IDE, wenn man statt einem Groovy- ein Kotlin-File als build.gradle verwendet, eine Codevervollständigung erhält. Deshalb sind wir gerade dabei, die Files umzuziehen und evtl. ein eigenes Gradle-Plugin anzulegen, in dem wir zentral unser Coding zum Publishen von Libraries ablegen können. Dadurch würde das Herumkopieren von unzähligen Zeilen Groovy-Codes wegfallen. Aber dafür fehlt noch ein bisschen mehr Recherchearbeit nächste Woche.

2021-11-23 Willkommen zurück „Messy Middle“

Wir sind mitten drinnen, aber waten stetig weiter durch die Messy Middle. Wir haben uns das Exposed-Framework angeschaut, aber es passt nicht wirklich zu dem was wir brauchen, also geht es eventuell zurück ans ORM-Reißbrett.

Unsere ServiceProvider-Library wollte sich nicht in unserem TeamSlimster-Android-Projekt einbinden lassen. Beim ersten Fetch ging nichts mehr. Debuggen war bis vor ein paar Stunden auch nicht möglich. Zum Debuggen müssen die Source-Files heruntergeladen werden, die allerdings nicht Teil unserer Library waren. Deshalb war heute der Gradle-Fortbildungstag und letztendlich wird jetzt auch das Source-File für die Library generiert.

2021-11-16 Up-to-date

Die turbulenten Wochen kommen langsam zum Ende, weshalb wir uns diese Woche wieder ein bisschen mehr mit unserer App beschäftigt haben. Es hieß erstmal, uns gegenseitig wieder auf den neusten Stand zu bringen und vor allem das Wissen über Gradle und die Libraries zu teilen. Außerdem versuchen wir, in unserem Backend Spring Data JPA mit dem Intellij Exposed-Framework zu ersetzen.

Der ServiceProvider, unsere erste Kotlin-Library, ist jetzt geunittestet und war bereit, in unsere Projekte eingebunden zu werden. Zuerst war das Backend-Projekt an der Reihe und nach ein paar Anpassungen läuft jetzt das erste Projekt mit der eingebundenen Library. Yippee!

2021-11-02 Li-La-Library

Es bleibt weiterhin sehr still um die App. Es gibt bei uns gerade immer noch sehr viel nebenher, aber wir arbeiten immer mal wieder ein bisschen an unseren derzeitigen Themen. Nachdem Peter uns in den letzten Wochen ein eigenes ORM-Framework angelegt hat, war es soweit, uns dem eigentlichen Problem zu widmen: den Relationen. Dabei sind wir nochmal ein Stück weiter gekommen, die Lazy-Loading-Thematik von SpringBoot zu verstehen, vor der wir nun auch stehen. Wir wollten unsere DO’s nicht erben lassen, um uns größtmögliche Flexibilität zu bewahren, sondern mit Annotationen arbeiten. Jetzt stehen wir allerdings vor der Frage, wie das DO sich die Relationen, die zunächst lazy geladen werden sollen, nachträglich beschafft und sind letztendlich wieder bei der Überlegung angekommen, doch zu vererben, um das Nachladen zu vereinfachen. Die Vererbung war auch beim Exposed-Framework von JetBrains, neben der Doppelpflege der Attribute, ein Ausschlusskriterium für uns. Nun Fragen wir uns, ob es sich nicht vielleicht doch lohnt, nochmal einen Blick auf Exposed zu werfen und werden dies als nächstes noch einmal angehen.

Nach gefühlt wochenlangem Herumprobieren ist es geschafft. Wir haben eine vollwertige Library auf GithubPackages, in der auch die transitiven Dependencies automatisch beim Einbinden in ein Projekt geladen werden. Transitive Dependencies sind die, die von unserer intern Library genutzt werden und deshalb auch im Projekt, in dem die Library eingebunden wird, vorhanden sein müssen. Bisher mussten wir diese händisch unserem verwendenden Projekt hinzufügen. Der Trick hierbei ist das Hinzufügen der Dependencies in das pom.xml, also das Metafile für die Lib, welches ebenfalls gepublished wird:

build.gradle:
...
publishing {
    publications {
        bar(MavenPublication) {
            groupId getGroupId()
            artifactId getArtifactId()
            version getVersionName()
            artifact("$buildDir/libs/${getArtifactId()}.jar")

            //add all implementation dependencies to the pom file
            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')

                configurations.implementation.allDependencies.each { 
                    dep ->
                    def newDepNode =
                    dependenciesNode.appendNode('dependency')
                    newDepNode.appendNode('groupId', dep.group)
                    newDepNode.appendNode('artifactId', dep.name)
                    newDepNode.appendNode('version', dep.version)
                }
            }
        }
    }

Um den Inhalt des pom-Files zu überprüfen, kann im Gradle-Menü der Punkt „generatePomFileForBarPublication“ unter dem Punkt „Publish“ ausgeführt werden und anschließend das pom-File im Build-Ordner geprüft werden. Hier finden sich dann die Dependencies, welche beim Herunterladen der Lib automatisch mit geladen werden:

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.outlivethesun</groupId>
  <artifactId>serviceprovider</artifactId>
  <version>1.0.1</version>
  <dependencies>
    <dependency>
      <groupId>org.reflections</groupId>
      <artifactId>reflections</artifactId>
      <version>0.9.12</version>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-reflect</artifactId>
      <version>1.5.31</version>
    </dependency>
  </dependencies>
</project>

Im nächsten Schritt können wir nun unsere Framework-Komponenten, wie beispielsweise den ServiceProvider, auslagern und unsere lokalen, doppelten Implementierungen in unseren beiden Projekten ersetzen.

2021-10-05 Library Erstellung und ORM

Viel Neues gibt es auch diese Woche nicht zu berichten. Grundsätzlich arbeiten wir weiter an unserem Backend, an unserem ORM-Framework.
Dank standardisierter Programmiersprache für Backend und Frontend und einem Standard für das Deployment (Gradle), wollen wir unsere bereits implementierten Frameworks für die TeamSlimster-App und für unser Spring Boot Backend nutzen. Hierzu kämpfen wir uns momentan durch die Möglichkeiten, um kleine APIs als Libraries in Github abzulegen, um sie an beliebigen Stellen nutzen zu können.
Bspw. wollen wir unseren ServiceProvider in beliebigen Anwendungen nutzen. Auf der anderen Seite haben wir eine kleine API, mit der wir Datenbank-Tabellen generieren können. Diese API soll aber auch die ServiceProvider API nutzen. Hier liegt momentan der Hund begraben. Wie können wir mit einer API weitere APIs einbinden. Derzeit muss man wissen das DBAccess den ServiceProvider nutzt und beide Bibliotheken einbinden. Es wird sicherlich funktionieren, aber wie wissen wir derzeit noch nicht.
Bekommen wir aber noch hin.

2021-09-28 DAOs, DOs und Annotationen

Unsere Beiträge sind momentan sehr kurzgefasst, aber das ist besser als nichts. Neben unseren Projekten läuft relativ viel. Trotzdem versuchen wir an Team-Slimster weiterzuarbeiten und auch unseren Blog fortzuführen.

Was ging denn diesen Sprint? Auch in diesem Sprint haben wir an unserem Persistenz-Framework weitergearbeitet. Grob teilen wir die Entwicklung in 3 Teile.
In ersten geht es um die Api für verwendende Entwickler (als uns :P). Wir geben alles dem verwendenden Entwickler an die Hand, um eigene DataObjects oder DataAccessObjects zu implementieren. Das ist das erste Mal, dass wir eigene Annotation-Klassen erzeugen und verwenden. Daraus ist bisher eine kleine API entstanden, die mit der Zeit sicherlich noch deutlich wachsen wird.
Im zweiten Teil geht es um die Generierung von Datenbank-Tabellen aus den als DataObjects gekennzeichneten Klassen. Dabei lesen wir die Klassenattribute mit Typ aus und erzeugen daraus Tabellenfelder. Zukünftig werden wir hier sicherlich auch so etwas wie Drop Table oder Modify Table anbieten.
Im dritten Teil geht es um die DataAccessObject Klasse. Diese kümmert sich um das ORM (Object Related Mapping). Über eine DataSource werden Daten aus der Datenbank gelesen und DataObjects erstellt, gespeichert, gereloadet oder gelöscht.
Mit dem aktuellen Stand sind wir auch soweit zufrieden und versuchen gerade alles mehr zu abstrahieren und zu generalisieren, um evtl. sogar eine kleine Library zu erzeugen, die wir anderen Entwicklern zu Verfügung stellen können.
Viele Punkte sind noch offen, deshalb werden wir sicherlich noch eine Weile zutun haben. Aber es macht auch jede Menge Spaß.

2021-09-21 Auf dem Weg zur eigenen Persistenz

Diese Woche haben wir wieder viel herumprobiert, sind aber dafür ein ganzes Stück weitergekommen. Dank Peter kann jetzt munter „gequeried“ werden. Queries können auf einfache Art mittels Methoden wie z.B. equals oder greaterThan aufgebaut werden, aber auch als Literal mit und ohne Platzhalter erstellt werden. Hier haben wir jetzt also volle Flexibilität. Auch das DataAccessObject ist soweit fertig und hat die zusätzlichen Methoden „findByQuery“, „deleteByQuery“ und „existsByQuery“ erhalten, bei denen man die gleiche Query mitgeben kann. Awesome! Zuletzt gab es noch ein paar Probleme mit dem Zurückliefern der ID nach dem Speichern, aber selbst das ist jetzt auf einem guten Weg.

Außerdem haben wir weiter mit Annotationen herumgespielt und haben jetzt eine DataObject und eine DataAccessObject-Annotation, mit denen wir unsere Klassen versehen können. Durch diese Meta-Informationen, in denen z.B. auch der Tabellenname enthalten ist, können wir nun aus unseren Datenobjekten nur durch das Hinzufügen einer Annotation unsere eigenen Tabellen generieren. Da sich alles durch das Herumprobieren in Beispielprojekten tummelt, werden wir uns nächste Woche über das Herausziehen in Libraries Gedanken machen und dann sind wir mit unserem Persistenz-Framework schon ein ganzes Stück weiter.