View Controller Model

Singular
#gwtcreate
+DanielKurka
@dankurka
AngularJs
http://upload.wikimedia.org/wikipedia/commons/2/2a/Boxing_Tournament_in_Aid_of_King_George's_Fund_For_Sailors_at_the_Royal_Naval_Air_Station,_Henstridge,_Somerset,_July_1945_A29806.jpg
The good
http://upload.wikimedia.org/wikipedia/commons/0/02/Nice_view_(3201807289).jpg
Developer productivity
Express intend
Eliminate boilerplate
Application structure
Testing as a first class
citizen
How does Angular do it?
A Todo application
JavaScript
function TodoCtrl($scope) {
$scope.todos = [
{text:'Learn AngularJS', done:false},
{text: 'Build an app', done:false}
];
$scope.addTodo = function () {
$scope.todos.push({text:$scope.formTodoText, done:false});
$scope.formTodoText = '';
};
!
$scope.clearCompleted = function () {
$scope.todos = _.filter($scope.todos, function(todo){
return !todo.done;
});
};
}
JavaScript
function TodoCtrl($scope) {
$scope.todos = [
{text:'Learn AngularJS', done:false},
{text: 'Build an app', done:false}
];
$scope.addTodo = function () {
$scope.todos.push({text:$scope.formTodoText, done:false});
$scope.formTodoText = '';
};
!
$scope.clearCompleted = function () {
$scope.todos = _.filter($scope.todos, function(todo){
return !todo.done;
});
};
}
JavaScript
function TodoCtrl($scope) {
$scope.todos = [
{text:'Learn AngularJS', done:false},
{text: 'Build an app', done:false}
];
$scope.addTodo = function () {
$scope.todos.push({text:$scope.formTodoText, done:false});
$scope.formTodoText = '';
};
!
$scope.clearCompleted = function () {
$scope.todos = _.filter($scope.todos, function(todo){
return !todo.done;
});
};
}
JavaScript
function TodoCtrl($scope) {
$scope.todos = [
{text:'Learn AngularJS', done:false},
{text: 'Build an app', done:false}
];
$scope.addTodo = function () {
$scope.todos.push({text:$scope.formTodoText, done:false});
$scope.formTodoText = '';
};
!
$scope.clearCompleted = function () {
$scope.todos = _.filter($scope.todos, function(todo){
return !todo.done;
});
};
}
HTML
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input type="text" ng-model="formTodoText" />
<button ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button ng-click="clearCompleted()">Clear completed</button>
</div>
HTML
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input type="text" ng-model="formTodoText" />
<button ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button ng-click="clearCompleted()">Clear completed</button>
</div>
HTML
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input type="text" ng-model="formTodoText" />
<button ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button ng-click="clearCompleted()">Clear completed</button>
</div>
HTML
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input type="text" ng-model="formTodoText" />
<button ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button ng-click="clearCompleted()">Clear completed</button>
</div>
HTML
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input type="text" ng-model="formTodoText" />
<button ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button ng-click="clearCompleted()">Clear completed</button>
</div>
HTML
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input type="text" ng-model="formTodoText" />
<button ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button ng-click="clearCompleted()">Clear completed</button>
</div>
The bad
Performance
Multiple problems
Scanning the DOM at
runtime to find directives
Dirty checking loop
Not optimizable by
compilers
These cause serious
performance issues!
Get the good without the
bad?
What do we need to do?
Parse templates at
compile time
Resolve directives at
compile time
Understand the scope
sufficient enough to not
require dirty checking
Make downloads
smaller
Remember GWT:
Smallest and Fastest in
class?
Singular
Angular in Java
Static typing helps us
understand the scope
No dirty checking!
Will scale to big
applications & run
efficiently on mobile
Java gives us great
tools support
Java gives us best in
class output size
Demo
Already 4x smaller
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
Initial rendering
already 20x faster
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
Runtime
already 5x faster
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
But there is more
Application structure
Model
Model
Controller
Model
View
Controller
MVC
Presentation
state
Model
Rendering
logic
Presentation
state
Model
View
Screen
Rendering
logic
Presentation
state
Model
View
Screen
Rendering
logic
Presentation
state
Model
Controller
UI Event
Handling logic
View
Screen
Rendering
logic
Presentation
state
Model
Controller
UI Event
Handling logic
View
Screen
Rendering
logic
Presentation
state
Model
Controller
UI Event
Handling logic
View
Screen
Rendering
logic
Presentation
state
Model
Controller
UI Event
Handling logic
View
Screen
Rendering
logic
Presentation
state
Model
Controller
UI Event
Handling logic
View
Screen
Angular
Model
View
Controller
Controller
Model
Application
logic
Presentation
state
Event
Handling
View
Rendering
logic
Screen
Controller
Model
Application
logic
Presentation
state
Event
Handling
View
Rendering
logic
Screen
Controller
Model
Application
logic
Presentation
state
Event
Handling
View
Rendering
logic
Screen
Controller
Model
Application
logic
Presentation
state
Event
Handling
View
Rendering
logic
Screen
Controller
Model
Application
logic
Presentation
state
Event
Handling
Directives
Rendering
logic
Screen
Sweet spot: Cross platform apps
Platform specific template
files:
!
Web: HTML
Android: xml files
iOS: UiBuilder
Optionally: Customize
template per platform
Freedom to change the UI
Share controllers across
platforms
Keeps application logic in
sync
Easy way to break out
Demo
Singular on Android
Cross platform APIs
HTTP
Interface
HTTP
Interface
Web
HTTP
Interface
Android
Web
HTTP
Interface
Android
Web
iOS
Dependency injection
to wire it up
HTTP, Sockets
HTTP, Sockets
Storage, FileSystem
HTTP, Sockets
Storage, FileSystem
Location, Camera, Media
HTTP, Sockets
Storage, FileSystem
Location, Camera, Media
Notifications, Status
Existing work
Phonegap
Break out?
http://upload.wikimedia.org/wikipedia/commons/1/1e/Dog_in_animal_shelter_in_Washington,_Iowa.jpg
Web
@NGApp(template = "hello.html")
public interface HelloApp extends NGBinder<Element> {
}
Definition
Web
@NGApp(template = "hello.html")
public interface HelloApp extends NGBinder<Element> {
}
NGBinder<Element> binder = new HelloAppBinder();
binder.start(Document.get().getBody());
Definition
Usage
Android
@NGApp(os = OS.ANDROID, template = "hello.xml")
public interface HelloApp extends NGBinder<View>{
}
Definition
Android
@NGApp(os = OS.ANDROID, template = "hello.xml")
public interface HelloApp extends NGBinder<View>{
}
Definition
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
!
LinearLayout l = (LinearLayout) findViewById(R.id.root);
!
NgBinder<View> binder = new HelloAppBinder(getBaseContext());
binder.start(l);
}
}
Example usage
Android
@NGApp(os = OS.ANDROID, template = "hello.xml")
public interface HelloApp extends NGBinder<View>{
}
Definition
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
!
LinearLayout l = (LinearLayout) findViewById(R.id.root);
!
NgBinder<View> binder = new HelloAppBinder(getBaseContext());
binder.start(l);
}
}
Example usage
Android
@NGApp(os = OS.ANDROID, template = "hello.xml")
public interface HelloApp extends NGBinder<View>{
}
Definition
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
!
LinearLayout l = (LinearLayout) findViewById(R.id.root);
!
NgBinder<View> binder = new HelloAppBinder(getBaseContext());
binder.start(l);
}
}
Example usage
Framework
public interface NGBinder<T> {
Registration start(T parent);
}
Base interface
public interface Registration {
void cancel();
}
Registration
Integrate it into any
existing app
Just pass the parent
Also: Mark nodes as
external
Easy migration path for
existing GWT apps
Testing in Singular
Controller
Model
Application
logic
Presentation
state
Event
Handling
View
Rendering
logic
Screen
Controller
Model
Application
logic
Presentation
state
pure Java
No more GWTTestcase
Works with any Java
mocking framework
Java
@Test
public void addTodo() {
NGTodoScope scope = new NGTodoScope();
TodoController todoController = new TodoController(scope);
!
assertEquals(2, scope.getTodos().size());
assertEquals("Learn singular", scope.getTodos().get(0).getText());
assertEquals("Build app", scope.getTodos().get(1).getText());
!
scope.setFormTodoText("foobar");
todoController.addTodo();
!
assertEquals(3, scope.getTodos().size());
assertEquals("foobar", scope.getTodos().get(2).getText());
}
Java
@Test
public void addTodo() {
NGTodoScope scope = new NGTodoScope();
TodoController todoController = new TodoController(scope);
!
assertEquals(2, scope.getTodos().size());
assertEquals("Learn singular", scope.getTodos().get(0).getText());
assertEquals("Build app", scope.getTodos().get(1).getText());
!
scope.setFormTodoText("foobar");
todoController.addTodo();
!
assertEquals(3, scope.getTodos().size());
assertEquals("foobar", scope.getTodos().get(2).getText());
}
Java
@Test
public void addTodo() {
NGTodoScope scope = new NGTodoScope();
TodoController todoController = new TodoController(scope);
!
assertEquals(2, scope.getTodos().size());
assertEquals("Learn singular", scope.getTodos().get(0).getText());
assertEquals("Build app", scope.getTodos().get(1).getText());
!
scope.setFormTodoText("foobar");
todoController.addTodo();
!
assertEquals(3, scope.getTodos().size());
assertEquals("foobar", scope.getTodos().get(2).getText());
}
Java
@Test
public void addTodo() {
NGTodoScope scope = new NGTodoScope();
TodoController todoController = new TodoController(scope);
!
assertEquals(2, scope.getTodos().size());
assertEquals("Learn singular", scope.getTodos().get(0).getText());
assertEquals("Build app", scope.getTodos().get(1).getText());
!
scope.setFormTodoText("foobar");
todoController.addTodo();
!
assertEquals(3, scope.getTodos().size());
assertEquals("foobar", scope.getTodos().get(2).getText());
}
Sum
http://upload.wikimedia.org/wikipedia/commons/6/65/Cute_beagle_puppy_lilly.jpg
AngularJs
http://upload.wikimedia.org/wikipedia/commons/2/2a/Boxing_Tournament_in_Aid_of_King_George's_Fund_For_Sailors_at_the_Royal_Naval_Air_Station,_Henstridge,_Somerset,_July_1945_A29806.jpg
The good
http://upload.wikimedia.org/wikipedia/commons/0/02/Nice_view_(3201807289).jpg
Developer productivity
Testing as a first class
citizen
The bad
Performance
Singular
Angular in Java
No dirty checking!
Will scale to big
applications & run
efficiently on mobile
Already 4x smaller
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
Initial rendering
already 20x faster
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
Runtime
already 5x faster
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
Controller
Model
Application
logic
Presentation
state
Event
Handling
Directives
Rendering
logic
Screen
Android
Web
iOS
Platform specific template
files:
!
Web: HTML
Android: xml files
iOS: UiBuilder
Freedom to change the UI
Share controllers across
platforms
Singular on Android
Singular on iOS
Thank you!
+DanielKurka
@dankurka
#gwt
Any questions?
+DanielKurka
@dankurka
#gwt