Lecciones aprendidas creando una red social

Post on 18-Jul-2015

4.064 views 0 download

Transcript of Lecciones aprendidas creando una red social

Lecciones aprendidas creando una red social

Roberto Luis Bisbé

roberto.luis@frontiersin.org

@rlbisbe

¿Qué es esta charla?

Lo que queremos

hacer

Lo que hacemos

ahora

¿Por qué una red social para científicos?

Presencia

ConocimientoColaboración

Divulgación

¿Cómo?

Usuarios Pruebas Entornos Código Herramientas Docs

¿Bonito o accesible?

Fuente: http://thenextweb.com/insider/2014/05/01/ie11-market-share-passes-ie10-ie9-combined-chrome-cements-lead-firefox/

¿Bonito o accesible?

Chrome41%

Firefox24%

Safari17%

IE 9+12%

< IE 82%

Otros4%

¿Bonito o accesible?

HTML5

CSS3Javascript

El uso que le dan los usuarios

Métricas

TestingOptimización

Métricas

• Google analytics

• Uso de la página

• Llamadas a APIs

• Profiling de consultas

• New Relic

• Redis

• Nagios

Optimización

• Minificación de CSS y Javascript

• Minificación de HTML

• Imágenes en Base64 en Javascript

• Sprites

• CDN

• Local storage

A/B Testing

Fuente: http://www.astekweb.com/the-web/what-is-ab-testing/

Tests

Unitarios

JS: Componentes + Viewmodels Backend

Integración

JS + Vistas API Tests

Aceptación

Selenium Pruebas manuales

Selenium es lento

Imagen: http://content.time.com/time/specials/packages/article/0,28804,1991915_1991909_1991755,00.html

Selenium es LENTO

Imagen: http://content.time.com/time/specials/packages/article/0,28804,1991915_1991909_1991755,00.html

Selenium es LENTO

Imagen: http://content.time.com/time/specials/packages/article/0,28804,1991915_1991909_1991755,00.html

Selenium es LENTO… y caro

Imagen: http://content.time.com/time/specials/packages/article/0,28804,1991915_1991909_1991755,00.html

Selenium es LENTO… y caro

Imagen: http://content.time.com/time/specials/packages/article/0,28804,1991915_1991909_1991755,00.html

• Basado en navegador

• Mal necesario

• Solamente casos completos

Integración y unitarios

Imagen: http://www.ceviu.com.br/blog/info/artigos/teste-de-sistema-system-integration-test/

QUnit

QUnit.test( "hello test", function( assert ) {

assert.ok( 1 == "1", "Passed!" );

});

Sinon

FakeServer

SpiesStubs

Mocks

Sinon - fakeserver

function getFollowers(listId, callback) {jQuery.ajax({

url: "/user/" + userId + "/followers",success: function (data) {

callback(null, data);}

});}

it("passes", function () {var server = sinon.fakeServer.create();server.respondWith(200, { "Content-Type": "application/json" },

JSON.stringify([{ id: 23, name: "foo"}]));

getTodos(42);server.respond();server.restore();

});

Sinon - fakeserver

function getFollowers(listId, callback) {jQuery.ajax({

url: "/user/" + userId + "/followers",success: function (data) {

callback(null, data);}

});}

it("passes", function () {var server = sinon.fakeServer.create();server.respondWith(200, { "Content-Type": "application/json" },

JSON.stringify([{ id: 23, name: "foo"}]));

getTodos(42);server.respond();server.restore();

});

Chutzpah

• Test Runner Javascript para Visual Studio

• Compatible con TFS

• Open Source

Carga - JMeter

• Escenarios específicos

• Múltiples usuarios concurrentes

• Detectar picos

¿Dónde hacemos los test?

Entornos

Live

Test

QA

Integración

Dev

Casos de prueba

• No buscar perfección

• Significativos

• Extremos

• De datos reales, mucho mejor

El código

MVVM

Model

ViewmodelView

Arquitectura

Page

ModalDialog

ModalDialog

Brick

ViewModel

CommunicationServices

ModalDialog

KnockoutTemplate

Navigation

Knockout.js

• Ligero

• Fácil de aprender

• Usa jQuery

Knockout.js

var myViewModel = {personName: ko.observable('Bob'),personAge: ko.observable(123)

};

The name is <span data-bind="text: personName"></span>

ko.applyBindings(myViewModel);

Knockout.js

var myViewModel = {personName: ko.observable('Bob'),personAge: ko.observable(123)

};

The name is <span data-bind="text: personName"></span>

ko.applyBindings(myViewModel);

Knockout.js

var myViewModel = {personName: ko.observable('Bob'),personAge: ko.observable(123)

};

The name is <span data-bind="text: personName"></span>

ko.applyBindings(myViewModel);

Knockout.js

var myViewModel = {personName: ko.observable('Bob'),personAge: ko.observable(123)

};

The name is <span data-bind="text: personName"></span>

ko.applyBindings(myViewModel);

Knockout.js - Observable Arrays

<ul data-bind="foreach: users"><li data-bind="text: name"></li>

</ul>

self.users = ko.observableArray([{name: "Carlos"},{name: "Ivan"},{name: "Maria"}, {name: "Quique"},

]);

Knockout.js - Observable Arrays

<ul data-bind="foreach: users"><li data-bind="text: name"></li>

</ul>

self.users = ko.observableArray([{name: "Carlos"},{name: "Ivan"},{name: "Maria"}, {name: "Quique"},

]);

Knockout.js - Observable Arrays

<ul data-bind="foreach: users"><li data-bind="text: name"></li>

</ul>

self.users = ko.observableArray([{name: "Carlos"},{name: "Ivan"},{name: "Maria"}, {name: "Quique"},

]);

Knockout.js - Templates

<div data-bind="template: { name: 'person-template', data: seller }"></div>

<script type="text/html" id="person-template"><h3 data-bind="text: name"></h3><p>Credits: <span data-bind="text: credits"></span></p>

</script>

Knockout.js - Templates

<div data-bind="template: { name: 'person-template', data: seller }"></div>

<script type="text/html" id="person-template"><h3 data-bind="text: name"></h3><p>Credits: <span data-bind="text: credits"></span></p>

</script>

Knockout.js - Templates

<div data-bind="template: { name: 'person-template', data: seller }"></div>

<script type="text/html" id="person-template"><h3 data-bind="text: name"></h3><p>Credits: <span data-bind="text: credits"></span></p>

</script>

Knockout.js –Animaciones

<ul data-bind="foreach: {data: users, afterAdd: fadeIn}"><li data-bind="text: name"></li>

</ul>

self.fadeIn: function(element, index, data) {$(element).filter("li")

.animate({ backgroundColor: 'yellow' }, 200)

.animate({ backgroundColor: 'white' }, 800);};

Knockout.js –Animaciones

<ul data-bind="foreach: {data: users, afterAdd: fadeIn}"><li data-bind="text: name"></li>

</ul>

self.fadeIn: function(element, index, data) {$(element).filter("li")

.animate({ backgroundColor: 'yellow' }, 200)

.animate({ backgroundColor: 'white' }, 800);};

Knockout.js –Animaciones

<ul data-bind="foreach: {data: users, afterAdd: fadeIn}"><li data-bind="text: name"></li>

</ul>

self.fadeIn: function(element, index, data) {$(element).filter("li")

.animate({ backgroundColor: 'yellow' }, 200)

.animate({ backgroundColor: 'white' }, 800);};

Knockout.js –Animaciones

<ul data-bind="foreach: {data: users, afterAdd: fadeIn}"><li data-bind="text: name"></li>

</ul>

self.fadeIn: function(element, index, data) {$(element).filter("li")

.animate({ backgroundColor: 'yellow' }, 200)

.animate({ backgroundColor: 'white' }, 800);};

Un apunte sobre las animaciones

Un apunte sobre las animaciones

• Cuestan tiempo

• Penalizan el rendimiento

• Para tests: jQuery.fx.off

Sammy

Sammy('#main', function() {

this.get('#/path', function() {

this.$element().html('A new route!');

});

}).run();

Sammy

Sammy('#main', function() {

this.get('#/path', function() {

this.$element().html('A new route!');

});

}).run();

¿Y si Javascript está deshabilitado?

¿Y si Javascript está deshabilitado?

• Header estático con información principal

• Advertencia de uso de Javascript

Herramientas

Herramientas

JIRA

Panel Kanban

Visual Studio

Chrome tools

TFS + Chutzpah

Documentación

Imagen: http://sharpen.engr.colostate.edu/mediawiki/index.php/CHOMP:_Documentation

Swagger

• Documentación a partir de comentarios

• Especificación basada en JSON

• Multilenguaje y multiplataforma

• Extensible y personalizable

Swagger

{

"apiVersion": "1.0.0",

"swaggerVersion": "1.2",

"basePath": "http://petstore.swagger.wordnik.com/api",

"resourcePath": "/store",

"produces": [

"application/json"

],

"apis": [

],

"models": {

}

}

Swagger - APIs

"method": "GET",

"summary": "Get by user name",

"type": "User",

"parameters": [

{

"name": "username",

"description": "The name.",

"required": true,

"type": "string",

"paramType": "path",

"allowMultiple": false

}

]

"responseMessages": [

{

"code": 400,

"message": "Invalid username supplied"

},

{

"code": 404,

"message": "User not found"

}

]

Swagger - Modelos

"User": {

"id": "User",

"properties": {

"id": {

"type": "integer",

"format": "int64"

},

"username": {

"type": "string"

}

"userStatus": {

"type": "integer",

"format": "int32",

"description": "User Status",

"enum": [

"1-registered",

"2-active",

"3-closed"

]

}

Conclusiones

• Toda una experiencia

• Muchas tecnologías y frameworks

• Pruebas, pruebas, pruebas

• Algo se te va a colar

• Rendimiento

frontiers is hiring

• Buscamos desarrolladores full-stack

• Retos interesantes

• .NET y Javascript

• Bolis de colores

• Gente maja

• Café gratis

¿Preguntas?

Gracias!roberto.luis@frontiersin.org

@rlbisbe