Lecciones aprendidas creando una red social
-
Upload
roberto-luis-bisbe -
Category
Software
-
view
4.064 -
download
0
Transcript of Lecciones aprendidas creando una red social
¿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?
@rlbisbe