65
Modeling Industry Data with Eclipse Modeling Project Sven Efftinge (itemis AG) Dr. Jan Koehnlein (itemis AG)

Eclipse Banking Day

Embed Size (px)

Citation preview

Page 1: Eclipse Banking Day

Modeling Industry Data with

Eclipse Modeling Project Sven Efftinge (itemis AG)

Dr. Jan Koehnlein (itemis AG)

Page 2: Eclipse Banking Day
Page 3: Eclipse Banking Day

Frameworks and Tools used to design, use and process

Domain-Specific Languages

Page 4: Eclipse Banking Day

EMF

Page 5: Eclipse Banking Day

EMF

GMF

Page 6: Eclipse Banking Day

EMF

GMF TMF

Page 7: Eclipse Banking Day

EMF

GMF TMF

M2M

Page 8: Eclipse Banking Day

EMF

GMF TMF

M2M M2T

Page 9: Eclipse Banking Day

Experiences made in a real world project

Page 10: Eclipse Banking Day

• DB-Application

• Oracle DB

• Oracle Forms

Initial Situation

Page 11: Eclipse Banking Day

• Oracle DB

• Java Rich Client

• JPA

• Spring

• Swing / JGoodies Forms

Goal

Page 12: Eclipse Banking Day

Quantities• 1722 tables

Page 13: Eclipse Banking Day

Quantities• 1722 tables

• 19572 columns

Page 14: Eclipse Banking Day

Quantities• 1722 tables

• 19572 columns

• over 300 Forms

Page 15: Eclipse Banking Day

Quantities• 1722 tables

• 19572 columns

• over 300 Forms

Our job

Page 16: Eclipse Banking Day

Quantities• 1722 tables

• 19572 columns

• over 300 Forms

Our job• Find suitable abstractions

Page 17: Eclipse Banking Day

Quantities• 1722 tables

• 19572 columns

• over 300 Forms

Our job• Find suitable abstractions

• Simplify code

Page 18: Eclipse Banking Day

Domain Model

Page 19: Eclipse Banking Day

@SuppressWarnings("serial")@Entity@Table(name = "BUCHUNGSKREISE_F")public class BuchungskreiseF extends AbstractEntity implements Serializable {

@SuppressWarnings("unused") @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bkrIdSeq") @SequenceGenerator(name = "bkrIdSeq", sequenceName = "BKR_SEQ", allocationSize = 1) @Column(name = "BKR_ID", nullable = false) private Long bkrId;

public Long getBkrId() { return bkrId; }

public void setBkrId(final Long bkrId) { this.bkrId = bkrId; }

@Column(name = "KONTO_NR", nullable = false, length = 45) private String kontoNr;

public String getKontoNr() { return kontoNr; }

public void setKontoNr(final String kontoNr) { String oldValue = this.kontoNr; this.kontoNr = kontoNr; firePropertyChangeEvent("kontoNr", oldValue, this.kontoNr); }

@Column(name = "RG_NR_BKR_IDENTIFIKATOR", nullable = false, length = 1) private Long rgNrBkrIdentifikator;

public Long getRgNrBkrIdentifikator() { return rgNrBkrIdentifikator; }

public void setRgNrBkrIdentifikator(final Long rgNrBkrIdentifikator) { Long oldValue = this.rgNrBkrIdentifikator; this.rgNrBkrIdentifikator = rgNrBkrIdentifikator; firePropertyChangeEvent("rgNrBkrIdentifikator", oldValue, this.rgNrBkrIdentifikator); }

@Column(name = "REFERENZCODE_KONTO_NR", nullable = false, length = 45) private String referenzcodeKontoNr;

public String getReferenzcodeKontoNr() { return referenzcodeKontoNr; }

public void setReferenzcodeKontoNr(final String referenzcodeKontoNr) { String oldValue = this.referenzcodeKontoNr; this.referenzcodeKontoNr = referenzcodeKontoNr; firePropertyChangeEvent("referenzcodeKontoNr", oldValue, this.referenzcodeKontoNr); }

@Column(name = "PC_NR_RG", nullable = false, length = 45) private String pcNrRg;

public String getPcNrRg() { return pcNrRg; }

public void setPcNrRg(final String pcNrRg) { String oldValue = this.pcNrRg; this.pcNrRg = pcNrRg; firePropertyChangeEvent("pcNrRg", oldValue, this.pcNrRg); }

@Column(name = "PC_NR_PVA", nullable = false, length = 45) private String pcNrPva;

public String getPcNrPva() { return pcNrPva; }

public void setPcNrPva(final String pcNrPva) { String oldValue = this.pcNrPva; this.pcNrPva = pcNrPva; firePropertyChangeEvent("pcNrPva", oldValue, this.pcNrPva); }

@Column(name = "MWST_NR", nullable = false, length = 10) private Long mwstNr;

public Long getMwstNr() { return mwstNr; }

public void setMwstNr(final Long mwstNr) { Long oldValue = this.mwstNr; this.mwstNr = mwstNr; firePropertyChangeEvent("mwstNr", oldValue, this.mwstNr); }

@Column(name = "J_VERSION", nullable = false, insertable = false, updatable = false, length = 22)@org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.ALWAYS) @Version private Long jVersion;

public Long getJVersion() { return jVersion; }

public void setJVersion(final Long jVersion) { Long oldValue = this.jVersion; this.jVersion = jVersion; firePropertyChangeEvent("jVersion", oldValue, this.jVersion); }

@Column(name = "IBAN", nullable = false, length = 34) private String iban;

public String getIban() { return iban; }

public void setIban(final String iban) { String oldValue = this.iban; this.iban = iban; firePropertyChangeEvent("iban", oldValue, this.iban); }

@Column(name = "BUCHUNGSKREIS_NR", nullable = false, length = 4) private Long buchungskreisNr;

public Long getBuchungskreisNr() { return buchungskreisNr; }

public void setBuchungskreisNr(final Long buchungskreisNr) { Long oldValue = this.buchungskreisNr; this.buchungskreisNr = buchungskreisNr; firePropertyChangeEvent("buchungskreisNr", oldValue, this.buchungskreisNr); }

}

Entity

BuchungskreiseF

Id

Long bkrId

String kontoNr

nullable = false

nullable = false 45

BUCHUNGSKREISE_F

BKR_ID

KONTO_NR

BKR_SEQ

Page 20: Eclipse Banking Day

@SuppressWarnings("serial")@Entity@Table(name = "BUCHUNGSKREISE_F")public class BuchungskreiseF extends AbstractEntity implements Serializable {

@SuppressWarnings("unused") @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bkrIdSeq") @SequenceGenerator(name = "bkrIdSeq", sequenceName = "BKR_SEQ", allocationSize = 1) @Column(name = "BKR_ID", nullable = false) private Long bkrId;

public Long getBkrId() { return bkrId; }

public void setBkrId(final Long bkrId) { this.bkrId = bkrId; }

@Column(name = "KONTO_NR", nullable = false, length = 45) private String kontoNr;

public String getKontoNr() { return kontoNr; }

public void setKontoNr(final String kontoNr) { String oldValue = this.kontoNr; this.kontoNr = kontoNr; firePropertyChangeEvent("kontoNr", oldValue, this.kontoNr); }

@Column(name = "RG_NR_BKR_IDENTIFIKATOR", nullable = false, length = 1) private Long rgNrBkrIdentifikator;

public Long getRgNrBkrIdentifikator() { return rgNrBkrIdentifikator; }

public void setRgNrBkrIdentifikator(final Long rgNrBkrIdentifikator) { Long oldValue = this.rgNrBkrIdentifikator; this.rgNrBkrIdentifikator = rgNrBkrIdentifikator; firePropertyChangeEvent("rgNrBkrIdentifikator", oldValue, this.rgNrBkrIdentifikator); }

@Column(name = "REFERENZCODE_KONTO_NR", nullable = false, length = 45) private String referenzcodeKontoNr;

public String getReferenzcodeKontoNr() { return referenzcodeKontoNr; }

public void setReferenzcodeKontoNr(final String referenzcodeKontoNr) { String oldValue = this.referenzcodeKontoNr; this.referenzcodeKontoNr = referenzcodeKontoNr; firePropertyChangeEvent("referenzcodeKontoNr", oldValue, this.referenzcodeKontoNr); }

@Column(name = "PC_NR_RG", nullable = false, length = 45) private String pcNrRg;

public String getPcNrRg() { return pcNrRg; }

public void setPcNrRg(final String pcNrRg) { String oldValue = this.pcNrRg; this.pcNrRg = pcNrRg; firePropertyChangeEvent("pcNrRg", oldValue, this.pcNrRg); }

@Column(name = "PC_NR_PVA", nullable = false, length = 45) private String pcNrPva;

public String getPcNrPva() { return pcNrPva; }

public void setPcNrPva(final String pcNrPva) { String oldValue = this.pcNrPva; this.pcNrPva = pcNrPva; firePropertyChangeEvent("pcNrPva", oldValue, this.pcNrPva); }

@Column(name = "MWST_NR", nullable = false, length = 10) private Long mwstNr;

public Long getMwstNr() { return mwstNr; }

public void setMwstNr(final Long mwstNr) { Long oldValue = this.mwstNr; this.mwstNr = mwstNr; firePropertyChangeEvent("mwstNr", oldValue, this.mwstNr); }

@Column(name = "J_VERSION", nullable = false, insertable = false, updatable = false, length = 22)@org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.ALWAYS) @Version private Long jVersion;

public Long getJVersion() { return jVersion; }

public void setJVersion(final Long jVersion) { Long oldValue = this.jVersion; this.jVersion = jVersion; firePropertyChangeEvent("jVersion", oldValue, this.jVersion); }

@Column(name = "IBAN", nullable = false, length = 34) private String iban;

public String getIban() { return iban; }

public void setIban(final String iban) { String oldValue = this.iban; this.iban = iban; firePropertyChangeEvent("iban", oldValue, this.iban); }

@Column(name = "BUCHUNGSKREIS_NR", nullable = false, length = 4) private Long buchungskreisNr;

public Long getBuchungskreisNr() { return buchungskreisNr; }

public void setBuchungskreisNr(final Long buchungskreisNr) { Long oldValue = this.buchungskreisNr; this.buchungskreisNr = buchungskreisNr; firePropertyChangeEvent("buchungskreisNr", oldValue, this.buchungskreisNr); }

}

Entity

BuchungskreiseF

Id

Long bkrId

String kontoNr

nullable = false

nullable = false 45

BUCHUNGSKREISE_F

BKR_ID

KONTO_NR

BKR_SEQ

Page 21: Eclipse Banking Day

entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {

String kontoNr

Long rgNrBkrIdentifikator

String referenzcodeKontoNr

}

(notNull, length=45)

(notNull, length=45)

(notNull, length=1)

External DSL with TMF Xtext

Page 22: Eclipse Banking Day

entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {

String kontoNr

Long rgNrBkrIdentifikator

String referenzcodeKontoNr

}

External DSL with TMF Xtext

Page 23: Eclipse Banking Day

entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {

String kontoNr

Long rgNrBkrIdentifikator

String referenzcodeKontoNr

}

BUCHUNGSKREISE_F

RG_NR_BKR_IDENTIFIKATOR

External DSL with TMF Xtext

Page 24: Eclipse Banking Day

entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {}

Page 25: Eclipse Banking Day

entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {}

Database Schema

TABLE BUCHUNGSKREISE_F

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

Page 26: Eclipse Banking Day
Page 27: Eclipse Banking Day

0 TZ

60 TZ

120 TZ

180 TZ

240 TZ

300 TZ

0 20 40

30.000 (DSL)+ 50.000 (code generator)+ 170 / Entity

7000 / Entity

Number of Characters (Domain model DSL)

With DSL

Without DSL

11 Entities

Page 28: Eclipse Banking Day

Views

Page 29: Eclipse Banking Day
Page 30: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

Page 31: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

Page 32: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

Page 33: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

Page 34: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

private JComponent vornameTextField;

Page 35: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

private JComponent vornameTextField;

Page 36: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

private JComponent vornameTextField;

@Overrideprotected void initComponents() {

...vornameTextField = builder.createTextField(desc.vorname(),

Editable.PROPERTY_DEFAULT, MANDATORY);

gepardBuilder.setNoLeadingBlanks(vornameTextField);

Page 37: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

private JComponent vornameTextField;

@Overrideprotected void initComponents() {

...vornameTextField = builder.createTextField(desc.vorname(),

Editable.PROPERTY_DEFAULT, MANDATORY);

gepardBuilder.setNoLeadingBlanks(vornameTextField);

Page 38: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

private JComponent vornameTextField;

@Overrideprotected void initComponents() {

...vornameTextField = builder.createTextField(desc.vorname(),

Editable.PROPERTY_DEFAULT, MANDATORY);

gepardBuilder.setNoLeadingBlanks(vornameTextField);

@Override protected JComponent buildPanel() {

TwoColumnsPanelBuilder builder = TwoColumnsPanelBuilder.instance(getBuilderFactory(),

getResourceMap());...builder.add("vorname", vornameTextField);

Page 39: Eclipse Banking Day

public class PersonenForm extends Form<Personen> {

public class PersonenHauptSubForm extends SubForm<Personen> {

private JComponent vornameTextField;

@Overrideprotected void initComponents() {

...vornameTextField = builder.createTextField(desc.vorname(),

Editable.PROPERTY_DEFAULT, MANDATORY);

gepardBuilder.setNoLeadingBlanks(vornameTextField);

@Override protected JComponent buildPanel() {

TwoColumnsPanelBuilder builder = TwoColumnsPanelBuilder.instance(getBuilderFactory(),

getResourceMap());...builder.add("vorname", vornameTextField);

Page 40: Eclipse Banking Day

Why not GUI-Builder?• No control over generated

code

• Too many details

• Do not directly leverage information from the domain models

Page 41: Eclipse Banking Day

Graphical GUI-DSL with GMF

Page 42: Eclipse Banking Day

Graphical GUI-DSL with GMF

Page 43: Eclipse Banking Day

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

ID NAME PROP1 DATE ATTR1

model : gepard; import "platform:/resource/com.affichage.it21.gp.dao/src/main/model/types.dao"

com.affichage.it21.gp.dao {

flaechen { readOnly entity WaehrungF (id =(rvLowValue)) { } readOnly entity GepardVerwendungPvF (id =(pvOid)) { temporal manyToOne GeschpartnerAllBsF geschpartner (joinColum } } verkauf { readOnly entity GepardVerwendungKdvtF (id =(kdvtId)) { temporal notNull manyToOne GeschpartnerAllBsF geschpartner (j notNull Number istLangfrist (castTo=Boolean) notNull Number istLokaldispo (castTo=Boolean) } }

gepard { readOnly entity AbcKundenF (id = (rvLowValue)) {

Referencing

Page 44: Eclipse Banking Day

Validation

Page 45: Eclipse Banking Day
Page 46: Eclipse Banking Day

addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } });

Page 47: Eclipse Banking Day

addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } });

Eliminate framework code

Page 48: Eclipse Banking Day

addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } });

Eliminate framework codeAvoid repetitive null pointer checks

Page 49: Eclipse Banking Day

addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } });

Eliminate framework codeAvoid repetitive null pointer checksUse static imports

Page 50: Eclipse Banking Day

addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } });

Eliminate framework codeAvoid repetitive null pointer checksUse static importsUse and define library methods

error("validation.esr.msg", desc.esrNr());

Page 51: Eclipse Banking Day

@Check void checkEsrMsg() { if (!checkKontoNrPruefziffer(parseLong(_this.getEsrNr()))) error("validation.esr.msg",desc.esrNr()); }

Internal DSL in Java

• Junit-like• catches null pointer exceptions

Page 52: Eclipse Banking Day

Why do we want to

abstract?

Page 53: Eclipse Banking Day

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 54: Eclipse Banking Day

2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 55: Eclipse Banking Day

5%2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 56: Eclipse Banking Day

6%5%2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 57: Eclipse Banking Day

5%

6%5%2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 58: Eclipse Banking Day

7%

5%

6%5%2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 59: Eclipse Banking Day

8%

7%

5%

6%5%2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 60: Eclipse Banking Day

67%

8%

7%

5%

6%5%2%

RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance

Software Life-Cycle Costs (Schach 2002)

Page 61: Eclipse Banking Day

Software maintenance - proportional costs

Page 62: Eclipse Banking Day

Software maintenance - proportional costs

Page 63: Eclipse Banking Day

Software Rots

Page 64: Eclipse Banking Day

Finance related applications of Eclipse Modeling

Page 65: Eclipse Banking Day

Questions ?