Web/Mobile Applications Principles Pedro Alves Pedro Alves FCT / UNL Projecto Integrador 2015
Coupling
Coupling If changing one module in a program requires changing another module, then coupling exists Martin Fowler 2001
Coupling - Duplication <?php login_cookie_check()?> <?php db_connect( $g_hostname, $g_db_username, $g_db_password, $g_database_ name ); $query = "SELECT * FROM $g_mantis_user_table WHERE cookie_string='$g_string_cookie_val'";?> <p> <div align="center"> <table class="width75" cellspacing="1"> <form method="post" action="<?php echo $g_account_update?>"> <tr> <td class="form-title"> <?php echo $s_edit_account_title?> </td>
Coupling Too much intimacy
Coupling Dependency What if I want an alternative Renderer (e.g., HTML5ListRenderer)?
MVC Model Controller View Model Application state (data) and business logic View Presentation Controller Action handling (examples: press a button, submit a form, download a report)
MVC versão web
app/models/user.rb app/views/users/index.html app/controllers/users_controller.rb
MVC versão mobile Model Stores the value 3.14159 and the calculator operations such as add, subtract and multiply View Cotains 15 buttons and an input field Controller Catches the events triggered by pressing buttons, comunicates with the Model and updates the View with the new value from the Model
They don t talk to each other!! Model View
Vantagens da separação entre Model e View É possível ter o mesmo Model para várias Views (exemplos: HTML5/HTML4 ou Portrait/Landscape) É fácil testar o Model programaticamente A lógica de negócio está concentrada num componente, em vez de estar espalhada pela aplicação Mais fácil manutenção
Rule of thumb If it s hard to test, you have excessive coupling
What s wrong with this test??
Reduced coupling with DBManager: Testing is much easier!!
Taking decoupling to the next level
Model Controller View
Model Controller View
REST Webservices View Controller Model View View
Native Apps vs twitter.com
Single Page Applications Server responsibilities User authentication Secure and authorized access to resources Serve static content (images, etc.) Receive form submission Produce dynamic HTML pages Provide webservices to receive AJAX (JSON) requests
Single Page Applications <html ng-app="theaterapp"> <head> <title>theater</title> </head> <body> <div ng-view=""></div> <script src= js/angular.js"></script> <script src="js/theaterapp.js"></script> </body> </html>
What about mobile? Computing Devices Sales in Portugal - source: IDC
What about mobile? Mobile applications can be: Native An application that is downloaded to the device, runs directly over the operating system and has full access to the device Web An application that runs within the device browser and has limited access to the device
What about mobile? Developing for mobile Native ios Android Multi-platform (xamarin, titanium, ) Web Responsive web design Dynamic serving
Responsive Web Design
Responsive Web Design CSS3 Media Queries
Responsive Web Design <section id="recent" class="blog"> <article> <h1>best Summer Cookbooks</h1> <p>with the best of the season coming from...</p> <p class="meta"> <time datetime="2012-05-23t02:41-05:00" pubdate>may 23, 2012</time> </p> </article> </section> HTML5 Controller Model CSS3 View
Dynamic serving Themes are chosen based on device rules Problem: We have to develop (and maintain!!) a theme for each set of devices
Guidelines for Web Applications Expose everything as a (REST) service or HTML5 (without CSS!) don t bother with the UI, provide a minimal basic HTML client Everything must be testable without UI it s too slow to test through the UI Develop the UI (native app, single page application, etc.) as a third-party you (UI) don t know the core team, they don t know about you The service API is king stabilize it before anything else; core team is allowed to change anything as long as it keeps the API intact
Tests UI tests are very difficult to automate Good News: Glad we have a Service API!
Tests Use Unit Tests to test the Models class TestAccount < Test::Unit::TestCase def setup @account = Account.new() end def teardown ## Nothing really end def test_withdraw @account.deposit(300) assert_equal( 300, @account.balance ) @account.withdraw(100) assert_equal( 200, @account.balance ) end
Tests Use Functional Tests to test the Controllers def test_login(self): c = Client() response = c.post( login', { user': pedro, password : qwerty }) self.assertequals(unauthorized, response.status_code) response = c.post( login', { user': pedro, password : l45f43 }) self.assertequals(ok, response.status_code)
Tests Functional tests workflow 1. Create test DB 2. Create tables 3. Populate with general information (tests/fixtures) 4. Populate with specific information 5. Run test 6. Clear test DB (savepoint, drop,...)
Tests Run all the tests often 1. After making changes to the code 2. Before commiting to the repository 3. Before deploying a new version 4. Every night 5....
Tests Fixtures an environment for running tests which is in a fixed state (i.e. it is fixed ) Example: Initial data in the database Alert: Fixtures can become a maintenance nightmare!
Tests Mock objects Mock objects are simulated objects that mimic the behavior of real objects in controlled ways. public class DummyLogin extends Login { } public boolean ispasswordvalid(string password) { return true; // always returns true }
Tests Mock objects 1. Reduce dependency from resources outside our control e.g., third-party webservices 2. Allow faster development cycles start with mock, connect to real thing later on
Agile Development Test Dev 1 Version Control System Continuous Integration Dev 2 Production
Version Control Systems (centralized)
Version Control Systems ( half - distributed)
Version Control Systems (fully distributed)
Continuous Integration
Continuous Integration Maintain a code repository Automate the build Make the build self-testing Commit often Make it easy to get deliverables Everyone can see build results Gather metrics over time (e.g., code coverage) Automate deployment
Deployment
Deployment Cloud Application Platforms Virtual Private Server In-house Server
Deployment Automate deployment from scratch (assume only bare-bones OS) apt_get_install_ifnot_installed('apache2') apt_get_install_ifnot_installed('libapache2-mod-wsgi') sudo("sudo a2enmod rewrite") apt_get_install_ifnot_installed('debconf-utils') apt_get_install_ifnot_installed('htop') apt_get_install_ifnot_installed('gcc') # see http://jj.isgeek.net/2011/09/install-pil-with-jpeg-support-on-ubuntu-oneiric-64bits/ sudo('ln -sf /usr/lib/`uname -i`-linux-gnu/libfreetype.so /usr/lib/') sudo('ln -sf /usr/lib/`uname -i`-linux-gnu/libjpeg.so /usr/lib/') sudo('ln -sf /usr/lib/`uname -i`-linux-gnu/libz.so /usr/lib/') Tools: fabric (python), chef (ruby)
Deployment Tests/Quality/Production Environment No IDE No debug Concurrent access Can t see what the user sees Performance Recover from failures (reboot is not an option) Can t control dependencies (twitter is down??) People using the system at 3am Multiple browser, multiple OSs Multitple languages, multiple timezones...
Deployment Logs are your best friend At least one line for each user request INFO 2011-04-01 12:45:33 palves GetUsersList - OK At least two lines for each external call INFO 2011-04-01 12:45:33 Twitter sent request INFO 2011-04-01 12:45:53 Twitter received response
Deployment Logs are your best friend On exceptions, show everything you have User Request Context Stacktrace...
Deployment Logs are your best friend Find out how to turn on SQL logging Users reporting strange results Application is slow
Deployment Prevent surprises Automate the build process You should be able to deploy a version in one step Lots of build tools available use them Ant, Make, Rake,... The build process includes: Getting the code, compile, run tests, package, send to test server (ssh/scp), install, restart server,...
Deployment Prevent surprises Use a Version Control System (CVS, SVN, Git) Always build from the VCS, never from your computer Be prepared to rollback
Deployment - Performance Use a Web Server (Apache, lighttpd,...) for static content Protect your resources (DB, webservices) from high load conditions Use Pools Cache frequently accessed data that rarely changes e.g., User data
Pedro Alves palves@opensoft.pt