Abstractie (Dutch)

Post on 05-Dec-2014

1.006 views 5 download

description

De slides van mijn college over abstractie, zoals gegeven aan de Rijksuniversiteit Groningen.

Transcript of Abstractie (Dutch)

Write('A');

abstractie

wat?waarom?hoe?valkuilenconclusie

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

mappen

multi-tasking

vensters

knoppen

invoer velden

hoe?

printChar('N');printChar('a');printChar('a');printChar('m');printChar(':');printChar(' ');

char[] vnBuffer = new char[255];int vnLength = 0;char inp;do { inp = readChar(); vnBuffer[vnLength] = inp; vnLength++;while (inp != '\n');

printChar('A');printChar('c');printChar('h');printChar('t');printChar('e');printChar('r');printChar('n');printChar('a');printChar('a');printChar('m');printChar(':');

char[] anBuffer = new char[255];int anLength = 0;do { inp = readChar(); anBuffer[anLength] = inp; anLength++;while (inp != '\n');

printChar('H');printChar('a');printChar('l');printChar('l');printChar('o');printChar(' ');int i = 0;while(i < vnLength) { printChar(vnBuffer[i]); i++;}printChar(' ');i = 0;while(i < anLength) { printChar(anBuffer[i]); i++;}

printChar('N');printChar('a');printChar('a');printChar('m');printChar(':');printChar(' ');

char[] vnBuffer = new char[255];int vnLength = 0;char inp;do { inp = readChar(); vnBuffer[vnLength] = inp; vnLength++;while (inp != '\n');

printChar('A');printChar('c');printChar('h');printChar('t');printChar('e');printChar('r');printChar('n');printChar('a');printChar('a');printChar('m');printChar(':');

char[] anBuffer = new char[255];int anLength = 0;do { inp = readChar(); anBuffer[anLength] = inp; anLength++;while (inp != '\n');

printChar('H');printChar('a');printChar('l');printChar('l');printChar('o');printChar(' ');int i = 0;while(i < vnLength) { printChar(vnBuffer[i]); i++;}printChar(' ');i = 0;while(i < anLength) { printChar(anBuffer[i]); i++;}

printChar('N');printChar('a');printChar('a');printChar('m');printChar(':');printChar(' ');

char[] vnBuffer = new char[255];int vnLength = 0;char inp;do { inp = readChar(); vnBuffer[vnLength] = inp; vnLength++;while (inp != '\n');

printChar('A');printChar('c');printChar('h');printChar('t');printChar('e');printChar('r');printChar('n');printChar('a');printChar('a');printChar('m');printChar(':');

char[] anBuffer = new char[255];int anLength = 0;do { inp = readChar(); anBuffer[anLength] = inp; anLength++;while (inp != '\n');

printChar('H');printChar('a');printChar('l');printChar('l');printChar('o');printChar(' ');int i = 0;while(i < vnLength) { printChar(vnBuffer[i]); i++;}printChar(' ');i = 0;while(i < anLength) { printChar(anBuffer[i]); i++;}

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

View ControllerModel

Data: Hibernate@Entitypublic 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

Gebruikermakenwijzigenverwijderenkoppelen

allemaal hetzelfde

Gebruikermakenwijzigenverwijderenkoppelen

Bericht

allemaal hetzelfde

Gebruikermakenwijzigenverwijderenkoppelen

Berichtmakenwijzigenverwijderenkoppelen

allemaal hetzelfde

Gebruikermakenwijzigenverwijderenkoppelen

Berichtmakenwijzigenverwijderenkoppelen

Reactie

allemaal hetzelfde

Gebruikermakenwijzigenverwijderenkoppelen

Berichtmakenwijzigenverwijderenkoppelen

Reactiemakenwijzigenverwijderenkoppelen

allemaal hetzelfde

Gebruikermakenwijzigenverwijderenkoppelen

Berichtmakenwijzigenverwijderenkoppelen

Reactiemakenwijzigenverwijderenkoppelen

boiler plate code

Data@Entitypublic 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 Blog { author -> User (inverse=User.blogs) title :: String entries <> Set<BlogEntry>}

@Entitypublic 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; }}

Pagina’s<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>

@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); } ...}

Pagina’s

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> ... <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>

@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); } ...}

Pagina’s<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>

@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); } ...}

Pagina’s

define page editBlogEntry(e : BlogEntry) { derive editPage from e}

<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>

@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); } ...}

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

WebDSL compiler

Template expander

Java applicatie(Java, JSF, Hibernate)

template expanderdefine 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

WebDSL compiler

Template expander

Java applicatie(Java, JSF, Hibernate)templates

WebDSL code

WebDSL compiler

Template expander

Java applicatie(Java, JSF, Hibernate)templates

templates

WebDSL code

WebDSL compiler

Template expander

Java applicatie(Java, JSF, Hibernate)templates

templates

herimplementeerttemplates

abstraction inversion

WebDSL code

WebDSL compiler

Template expander

Java applicatie(Java, JSF, Hibernate)templates

templates

herimplementeerttemplates

abstraction inversion

WebDSL code

WebDSL compiler

Template expander

Java applicatie(Java, JSF, Hibernate)templates

templates

herimplementeerttemplates

slechte abstractie

“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 templatesNFS/SMB

abstracties verbergen implementatie

dat lukt eigenlijk nooit volledig

WebDSL templatesNFS/SMBtwee-dimensionale arrays

abstracties verbergen implementatie

dat lukt eigenlijk nooit volledig

WebDSL templatesNFS/SMBtwee-dimensionale arraysSQL

conclusie

abstractie is essentieel

abstractie is essentieelmoeilijk

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