summaryrefslogtreecommitdiffstats
path: root/documentation/advanced/advanced-architecture.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/advanced/advanced-architecture.asciidoc')
-rw-r--r--documentation/advanced/advanced-architecture.asciidoc298
1 files changed, 0 insertions, 298 deletions
diff --git a/documentation/advanced/advanced-architecture.asciidoc b/documentation/advanced/advanced-architecture.asciidoc
deleted file mode 100644
index 437c6f4a1d..0000000000
--- a/documentation/advanced/advanced-architecture.asciidoc
+++ /dev/null
@@ -1,298 +0,0 @@
----
-title: Advanced Application Architectures
-order: 10
-layout: page
----
-
-[[advanced.architecture]]
-= Advanced Application Architectures
-
-In this section, we continue from the basic application architectures described
-in
-<<dummy/../../../framework/application/application-architecture#application.architecture,"Building
-the UI">> and discuss some of the more advanced patterns that are often used in
-Vaadin applications.
-
-[[advanced.architecture.layering]]
-== Layered Architectures
-
-Layered architectures, where each layer has a clearly distinct responsibility,
-are probably the most common architectures. Typically, applications follow at
-least a three-layer architecture:
-
-* User interface (or presentation) layer
-* Domain layer
-* Data store layer
-
-Such an architecture starts from a __domain model__, which defines the data
-model and the "business logic" of the application, typically as beans or POJOs.
-A user interface is built on top of the domain model, in our context with the
-Vaadin Framework. The Vaadin user interface could be bound directly to the data
-model through the Vaadin Data Model, described in
-<<dummy/../../../framework/datamodel/datamodel-overview.asciidoc#datamodel.overview,"Binding
-Components to Data">>. Beneath the domain model lies a data store, such as a
-relational database. The dependencies between the layers are restricted so that
-a higher layer may depend on a lower one, but never the other way around.
-
-[[figure.advanced.architecture.layering]]
-.Three-Layer Architecture
-image::img/three-layer-architecture-hi.png[]
-
-An __application layer__ (or __service layer__) is often distinguished from the
-domain layer, offering the domain logic as a service, which can be used by the
-user interface layer, as well as for other uses. In Java EE development,
-Enterprise JavaBeans (EJBs) are typically used for building this layer.
-
-An __infrastructure layer__ (or __data access layer__) is often distinguished
-from the data store layer, with a purpose to abstract the data store. For
-example, it could involve a persistence solution such as JPA and an EJB
-container. This layer becomes relevant with Vaadin when binding Vaadin
-components to data with the JPAContainer, as described in
-<<dummy/../../../framework/jpacontainer/jpacontainer-overview.asciidoc#jpacontainer.overview,"Vaadin
-JPAContainer">>.
-
-
-[[advanced.architecture.mvp]]
-== Model-View-Presenter Pattern
-
-The Model-View-Presenter (MVP) pattern is one of the most common patterns in
-developing large applications with Vaadin. It is similar to the older
-Model-View-Controller (MVC) pattern, which is not as meaningful in Vaadin
-development. Instead of an implementation-aware controller, there is an
-implementation-agnostic presenter that operates the view through an interface.
-The view does not interact directly with the model. This isolates the view
-implementation better than in MVC and allows easier unit testing of the
-presenter and model.
-
-[[figure.advanced.architecture.mvp]]
-.Model-View-Presenter Pattern
-image::img/mvp-pattern-hi.png[]
-
-<<figure.advanced.architecture.mvp>> illustrates the MVP pattern with a simple
-calculator. The domain model is realized in the [classname]#Calculator# class,
-which includes a data model and some model logic operations. The
-[classname]#CalculatorViewImpl# is a Vaadin implementation of the view, defined
-in the [interfacename]#CalculatorView# interface. The
-[classname]#CalculatorPresenter# handles the user interface logic. User
-interaction events received in the view are translated into
-implementation-independent events for the presenter to handle (the view
-implementation could also just call the presenter).
-
-Let us first look how the model and view are bound together by the presenter in
-the following example:
-
-
-[source, java]
-----
-
-// Create the model and the Vaadin view implementation
-CalculatorModel model = new CalculatorModel();
-CalculatorViewImpl view = new CalculatorViewImpl();
-
-// The presenter binds the model and view together
-new CalculatorPresenter(model, view);
-
-// The view implementation is a Vaadin component
-layout.addComponent(view);
-----
-
-You could add the view anywhere in a Vaadin application, as it is a composite
-component.
-
-[[advanced.architecture.mvp.model]]
-=== The Model
-
-Our business model is quite simple, with one value and a number of operations
-for manipulating it.
-
-
-[source, java]
-----
-/** The model **/
-class CalculatorModel {
- private double value = 0.0;
-
- public void clear() {
- value = 0.0;
- }
-
- public void add(double arg) {
- value += arg;
- }
-
- public void multiply(double arg) {
- value *= arg;
- }
-
- public void divide(double arg) {
- if (arg != 0.0)
- value /= arg;
- }
-
- public double getValue() {
- return value;
- }
-
- public void setValue(double value) {
- this.value = value;
- }
-}
-----
-
-
-[[advanced.architecture.mvp.view]]
-=== The View
-
-The purpose of the view in MVP is to display data and receive user interaction.
-It relays the user interaction to the presenter in an fashion that is
-independent of the view implementation, that is, no Vaadin events. It is defined
-as a UI framework interface that can have multiple implementations.
-
-
-[source, java]
-----
-interface CalculatorView {
- public void setDisplay(double value);
-
- interface CalculatorViewListener {
- void buttonClick(char operation);
- }
- public void addListener(CalculatorViewListener listener);
-}
-----
-
-The are design alternatives for the view. It could receive the listener in its
-constructor, or it could just know the presenter. Here, we forward button clicks
-as an implementation-independent event.
-
-As we are using Vaadin, we make a Vaadin implementation of the interface as
-follows:
-
-
-[source, java]
-----
-class CalculatorViewImpl extends CustomComponent
- implements CalculatorView, ClickListener {
- private Label display = new Label("0.0");
-
- public CalculatorViewImpl() {
- GridLayout layout = new GridLayout(4, 5);
-
- // Create a result label that spans over all
- // the 4 columns in the first row
- layout.addComponent(display, 0, 0, 3, 0);
-
- // The operations for the calculator in the order
- // they appear on the screen (left to right, top
- // to bottom)
- String[] operations = new String[] {
- "7", "8", "9", "/", "4", "5", "6",
- "*", "1", "2", "3", "-", "0", "=", "C", "+" };
-
- // Add buttons and have them send click events
- // to this class
- for (String caption: operations)
- layout.addComponent(new Button(caption, this));
-
- setCompositionRoot(layout);
- }
-
- public void setDisplay(double value) {
- display.setValue(Double.toString(value));
- }
-
- /* Only the presenter registers one listener... */
- List<CalculatorViewListener> listeners =
- new ArrayList<CalculatorViewListener>();
-
- public void addListener(CalculatorViewListener listener) {
- listeners.add(listener);
- }
-
- /** Relay button clicks to the presenter with an
- * implementation-independent event */
- @Override
- public void buttonClick(ClickEvent event) {
- for (CalculatorViewListener listener: listeners)
- listener.buttonClick(event.getButton()
- .getCaption().charAt(0));
- }
-}
-----
-
-
-[[advanced.architecture.mvp.presenter]]
-=== The Presenter
-
-The presenter in MVP is a middle-man that handles all user interaction logic,
-but in an implementation-independent way, so that it doesn't actually know
-anything about Vaadin. It shows data in the view and receives user interaction
-back from it.
-
-
-[source, java]
-----
-class CalculatorPresenter
- implements CalculatorView.CalculatorViewListener {
- CalculatorModel model;
- CalculatorView view;
-
- private double current = 0.0;
- private char lastOperationRequested = 'C';
-
- public CalculatorPresenter(CalculatorModel model,
- CalculatorView view) {
- this.model = model;
- this.view = view;
-
- view.setDisplay(current);
- view.addListener(this);
- }
-
- @Override
- public void buttonClick(char operation) {
- // Handle digit input
- if ('0' <= operation && operation <= '9') {
- current = current * 10
- + Double.parseDouble("" + operation);
- view.setDisplay(current);
- return;
- }
-
- // Execute the previously input operation
- switch (lastOperationRequested) {
- case '+':
- model.add(current);
- break;
- case '-':
- model.add(-current);
- break;
- case '/':
- model.divide(current);
- break;
- case '*':
- model.multiply(current);
- break;
- case 'C':
- model.setValue(current);
- break;
- } // '=' is implicit
-
- lastOperationRequested = operation;
-
- current = 0.0;
- if (operation == 'C')
- model.clear();
- view.setDisplay(model.getValue());
- }
-}
-----
-
-In the above example, we held some state information in the presenter.
-Alternatively, we could have had an intermediate controller between the
-presenter and the model to handle the low-level button logic.
-
-
-
-
-