• No results found

Getting rid of the multitier model in web development by using a toolset supporting event-driven widgets.

N/A
N/A
Protected

Academic year: 2021

Share "Getting rid of the multitier model in web development by using a toolset supporting event-driven widgets."

Copied!
31
0
0

Bezig met laden.... (Bekijk nu de volledige tekst)

Hele tekst

(1)

Getting rid of the multitier model in web development by using a toolset supporting event-driven widgets.

January 30, 2016

Mohamed Alkaduhimi (5828600) Msc. Software Engineering

Faculty of Science Universiteit van Amsterdam Supervised by:

dr. M. Bruntink Universiteit van Amsterdam

Abstract

In this thesis, we will provide a toolkit for developing highly reactive web applica-tions. This toolkit is based on knowledge acquired by studying pragmatic solutions for encapsulating the complexity of the multi-tier model, which web programmers have to use for developing such applications.

The toolkit we will provide, uses events to encapsulate communication between the server side part and the client side part of the web application. Isolated parts of a page, called widgets, can listen to events and changing parameters which are trig-gered by the client side part of the code, as a result, the widget (now on the server side) could react by adjusting some parameters itself and eventually refreshing its view.

(2)

Contents

1 Introduction 3

1.1 Problem definition . . . 3

1.2 Our solution . . . 5

2 Current efforts 5 2.1 Pragmatic (scientific) programming languages . . . 5

2.1.1 Links language . . . 5 2.2 Front-end MVC frameworks . . . 6 2.3 Component frameworks . . . 6 2.4 Isomorphic frameworks . . . 6 3 The requirements 7 4 Traffica 7 4.1 Stateful event driven widgets . . . 7

4.1.1 Three types of implementations . . . 8

4.1.2 DOM Manipulation from the server side . . . 9

4.2 PSR-4 . . . 10 4.3 The Framework . . . 10 4.3.1 Choices . . . 10 4.3.2 Architecture . . . 10 4.4 Syntax . . . 11 4.4.1 Defining a widget . . . 11 4.4.2 Triggering events . . . 13

4.4.3 Getting a parameter value . . . 13

4.4.4 Using Dwoo templates in the widget . . . 14

5 Limits 14 5.1 Non-reactive pages . . . 14

5.2 Compatibility with other Javascript tools . . . 15

5.3 Real time web applications . . . 15

6 Comparison with other frameworks 15 6.1 Setup . . . 15

6.2 Lines of code . . . 15

6.3 Distribution of controlling code between front and back-end . . . 16

6.4 Reuse of widgets and other OOP techniques . . . 17

6.5 Similarity to Links . . . 17

(3)

A Traffica Manual 21

A.1 Setup . . . 21

A.2 Environment . . . 21

A.3 Pages . . . 21

A.3.1 Class definition . . . 21

A.3.2 Adding a page to an environment . . . 22

A.4 Widgets . . . 22

A.4.1 Class definition . . . 22

A.4.2 Event listeners . . . 23

A.4.3 Parameter change listener . . . 24

A.4.4 Triggering events . . . 24

A.4.5 Getting a parameter value . . . 24

A.4.6 Using Dwoo templates in the widget . . . 24

(4)

1

Introduction

1.1 Problem definition

Since the uprise of the world wide web, a lot has changed in the structure, purpose and usage of web pages. In the past, web pages served merely as a one-way communication channel. Big companies and government instances used web pages to inform people about what they do. The users used it to obtain this information, download music and interesting programs.

Nowadays, the web is also used for many other purposes. Ways to interact with web pages have gained popularity and reactivity has become an important requirement for a lot of web applications. The incremental development of methods to enable web developers to achieve reactive web applications resulted in a very inconvenient system consisting of multiple layers having incompatible data representation models (impedance mismatch) [1]. While the use of Active Record in ORM (Object Relation Mapping) tools [11] or NoSQL databases in combination with JSON [12] is very effective in solving the impedance mismatch problem, the direct use of AJAX [10], transforms the simple classical one-way process (figure 1) into a cyclic process (figure 2). A characteristic for this cyclic process is the seperation between code which is executed on the server side (known as back-end) and code which is executed on the client side (known as front-end). The back-end code is executed once for each request and exits after responding to this request. In the back-end there is absence of a process running in the background, or a processing loop which can be requested on each interaction. The front-end is an event-driven piece of code which is triggered every time a user responds to the interface. Because the front-end code is sent directly to the user and is interpreted by the browser, no code should be written here which accesses sensitive information (like a database), this is always done in the back-end. Here is where AJAX comes into action, enabling the always awake front-end to invoke requests for the back-end code and to process the response afterwards.

(5)

Figure 1: The classical one-way process for serving web content

Figure 2: The cyclic process when using AJAX and DOM manipulations. The red arrows resemble the reactional part of the process.

(6)

1.2 Our solution

Because we are restricted by the way browsers work (HTTP), we are obliged to work by this cyclical process when developing reactive web applications. However, there is a possibility to encapsulate this process by providing a toolkit or framework which uses this internally, but provides an interface for the developer to write reactive applications without needing to interfere with the communication between the back-end and the front-end. There have been some attempts to solve this problem (see section 2), however most of those attempts require the developer to adapt to a very new way of working. In section 3, we will explore the requirements which need to be fulfilled for such a solutions to work and in section 4 we will introduce Traffica, a toolkit which uses an event system in combination with widgets to encapsulate all AJAX communication. Each widget is able to specify the events it listens to and is able to do DOM manipulations as a reaction to those events directly from the back-end. It is inspired by the Links language [1] and an event bus for enabling communication between mashup systems [16]. In section 5 and 6 we respectively explore the limits and compare Traffica to other solutions. In section 7, we summarize the conclusions and offer idea’s for further research.

2

Current efforts

Of course the problem we are discussing has been analyzed many times and multiple solutions have been devised to solve it. However each of these known solutions has its drawbacks. In this section follows a short summary of the most important works.

2.1 Pragmatic (scientific) programming languages

In a couple of attempts to solve this problem, scientists have devised some formal and theoretical languages like Links [1], Hop [2] and SQL++ [3]. We will briefly discuss the Links language as an example and then discuss the reason which makes such solutions not usable in practical situations.

2.1.1 Links language

The links language is devised in 2006 as an attempt to solve the impedance mismatch problem caused by the multi-tier architecture used for web programming [1]. The solu-tion the writers of this language came up with is to have one language with one syntax which can be compiled into code for the three tiers. This solution basically accepts the necessity of the existence of the three tiers. However, it provides a higher level language saving the programmer from needing to learn three different languages and to ensure that the codes for the three tiers communicate properly with one another.

The developer can attach event handler functions to events, so on propagation of the event, these functions are automatically called through AJAX. In the event handler functions, changes can be applied to the DOM tree (even though they are called on the server side). This way, the programmer will not even notice that there are separated

(7)

codes for the client and the server.

The links language solution has two problems: 1. The developer needs to learn a new language.

2. It can not run on a standard configuration for a web server without compiling.

2.2 Front-end MVC frameworks

One of the most important and maybe the most important state of the art solution is the front-end MVC framework. Example front-end MVC frameworks are Ember.js [4], An-gular.js [5] and Backbone [6]. In this solution, a web application is programmed mainly using JavaScript. A pre-processing language is only used for a secure communication with the database. The parsing of URL’s is done directly by the JavaScript controller without the interference of a pre-processing language. The controller uses models to communicate with the database through the pre-processing language using an uniform protocol (RESTful in most cases). This enables the pre-processing layer to be as simple and small as possible.

The drawback for using such frameworks is that you have to change the way of working. Companies which have always hired back-end PHP specialists, would have to change their whole staff into a staff consisting of rare geeky front-end developers. Another drawback is that such frameworks result in loading times larger than 2 seconds [14].

2.3 Component frameworks

Another flavour for simplicizing the multitier model is seen in the component frame-works. Component frameworks tend to try to minimize HTML and JavaScript usage and concentrate on building GUI’s with only a toolkit written in a pre-processing lan-guage (PHP / Java). Examples of such frameworks are Tapestry [7], NOLOH (No Line Of HTML) [8] and PRADO [9]. This type of frameworks is highly inspired by the pro-gramming of GUI’s for Java and C++. HTML and JavaScript generation is totally encapsulated and the web page is not a page anymore, but a window. This window is represented by a class in the code which has event bindings for the start of the program, end of the program etc. Further, there is a possibility to add buttons and other UI elements to this window and to listen to their click events.

The main reason that using such frameworks is not popular is because writing an UI el-ement, which is not offered by default, is very troublesome and requires deep knowledge of how the magical well-encapsulated system works.

2.4 Isomorphic frameworks

Like other active members of the web programming industry, I have witnessed the hype of Isomorphic frameworks. The main goal of these framework is not different from the links language or the component frameworks. It is simply to develop a way to program a web application in one programming language. Links uses HTML as the main language with

(8)

a couple of DSL’s to reach this goal, the component frameworks, choose a pre-processing language (like PHP or Java) and try to encapsulate the other languages by providing a large set of UI elements. This makes links and component frameworks belong to the set of isomorphic frameworks. Other well-known isomorphic frameworks are NodeJs, react, meteor and wicket, however those tend to focus on using the JavaScript language as the main language. The solution we will be introducing in this thesis, also belongs to this family of frameworks.

3

The requirements

For a solution to our problem to work, it needs to fulfill the needs of the group of people who will use the solution (the stakeholders). As an active participator in the community of web developers, I think that it is necessary for a solution to not revolutionary change the way web developers work. It should offer them a toolkit providing handy tools and syntactical sugar to enable the developer to maintain his current working strategy while enjoying the possibility to write descriptive code without the need to cut through the layers of the multi-layered system. Practically, the requirements can be expressed as:

1. The solution should encapsulate AJAX scripting.

2. The solution should work on a standard configuration for a web server (LAMP). 3. The solution will not need the developer to learn a new language.

4. The solution should not result in more lines of code compared to the classic method. 5. The solution should not result in more complex code compared to the classic

method.

6. The solution should not result in a loading time greater than two seconds (Research has shown that response time for software to a simple inquiry of status should be within 2 seconds [13]).

4

Traffica

We will give the toolkit we will provide and test in this thesis the name Traffica, because the way it regulates communication between the server side code and the client side code is similiar to that of a traffic light.

4.1 Stateful event driven widgets

Analyzing most pages in web applications, we will find that they consist of different components, each with a different task. In our toolkit, we will call those components widgets. They have a lot in common with mashups [17], however our widgets do not reside on an external server. Our choice for having widgets is inspired by A frame-work

(9)

for rapid integration of presentation components [16]. In short, Jin Yu describes that event driven communication between page components (in our case widgets) can be achieved by having a stateful middle ware component, where all the event listeners for each widget are registered and which handles the event propagation and state passing. In our toolkit, this middle ware will be Traffica itself. A diagram which depicts the process is shown in figure 3.

Figure 3: The handling of events in Traffica. First a widget registers callbacks to events. The callbacks, when called (automatically by traffica on occurence of the event), return a set of changes to the DOM tree which are automatically applied by Traffica. In the diagram, only step 1.1, 2.2 and 2.4 should be implemented manually, while the rest is handled by traffica.

4.1.1 Three types of implementations

The event system described by Jin Yu [16] can be implemented in three ways. We will examine the three implementations and choose the one which best matches our goal. The implementations:

Render on every event Initially, the code to build a widget is called to render it in its initial form. Every time an event occurs to which the widget listens, the code to

(10)

build and render the widget is called again. The code will render the widget depending on the new state. This method works the same as the C++ style proc loop. In our case, it has the drawback that every change in the DOM tree should be done using a call to the server side script which determines how to re-render the widget. This could slow down the interaction as a call to the server side is done by using an AJAX request and this type of requests are relatively slow.

Send DOM changes from server to client on every event This solutions is

almost the same as the previous, however, after building the widget initially, instead of calling the same re-building the widget again, we call the server side code again to send only the changes to the client side script. This way, the communication stream is smaller, but the request overhead is the same.

Unparse event listeners which change DOM to client code In this solution, the widget is initially built by the server side again, however, event listening code is directly unparsed into JavaScript on initialization of the widget. Reactions to events do not need to call any server side script, but instead will execute directly on the client side.

Decision If we choose to unparse event listeners to client code, we could choose to write listener code in a DSL or to write it in server side code. When chosen to write listener code in a DSL, the developer has to learn a new language to use the toolkit. This is against requirement 3. The other possibility for unparsing listener code to client side code, requires translating server side code to client side code. This basically is possible (see services as Transifex), however communication with the database would also be done from the client side. This would cause a security problem, because client side code is executed on the client side and thereby readable by the client.

To make the better choice, it is important to analyse the types of reactions which can be triggered by event listeners. There are two types of reactions:

1. Changes on the presentation level (DOM tree changes) without any calculations or processing.

2. Calculations and processing with potential changes to the DOM tree.

We choose to only unparse event reactions of type 1, which most of the time are expected to be faster than those of type 2 [13]. Event reactions of type 2, will be handled by calling the server side code and make it send the DOM tree changes instead of re-rendering the whole widget view. Not unparsing event reactions of type 2 save us from writing difficult unparsing techniques. In section 4.1.2, the reader can see that this choice enables us to write an embedded DSL in PHP for DOM manipulations.

4.1.2 DOM Manipulation from the server side

Inspired by the links language (see section 2.1.1), the choice has been made to give the DOM manipulation instructions from the server side using an embedded DSL. For

(11)

this purpose, we will use a library called Phery [18] which uses the JQuery syntax to manipulate the DOM tree from the server side. The library can be added through composer easily. The syntax for the DOM tree manipulation is exactly like JQuery. An example code of Phery where we change the font color of all elements with class hi to black is:

P h e r y R e s p o n s e::f a c t o r y() - >j q u e r y(’ . hi ’) - >css(’ c o l o r ’,’ # 0 0 0 0 0 0 ’);

4.2 PSR-4

The PSR-4 standard is applied to be compatible with composer autoloading. The toolkit could then be offered as an easy to include package through packagist.

4.3 The Framework

In section 4.3.1, we will discuss some choices shortly and in section 4.3.2, the architecture of Traffica is explained shortly.

4.3.1 Choices

Symfony routing Every web application needs a routing mechanism to map URL’s to code sections. Instead of writing difficult and Apache-specific htaccess rules, we have chosen to use Symfony’s routing system to handle the URL’s. The choice for Symfony’s routing has been made because of how easy it is to use and to include into the project through composer.

Dwoo templating engine Dwoo is a templating engine which revives smarty, the dead templating engine with state of the art PHP5 features. The choice for Dwoo is because of its popular syntax. Dwoo also fits easily in the package because it is easy to add through composer.

Multiple environments We have added an environment layer, so multiple environ-ments could be defined in one application. Think about an admin environment, which is coded separately from the public environment.

4.3.2 Architecture

In figure 4, you can see the architecture of Traffica.

As you can see, we have the traffica engine, which acts like a bus or a middle ware component, like described by [16]. We have the Symfony routing mechanism, which links url’s to the Url Arbiter of the traffica engine and so, connects the browser to traffica. The lower part of the diagram (Traffica Engine, Symfony Routing and Browser code) represents the raw core of Traffica. The upper part, represents the code of the user, which should be structured in environments, pages and widgets. There is a possibility

(12)

to use the dwoo templating engine as it is provided together with the framework, but any other templating engine can be used.

Figure 4: The internal structure of Traffica. See section 4.3.2 for a short explanation.

4.4 Syntax

In this section we will give some small examples to present the syntax of the toolkit. A complete manual can be found in appendix A and the complete example for building MVCTodo is given in B.

4.4.1 Defining a widget

In Traffica you can define a widget which listens to events and parameter changes.

Class definition Widgets in Traffica are normal classes extended from Traffica\Base\Widget. In the end of this paragraph, an example class definiton for a widget can be found.

(13)

But before the example, here follows a list with some basic functions which are called automatically by the toolkit:

init The init function is called in the start of the widget to initiate basic settings of the widget.

execute The execute function is called before calling the correct function for build-ing the widget response.

build The build function is called when the widget will be drawn for the first time. This function should build the widget HTML-structure.

c l a s s T o d o W i d g e t e x t e n d s \T r a f f i c a\B a s e\W i d g e t { f u n c t i o n i n i t() { // I n i t i a t i n g w i d g e t ( w i d g e t n a m e / o t h e r c l a s s // p r o p e r t i e s ) } f u n c t i o n e x e c u t e() { // E x e c u t e w i d g e t f u n c t i o n a l i t y ( b e f o r e c a l l i n g // f u n c t i o n b u i l d or o t h e r e v e n t l i s t e n e r s ) } f u n c t i o n b u i l d() {

// The w i d g e t w i l l s h o w hii in a div ( div is an // H T M L tag )

r e t u r n ’ < div > hii </ div > ’; }

}

Event listeners In traffica the communication between widgets is done with the use of events. A widget can listen to any event, by adding a function which starts with on and then the event name in StudlyCaps. So if we want our widget to listen to the event add-new-task, we have to define a function onAddNewTask. A listener function must always have the array parameter $data (event data is passed through this parameter) and return a JQuery response which is executed after the execution of the function. For example, we want to change the font color of all div elements to gray on the occurence of a gray-button-clicked event. The code would look like this:

(14)

c l a s s T o d o W i d g e t e x t e n d s \T r a f f i c a\B a s e\W i d g e t { ... f u n c t i o n o n G r a y B u t t o n C l i c k e d(a r r a y $ d a t a) { r e t u r n J Q u e r y::f a c t o r y(’ div ’) - >css(’ c o l o r ’, ’ # 6 6 6 ’); } ... }

Parameter change listener Parameter change listeners are a special form of listeners which are executed on every change of a specific variable. If you want to listen to a change in the nr-tasks variable, you can add a function to your widget called onChangeNrTasks. As you can see, it should start with onChange and end with the variable name in studly caps. A parameter change listener should always accept two parameters, which are $old and $new and respectively hold the old value and the new value of the variable. A parameter change listener should return a JQuery response, just like normal event listeners.

4.4.2 Triggering events

Triggering events always happens from JavaScript on the client side. There are two functions defined for this purpose, the event function and the param function. The first triggers an event and accepts a JavaScript object as event data. The second changes a parameter value and accepts two parameters: the name of the parameter and its new value. Example code for triggering an add-new-task event on clicking a link is:

<a id=" new - t a s k " h r e f=" # ">New task</a> <script>

$(’ # new - t a s k ’).c l i c k(f u n c t i o n(e) {

e v e n t(’ add - new - t a s k ’, { } ) ; });

</script>

4.4.3 Getting a parameter value

Anywhere inside the widget code, you can get the current value for any parameter. You can do so by calling traffica()->state->get(’parameter-name’, ’default-value’). The first argument is the name of the parameter you want the value of and the second argument is the default value that the call should return if the parameter is not defined. The second argument can be left out and the call will return false when the parameter is not defined.

(15)

4.4.4 Using Dwoo templates in the widget

As can be seen in section 4.4.1, the build function should return the HTML code for the widget. To not contaminate your PHP code with HTML, you can use a DWOO template. An example for using dwoo in the widget:

c l a s s T o d o W i d g e t e x t e n d s \T r a f f i c a\B a s e\W i d g e t

{

...

f u n c t i o n b u i l d() {

// you can p a s s the t e m p l a t e f i l e n a m e w h i c h w i l l be s e a r c h e d // for in the v i e w s dir l o c a t e d in the web r o o t and v a r i a b l e s // w h i c h can be u s e d in t e m p l a t e r e t u r n t r a f f i c a() - >t e m p l a t e- >get( ’ t e m p l a t e n a m e . tpl ’, a r r a y(’ n a m e ’= >’ t r a f f i c a ’) ); } ... }

and in templatename.tpl you can output the variable name with double braces: <div>

h i i i {{n a m e}} </div>

5

Limits

In this section, we will try to explore the limits of Traffica and try to answer questions as: In which scenario’s would Traffica not be the best choice.

5.1 Non-reactive pages

A situation where Traffica is obviously not the best choice is when you want to build a web application or website where no reactiveness is needed. For example an informative web page or RSS feed. Some overhead is added by the use of Traffica with defining separate widget classes and adding them to pages. The development of such static web sites is decreasing day by day as most websites which are built nowadays use a Content Management System (CMS). Such a system is most of the time required to be reactive.

(16)

5.2 Compatibility with other Javascript tools

Traffica uses JQuery and JQuery is known to not being compatible with other JavaScript tools as Prototype and Dojo. However, because Traffica uses the JQuery noConflict mode, those other tools can be used without any problems!

5.3 Real time web applications

For applications as an online document sharing and editing paltform where changes in the file made by other users should be pushed automatically to the screen of the web application user, other frameworks like NodeJS in combination with Socket.io are more efficient. This is because the mentioned frameworks have a built-in functionality to react to events from requests outside the client-server session. In our case, this functionality is not provided as part of the toolkit and should be implemented by the developer using the toolkit whenever needed, possibly using other tools as ReactPHP or Ratchet.

6

Comparison with other frameworks

In this section, Traffica is compared to other solutions to the AJAX problem. In most of the cases, the comparison is done with Ember.js, because that is a good representative for front-end MVC frameworks and those frameworks represent the most adopted solution.

6.1 Setup

The setup is done by installing the package through composer and starting to define the theme (if there is any) and the pages for the application (see Appendix A voor de-tails). The setup is quite similiar to most other frameworks where you have to download the framework first, then develop the theme and routing before you can really see any application on the screen.

6.2 Lines of code

To test our solution against the other solutions mentioned in section 2, we will have to do some measurements. The choise is made to compare our toolkit with Ember.js using the well-known TodoMVC [15] as a benchmark application. As can be seen in the results (table 1), the there is not a big difference in the number of lines of code.

For counting the lines of code, we choose to use Logical Lines Of Code (LLOC) [19]. The tool which is used for the measurement is CLOC (http://sourceforge.net/projects/cloc) which is able to calculate LLOC for JavaScript and for PHP. Further, we will only count the lines of files where the logic is defined. Files with the HTML structure and stylesheets and files for initiating the framework are ignored.

(17)

Toolkit / Framework Lines of code

Traffica 112

Ember.js 128

Table 1: LLOC measurements for an example implementation of TodoMVC

6.3 Distribution of controlling code between front and back-end

One of the biggest problems in building a web application using AJAX is that you have to write a part of the controlling code in the back-end and a part in the front-end (Javascript). A developer has to master the coding languages for both systems and would have to write the controlling code in a way that those two systems work together seemlessly. Ember.js and other front-end MVC frameworks, try to shift the control to the front-end. See figure 5 for a distribution of tasks between back-end and front-end in ember.js. However, they end up needing to write controlling code in the back-end because some parts of the applications aren’t secure if sent to the browser (Like database passwords). In the case of Traffica, the control is shifted towards the PHP side and because the PHP-side is able to generates Front-end code (by echoing Javascript into the generated HTML), a user is not needed to write controlling code in the front-end. Even better, there is no seperation between front-end and back-end in traffica. The only part which has to be written in Javascript is the translation between UI events like clicks and Traffica events which can be listened to by widgets, see section 4.4.2 and figure 6.

Figure 5: The distribution of tasks between back-end and front-end in a typical Ember.js application

(18)

Figure 6: The distribution of tasks between back-end and front-end in a traffica appli-cation

6.4 Reuse of widgets and other OOP techniques

Of course measuring the lines of code for the (simple) TodoMVC application as done in section 6.2 is merely an indication that Traffica does not have too much overhead in the code. One of the benefits of Traffica above JavaScript toolkits is that it offers the possibility to use the Object Orientated Programming of PHP. This makes it possible to reuse already defined widgets, loosely coupling, class inheritance and other OOP techniques. Expectations are that the lines of code needed to write a bigger application than TodoMVC would be less in Traffica than in Ember.js because of the possibility to reuse widget code. However this is not the only benefit gained by reusing already defined widgets, using object inheritance is known to potentially increase understandability and maintainability [20]

6.5 Similarity to Links

Traffica is somewhat similar to Links in the way it handles events. In Links, events triggered by the client side are handled in the code alongside server side code. From the event handling functions there is a possibility to directly manipulate the DOM tree. The same principles are also embedded into Traffica, see listing 1 and 2 for examples of event handling of Traffica and Links respectively.

Listing 1: An example of event handler in Traffica

f u n c t i o n o n C h a n g e P r o g r e s s($old, $ n e w) { r e t u r n J Q u e r y::f a c t o r y(’ # id ’) - >css(’ w i d t h ’, $ n e w) - >css(’ b a c k g r o u n d ’, ’ b l a c k ’) ; }

Listing 2: An example of event handler in Links

fun s h o w P r o g r e s s(p r o g r e s s) c l i e n t {

r e p l a c e N o d e( <div id=’ bar ’

(19)

</div> ,

g e t N o d e B y I d(’ bar ’) )

}

7

Conclusions and further research

With Traffica, we have demonstrated that it is possible to design a toolkit which en-capsulates AJAX communication using already available industrial methods, saving the developer from writing seperate controlling code for the front-end and the back-end. The solution does not need developers to change their whole environment and works on a popular setup like LAMP (Linux, Apache, Mysql and PHP). The mentioned properties of the designed toolkit make it practical for current teams to adapt their already working applications to work with it. Because of the fact that it reduces the front-end to only translate input events to Traffica events, it reduces maintainance costs. Understanding and maintaining one system (only back-end) is easier than maintaining two heteroge-neous systems (back-end and front-end). More benefits in maintainability can be gained by using OOP possibilities which PHP has which can not be implemented in Javascript. We have seen that it shows some similarity to pragmatic methods and argued that it does not result in overhead in lines of code.

Further research can be done to provide an empirical prove that using Traffica results in an increase in understandability and maintainability.

Further research is also needed to decide on wether and when it is beneficial to have a GUI toolkit (like Swing for Java) instead of writing raw HTML. The use of such a toolkit would save new developers from learning HTML, but at the same time restricts him / her to use only predefined UI elements.

Another possibility for further development is to consider moving even the translation from input events to Traffica events, to PHP. Doing so, we annihilate the need to use any Javascript at all. However, this is not beneficial per se, because the translation step is not written as controlling code which needs thorough understanding of the process.

(20)

References

[1] Links:Web programming without tiers, E. Cooper, S. Lindley, P. Wadler, and J. Yallop, FMCO, pages 266-296, 2006.

[2] Hop: a language for programming the web 2.0, M. Serrano, E. Gallesio, F. Loitsch, Proceedings of the First Dynamic Languages Symposium, 2006.

[3] Declarative ajax web applications through sql++ on a unified application state, Y. Fu, K. W. Ong, Y. Papakonstantinou, In DBPL, 2013.

[4] Ajax: a new approach to web applications, J. J. Garret, Adaptive Path, 2005. [5] Patterns of Enterprise Application Architecture, M. Fowler, Addison-Wesley

Profes-sional, 2003.

[6] The JavaScript Object Notation (JSON) Data Interchange Format, T. Bray, RFC 7159, 2014.

[7] Response time in man-computer conversational transactions, R. B. Miller, fall joint computer conference, part I, Proceedings of the December 9-11, 1968.

[8] A framework for rapid integration of presentation components, J. Yu, B. Benatal-lah, R. Saint-Paul, F. Casati, F. Daniel and M. Matera, Proceedings of the 16th international conference on World Wide Web. 2007.

[9] Mashups: The new breed of Web app, D. Merrill, IBM Web Architecture Technical Library: 1-13, 2006.

[10] A SLOC Counting Standard, V. Nguyen, S. Deeds-Rubin, T. Tan, B. Boehm, CO-COMO II Forum, 2007.

[11] Evaluating inheritance depth on the maintainability of object-oriented software, J. Daly, A. Brooks, J. Miller, M. Roper, M. Wood, Empirical Software Engineering, Volume 1, Issue 2 , pp 109-132, 1996.

[12] A framework for creating ambitious web applications, Ember, http://emberjs.com [13] HTML enhanced for web apps!, Angular, https://angularjs.org

[14] Backbone.js, Backbone, https://http://backbonejs.org

[15] Apache tapestry 5. Code less, deliver more, Apache Foundation,

https://tapestry.apache.org, 2000.

[16] NOLOH, Build for the web faster and easier, NOLOH LLC, http://www.noloh.com, 2005.

[17] Prado, component framework for PHP 5, PRADO Group,

(21)

[18] TodoMVC, helping you select an MV* framework, http://todomvc.com

[19] Research: Performance Impact of Popular JavaScript MVC Frameworks, J. Bender, T. Parker, S. Jehl, http://www.filamentgroup.com/lab/mv-initial-load-times.html [20] PHP AJAX jQuery integration, Phery.js, http://phery-php-ajax.net/

(22)

A

Traffica Manual

A.1 Setup

Setting up traffica uses composer create-project. To set up a new project, use the command composer create-project traffica/application [project-dir] and sub-stitute [project-dir] with the name of the directory, you want to use traffica in. If you are inside your document root directory, use the command composer create-project traffica/application . to create the project into the current directory.

A.2 Environment

In traffica, you have the possibility to add multiple environments. The typical place to define environments is in the /start/load pages.php file, because this file is loaded when any request is done. The environment is seen in the url as the first url segment. For example, when you build a website, you want to have a public section where the website is shown and an admin section, where the content of the website can be man-aged. This can be done by adding two environments: the admin environment and the public environment. You can add a slug to each environment, so requests to the admin environment would look like http://domain.com/admin and requests to the website would look like http://domain.com/public/.

When defining environments, you can set up a default environment, so requests to http://domain.com/ would automatically trigger this environment. Example code for defining environment is:

file /start/load pages.php

// A d d i n g the p u b l i c e n v i r o n m e n t . N o t i c e t h a t g i v i n g t r u e as

// the o p t i o n a l 3 rd p a r a m e t e r w i l l set t h i s e n v i r o n m e n t as d e f a u l t

$ p u b l i c = t r a f f i c a() - >m a k e(’ p u b l i c ’, ’ p u b l i c ’, t r u e);

A.3 Pages

In traffica, you can implement the whole application as a single page, however, some-times you choose to have multiple pages for other reasons (for example: search engine optimization). If this is the case, it is possible to add multiple pages to an environ-ment. Pages, can also have a slug or be the default page for the environenviron-ment. A page to show all news items in a blog, could have the slug news and if added to the default environment, would then be accessible by requesting http://domain.com/news.

A.3.1 Class definition

Widgets in Traffica are normal classes extended from Traffica\Base\Page. In the end of this paragraph, an example class definiton for a page is:

(23)

{ p u b l i c f u n c t i o n _ _ c o n s t r u c t() { $this- >s e t S l u g(’ m a i n ’); } p u b l i c f u n c t i o n i n i t() { $this- >s e t L a y o u t(new L a y o u t);

// h e r e add a w i d g e t s to the c o n t e n t of the p a g e

$this- >w i d g e t(new Widget, ’ c o n t e n t ’);

// a d d i n g a s t y l e s h e e t to the p a g e

$this- >s t y l e(’ css / b a s e . css ’);

r e t u r n p a r e n t::i n i t(); }

}

A.3.2 Adding a page to an environment

Adding a page to an environment is typically done in /start/load pages.php, as that is the file which is loaded everytime a request is made. Example code for this task is: file /start/load pages.php

// A d d i n g the p u b l i c e n v i r o n m e n t . N o t i c e t h a t g i v i n g t r u e as

// the o p t i o n a l 3 rd p a r a m e t e r w i l l set t h i s e n v i r o n m e n t as d e f a u l t

$ p u b l i c = t r a f f i c a() - >m a k e(’ p u b l i c ’, ’ p u b l i c ’, t r u e);

// Add a p a g e to the p u b l i c e n v i r o n m e n t

$public- >a d d P a g e(new Page, t r u e);

A.4 Widgets

In Traffica you can define a widget which listens to events and parameter changes.

A.4.1 Class definition

Widgets in Traffica are normal classes extended from Traffica\Base\Widget. In the end of this paragraph, an example class definiton for a widget can be found.

But before the example, here follows a list with some basic functions which are called automatically by the toolkit:

init The init function is called in the start of the widget to initiate basic settings of the widget.

(24)

execute The execute function is called before calling the correct function for building the widget response.

build The build function is called when the widget will be drawn for the first time. This function should build the widget HTML-structure.

c l a s s T o d o W i d g e t e x t e n d s \T r a f f i c a\B a s e\W i d g e t { f u n c t i o n i n i t() { // I n i t i a t i n g w i d g e t ( w i d g e t n a m e / o t h e r c l a s s // p r o p e r t i e s ) } f u n c t i o n e x e c u t e() { // E x e c u t e w i d g e t f u n c t i o n a l i t y ( b e f o r e c a l l i n g // f u n c t i o n b u i l d or o t h e r e v e n t l i s t e n e r s ) } f u n c t i o n b u i l d() {

// The w i d g e t w i l l s h o w hii in a div ( div is an // H T M L tag )

r e t u r n ’ < div > hii </ div > ’; }

}

A.4.2 Event listeners

In traffica the communication between widgets is done with the use of events. A widget can listen to any event, by adding a function which starts with on and then the event name in StudlyCaps. So if we want our widget to listen to the event add-new-task, we have to define a function onAddNewTask. A listener function must always have the array parameter $data (event data is passed through this parameter) and return a JQuery response which is executed after the execution of the function. For example, we want to change the font color of all div elements to gray on the occurence of a gray-button-clicked event. The code would look like this:

use T r a f f i c a\B a s e\J Q u e r y; c l a s s T o d o W i d g e t e x t e n d s \T r a f f i c a\B a s e\W i d g e t { ... f u n c t i o n o n G r a y B u t t o n C l i c k e d(a r r a y $ d a t a) {

(25)

r e t u r n J Q u e r y::f a c t o r y(’ div ’) - >css(’ c o l o r ’, ’ # 6 6 6 ’); }

... }

A.4.3 Parameter change listener

Parameter change listeners are a special form of listeners which are executed on every change of a specific variable. If you want to listen to a change in the nr-tasks variable, you can add a function to your widget called onChangeNrTasks. As you can see, it should start with onChange and end with the variable name in studly caps. A parameter change listener should always accept two parameters, which are $old and $new and respectively hold the old value and the new value of the variable. A parameter change listener should return a JQuery response, just like normal event listeners.

A.4.4 Triggering events

Triggering events always happens from JavaScript on the client side. There are two functions defined for this purpose, the event function and the param function. The first triggers an event and accepts a JavaScript object as event data. The second changes a parameter value and accepts two parameters: the name of the parameter and its new value. Example code for triggering an add-new-task event on clicking a link is:

<a id=" new - t a s k " h r e f=" # ">New task</a> <script>

$(’ # new - t a s k ’).c l i c k(f u n c t i o n(e) {

e v e n t(’ add - new - t a s k ’, { } ) ; });

</script>

A.4.5 Getting a parameter value

Anywhere inside the widget code, you can get the current value for any parameter. You can do so by calling traffica()->state->get(’parameter-name’, ’default-value’). The first argument is the name of the parameter you want the value of and the second argument is the default value that the call should return if the parameter is not defined. The second argument can be left out and the call will return false when the parameter is not defined.

A.4.6 Using Dwoo templates in the widget

As can be seen in section 4.4.1, the build function should return the HTML code for the widget. To not contaminate your PHP code with HTML, you can use a DWOO template. An example for using dwoo in the widget:

(26)

c l a s s T o d o W i d g e t e x t e n d s \T r a f f i c a\B a s e\W i d g e t

{

...

f u n c t i o n b u i l d() {

// you can p a s s the t e m p l a t e f i l e n a m e w h i c h w i l l be s e a r c h e d // for in the v i e w s dir l o c a t e d in the web r o o t and v a r i a b l e s // w h i c h can be u s e d in t e m p l a t e r e t u r n t r a f f i c a() - >t e m p l a t e- >get( ’ t e m p l a t e n a m e . tpl ’, a r r a y(’ n a m e ’= >’ t r a f f i c a ’) ); } ... }

and in templatename.tpl you can output the variable name with double braces: <div>

h i i i {{n a m e}} </div>

B

Traffica MVCTodo implementation

The MVCTodo app exists of a widget object. The widget object uses 3 template files. Below the code for the widget object and the 3 templates.

The definition of the widget:

use T r a f f i c a\B a s e\J Q u e r y; use T r a f f i c a\B a s e\W i d g e t; c l a s s T o d o W i d g e t e x t e n d s W i d g e t { p u b l i c f u n c t i o n o n T a s k A d d(a r r a y $ d a t a) { $ i t e m s = t r a f f i c a() - >state- >get(’ i t e m s ’, a r r a y( ) ) ; $ i t e m s[] = a r r a y( ’ id ’ = > c o u n t($ i t e m s) + 1 , ’ n a m e ’ = > $ d a t a[’ t a s k ’] , ’ s t a t e ’ = > ’ a c t i v e ’, ); t r a f f i c a() - >state- >set(’ i t e m s ’, $ i t e m s); r e t u r n $this- >u p d a t e B u i l d()

(27)

- >j q u e r y(’ # new - t o d o ’) - >val(’ ’) ; } p u b l i c f u n c t i o n o n D e s t r o y(a r r a y $ d a t a) { $ i t e m s = t r a f f i c a() - >state- >get(’ i t e m s ’, a r r a y( ) ) ; f o r e a c h($ i t e m s as $ k e y = > $ i t e m) { if($ i t e m[’ id ’] == $ d a t a[’ id ’]) { u n s e t($ i t e m s[$ k e y]); } } t r a f f i c a() - >state- >set(’ i t e m s ’, $ i t e m s); r e t u r n $this- >u p d a t e B u i l d(); } p u b l i c f u n c t i o n o n T o g g l e C o m p l e t e(a r r a y $ d a t a) { $ i t e m s = t r a f f i c a() - >state- >get(’ i t e m s ’, a r r a y( ) ) ; f o r e a c h($ i t e m s as $ k e y = > $ i t e m) { if($ i t e m[’ id ’] == $ d a t a[’ id ’]) { if ($ i t e m s[$ k e y][’ s t a t e ’] == ’ c o m p l e t e d ’) $ i t e m s[$ k e y][’ s t a t e ’] = ’ a c t i v e ’; e l s e $ i t e m s[$ k e y][’ s t a t e ’] = ’ c o m p l e t e d ’; } } t r a f f i c a() - >state- >set(’ i t e m s ’, $ i t e m s); r e t u r n $this- >u p d a t e B u i l d(); } p u b l i c f u n c t i o n o n C h a n g e F i l t e r($old, $ n e w) { if ($ o l d != $ n e w) { r e t u r n $this- >u p d a t e B u i l d(); } r e t u r n J Q u e r y::f a c t o r y(); } p u b l i c f u n c t i o n b u i l d() { $ l i s t = $this- >b u i l d L i s t();

(28)

$ f o o t e r = $this- >b u i l d F o o t e r(); r e t u r n t r a f f i c a() - >t e m p l a t e- >get( ’ t o d o . tpl ’, a r r a y(’ l i s t ’= >$list, ’ f o o t e r ’= >$ f o o t e r) ); } p u b l i c f u n c t i o n i n i t() { $this- >s e t N a m e(’ todo - w i d g e t ’) - >s c r i p t( ’ todo - w i d g e t ’, ’ js / m a i n . js ’, a r r a y(’ j q u e r y ’) ) ; r e t u r n p a r e n t::i n i t(); } p r o t e c t e d f u n c t i o n u p d a t e B u i l d() { $ l i s t = $this- >b u i l d L i s t(); $ f o o t e r = $this- >b u i l d F o o t e r(); r e t u r n J Q u e r y::f a c t o r y(’ # m a i n ’) - >r e p l a c e W i t h($ l i s t) - >j q u e r y(’ f o o t e r ’) - >r e p l a c e W i t h($ f o o t e r) ; } p r o t e c t e d f u n c t i o n g e t F i l t e r e d I t e m s() { if (t r a f f i c a() - >state- >get(’ i t e m s ’) == f a l s e) { t r a f f i c a() - >state- >set(’ i t e m s ’, a r r a y( ) ) ; } $ i t e m s = a r r a y(); $ r a w I t e m s = t r a f f i c a() - >state- >get(’ i t e m s ’); s w i t c h(t r a f f i c a() - >state- >get(’ f i l t e r ’, ’ a c t i v e ’)) { c a s e ’ a c t i v e ’: f o r e a c h($ r a w I t e m s as $ i t e m) { if ($ i t e m[’ s t a t e ’] == ’ a c t i v e ’) $ i t e m s[] = $ i t e m; } b r e a k; c a s e ’ c o m p l e t e d ’: f o r e a c h($ r a w I t e m s as $ i t e m) { if ($ i t e m[’ s t a t e ’] == ’ c o m p l e t e d ’)

(29)

$ i t e m s[] = $ i t e m; } b r e a k; d e f a u l t: $ i t e m s = t r a f f i c a() - >state- >get(’ i t e m s ’); b r e a k; } r e t u r n $ i t e m s; } p r o t e c t e d f u n c t i o n b u i l d L i s t() { r e t u r n t r a f f i c a() - >t e m p l a t e- >get( ’ l i s t . tpl ’, a r r a y(’ i t e m s ’= >$this- >g e t F i l t e r e d I t e m s()) ); } p r o t e c t e d f u n c t i o n b u i l d F o o t e r() { r e t u r n t r a f f i c a() - >t e m p l a t e- >get( ’ f o o t e r . tpl ’, a r r a y( ’ n r _ i t e m s ’ = > c o u n t($this- >g e t F i l t e r e d I t e m s()) , ’ f i l t e r ’ = > t r a f f i c a() - >state- >get(’ f i l t e r ’) , ) ); } }

The widget basic structure todo.tpl: <s e c t i o n id=" t o d o a p p "> <h e a d e r id=" h e a d e r "> <h1>todos</h1> <i n p u t id=" new - t o d o " p l a c e h o l d e r=" W h a t n e e d s to be d o n e ? " a u t o f o c u s=" "> </header> {$ l i s t} {$ f o o t e r} </section>

The list template list.tpl: <s e c t i o n id=" m a i n ">

<i n p u t id=" toggle - all " t y p e=" c h e c k b o x ">

<l a b e l for=" toggle - all ">M a r k all as c o m p l e t e</label> <ul id=" todo - l i s t ">

(30)

{f o r e a c h f r o m=$ i t e m s i t e m=i t e m} <li {if $ i t e m.s t a t e eq ’ c o m p l e t e d ’}c l a s s=" c o m p l e t e d "{/if} > <div c l a s s=" v i e w "> <i n p u t c l a s s=" t o g g l e " data-t o g g l e i d=" { $ i t e m . id } " t y p e=" c h e c k b o x " {if $ i t e m.s t a t e eq ’ c o m p l e t e d ’}c h e c k e d=" c h e c k e d "{/if} / > <label>{$ i t e m.n a m e} </label> <b u t t o n data-d e s t r o y i d=" { $ i t e m . id } " c l a s s=" d e s t r o y "> </button> </div> <i n p u t c l a s s=" e d i t " v a l u e=" { $ i t e m . n a m e } "> </li> {/f o r e a c h} </ul> </section>

The widget footer template footer.tpl:

<f o o t e r id=" f o o t e r " s t y l e=" d i s p l a y : b l o c k ; ">

<s p a n id=" todo - c o u n t "> <strong>{$ n r _ i t e m s} </strong>

i t e m l e f t </span> <ul id=" f i l t e r s "> <li> <a {if $ f i l t e r eq ’ all ’}c l a s s=" s e l e c t e d "{/if} o n c l i c k= " p a r a m ( ’ f i l t e r ’ , ’ all ’); " h r e f=" #/ " > All </a> </li> <li> <a {if $ f i l t e r eq ’ a c t i v e ’}c l a s s=" s e l e c t e d "{/if} o n c l i c k= " p a r a m ( ’ f i l t e r ’ , ’ a c t i v e ’); " h r e f=" #/ a c t i v e " > A c t i v e </a> </li> <li> <a {if $ f i l t e r eq ’ c o m p l e t e d ’}c l a s s=" s e l e c t e d "{/if} o n c l i c k=" p a r a m ( ’ f i l t e r ’ , ’ c o m p l e t e d ’); " h r e f=" #/ c o m p l e t e d " > C o m p l e t e d </a> </li> </ul>

(31)

Referenties

GERELATEERDE DOCUMENTEN

One can conclude that rumors before officially announcing an international acquisition could influence the abnormal returns after the announcement date for a target and or acquiring

Using the established success factors, it is possible to create a systematic approach designing a successful utilization of a telecare system by examining key factors in the

The compilation of paired events shows that in all cases, reductions in flood damage between the first and second flood occurred mainly along with large reductions of the three

Besides the difference in absolute values reached in the funnel (which are merely related to the floor level), there are also qualitative differences concerning the cells near the

Binnen het andere nieuwe wegtracé, werkput 2, kwamen wel enige interessante structuren aan het licht, met name muurresten die mogelijk aan de 15 e eeuwse kapel zijn toe

Results show that relevance feedback on both concept and video level improves performance compared to using no relevance feedback; relevance feedback on video level obtains

Other than for strictly personal use, it is not permitted to download or to forward/distribute the text or part of it without the consent of the author(s) and/or copyright

Furthermore, the design can be used to extend existing integration (management) platforms with event stream processing support to allow for centralised management across