Taller 1
Vamos a aclarar algunos conceptos .
Tecnología
Es una forma de hacer las cosas.
La tecnología tiene el objetivo de eliminar las tareas repetitivas, facilitando el trabajo y haciéndolo más eficiente así como aumentando la productividad y los beneficios de la empresa.
Programación
La programación es el instrumento que permite la ejecución de las tareas automatizadas de un sistema informático.
Metodología de programación
Conjunto de normas, métodos y anotaciones que nos indican la forma de programar.
Cada lenguaje de programación sigue una metodología distinta.
Paradigmas de programación
Imperativo
- Conjunto de sentencias que cambian su ESTADO
- Secuencias de comandos que ordenan acciones específicas.
- ¿Cómo hacer esto?
Declarativo
- Describen los resultados esperados sin decir explicitamente los pasos
- ¿Que hay
que hacer ?
Tipos de programación?
Programación estructurada
Secuencia de instrucciones que cumplen un objetivo
Diseño Top-Down -> Jerarquia
PROS | CONTRAS |
---|---|
No hay bucles | Muy extenso |
Fácil de entender | No es escalable |
Menor complejidad | No es reusable |
Programación orientada a objetos
TODO es considerado un objeto con características y habilidades.
Permite el Polimorfismo y la herencia
PROS | CONTRAS |
---|---|
Reusable | Aumenta la complejidad |
Escalable | Subjetiva |
Modularidad | Más documentación |
Programación funcional
Basado en el cálculo lambda
Transparencia referencial, funciones puras y evaluación peresoza.
PROS | CONTRAS |
---|---|
Alto nivel de abstracción | Curva de aprendizaje |
Inmutabilidad | Se produce mucha basura |
Bajo indice de errores | No sirve para todo |
Es un sistema formal diseñado para investigar la definición de función, la noción de aplicación de funciones y la recursión.
Considere las siguientes funciones:
Las funciones no necesitan ser explícitamente nombradas
El argumento de x se mapea a si mismo
El par de x e y se mapea a x + y
El nombre de una función es irrelevante
Función identidad
Función suma
Toda función que requiere dos arg. puede ser reescrita como una función que acepta un único argumento
Currificación
Un argumento puede aceptar como argumento otra función siempre y cuando tenga ella misma un sólo argumento
equivale a
equivale a
Cálculo lambda
¡Ahora si, vamos a empezar!
Problema
- Sistema de usuarios
- Manejo de roles
- Suscripción de clientes
- Manejo de pedidos
- Cierre de caja
- Manejo de inventario
¿Qué es lo primero que debemos hacer?
Algo que se encargue de usuarios
Algo que se encargue de las cuentas
Algo que se encargue de los pedidos
Algo que se encargue de suscripciones
Algo que se encargue de los roles
Algo que se encargue de los inventarios
Priorizar
Usuarios
1
Cuentas
5
Pedidos
2
Suscripciones
6
Roles
4
Inventarios
3
Definir una arquitecura inicial
APP
DB
Mailer
Definir lenguajes
Definir tecnologías
Definir la arquitectura del código <3
Depende del paradigma
Disfruta lo que viene
Taller 2
Cómo capturar requerimientos?
Tener en cuenta:
- No es un proceso fácil
- No es exacto
- Se trata de lo que el cliente quiere, pero podemos dar consejos
Una persona del equipo va a pensar en la casa de sus sueños.
El resto debemos hacer 3 preguntas por persona en pro de poder dibujar un bosquejo de la casa que quiere esa persona.
Hagamos el siguiente ejercicio .
Análisis de requerimientos
Enfoquémonos en POO
Tipos de lenguajes
Fuertemente tipados
Debilmente tipados
var a = "holi"
var b = 2345
var c = null
var d = Perro.new()
var e = true
a = "holi"
b = 12345
c = nil
d = Perro.new
e = true
string a = "holi"
int b = 2345
Perro d = Perro.new()
bool e = true
Herencia
Polimorfismo
Definición: El polimorfismo es una relajación del sistema de tipos, de tal manera que una referencia a una clase (atributo, parámetro o declaración local o elemento de un vector) acepta direcciones de objetos de dicha clase y de sus clases derivadas (hijas, nietas, …).
Polimorfismo se refiere a la posibilidad de definir clases diferentes que tienen métodos o atributos denominados de forma idéntica, pero que se comportan de manera distinta.
class A
def my_method
print "A"
end
end
class B < A
def my_method
print "B"
end
end
class C < B
def my_method
print "C"
end
end
class D
include C
def my_method
print "D"
end
end
Principios de la programación
- Single responsibility
- Open / closed
- Liskov substitution
- Interface segregation
- Dependency inversion
Single Responsability
El Principio de Responsabilidad Única es una herramienta indispensable para proteger nuestro código frente a cambios, ya que implica que sólo debería haber un motivo por el que modificar una clase.
¿Cómo sabemos si estamos violando este principio?
- Si estámos mezclando dos capas de la misma arquitectura.
2. Tenemos muchos metodos públicos en una clase
3. Dificultad a la hora de testear la clase.
4. Cada vez que escribes una nueva funcionalidad, esa clase se ve afectada: si una clase se modifica a menudo, es porque está involucrada en demasiadas cosas.
class ServeCoffee
def serve(coffee_variety, specialty, machine_type)
result = grind_coffee(coffee_variety)
if result.eql?(true)
coffee = make_coffee_with(machine_type, coffee_variety, specialty)
if coffee.present?
served = serve_coffee(coffee)
if served
"Coffee Served"
else
raise "We haven't any cup, sorry bro"
end
else
raise "Our barista is new, he doesn't know how to make that shit."
end
else
raise "That coffee is to strong, we couldn't grind it"
end
end
end
class ServeCoffee
def call(machine_type, coffee_seeds, specialty)
made = MakeCoffee.(machine_type, coffee_seeds, specialty)
served = serve_coffee(coffee)
if served
"Coffee Served"
else
"We haven't any cup, sorry bro"
end
end
end
class MakeCoffee
def call(machine_type, coffee_seeds, specialty)
ground_coffee = GrindCoffee.(coffee_seeds)
made = make_coffee(machine_type, ground_coffee, specialty)
if served
"Coffee made"
else
"We haven't any cup, sorry bro"
end
end
end
class GrindCoffee
def call(coffee_seeds)
ground = grind(coffee_seeds)
if ground
"Coffee Ground"
else
"That coffee is to strong, we couldn't grind it"
end
end
end
Open/Closed
Una clase debe estar abierta a extensiones, pero cerrada a las modificaciones.
D diseñar clases que nunca cambien, y cuando un requisito cambie, lo que debemos hacer es extender el comportamiento de dichas clases añadiendo código, no modificando el existente.
- Son abiertas para la extensión; es decir, que la lógica o el comportamiento de esas clases puede ser extendida en nuevas clases.
- Son cerradas para la modificación, y por tanto el código fuente de dichas clases debería permanecer inalterado.
Liskov Substitution
El principio de sustitución de Liskov nos dice que si en alguna parte de nuestro código estamos usando una clase, y esta clase es extendida, tenemos que poder utilizar cualquiera de las clases hijas y que el programa siga siendo válido. Esto nos obliga a asegurarnos de que cuando extendemos una clase no estamos alterando el comportamiento de la padre.
Si un método sobrescrito no hace nada o lanza una excepción, es muy probable que estés violando el principio de sustitución de Liskov.
Si los tests de la clase padre no funcionan para la hija, también estarás violando este principio.
http://blog.logicalbricks.com/node/223
Interfaces segregation
“Muchas interfaces específicas son mejores que una única más general”
“Los clientes no deberían verse forzados a depender de interfaces que no usan”
Cuando los clientes son forzados a utilizar interfaces que no usan por completo, están sujetos a cambios de esa interfaz. Esto al final resulta en un acoplamiento innecesario entre los clientes.
https://youtu.be/rMlPvEhrHDs?t=298
Estamos implementando un zoo, y queremos crear una interfaz que sirva para todas las aves.
Pensamos en loros, flamencos, gaviotas, aves rapaces y gorriones, por lo que implementamos los métodos de comer y volar.
Posteriormente el zoo consigue presupuesto extra y compra una pareja de avestruces, por lo que definimos también el método correr.
No nos podemos olvidar tampoco de los pingüinos, necesitamos un método para nadar.
El problema viene con que, por ejemplo, el avestruz tiene que implementar métodos que no usa, y con la llegada del pingüino tuvo que cambiar innecesariamente para implementar el método de nadar.
https://www.adictosaltrabajo.com/2014/10/27/solid-4/
Principio de inversión de dependencias
A: Los módulos de alto nivel no deberían depender de los de bajo nivel. Ambos deberían depender de abstracciones.
B: Las abstracciones no deberían depender de los detalles. Son los detalles los que deberían depender de abstracciones.
Un bosque contiene árboles, que a su vez contienen hojas, que contienen células…
Por eso se eligió la palabra “inversión”, porque rompe con esta dinámica.
Lo que se pretende es que no exista la necesidad de que los módulos dependan unos de otros, sino que dependan de abstracciones. De esta forma, nuestros módulos pueden ser más fácilmente reutilizables.
¿Soldamos directamente una lámpara al cableado eléctrico de un pared?
No, creamos abstracción enchufe y así podemos enchufar cualquier aparato electrónico.
http://xurxodev.com/solid-inversion-de-dependencia/
Y si ya no
https://medium.com/eduesqui/principio-de-inversi%C3%B3n-de-dependencias-solid-d2ad865ac0c3
Resumiendo:
S.O.L.I.D
Ejercicio:
class Bar
TamanoVasos = { grande: "Vaso grande", mediano: "Vaso mediano", pequeno: "Vaso pequeño" }
TipoPola = { roja: "Pola roja", rubia: "Pola Rubia", negra: "La mas deli: negrita" }
def inicializar_bar(barista)
@barista = barista
end
def pedir_cerveza(tipo, tamano)
saludar_al_cliente
escoger_vaso(tamano)
abrir_llave_de_cerveza_tipo(tipo)
cobrar_por_la_pola(tipo, tamano)
puts "Disfrute su cerveza, buen día"
end
def saludar_al_cliente
BuenosDias.new.saludar(nombre_barista)
end
def escoger_vaso(tamano)
puts "escogiendo un vaso para tu cerveza tamaño #{tamaño}"
puts TamanoVasos.has_key?(tamano) ? TamanoVasos[tamano] : "No tenemos esos tamaños de vaso, te daré uno grande"
end
def abrir_llave_de_cerveza_tipo(tipo)
puts "abriendo llave de #{TipoPola[tipo]}"
puts "sirviendo cerveza, se ve deli"
puts "te estoy entregando tu cerveza"
end
def cobrar_por_la_pola(tipo, tamano)
costo = 0
if tamano.eql?(:mediano)
costo = costo + 3000
end
if tamano.eql?(:grande)
costo = costo + 5000
end
if tamano.eql?(:pequeno)
costo = costo + 1000
end
if tipo.eql?(:rubia)
costo = costo + 1000
end
if tipo.eql?(:roja)
costo = costo + 2000
end
if tipo.eql?(:negra)
costo = costo + 5000
end
puts "Serían #{costo} pesos por favor"
end
end
class BuenosDias
def saludar(nombre)
puts "Buenos días, mi nombre es #{nombre}"
end
end
Taller 4
Patrones de Programación
1. Te ahorran tiempo
2. Te ayudan a estar seguro de la validez de tu código
3. Establecen un lenguaje común
https://www.amazon.es/Head-First-Design-Patterns-Freeman/dp/0596007124/tag=licrla-21
Patrones creacionales
Son los que facilitan la tarea de creación de nuevos objetos, de tal forma que el proceso de creación pueda ser desacoplado de la implementación del resto del sistema.
https://devexperto.com/patrones-de-diseno-software/
Los patrones creacionales están basados en dos conceptos:
- Encapsular el conocimiento acerca de los tipos concretos que nuestro sistema utiliza. Estos patrones normalmente trabajarán con interfaces, por lo que la implementación concreta que utilicemos queda aislada.
- Ocultar cómo estas implementaciones concretas necesitan ser creadas y cómo se combinan entre sí.
- Abstract Factory
- Factory Method
- Builder
- Singleton
- Prototype
Patrones estructurales
Text
Son patrones que nos facilitan la modelización de nuestro software especificando la forma en la que unas clases se relacionan con otras.
Estos son los patrones estructurales que definió la Gang of Four:
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides
Design Patterns
En este último grupo se encuentran la mayoría de los patrones, y se usan para gestionar algoritmos, relaciones y responsabilidades entre objetos.
Patrones de comportamiento
- Command
- Chain of responsibility
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Abstract Factory
- Define una interfaz para crear familias de objetos relacionados o dependientes, sin especificar sus clases concretas
- También conocido como kit
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
Usa el patrón Abstract factory cuando:
- Un sistema debe ser independiente de cómo se crean, componen y representan sus productos
- Un sistema debe configurarse con una de entre varias familias de productos
- Una familia de productos relacionados están hechos para usarse juntos, y se necesita cumplir esa restricción
- Se desea ofrecer una biblioteca de clases-producto, revelando sus interfaces pero no sus implementaciones
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
Factory Method
- Define una interfaz para crear un objeto, pero dejando en manos de las subclases la decisión de qué clase concreta instanciar
- Permite que una clase delegue en sus subclases la creación de objetos
- También conocido como virtual constructor
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
Usa el patrón factory method cuando:
- Una clase no puede prever la clase de objetos que tiene que crear
- Una clase quiere que sus subclases decidan qué objetos crean
- Las clases delegan responsabilidades a una de entre varias subclases auxiliares, y queremos localizar en qué subclase concreta se ha delegado
http://arantxa.ii.uam.es/~eguerra/docencia/0708/04%20Creacion.pdf
https://reactiveprogramming.io/books/design-atterns/es/catalog/factory-method
https://reactiveprogramming.io/books/design-atterns/es/catalog/factory-method
https://reactiveprogramming.io/books/design-atterns/es/catalog/factory-method
https://www.arquitecturajava.com/usando-el-patron-factory/
Singleton
El patrón de diseño Singleton (soltero) recibe su nombre debido a que sólo se puede tener una única instancia para toda la aplicación de una determinada clase, esto se logra restringiendo la libre creación de instancias de esta clase mediante el operador new e imponiendo un constructor privado y un método estático para poder obtener la instancia.
TDD
Piramide de pruebas
QA
Basics
By Nathaly Villamor
Basics
- 293