Upload
sven-efftinge
View
1.157
Download
4
Tags:
Embed Size (px)
Citation preview
Modeling Industry Data with
Eclipse Modeling Project Sven Efftinge (itemis AG)
Dr. Jan Koehnlein (itemis AG)
Frameworks and Tools used to design, use and process
Domain-Specific Languages
EMF
EMF
GMF
EMF
GMF TMF
EMF
GMF TMF
M2M
EMF
GMF TMF
M2M M2T
Experiences made in a real world project
• DB-Application
• Oracle DB
• Oracle Forms
Initial Situation
• Oracle DB
• Java Rich Client
• JPA
• Spring
• Swing / JGoodies Forms
Goal
Quantities• 1722 tables
Quantities• 1722 tables
• 19572 columns
Quantities• 1722 tables
• 19572 columns
• over 300 Forms
Quantities• 1722 tables
• 19572 columns
• over 300 Forms
Our job
Quantities• 1722 tables
• 19572 columns
• over 300 Forms
Our job• Find suitable abstractions
Quantities• 1722 tables
• 19572 columns
• over 300 Forms
Our job• Find suitable abstractions
• Simplify code
Domain Model
@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
@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
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
entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {
String kontoNr
Long rgNrBkrIdentifikator
String referenzcodeKontoNr
}
External DSL with TMF Xtext
entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {
String kontoNr
Long rgNrBkrIdentifikator
String referenzcodeKontoNr
}
BUCHUNGSKREISE_F
RG_NR_BKR_IDENTIFIKATOR
External DSL with TMF Xtext
entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) {}
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
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
Views
public class PersonenForm extends Form<Personen> {
public class PersonenForm extends Form<Personen> {
public class PersonenForm extends Form<Personen> {
public class PersonenHauptSubForm extends SubForm<Personen> {
public class PersonenForm extends Form<Personen> {
public class PersonenHauptSubForm extends SubForm<Personen> {
public class PersonenForm extends Form<Personen> {
public class PersonenHauptSubForm extends SubForm<Personen> {
private JComponent vornameTextField;
public class PersonenForm extends Form<Personen> {
public class PersonenHauptSubForm extends SubForm<Personen> {
private JComponent vornameTextField;
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);
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);
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);
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);
Why not GUI-Builder?• No control over generated
code
• Too many details
• Do not directly leverage information from the domain models
Graphical GUI-DSL with GMF
Graphical GUI-DSL with GMF
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
Validation
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; } });
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
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
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
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());
@Check void checkEsrMsg() { if (!checkKontoNrPruefziffer(parseLong(_this.getEsrNr()))) error("validation.esr.msg",desc.esrNr()); }
Internal DSL in Java
• Junit-like• catches null pointer exceptions
Why do we want to
abstract?
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
5%2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
6%5%2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
5%
6%5%2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
7%
5%
6%5%2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
8%
7%
5%
6%5%2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
67%
8%
7%
5%
6%5%2%
RequirementsSpecificationDesignCodingUnit TestingIntegrationMaintenance
Software Life-Cycle Costs (Schach 2002)
Software maintenance - proportional costs
Software maintenance - proportional costs
Software Rots
Finance related applications of Eclipse Modeling
Questions ?