50
Eelco Visser http://eelcovisser.org Software Language Design & Engineering Zürich, May 12, 2011

Software Language Design & Engineering

Embed Size (px)

DESCRIPTION

Slides for a talk at Faculty Summit 2011 at Google Zurich about software language design and engineering, with mobl as big example.

Citation preview

Page 1: Software Language Design & Engineering

Eelco Visserhttp://eelcovisser.org

Software Language Design & Engineering

Zürich, May 12, 2011

Page 2: Software Language Design & Engineering

bridging the gap between problem domain and solution domain

Software Engineering

ProblemDomain Machine

Page 3: Software Language Design & Engineering

HLLs reduce gap

High-Level Languages

ProblemDomain HLL Machine

Page 4: Software Language Design & Engineering

domain-specific languages support more specialization

Domain-Specific Languages

ProblemDomain HLL MachineDSL

Page 5: Software Language Design & Engineering

domain-specific languages support more specialization

Domain-Specific Languages

ProblemDomain HLL MachineDSL

Even Higher-Level

Languages

Page 6: Software Language Design & Engineering

Software Language Design & Engineering

enable software engineers to effectively design, implement, and apply domain-specific

software languages

Page 7: Software Language Design & Engineering

Research: Software Language Design

Systematically design domain-

specific software languages with optimal tradeoff between expressivity,

completeness, portability, coverage, and maintainability

Page 8: Software Language Design & Engineering

expressivity: fewer irrelevant details => concisenesscoverage: which portion of domain can we express

Expressivity vs Coverage

Page 9: Software Language Design & Engineering

Software Language Design Case Studies

Mobl: client-side stateful web applications

WebDSL: server-side restful web applications

Page 10: Software Language Design & Engineering

http://www.mobl-lang.org

Zef Hemel

Page 11: Software Language Design & Engineering

Native Applications not Portable

Divergence in Mobile Platforms

Objective-C Java J2ME/C++

HTML/Javascript Java .NET

Page 12: Software Language Design & Engineering

Convergence in Mobile Platform

Webkit browser

Webkit browser

Webkit browser

Webkit browser

Page 13: Software Language Design & Engineering

The Universal Userinterface Engine

Page 14: Software Language Design & Engineering

Mobile Web Architecture

Page 15: Software Language Design & Engineering

Rich Applications

WebDatabases

Location information (GPS)

Canvas

Multi-touch

Offline support

Full-screen support

Accelerator support

Audio

Page 16: Software Language Design & Engineering

Native Applications

Address book

Camera

Compass

File IO

Notifications

Page 17: Software Language Design & Engineering

MVC, No Integration, No Abstraction, Accidental Complexity

Software Engineering with JavaScript

annotated HTML imperative Javascript

Page 18: Software Language Design & Engineering

declarativetyped

integrated concise

Page 19: Software Language Design & Engineering

Web Application with Touch

Page 20: Software Language Design & Engineering

Portable Applications

Page 21: Software Language Design & Engineering

Mobl Architecture

Page 22: Software Language Design & Engineering

tipcalculator.mobl

application tipcalculator

import mobl::ui::generic

screen root() { var amount = 20 var percentage = 10 header("Tip calculator") group { item { numField(amount, label="amount") } item { numField(percentage, label="percentage") } item { "$" label(Math.round(amount * (1 + percentage/100))) } } nl()}

Page 23: Software Language Design & Engineering

Model-View Pattern

Page 24: Software Language Design & Engineering

Task Manager

Page 25: Software Language Design & Engineering

HTML5 Data Persistence

Data Model

entity Task { name : String (searchable) done : Bool due : DateTime category : Category (inverse: tasks) tags : Collection<Tag> (inverse: tasks)}entity Category { name : String tasks : Collection<Task> (inverse: category)}entity Tag { name : String tasks : Collection<Task> (inverse: tags)}

Page 26: Software Language Design & Engineering

statically typed: catch errors early

Logic

entity Task { name : String (searchable) done : Bool due : DateTime category : Category (inverse: tasks) tags : Collection<Tag> (inverse: tasks) function postpone(days : Num) { this.due = DateTime.create( this.due.getFullYear(), this.due.getMonth(), this.due.getDate() + days); } function import(user : String, pw : String) { var tasksJSON = httpRequest("/export?user="+ user + "&pw=" + pw); foreach(t in tasksJSON) { add(Task.fromSelectJSON(t)); } }}

Page 27: Software Language Design & Engineering

screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}

Reactive User Interfaces

Page 28: Software Language Design & Engineering

screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}

Reactive User Interfaces

Page 29: Software Language Design & Engineering

screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}

Navigation

Page 30: Software Language Design & Engineering

screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}

screen addTask() { var t = Task() header("Add") { button("Done", onclick={ add(t); screen return; }) } textField(t.name) datePicker(t.due)}

Navigation

Page 31: Software Language Design & Engineering

screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}

Navigation

Page 32: Software Language Design & Engineering

Continuations

screen root() { button("Ask", onclick={ alert("Hello " + prompt("First name") + " " + prompt("Last name")); })}screen prompt(question : String) : String { var answer = "" header(question) { button("Done", onclick={ screen return answer; }) } textField(answer)}

Page 33: Software Language Design & Engineering

User Interface Idiom: Tab

control tab1() { header("Tab 1") label("This is tab 1")}control tab2() { header("Tab 2") label("This is tab 2")}screen root() { tabSet([("One", tab1), ("Two", tab2)], defaultTab="One")}

Page 34: Software Language Design & Engineering

increase coverage: developers can create abstractions

Tab Set: Higher-Order Control

control tabSet(tabs : [(String,Control)], activeTab : String) { list((tabName, tabControl) in tabs) { block(onclick={ activeTab = tabName; }, style=activeTab==tabName ? activeTabButton : inactiveTabButton) { label(tabName) } } list((tabName, tabControl) in tabs) { block(activeTab==tabName ? visibleTab : invisibleTab) { tabControl() } }}

Page 35: Software Language Design & Engineering

User Interface Idiom: Master Detail

control taskItem(t : Task) { checkBox(t.done, label=t.name)}control taskDetail(t : Task) { textField(t.name) datePicker(t.due)}screen root() { header("Tasks") masterDetail(Task.all() order by due desc, taskItem, taskDetail)}

Page 36: Software Language Design & Engineering

User Interface Idiom: Master Detail

control taskItem(t : Task) { checkBox(t.done, label=t.name)}control taskDetail(t : Task) { textField(t.name) datePicker(t.due)}screen root() { header("Tasks") masterDetail(Task.all() order by due desc, taskItem, taskDetail)}

Page 37: Software Language Design & Engineering

Master Detail: Higher-Order Control

control masterDetail(items : Collection<?>, masterItem : Control1<?>, detail : Control1<?>) { group { list(it in items) { item(onclick={ detailScreen(it,detail); }) { masterItem(it) } } }}screen detailScreen(it : ?, detail : Control1<?>) { header("Detail") { backButton() } detail(it)}

Page 38: Software Language Design & Engineering

Mobl Applications

Page 39: Software Language Design & Engineering

GR8 Conference Program

Page 40: Software Language Design & Engineering

mPodder

Page 41: Software Language Design & Engineering

Ken

http://itsneh.com/ken/

Page 42: Software Language Design & Engineering

static cross-concern consistency checking

Mobl IDE

Page 43: Software Language Design & Engineering

Research: Software Language Engineering

Automatically derive efficient, scalable, incremental compiler +

usable IDE from high-level,

declarative language definition

Page 44: Software Language Design & Engineering

creating full featured IDEs for domain-specific languages

The Spoofax Language Workbench

Page 45: Software Language Design & Engineering

an IDE for developing languages and their IDEs

The Spoofax Language Workbench

Page 46: Software Language Design & Engineering

Integrated Language Definition Testing

The Spoofax Language Workbench

Page 47: Software Language Design & Engineering

Syntax Definition

module MoBL-Data

imports Common MoBL

exports context-free syntax MetaAnno* "entity" QId ":" Type "{" Property* "}" -> Definition {cons("Entity")} MetaAnno* "entity" QId "{" Property* "}" -> Definition {cons("EntityNoSuper")} MetaAnno* ID ":" Type "(" {Anno ","}* ")" -> Property {cons("Property")} MetaAnno* ID ":" Type -> Property {cons("PropertyNoAnnos")} ID -> Anno {cons("SimpleAnno")} "inverse" ":" ID -> Anno {cons("InverseAnno")}

context-free syntax "@sync" UriPath -> MetaAnno {cons("SyncEntityAnno")}

Page 48: Software Language Design & Engineering

Type Checking

rules

constraint-error : t@SimpleType(_) -> (t, $[Type is not defined: [<pp-mobl-type> t]]) where not(<lookup-type> t)

constraint-error : t@FieldAccess(e, x) -> (t, $[Property [x] not defined]) where <type-of> e where not(type-of)

Page 49: Software Language Design & Engineering

Code Generation

rules property-to-js(|ent) : Property(_, x, t@SimpleType(_), anno*) -> $['[x]': '[sqlType]'] where not(<is-entity-type> t) with sqlType := <sql-type> t ; if [_] := <filter(?SimpleAnno("searchable"))> anno* then rules ( SearchableProperties :+= (ent, x) ) end

Page 50: Software Language Design & Engineering

http://researchr.org/search/publication/mobl+spoofax+webdsl

Software Language Design & Engineering

http://eelcovisser.org

http://spoofax.org

http://mobl-lang.org

http://webdsl.org

http://researchr.org

Language Design as Engineering Discipline

(More) Declarative Language Definition

Static Analysis of Language Definitions

Language Workbench in the Cloud