SlideShare uma empresa Scribd logo
1 de 91
Baixar para ler offline
Write('A');
abstractie
wat?
waarom?
hoe?
valkuilen
conclusie
wat?
“Abstraction is the process of generalization by
 reducing the information content of a concept in
order to retain only information which is relevant
             for a particular purpose.”
                                    -- Wikipedia (ed.)
waarom?
bestanden
                                vensters


                  mappen

                            knoppen
multi-tasking


                invoer velden
hoe?
printChar('N');                    char[] anBuffer = new char[255];
printChar('a');                    int anLength = 0;
printChar('a');                    do {
printChar('m');                      inp = readChar();
printChar(':');                      anBuffer[anLength] = inp;
printChar(' ');                      anLength++;
                                   while (inp != 'n');
char[] vnBuffer = new char[255];
int vnLength = 0;                  printChar('H');
char inp;                          printChar('a');
do {                               printChar('l');
  inp = readChar();                printChar('l');
  vnBuffer[vnLength] = inp;        printChar('o');
  vnLength++;                      printChar(' ');
while (inp != 'n');               int i = 0;
                                   while(i < vnLength) {
printChar('A');                      printChar(vnBuffer[i]);
printChar('c');                      i++;
printChar('h');                    }
printChar('t');                    printChar(' ');
printChar('e');                    i = 0;
printChar('r');                    while(i < anLength) {
printChar('n');                      printChar(anBuffer[i]);
printChar('a');                      i++;
printChar('a');                    }
printChar('m');
printChar(':');
printChar('N');                    char[] anBuffer = new char[255];
printChar('a');                    int anLength = 0;
printChar('a');                    do {
printChar('m');                      inp = readChar();
printChar(':');                      anBuffer[anLength] = inp;
printChar(' ');                      anLength++;
                                   while (inp != 'n');
char[] vnBuffer = new char[255];
int vnLength = 0;                  printChar('H');
char inp;                          printChar('a');
do {                               printChar('l');
  inp = readChar();                printChar('l');
  vnBuffer[vnLength] = inp;        printChar('o');
  vnLength++;                      printChar(' ');
while (inp != 'n');               int i = 0;
                                   while(i < vnLength) {
printChar('A');                      printChar(vnBuffer[i]);
printChar('c');                      i++;
printChar('h');                    }
printChar('t');                    printChar(' ');
printChar('e');                    i = 0;
printChar('r');                    while(i < anLength) {
printChar('n');                      printChar(anBuffer[i]);
printChar('a');                      i++;
printChar('a');                    }
printChar('m');
printChar(':');
printChar('N');                    char[] anBuffer = new char[255];
printChar('a');                    int anLength = 0;
printChar('a');                    do {
printChar('m');                      inp = readChar();
printChar(':');                      anBuffer[anLength] = inp;
printChar(' ');                      anLength++;
                                   while (inp != 'n');
char[] vnBuffer = new char[255];
int vnLength = 0;                  printChar('H');
char inp;                          printChar('a');
do {                               printChar('l');
  inp = readChar();                printChar('l');
  vnBuffer[vnLength] = inp;        printChar('o');
  vnLength++;                      printChar(' ');
while (inp != 'n');               int i = 0;
                                   while(i < vnLength) {
printChar('A');                      printChar(vnBuffer[i]);
printChar('c');                      i++;
printChar('h');                    }
printChar('t');                    printChar(' ');
printChar('e');                    i = 0;
printChar('r');                    while(i < anLength) {
printChar('n');                      printChar(anBuffer[i]);
printChar('a');                      i++;
printChar('a');                    }
printChar('m');
printChar(':');
printChars(new char[] { 'N', 'a', 'a', 'm', ':', ' '}, 6);
char[] vnBuf = new char[255];
int vnLength = readChars(vnBuf);

printChars(new char[] { 'A', 'c', 'h', 't', 'e', 'r', 'n', 'a', 'a', 'm', ':', ' '},
           12);
char[] anBuf = new char[255];
int anLength = readChars(vnBuf);

printChars(new char[] {'H', 'a', 'l', 'l', 'o', ' '}, 6);
printChars(vnBuf, vnLength);
printChars(anBuf, anLength);
String voornaam = readLine("Naam: ");
String achternaam = readLine("Achternaam: ");
print("Hallo " + voornaam + " " + achternaam);
FullName fn = FullName.read();
fn.printGreeting();
readNameAndPrintGreeting();
goed abstractie
   niveau?
readNameAndPrintGreeting();




  nieuwe eis: vraag ook naar leeftijd
readNameAndPrintGreeting();




  nieuwe eis: vraag ook naar leeftijd   ✖
FullName fn = FullName.read();
fn.printGreeting();




  nieuwe eis: vraag ook naar leeftijd
FullName fn = FullName.read();
fn.printGreeting();




  nieuwe eis: vraag ook naar leeftijd   ✖
String voornaam = readLine("Naam: ");
String achternaam = readLine("Achternaam: ");
print("Hallo " + voornaam + " " + achternaam);




  nieuwe eis: vraag ook naar leeftijd
String voornaam = readLine("Naam: ");
String achternaam = readLine("Achternaam: ");
int leeftijd = stringToInt(readLine("Leeftijd: "));
print("Hallo " + voornaam + " " + achternaam +
      ", jij bent " + leeftijd + " jaar oud.");




  nieuwe eis: vraag ook naar leeftijd                 ✔
goed abstractie niveau afhankelijk van
goed abstractie niveau afhankelijk van

             gebruik nu
goed abstractie niveau afhankelijk van

             gebruik nu

            gebruik later
Web applicaties in
  Java/Seam
Model   View   Controller
Data: Hibernate
@Entity
public class Blog {
   protected String _title = "";
   public String getTitle() {
     return _title;
   }
   public void setTitle(String value) {
     _title = value;
   }
   @ManyToOne
   protected User _author;
   public User getAuthor() {
     return _author;
   }
   public void setAuthor(User author) {
     _title = value;
   }
   @OneToMany(mappedBy="_blog",
              targetEntity=BlogEntry.class)
   @Cascade(...)
   protected List<BlogEntry> _entries;
   public List<BlogEntry> getEntries() {
     return _entries;
   }
   public void setEntries(List<BlogEntry> entries) {
     _entries = entries;
   }
}
View: JSF
<html ...> ... <body> ...
<h:form>
<table>
<tr><td><h:outputText value="Title: "/></td>
<td><h:inputText value="#{editBlogEntry.e.title}" /></td>
</tr><tr>
<td><h:outputText value="Created: "/></td>
<td><rich:calendar value="#{editBlogEntry.e.created}"
popup="true" datePattern="dd/MM/yyyy" .../></td>
</tr><tr>
<td><h:outputText value="Content: "/></td>
<td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td>
</tr><tr>
<td><h:outputText value="Status: "/></td>
<td><h:selectOneMenu value="#{editBlogEntry.e.status}">
<s:selectItems value="#{editBlogEntry.blogEntryStatusList}"
var="blogEntryStatus" label="#{blogEntryStatus.name}" />
<s:convertEntity/>
</h:selectOneMenu></td>
</tr>
</table>
<h:actionLink action=”#{editBlogEntry.save()}”/>
</h:form>
... </body> </html>
Controller
@Stateful @Name(“editBlogEntry”)
public class EditBlogEntry {
   ...
   @In @Out
   private BlogEntry e;

    public void setE(e) {
      this.e = e;
    }

    public BlogEntry getE() {
      return this.e;
    }

    public void save() {
      em.persist(e);
    }
    ...
}
Configuratie
<?xml version="1.0" ?>
<web-app ...>
  <context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/WEB-INF/blog.taglib.xml</param-value>
  </context-param>
  <filter>
    <filter-name>Seam Filter</filter-name>
    <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
  </filter>
  <filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <init-param>
       <param-name>logLevel</param-name>
       <param-value>WARN</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>Seam Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
      <servlet-name>Seam Resource Servlet</servlet-name>
      <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.seam</url-pattern>
  </servlet-mapping>
  ...
</web-app>
allemaal hetzelfde
allemaal hetzelfde

Gebruiker
allemaal hetzelfde

Gebruiker
maken
wijzigen
verwijderen
koppelen
allemaal hetzelfde

Gebruiker        Bericht
maken
wijzigen
verwijderen
koppelen
allemaal hetzelfde

Gebruiker        Bericht
maken            maken
wijzigen         wijzigen
verwijderen      verwijderen
koppelen         koppelen
allemaal hetzelfde

Gebruiker        Bericht       Reactie
maken            maken
wijzigen         wijzigen
verwijderen      verwijderen
koppelen         koppelen
allemaal hetzelfde

Gebruiker        Bericht       Reactie
maken            maken         maken
wijzigen         wijzigen      wijzigen
verwijderen      verwijderen   verwijderen
koppelen         koppelen      koppelen
allemaal hetzelfde

Gebruiker        Bericht       Reactie
maken            maken         maken
wijzigen         wijzigen      wijzigen
verwijderen      verwijderen   verwijderen
koppelen         koppelen      koppelen


              boiler plate code
Data
@Entity
public class Blog {
   protected String _title = "";
   public String getTitle() {
     return _title;
   }
   public void setTitle(String value) {
     _title = value;
   }
   @ManyToOne
   protected User _author;
   public User getAuthor() {
     return _author;
   }
   public void setAuthor(User author) {
     _title = value;
   }
   @OneToMany(mappedBy="_blog",
              targetEntity=BlogEntry.class)
   @Cascade(...)
   protected List<BlogEntry> _entries;
   public List<BlogEntry> getEntries() {
     return _entries;
   }
   public void
   setEntries(List<BlogEntry> entries) {
     _entries = entries;
   }
}
Data
@Entity
public class Blog {
   protected String _title = "";
   public String getTitle() {
     return _title;
   }
   public void setTitle(String value) {
     _title = value;
   }
   @ManyToOne
   protected User _author;
   public User getAuthor() {                  entity Blog {
     return _author;                            author   -> User (inverse=User.blogs)
   }                                            title    :: String
   public void setAuthor(User author) {         entries <> Set<BlogEntry>
     _title = value;                          }
   }
   @OneToMany(mappedBy="_blog",
              targetEntity=BlogEntry.class)
   @Cascade(...)
   protected List<BlogEntry> _entries;
   public List<BlogEntry> getEntries() {
     return _entries;
   }
   public void
   setEntries(List<BlogEntry> entries) {
     _entries = entries;
   }
}
<html ...> ... <body> ...
                                            Pagina’s
<h:form>
<table>
<tr><td><h:outputText value="Title: "/></td>                     @Stateful @Name(“editBlogEntry”)
<td><h:inputText value="#{editBlogEntry.e.title}" /></td>        public class EditBlogEntry {
</tr><tr>                                                           ...
<td><h:outputText value="Created: "/></td>                          @In @Out
<td><rich:calendar value="#{editBlogEntry.e.created}"               private BlogEntry e;
popup="true" datePattern="dd/MM/yyyy" .../></td>                     public void setE(e) {
</tr><tr>                                                              this.e = e;
<td><h:outputText value="Content: "/></td>                           }
<td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td>
</tr><tr>                                                            public BlogEntry getE() {
<td><h:outputText value="Status: "/></td>                              return this.e;
<td><h:selectOneMenu value="#{editBlogEntry.e.status}">              }
<s:selectItems value="#{editBlogEntry.blogEntryStatusList}"
                                                                     public void save() {
var="blogEntryStatus" label="#{blogEntryStatus.name}" />               em.persist(e);
<s:convertEntity/>                                                   }
</h:selectOneMenu></td>                                              ...
</tr>                                                            }
</table>
<h:actionLink action=”#{editBlogEntry.save()}”/>
</h:form>
... </body> </html>
<html ...> ... <body> ...
                                            Pagina’s
<h:form>
<table>
<tr><td><h:outputText value="Title: "/></td>                     @Stateful @Name(“editBlogEntry”)
<td><h:inputText value="#{editBlogEntry.e.title}" /></td>        public class EditBlogEntry {
</tr><tr>                                                           ...
<td><h:outputText value="Created: "/></td>                          @In @Out
<td><rich:calendar value="#{editBlogEntry.e.created}"               private BlogEntry e;
popup="true" datePattern="dd/MM/yyyy" .../></td>                     public void setE(e) {
</tr><tr>                                                              this.e = e;
<td><h:outputText value="Content: "/></td>                           }
<td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td>
</tr><tr>                                                            public BlogEntry getE() {
<td><h:outputText value="Status: "/></td>                              return this.e;
<td><h:selectOneMenu value="#{editBlogEntry.e.status}">              }
<s:selectItems value="#{editBlogEntry.blogEntryStatusList}"
                                                                     public void save() {
var="blogEntryStatus" label="#{blogEntryStatus.name}" />               em.persist(e);
<s:convertEntity/>                                                   }
</h:selectOneMenu></td>                                              ...
</tr>                                                            }
</table>
<h:actionLink action=”#{editBlogEntry.save()}”/>
</h:form>
... </body> </html>




define page editBlogEntry(e : BlogEntry) {
  form{
    table{
      row{ "Title: " input(e.title) }
      row{ "Created: " input(e.created) }
      row{ "Content: " input(e.content) }
      row{ "Status: " input(e.status) }
      action("Save", save())
    }
  }
  action save() {
    e.save();
    return blogEntry(e);
  }
}
<html ...> ... <body> ...
                                            Pagina’s
<h:form>
<table>
<tr><td><h:outputText value="Title: "/></td>                     @Stateful @Name(“editBlogEntry”)
<td><h:inputText value="#{editBlogEntry.e.title}" /></td>        public class EditBlogEntry {
</tr><tr>                                                           ...
<td><h:outputText value="Created: "/></td>                          @In @Out
<td><rich:calendar value="#{editBlogEntry.e.created}"               private BlogEntry e;
popup="true" datePattern="dd/MM/yyyy" .../></td>                     public void setE(e) {
</tr><tr>                                                              this.e = e;
<td><h:outputText value="Content: "/></td>                           }
<td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td>
</tr><tr>                                                            public BlogEntry getE() {
<td><h:outputText value="Status: "/></td>                              return this.e;
<td><h:selectOneMenu value="#{editBlogEntry.e.status}">              }
<s:selectItems value="#{editBlogEntry.blogEntryStatusList}"
                                                                     public void save() {
var="blogEntryStatus" label="#{blogEntryStatus.name}" />               em.persist(e);
<s:convertEntity/>                                                   }
</h:selectOneMenu></td>                                              ...
</tr>                                                            }
</table>
<h:actionLink action=”#{editBlogEntry.save()}”/>
</h:form>
... </body> </html>
<html ...> ... <body> ...
                                            Pagina’s
<h:form>
<table>
<tr><td><h:outputText value="Title: "/></td>                     @Stateful @Name(“editBlogEntry”)
<td><h:inputText value="#{editBlogEntry.e.title}" /></td>        public class EditBlogEntry {
</tr><tr>                                                           ...
<td><h:outputText value="Created: "/></td>                          @In @Out
<td><rich:calendar value="#{editBlogEntry.e.created}"               private BlogEntry e;
popup="true" datePattern="dd/MM/yyyy" .../></td>                     public void setE(e) {
</tr><tr>                                                              this.e = e;
<td><h:outputText value="Content: "/></td>                           }
<td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td>
</tr><tr>                                                            public BlogEntry getE() {
<td><h:outputText value="Status: "/></td>                              return this.e;
<td><h:selectOneMenu value="#{editBlogEntry.e.status}">              }
<s:selectItems value="#{editBlogEntry.blogEntryStatusList}"
                                                                     public void save() {
var="blogEntryStatus" label="#{blogEntryStatus.name}" />               em.persist(e);
<s:convertEntity/>                                                   }
</h:selectOneMenu></td>                                              ...
</tr>                                                            }
</table>
<h:actionLink action=”#{editBlogEntry.save()}”/>
</h:form>
... </body> </html>




define page editBlogEntry(e : BlogEntry) {
  derive editPage from e
}
10-50x
WebDSL code




WebDSL compiler




    Java applicatie
(Java, JSF, Hibernate)
valkuilen
entity User {
  username :: String
  password :: Secret
}

entity   Update {
  user   -> User
  date   :: DateTime
  text   :: Text
}
entity User {
  username :: String
  password :: Secret
}

entity   Update {
  user   -> User
  date   :: DateTime
  text   :: Text
}


define page home() {
  for(u : Update) {
    output(u.user.username) ": " output(u.text)
    spacer
  }
}
entity User {
  username :: String
  password :: Secret
}

entity   Update {
  user   -> User
  date   :: DateTime
  text   :: Text
}


define page home() {
  for(u : Update) {
    output(u.user.username) ": " output(u.text)
    spacer
  }
}
define page home() {
  header{ "Twitr" }
  spacer
  for(u : Update) {
    output(u.user.username) ": " output(u.text)
    spacer
  }
  "(C) Zef Hemel"
}
define page login() {
  header{ "Twitr" }
  spacer
  var u : User

    form {
      "Login: " input(u)
      action("Login", login())

     action login() {
       session.user := u;
       return home();
     }
    }
    spacer
    "(C) Zef Hemel"
}
define page login() {
  header{ "Twitr" }
  spacer
  var u : User

    form {
      "Login: " input(u)
      action("Login", login())

     action login() {
       session.user := u;
       return home();
     }
    }
    spacer
    "(C) Zef Hemel"
}
template
abstractie!
define template main() {
  header{ "Twitr" }
  spacer
  body()
  "(C) Zef Hemel"
}

define page home() {
  main()
  define body() {
    for(u : Update) {
      output(u.user.username) ": " output(u.text)
      spacer
    }
  }
}
WebDSL code




Template expander




WebDSL compiler




    Java applicatie
(Java, JSF, Hibernate)
template expander
  define page home() {
    main()
    define body()
      for(u : Update) {
        output(u.user.username) ": " output(u.text)
        spacer
      }
    }
  }




  define page home() {
    header{ "Twitr" }
    spacer
    for(u : Update) {
      output(u.user.username) ": " output(u.text)
      spacer
    }
    "(C) Zef Hemel"
  }
maar...


JSF had ook al templates
WebDSL code




            Template expander




            WebDSL compiler




                Java applicatie
templates   (Java, JSF, Hibernate)
WebDSL code




            Template expander




templates   WebDSL compiler




                Java applicatie
templates   (Java, JSF, Hibernate)
WebDSL code



herimplementeert
 templates         Template expander




 templates         WebDSL compiler




                       Java applicatie
templates          (Java, JSF, Hibernate)
abstraction
                    inversion
                       WebDSL code



herimplementeert
 templates           Template expander




 templates            WebDSL compiler




                         Java applicatie
templates            (Java, JSF, Hibernate)
abstraction
                    inversion
                       WebDSL code



herimplementeert
 templates           Template expander




 templates            WebDSL compiler         slechte abstractie



                         Java applicatie
templates            (Java, JSF, Hibernate)
“All non-trivial
abstractions, to some
 degree, are leaky.”
       -- Joel Spolsky
abstracties verbergen implementatie
abstracties verbergen implementatie

  dat lukt eigenlijk nooit volledig
abstracties verbergen implementatie

  dat lukt eigenlijk nooit volledig


  WebDSL templates
abstracties verbergen implementatie

  dat lukt eigenlijk nooit volledig


  WebDSL templates
  NFS/SMB
abstracties verbergen implementatie

  dat lukt eigenlijk nooit volledig


  WebDSL templates
  NFS/SMB
  twee-dimensionale arrays
abstracties verbergen implementatie

  dat lukt eigenlijk nooit volledig


  WebDSL templates
  NFS/SMB
  twee-dimensionale arrays
  SQL
conclusie
abstractie is essentieel
abstractie is essentieel
              moeilijk
denk kritisch na
denk kritisch na
heb ik dit vaker gedaan?
denk kritisch na
 heb ik dit vaker gedaan?
gaat iemand dit vaker doen?
ja?



abstraheer
webdsl.org
 zef.me

Mais conteúdo relacionado

Destaque

mobl presentation @ IHomer
mobl presentation @ IHomermobl presentation @ IHomer
mobl presentation @ IHomerzefhemel
 
Frontrow conf
Frontrow confFrontrow conf
Frontrow confzefhemel
 
Avoiding JavaScript Pitfalls Through Tree Hugging
Avoiding JavaScript Pitfalls Through Tree HuggingAvoiding JavaScript Pitfalls Through Tree Hugging
Avoiding JavaScript Pitfalls Through Tree Huggingzefhemel
 
Cloud9 IDE Talk at meet.js Poznań
Cloud9 IDE Talk at meet.js PoznańCloud9 IDE Talk at meet.js Poznań
Cloud9 IDE Talk at meet.js Poznańzefhemel
 
Internal DSLs
Internal DSLsInternal DSLs
Internal DSLszefhemel
 
WebWorkFlow
WebWorkFlowWebWorkFlow
WebWorkFlowzefhemel
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecturezefhemel
 
PIL - A Platform Independent Language
PIL - A Platform Independent LanguagePIL - A Platform Independent Language
PIL - A Platform Independent Languagezefhemel
 

Destaque (9)

mobl presentation @ IHomer
mobl presentation @ IHomermobl presentation @ IHomer
mobl presentation @ IHomer
 
mobl
moblmobl
mobl
 
Frontrow conf
Frontrow confFrontrow conf
Frontrow conf
 
Avoiding JavaScript Pitfalls Through Tree Hugging
Avoiding JavaScript Pitfalls Through Tree HuggingAvoiding JavaScript Pitfalls Through Tree Hugging
Avoiding JavaScript Pitfalls Through Tree Hugging
 
Cloud9 IDE Talk at meet.js Poznań
Cloud9 IDE Talk at meet.js PoznańCloud9 IDE Talk at meet.js Poznań
Cloud9 IDE Talk at meet.js Poznań
 
Internal DSLs
Internal DSLsInternal DSLs
Internal DSLs
 
WebWorkFlow
WebWorkFlowWebWorkFlow
WebWorkFlow
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
 
PIL - A Platform Independent Language
PIL - A Platform Independent LanguagePIL - A Platform Independent Language
PIL - A Platform Independent Language
 

Abstractie (Dutch)

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 11. wat?
  • 12. “Abstraction is the process of generalization by reducing the information content of a concept in order to retain only information which is relevant for a particular purpose.” -- Wikipedia (ed.)
  • 14.
  • 15. bestanden vensters mappen knoppen multi-tasking invoer velden
  • 16. hoe?
  • 17. printChar('N'); char[] anBuffer = new char[255]; printChar('a'); int anLength = 0; printChar('a'); do { printChar('m'); inp = readChar(); printChar(':'); anBuffer[anLength] = inp; printChar(' '); anLength++; while (inp != 'n'); char[] vnBuffer = new char[255]; int vnLength = 0; printChar('H'); char inp; printChar('a'); do { printChar('l'); inp = readChar(); printChar('l'); vnBuffer[vnLength] = inp; printChar('o'); vnLength++; printChar(' '); while (inp != 'n'); int i = 0; while(i < vnLength) { printChar('A'); printChar(vnBuffer[i]); printChar('c'); i++; printChar('h'); } printChar('t'); printChar(' '); printChar('e'); i = 0; printChar('r'); while(i < anLength) { printChar('n'); printChar(anBuffer[i]); printChar('a'); i++; printChar('a'); } printChar('m'); printChar(':');
  • 18. printChar('N'); char[] anBuffer = new char[255]; printChar('a'); int anLength = 0; printChar('a'); do { printChar('m'); inp = readChar(); printChar(':'); anBuffer[anLength] = inp; printChar(' '); anLength++; while (inp != 'n'); char[] vnBuffer = new char[255]; int vnLength = 0; printChar('H'); char inp; printChar('a'); do { printChar('l'); inp = readChar(); printChar('l'); vnBuffer[vnLength] = inp; printChar('o'); vnLength++; printChar(' '); while (inp != 'n'); int i = 0; while(i < vnLength) { printChar('A'); printChar(vnBuffer[i]); printChar('c'); i++; printChar('h'); } printChar('t'); printChar(' '); printChar('e'); i = 0; printChar('r'); while(i < anLength) { printChar('n'); printChar(anBuffer[i]); printChar('a'); i++; printChar('a'); } printChar('m'); printChar(':');
  • 19. printChar('N'); char[] anBuffer = new char[255]; printChar('a'); int anLength = 0; printChar('a'); do { printChar('m'); inp = readChar(); printChar(':'); anBuffer[anLength] = inp; printChar(' '); anLength++; while (inp != 'n'); char[] vnBuffer = new char[255]; int vnLength = 0; printChar('H'); char inp; printChar('a'); do { printChar('l'); inp = readChar(); printChar('l'); vnBuffer[vnLength] = inp; printChar('o'); vnLength++; printChar(' '); while (inp != 'n'); int i = 0; while(i < vnLength) { printChar('A'); printChar(vnBuffer[i]); printChar('c'); i++; printChar('h'); } printChar('t'); printChar(' '); printChar('e'); i = 0; printChar('r'); while(i < anLength) { printChar('n'); printChar(anBuffer[i]); printChar('a'); i++; printChar('a'); } printChar('m'); printChar(':');
  • 20. printChars(new char[] { 'N', 'a', 'a', 'm', ':', ' '}, 6); char[] vnBuf = new char[255]; int vnLength = readChars(vnBuf); printChars(new char[] { 'A', 'c', 'h', 't', 'e', 'r', 'n', 'a', 'a', 'm', ':', ' '}, 12); char[] anBuf = new char[255]; int anLength = readChars(vnBuf); printChars(new char[] {'H', 'a', 'l', 'l', 'o', ' '}, 6); printChars(vnBuf, vnLength); printChars(anBuf, anLength);
  • 21. String voornaam = readLine("Naam: "); String achternaam = readLine("Achternaam: "); print("Hallo " + voornaam + " " + achternaam);
  • 22. FullName fn = FullName.read(); fn.printGreeting();
  • 24. goed abstractie niveau?
  • 25. readNameAndPrintGreeting(); nieuwe eis: vraag ook naar leeftijd
  • 26. readNameAndPrintGreeting(); nieuwe eis: vraag ook naar leeftijd ✖
  • 27. FullName fn = FullName.read(); fn.printGreeting(); nieuwe eis: vraag ook naar leeftijd
  • 28. FullName fn = FullName.read(); fn.printGreeting(); nieuwe eis: vraag ook naar leeftijd ✖
  • 29. String voornaam = readLine("Naam: "); String achternaam = readLine("Achternaam: "); print("Hallo " + voornaam + " " + achternaam); nieuwe eis: vraag ook naar leeftijd
  • 30. String voornaam = readLine("Naam: "); String achternaam = readLine("Achternaam: "); int leeftijd = stringToInt(readLine("Leeftijd: ")); print("Hallo " + voornaam + " " + achternaam + ", jij bent " + leeftijd + " jaar oud."); nieuwe eis: vraag ook naar leeftijd ✔
  • 31. goed abstractie niveau afhankelijk van
  • 32. goed abstractie niveau afhankelijk van gebruik nu
  • 33. goed abstractie niveau afhankelijk van gebruik nu gebruik later
  • 34. Web applicaties in Java/Seam
  • 35. Model View Controller
  • 36. Data: Hibernate @Entity public class Blog { protected String _title = ""; public String getTitle() { return _title; } public void setTitle(String value) { _title = value; } @ManyToOne protected User _author; public User getAuthor() { return _author; } public void setAuthor(User author) { _title = value; } @OneToMany(mappedBy="_blog", targetEntity=BlogEntry.class) @Cascade(...) protected List<BlogEntry> _entries; public List<BlogEntry> getEntries() { return _entries; } public void setEntries(List<BlogEntry> entries) { _entries = entries; } }
  • 37. View: JSF <html ...> ... <body> ... <h:form> <table> <tr><td><h:outputText value="Title: "/></td> <td><h:inputText value="#{editBlogEntry.e.title}" /></td> </tr><tr> <td><h:outputText value="Created: "/></td> <td><rich:calendar value="#{editBlogEntry.e.created}" popup="true" datePattern="dd/MM/yyyy" .../></td> </tr><tr> <td><h:outputText value="Content: "/></td> <td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td> </tr><tr> <td><h:outputText value="Status: "/></td> <td><h:selectOneMenu value="#{editBlogEntry.e.status}"> <s:selectItems value="#{editBlogEntry.blogEntryStatusList}" var="blogEntryStatus" label="#{blogEntryStatus.name}" /> <s:convertEntity/> </h:selectOneMenu></td> </tr> </table> <h:actionLink action=”#{editBlogEntry.save()}”/> </h:form> ... </body> </html>
  • 38. Controller @Stateful @Name(“editBlogEntry”) public class EditBlogEntry { ... @In @Out private BlogEntry e; public void setE(e) { this.e = e; } public BlogEntry getE() { return this.e; } public void save() { em.persist(e); } ... }
  • 39. Configuratie <?xml version="1.0" ?> <web-app ...> <context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/blog.taglib.xml</param-value> </context-param> <filter> <filter-name>Seam Filter</filter-name> <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class> </filter> <filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> <init-param> <param-name>logLevel</param-name> <param-value>WARN</param-value> </init-param> </filter> <filter-mapping> <filter-name>Seam Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>Seam Resource Servlet</servlet-name> <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.seam</url-pattern> </servlet-mapping> ... </web-app>
  • 43. allemaal hetzelfde Gebruiker Bericht maken wijzigen verwijderen koppelen
  • 44. allemaal hetzelfde Gebruiker Bericht maken maken wijzigen wijzigen verwijderen verwijderen koppelen koppelen
  • 45. allemaal hetzelfde Gebruiker Bericht Reactie maken maken wijzigen wijzigen verwijderen verwijderen koppelen koppelen
  • 46. allemaal hetzelfde Gebruiker Bericht Reactie maken maken maken wijzigen wijzigen wijzigen verwijderen verwijderen verwijderen koppelen koppelen koppelen
  • 47. allemaal hetzelfde Gebruiker Bericht Reactie maken maken maken wijzigen wijzigen wijzigen verwijderen verwijderen verwijderen koppelen koppelen koppelen boiler plate code
  • 48.
  • 49.
  • 50. Data @Entity public class Blog { protected String _title = ""; public String getTitle() { return _title; } public void setTitle(String value) { _title = value; } @ManyToOne protected User _author; public User getAuthor() { return _author; } public void setAuthor(User author) { _title = value; } @OneToMany(mappedBy="_blog", targetEntity=BlogEntry.class) @Cascade(...) protected List<BlogEntry> _entries; public List<BlogEntry> getEntries() { return _entries; } public void setEntries(List<BlogEntry> entries) { _entries = entries; } }
  • 51. Data @Entity public class Blog { protected String _title = ""; public String getTitle() { return _title; } public void setTitle(String value) { _title = value; } @ManyToOne protected User _author; public User getAuthor() { entity Blog { return _author; author -> User (inverse=User.blogs) } title :: String public void setAuthor(User author) { entries <> Set<BlogEntry> _title = value; } } @OneToMany(mappedBy="_blog", targetEntity=BlogEntry.class) @Cascade(...) protected List<BlogEntry> _entries; public List<BlogEntry> getEntries() { return _entries; } public void setEntries(List<BlogEntry> entries) { _entries = entries; } }
  • 52. <html ...> ... <body> ... Pagina’s <h:form> <table> <tr><td><h:outputText value="Title: "/></td> @Stateful @Name(“editBlogEntry”) <td><h:inputText value="#{editBlogEntry.e.title}" /></td> public class EditBlogEntry { </tr><tr> ... <td><h:outputText value="Created: "/></td> @In @Out <td><rich:calendar value="#{editBlogEntry.e.created}" private BlogEntry e; popup="true" datePattern="dd/MM/yyyy" .../></td> public void setE(e) { </tr><tr> this.e = e; <td><h:outputText value="Content: "/></td> } <td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td> </tr><tr> public BlogEntry getE() { <td><h:outputText value="Status: "/></td> return this.e; <td><h:selectOneMenu value="#{editBlogEntry.e.status}"> } <s:selectItems value="#{editBlogEntry.blogEntryStatusList}" public void save() { var="blogEntryStatus" label="#{blogEntryStatus.name}" /> em.persist(e); <s:convertEntity/> } </h:selectOneMenu></td> ... </tr> } </table> <h:actionLink action=”#{editBlogEntry.save()}”/> </h:form> ... </body> </html>
  • 53. <html ...> ... <body> ... Pagina’s <h:form> <table> <tr><td><h:outputText value="Title: "/></td> @Stateful @Name(“editBlogEntry”) <td><h:inputText value="#{editBlogEntry.e.title}" /></td> public class EditBlogEntry { </tr><tr> ... <td><h:outputText value="Created: "/></td> @In @Out <td><rich:calendar value="#{editBlogEntry.e.created}" private BlogEntry e; popup="true" datePattern="dd/MM/yyyy" .../></td> public void setE(e) { </tr><tr> this.e = e; <td><h:outputText value="Content: "/></td> } <td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td> </tr><tr> public BlogEntry getE() { <td><h:outputText value="Status: "/></td> return this.e; <td><h:selectOneMenu value="#{editBlogEntry.e.status}"> } <s:selectItems value="#{editBlogEntry.blogEntryStatusList}" public void save() { var="blogEntryStatus" label="#{blogEntryStatus.name}" /> em.persist(e); <s:convertEntity/> } </h:selectOneMenu></td> ... </tr> } </table> <h:actionLink action=”#{editBlogEntry.save()}”/> </h:form> ... </body> </html> define page editBlogEntry(e : BlogEntry) { form{ table{ row{ "Title: " input(e.title) } row{ "Created: " input(e.created) } row{ "Content: " input(e.content) } row{ "Status: " input(e.status) } action("Save", save()) } } action save() { e.save(); return blogEntry(e); } }
  • 54. <html ...> ... <body> ... Pagina’s <h:form> <table> <tr><td><h:outputText value="Title: "/></td> @Stateful @Name(“editBlogEntry”) <td><h:inputText value="#{editBlogEntry.e.title}" /></td> public class EditBlogEntry { </tr><tr> ... <td><h:outputText value="Created: "/></td> @In @Out <td><rich:calendar value="#{editBlogEntry.e.created}" private BlogEntry e; popup="true" datePattern="dd/MM/yyyy" .../></td> public void setE(e) { </tr><tr> this.e = e; <td><h:outputText value="Content: "/></td> } <td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td> </tr><tr> public BlogEntry getE() { <td><h:outputText value="Status: "/></td> return this.e; <td><h:selectOneMenu value="#{editBlogEntry.e.status}"> } <s:selectItems value="#{editBlogEntry.blogEntryStatusList}" public void save() { var="blogEntryStatus" label="#{blogEntryStatus.name}" /> em.persist(e); <s:convertEntity/> } </h:selectOneMenu></td> ... </tr> } </table> <h:actionLink action=”#{editBlogEntry.save()}”/> </h:form> ... </body> </html>
  • 55. <html ...> ... <body> ... Pagina’s <h:form> <table> <tr><td><h:outputText value="Title: "/></td> @Stateful @Name(“editBlogEntry”) <td><h:inputText value="#{editBlogEntry.e.title}" /></td> public class EditBlogEntry { </tr><tr> ... <td><h:outputText value="Created: "/></td> @In @Out <td><rich:calendar value="#{editBlogEntry.e.created}" private BlogEntry e; popup="true" datePattern="dd/MM/yyyy" .../></td> public void setE(e) { </tr><tr> this.e = e; <td><h:outputText value="Content: "/></td> } <td><h:inputTextarea value="#{editBlogEntry.e.content}"/></td> </tr><tr> public BlogEntry getE() { <td><h:outputText value="Status: "/></td> return this.e; <td><h:selectOneMenu value="#{editBlogEntry.e.status}"> } <s:selectItems value="#{editBlogEntry.blogEntryStatusList}" public void save() { var="blogEntryStatus" label="#{blogEntryStatus.name}" /> em.persist(e); <s:convertEntity/> } </h:selectOneMenu></td> ... </tr> } </table> <h:actionLink action=”#{editBlogEntry.save()}”/> </h:form> ... </body> </html> define page editBlogEntry(e : BlogEntry) { derive editPage from e }
  • 56.
  • 58. WebDSL code WebDSL compiler Java applicatie (Java, JSF, Hibernate)
  • 60. entity User { username :: String password :: Secret } entity Update { user -> User date :: DateTime text :: Text }
  • 61. entity User { username :: String password :: Secret } entity Update { user -> User date :: DateTime text :: Text } define page home() { for(u : Update) { output(u.user.username) ": " output(u.text) spacer } }
  • 62. entity User { username :: String password :: Secret } entity Update { user -> User date :: DateTime text :: Text } define page home() { for(u : Update) { output(u.user.username) ": " output(u.text) spacer } }
  • 63. define page home() { header{ "Twitr" } spacer for(u : Update) { output(u.user.username) ": " output(u.text) spacer } "(C) Zef Hemel" }
  • 64. define page login() { header{ "Twitr" } spacer var u : User form { "Login: " input(u) action("Login", login()) action login() { session.user := u; return home(); } } spacer "(C) Zef Hemel" }
  • 65. define page login() { header{ "Twitr" } spacer var u : User form { "Login: " input(u) action("Login", login()) action login() { session.user := u; return home(); } } spacer "(C) Zef Hemel" }
  • 67. define template main() { header{ "Twitr" } spacer body() "(C) Zef Hemel" } define page home() { main() define body() { for(u : Update) { output(u.user.username) ": " output(u.text) spacer } } }
  • 68. WebDSL code Template expander WebDSL compiler Java applicatie (Java, JSF, Hibernate)
  • 69. template expander define page home() { main() define body() for(u : Update) { output(u.user.username) ": " output(u.text) spacer } } } define page home() { header{ "Twitr" } spacer for(u : Update) { output(u.user.username) ": " output(u.text) spacer } "(C) Zef Hemel" }
  • 70. maar... JSF had ook al templates
  • 71. WebDSL code Template expander WebDSL compiler Java applicatie templates (Java, JSF, Hibernate)
  • 72. WebDSL code Template expander templates WebDSL compiler Java applicatie templates (Java, JSF, Hibernate)
  • 73. WebDSL code herimplementeert templates Template expander templates WebDSL compiler Java applicatie templates (Java, JSF, Hibernate)
  • 74. abstraction inversion WebDSL code herimplementeert templates Template expander templates WebDSL compiler Java applicatie templates (Java, JSF, Hibernate)
  • 75. abstraction inversion WebDSL code herimplementeert templates Template expander templates WebDSL compiler slechte abstractie Java applicatie templates (Java, JSF, Hibernate)
  • 76.
  • 77. “All non-trivial abstractions, to some degree, are leaky.” -- Joel Spolsky
  • 79. abstracties verbergen implementatie dat lukt eigenlijk nooit volledig
  • 80. abstracties verbergen implementatie dat lukt eigenlijk nooit volledig WebDSL templates
  • 81. abstracties verbergen implementatie dat lukt eigenlijk nooit volledig WebDSL templates NFS/SMB
  • 82. abstracties verbergen implementatie dat lukt eigenlijk nooit volledig WebDSL templates NFS/SMB twee-dimensionale arrays
  • 83. abstracties verbergen implementatie dat lukt eigenlijk nooit volledig WebDSL templates NFS/SMB twee-dimensionale arrays SQL
  • 88. denk kritisch na heb ik dit vaker gedaan?
  • 89. denk kritisch na heb ik dit vaker gedaan? gaat iemand dit vaker doen?