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.

I(x) = x

Considere las siguientes funciones:

S(x, y) = x + y

Las funciones no necesitan ser explícitamente nombradas

x \to x
x, y \to x + y

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

y \to y
u, v \to u + v

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

x, y \to x + y = x \to ( y \to x + y )

Currificación

Un argumento puede aceptar como argumento otra función siempre y cuando tenga ella misma un sólo argumento

f(x) = x + 2
\boxed { \lambda x. x + 2 }

equivale a

f(3)

equivale a

\boxed { (\lambda x. x + 2) 3 }
(\lambda f.f3)(\lambda x. x + 2) = (\lambda x. x + 2) 3 = 3 + 2

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 

Si, definir un flujo de trabajo.

Tienes un equipo y muchos requerimientos. Así que después de pasar por lo que hablamos la vez pasada definimos el flujo de trabajo

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?

  1. 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 voy a usar MySQL??

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:

  1. 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.
  2. 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