-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
383 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,32 @@ | ||
# DataOrientedJava | ||
Contains examples I create to demonstrate the application of data oriented programming in modern Java | ||
|
||
In diesem Repository befindet sich ein kleines Beispiel in dem ich die Prinzipien des Data Oriented Programmings mit | ||
Java 19+ und Preview Features demonstriere. | ||
Dieses Beispiel verwende ich in Artikeln und Vorträgen zu dem Themenblock und werde es regelmäßig auf die neusten | ||
Versionen von Java aktualisieren. | ||
|
||
## Das Beispiel: RechnungenErstellen | ||
|
||
In diesem Beispiel erstelle ich für verschiedene Arten von Kunden Rechnungen. | ||
Kunden unterteilen sich in Privat- und Businesskunden, wobei | ||
Businesskunden [Vorsteuerabzugsberechtigt](https://buchhaltungslexikon.de/lexikon/vorsteuerabzugsberechtigt/) sein | ||
können. | ||
|
||
Zusätzlich gibt es zwei Rechnungsarten: intern und extern. | ||
Bei internen Rechnungen handelt es sich um Verrechnungen zu denen keine Rechnung im herkömmlichen Sinne versandt werden | ||
muss. | ||
Bei externen Rechnungen muss die Rechnung formatiert und als E-Mail an den Kunden versandt werden. | ||
|
||
![Domain Modell als Klassendiagramm](BeispielKlasssenDiagramm.svg) | ||
|
||
## Enthalten in dem aktuellen Stand | ||
|
||
1. [JEP 409: Sealed Classes](https://openjdk.java.net/jeps/409) um die Auswahlmöglichkeiten bei der Rechnung und dem | ||
Kunden zu modellieren | ||
2. [JEP 395: Records](https://openjdk.org/jeps/395) um kompakte Data Carrier für Rechnungen und Kunden zu definieren | ||
3. [JEP 394: Pattern Matching for instanceof](https://openjdk.org/jeps/394) um eine Fallunterscheidung zu machen wie ein | ||
Kunde bzw. eine Rechnung verarbeitet wird | ||
4. [JEP 433: Pattern Matching for switch (Fourth Preview)](https://openjdk.org/jeps/433) um die Fallunterscheidung | ||
lesbarer zu machen | ||
5. [JEP 432: Record Patterns (Second Preview)](https://openjdk.org/jeps/432) um direkt auf Record Inhalte zuzugreifen | ||
6. [JEP 430: String Templates (Preview)](https://openjdk.org/jeps/430) um Texte noch besser angenehm zu formatiere |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.github.mboegers.dop.invoice; | ||
|
||
final class Dummy { | ||
/** | ||
* Simuliert einen Versand per Mail. | ||
*/ | ||
static void sendViaMail(String empf, String txt) { | ||
System.out.printf("Sende E-Mail an %s mit Inhalt:%n%s%n", empf, txt); | ||
} | ||
|
||
/** | ||
* Simuliert ein Abspeichern in einer Datenbank | ||
*/ | ||
static void storeInDB(String abt, double value) { | ||
System.out.printf("Speicher %s€ zur Verrechnung mit Abteilung %s%n", value, abt); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package io.github.mboegers.dop.invoice; | ||
|
||
sealed interface Kunde permits Privatkunde, Businesskunde { | ||
String name(); | ||
|
||
String mail(); | ||
} | ||
|
||
record Privatkunde(String name, String mail) implements Kunde { | ||
} | ||
|
||
record Businesskunde(String name, String mail, boolean isVorsteuerAbzugsberechtigt) implements Kunde { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package io.github.mboegers.dop.invoice; | ||
|
||
import java.util.List; | ||
|
||
class Main { | ||
|
||
/** | ||
* Behandlet eine Rechnung abhing davon, ob sie intern oder extern ist. | ||
* Verwendet JEP 432: Record Patterns (Second Preview) https://openjdk.org/jeps/432 | ||
*/ | ||
static void processRechnung(Rechnung rechnung) { | ||
switch (rechnung) { | ||
case InterneVerechnung(var abt, double wert) -> Dummy.storeInDB(abt, wert); | ||
case ExternVersandt(Kunde kunde, var wert) -> { | ||
double mwst = MwStRechner.SwitchExpressionWhenClause.calculateMwSt(kunde, wert); | ||
var txt = formatMail(kunde.name(), wert, mwst); | ||
Dummy.sendViaMail(kunde.mail(), txt); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Formatiert eine Mail Text | ||
*/ | ||
static String formatMail(String name, double wert, double mwst) { | ||
return """ | ||
Hallo %s, | ||
Bitte senden Sie uns den Rechnungsbetrag in Höhe von %.2f€ plus %.2f€ MwSt. | ||
Mit freundlichen Grüßen | ||
Merlin Bögershausen | ||
""".formatted(name, wert, mwst); | ||
} | ||
|
||
/** | ||
* Formtiert eine Mail mit JEP 430: String Templates (Preview) https://openjdk.org/jeps/430 | ||
*/ | ||
/* | ||
static String formatMail_Template(String name, double wert, double mwst) { | ||
return FMT.""" | ||
Hallo \{name}, | ||
Bitte senden Sie uns den Rechnungsbetrag in Höhe von %.2f\{wert}€ plus %.2f\{mwst}€ MwSt. | ||
Mit freundlichen Grüßen | ||
Merlin Bögershausen | ||
"""; // anstelle String.formatted(name, wert, mwst) mit Format | ||
} | ||
*/ | ||
public static void main(String[] args) { | ||
var pk = new Privatkunde("Merlin", ""); | ||
var bk1 = new Businesskunde("adesso SE", "", false); | ||
var bk2 = new Businesskunde("Eureg JUG", "", true); | ||
|
||
System.out.println("Behandle Rechnung"); | ||
var rechnungen = List.of(new InterneVerechnung("HR", 10), new ExternVersandt(bk1, 10), new ExternVersandt(bk2, 10), new ExternVersandt(pk, 10)); | ||
|
||
rechnungen.forEach(Main::processRechnung); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package io.github.mboegers.dop.invoice; | ||
|
||
/** | ||
* Berechne MwSt für verschiedene Arten von Kunden | ||
*/ | ||
final class MwStRechner { | ||
private MwStRechner() { | ||
} | ||
|
||
/** | ||
* Verwende Plain OOP Mittel | ||
*/ | ||
final class PlainOOP { | ||
private PlainOOP() { | ||
} | ||
|
||
/** | ||
* ermöglicht einen einheitlichen Zugriff | ||
*/ | ||
public static double calculateMwSt(Kunde kunde, double wert) { | ||
return calculateMwSt(kunde, wert); | ||
} | ||
|
||
/** | ||
* immer 10% des Kaufwertes für Privatkunden | ||
*/ | ||
private static double calculateMwSt(Privatkunde p, double wert) { | ||
return wert * 0.1d; | ||
} | ||
|
||
/** | ||
* 0% wenn Vorsteuerabzugsberechtigt, sonst 10% | ||
*/ | ||
private static double calculateMwSt(Businesskunde b, double wert) { | ||
return b.isVorsteuerAbzugsberechtigt() ? 0d : wert * 0.1d; | ||
} | ||
} | ||
|
||
/** | ||
* Verwendung JEP 394: Pattern Matching for instanceof https://openjdk.org/jeps/394 | ||
*/ | ||
final class InstanceOfPattern { | ||
private InstanceOfPattern() { | ||
} | ||
|
||
public static double calculateMwSt(Kunde kunde, double wert) { | ||
if (kunde instanceof Businesskunde b) { // abhängig von dem Vorsteuerabzug | ||
if (b.isVorsteuerAbzugsberechtigt()) return 0.0d; | ||
else return wert * 0.1d; | ||
} else if (kunde instanceof Privatkunde) { // immer 10% des Kaufwertes | ||
return wert * 0.1d; | ||
} else { // behandle fehlende Implementierung | ||
throw new IllegalArgumentException("Typ %s nicht implementiert".formatted(kunde)); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Verwendung von JEP 433: Pattern Matching for switch (Fourth Preview) https://openjdk.org/jeps/433 | ||
*/ | ||
final class SwichExpression { | ||
private SwichExpression() { | ||
} | ||
|
||
public static double calculateMwSt(Kunde kunde, double wert) { | ||
return switch (kunde) { | ||
case Businesskunde b -> { | ||
if (b.isVorsteuerAbzugsberechtigt()) yield 0.0d; | ||
else yield wert * 0.1d; | ||
} // alternativ b.vorsteuerAbzug() ? 0.0d : wert * 0.1d; | ||
case Privatkunde p -> wert * 0.1d; | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* Verwendung von JEP 433: Pattern Matching for switch (Fourth Preview) https://openjdk.org/jeps/433 und when-Clause | ||
*/ | ||
final class SwitchExpressionWhenClause { | ||
private SwitchExpressionWhenClause() { | ||
} | ||
|
||
public static double calculateMwSt(Kunde kunde, double wert) { | ||
return switch (kunde) { | ||
case Businesskunde b when b.isVorsteuerAbzugsberechtigt() -> 0.0d; | ||
case Businesskunde b -> wert * 0.1d; | ||
case Privatkunde p -> wert * 0.1d; | ||
}; | ||
} | ||
|
||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package io.github.mboegers.dop.invoice; | ||
|
||
sealed interface Rechnung permits InterneVerechnung, ExternVersandt { | ||
} | ||
|
||
record InterneVerechnung(String abteilung, double wert) implements Rechnung { | ||
} | ||
|
||
record ExternVersandt(Kunde kunde, double wert) implements Rechnung { | ||
} | ||
|