¿Crear y almacenar clases?

Laravel trabaja con clases que generalmente se guardan en repositorios desde el cual son llamadas. Esta estructura requiere que ademas de conocer la organizacion del framework, comprendamos su enfoque para crear, almacenar y gestionar las claves.

Puede parecer para muchos complicado, pero es una estructura que desde mi punto de vista esta enfocada a componentes como parte de un todo, de ahi la necesidad de entenderla adecuadamente

Crear una clase

Las clases en Laravel se crean dentro de la carpeta App, usando psr-4. Basta con crear un archivo en una dirección dentro de App y comenzaremos a tener una clase reconocida, por la aplicación:

Creamos el archivo Conexión dentro de una carpeta nueva llamada Personalizado

  App/Personalizado/Conexión.php 

Y luego colocamos la clase con sus métodos y/o atributos. En nuestro caso estamos creando una clase que sustituirá los valores de conexión a la bd en el archivo env.

 class Conexion
 {
    public function conectar()
    {
         return 'conecto';
 }
 } 

Una vez creado, la clase principal que se encuentra ubicada en “App\Personalizado\Conexion\conexion.php”, tendrá como namespace y que es el que podrá ser usado desde cualquier lugar de la aplicación, o sea hacer bind, este:

 App\Personalizado\conexion 

Para que el bind funcione, son necesarios unos pasos más. Lo siguiente que haremos será crear el Service Provider de la clase.

Lo haremos con Artisan desde la consola:

 php artisan make:provider ConexionServiceProvider 

Lo que sigue es registrar la clase en el método register() del  ConexionServiceProvider, haciendo el adecuado bind.

  public function register()
     {
         //registramos la clase
         \App::bind('Conexion');
     }  

Y finalmente registramos ConexionServiceProvider en el fichero de configuración, que  se encuentra en la ruta config/app.php, agregando la clase, dentro del array de providers:

  /*
          * Application Service Providers...
          */
         App\Providers\AppServiceProvider::class,
         App\Providers\AuthServiceProvider::class,
         …………
          /*
          * Clases Propias añadidas...
          */
         App\Providers\ConexionServiceProvider::class,
   

Nos faltaría comprobar que nuestra clase es accesible, podemos hacer diferentes pruebas, como llamar la clase desde una ruta o correr una prueba con Tinker.

Comencemos con Tinker, llamándolo desde la consola:

  >>>php artisan tinker 

Una vez abierto, llamamos la clase, y la corremos :

  Psy Shell v0.9.12 (PHP 7.2.3 — cli) by Justin Hileman
 >>> use App\Personalizado\Conexion; 

La instanciamos :

 >>> $h =new Conexion();
 => App\Personalizado\Conexion {#3106} 

Y llamamos la funcion:

 >>> $h->conectar();
 => "conecto"
 >>>                         

Salimos de Tinker, con control +C.

Tambien podemos probarlo en el sistema de rutas de Laravel.

 Route::get('conectando', function(){
     if(class_exists('App\Personalizado\Conexion'))
     dd('hallada');
     else dd(' no hallada');
 }
 ); 

Si accedemos ahora a la ruta conectando deberíamos ver escrita la palabra hallada.

Ahora, nuestra clase esta lista y disponible para ser usada.

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

…., si avanzo sígueme, si me detengo empújame, si retrocedo mátame…….

Entendiendo el concepto de clases

Entender el concepto de clases es un elemento basico cuando programamos,  ya que en si, las clases constituyen la base de la organización estructural del codigo de programacion moderno.
Las clases nos permiten crear objetos que podremos reusar o no, pero que facilitaran la escalabilidad y eficiencia del codigo.

¿Por que?

Porque la clase es como el molde de un zapatero.

Es la base para crear un objeto, lo cual permitira organizar el codigo de una manera muy como en el mundo que nos rodea.

Digamos sin ser muy profundos que un zapato  de caballero, tiene cualquiera que sea el modelo, varias partes comunes: tacon, puntera, plantilla, etc.

Entonces el molde será la clase, cada modelo  será un objeto de esa clase y cada caracteristica un atributo.

De la clase  zapato pueden crearse diferentes objetos que seran usados de diferentes formas, venderse, exhibirse, trasladarse, y para eso necesitará relacionarse con otras clases, como tienda, caja, etc.

De estas relaciones es que hablaré, por la necesidad de su comprension para crear una mejor aplicación.

Las clases pueden relacionarse asociandose, dependiendo una de otra o mediante herencia.

Asociación

Tomemos como ejemplo una base de camiones para transporte. La relación de asociación es aquella necesaria para que la estructura funcione.

Como la que hay entre un usuario_chofer  y su camión, donde se relacionan en ambas direcciones, elusuario chofer posee un camión y ese  camion pertenece a ese chofer.

Una relación parecida  a esta pero de una sola dirección es la que se da entre  la clase combustible y camión. Digamos que hay dos acciones que el  camión realiza sobre el combustible en cada viaje: recibirlo y gastarlo por tanto es una relación unidireccional

Una expresion de esta relación seria algo asi

clase Camion {    
variable viaje;   
 función constructor() 
{        
 $viaje = new Combustible();     
}    
funcion publica recibir()      
funcion publica gastar()   

}

 clase Combustible { }

Lo anterior intenta mostrar la estructura básica de una clase, no está escrito en ningún lenguaje específico aunque inspirado en php y python

Ahí vemos dos clases camión y combustible con una variable viajes que crea un nuevo objeto de combustible sobre el cual incidirá el objeto camión del que se trate, con dos métodos recibir y gastar.

Hablemos de multiplicidad

Toda relación tiene multiplicidad doble, porque se ubica a cada lado de la relación y esta tiene un minimo y un maximo.

La mejor forma de explicarlo es entendiendo por ejemplo las relaciones entre las tablas de una base de datos del tipo relacional.

Los tipos son

1  indica que la multiplicidad a cada lado de la relación es de uno y solo uno

0..1  indica una multiplicidad de 0 o 1  y viene a ser el complemento de una relación de uno

*  indica una relación de cero o varios ( presente en el lado extremo varios del tipo de relación de unos a varios

*..0 cero o varios

1..* uno o varios

La multiplicidad, define además que cuando la  mínima es 0, la relación es opcional y si es mayor o igual que 1 se establece como una relación obligatoria.

Entonces nuestras tablas en una base de datos relacional tendrán una relación de:

 uno a uno si a ambos lados de la relación existe un uno

de uno a muchos si a un lado hay un 1 y al otro  *

de muchos a  muchos si a cada lado hay un *

Y por supuesto sus inversos.

Y para analizar la obligatoriedad por ejemplo en una bd con dos tablas: viajes y camiones, podemos decir que  un camión  podrá tener o no viajes (opcional-> 0..*), pero un viaje pertenecerá si o si un camión (obligatoria->1..*)

Dependencia

Es el tipo de relación, que existe entre dos clases que se necesitan para que la estructura funcione, por ejemplo siguiendo en el área transporte:

no puede hacerse un viaje si no están al clases orden de viaje y camión.

Un modo de verlo es pensar en un objeto que solicita un recurso o un servicio  y otro que lo brinda.

 Herencia

Son relaciones que surge cuando una subclase hereda los atributos de una superclase.  Un ejemplo práctico es pensar en familias de animales, digamos que tenemos una clase llamada Paquidermos.

Esta superclase entre otros atributos tiene:

tipo, trompa(posee un método llamado añadirTrompa) y cola = corta

De  ella heredaran diferentes subfamilias,  elefantes, rinocerontes, hipopótamos, con características y comportamientos parecidos ( no sudan, piel gruesa, y grandes dimensiones). 

Sin embargo,  las subfamilias(subclases), pueden incorporar características nuevas comunes a solo algunas, ejemplo hipopótamos y rinocerontes necesitan refrescarse constantemente.

Podemos seguir creando subclases y derivando. Por ejemplo de la clase elefante,  pueden heredar las subclases elefante africano y elefante asiático.

Mientras que del rinoceronte heredaran  5 subclases: el de java, el indio, el negro, el blanco y el de Sumatra

Y del hipopotamo   heredaran: el hipopotamo común y el hipopotamo pigmeo.

Para estas subclases existirán atributos de con acceso de carácter privado, de carácter protegido y de carácter público.

Expliquémoslo a través del la subclase elefante:

Si en la superclase  existe el atributo tipo, para  la elefante será público  ya que puede acceder a el, tanto elefante como elefante africano y elefante asiático.

El atributo cola, será privado, y no podrá acceder ninguna subclase, para todos la cola tiene un valor “corta”.

Y la variable trompa, es protegida  ya que solo podrá acceder la propia clase Paquidermo  y sus  subclases mediante el método añadirTrompa.  

Otra propiedad de trabajar con clases es el encapsulamiento

Encapsulamiento

Es justo lo que hemos visto en la relaciones , o sea es el mecanismo  que se emplea para  organizar los  datos y métodos de un objeto,  limitando el acceso a ellos solo por el modo que se determine .

Por tanto al crear la clases y respetar estas relaciones estamos encapsulandotodo cuanto necesitamos en una entidad, o estructura, o dicho de otro modo en un objeto

Al encapsular podemos abstraer, o sea podemos al tener concentrados los componentes de un objeto, crear superclases que representan de la manera más abstracta posible los objetos que irán heredando de ellas.

Ser fácil entender entonces, que  las formas de encapsular pueden ser :

  • Estándar: Forma predeterminada según nos interese
  • Abierto : Se puede acceder al atributo de la clase desde el exterior de la Clase
  • Protegido : Solo es accesible desde la superclase y las subclases que heredan  de ella,
  • Semi cerrado : Solo es accesible desde la subclase heredada, para la subclase.
  • Cerrado : Solo es accesible desde la superclase.

Relacionado con la herencia tenemos que entender el poliformismo

Poliformismo

No es más que capacidad que tienen los objetos de una clase para  responder ante un  mensaje en dependencia de los parámetros que utilicemos al invocarlos o llamarlos.

Creo que la forma más sencilla de mostrarlo es que llamemos desde cualquiera de las clases que derivan de Paquidermos al atributo trompa, podremos acceder a él mediante el mismo método añadirTrompa ().

En definitiva el uso de clases y su aprovechamiento permite controlar el comportamiento del usuario,  evitando acciones indeseadas, además de  que el medio mas efectivo para controlar y manejar la complejidad de  las Clases , obligandolas a actuar como cajas negras, que dejan ver mediante una interfaz  el comportamiento pero no los detalles internos.

Lo cual es una ventaja ya que ayuda al programador a separar la interfaz de una clase de su implementación.

De este modo es más fácil limitar el acceso a los datos y que solo se haga mediante las funciones que ponemos a su disposición, con las validaciones que consideremos necesarias.

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

….un sueño es casi todo  y más que  nada, más que todo al soñarlo, casi nada después……

Desarrollar funciones en Python

logo python

Desarrollar funciones en Python pueden ser necesario para hallar solucion a problemas que otras funciones existentes no nos resuelven.

La librería del lenguaje no deja de crecer, pero es común que si actuamos como investigadores, en mas de una ocasion, no encontremos lo que necesitamos para obtener la respuesta que buscamos.

Funciones

En Python como en muchos otros lenguajes existen funciones y métodos.

Veamos a  una función como trozo de código que controla   o ejecuta un conjunto de instrucciones, y a la que podemos necesitar utilizar varias veces, esperando siempre el mismo comportamiento.

Los tipos de funciones en Python son tres:

Las que son predefinidas como print() o help().

Las que son definidas por el usuario, ya que este las crea

Las funciones anónimas, o  funciones lambda, llamadas  asi porque no se declaran bajo el standard def, que es el que usa python en el resto de los casos.

Docstring

Antes de ir más allá, algo básico a la hora de escribir código  en Python como en todo lenguaje de programación, son los comentarios, o la documentación que explique lo que estamos creando.

Añadir docstrings a la función, permite conocer su comportamiento esperado, ya que mediante su descripción documentamos todo aquello que consideramos importante, para entender que hace.

Los docstring se colocan justo después de la primera línea de la función, y se inicializan con tres comillas dobles,  y se finaliza de igual modo.

def  nada():
"""
   esta función no hara nada
   retornara un campo de tipo none
"""
   return 

Métodos

Los métodos son pequeñas funciones, que forman parte de una clase, por tanto se accede a ellos instanciando esta o con un objeto, a diferencia de una función típica que puede ser llamada sin esa restricción.

 Puede parecer confuso, pero la mejor forma de verlo es pensando que: todos los métodos son funciones pero no todas las funciones son métodos.

Por ejemplo una función puede ser:

def función_x(a,b,c):
   return a*b+c

Habiendo definido la función y lo que esperamos de ella, para llamarla solo debemos  asignar valores a sus parámetros

función_x(2,3,5)

Comparemos como seria al crear una clase:

class Resultado(object):  
   def solucion(self, a,b,c):  
   self.contents = a*b+c 
   return self.contents

Si ahora deseamos llamar  al método solución(), al pertenecer a la clase Resultado, necesitamos primero crear un objeto o instanciar la clase.

solucionInstance = resultado() 
solucionInstance.solucion(1,2,4)

Un elemento que puede llamar a confusión cuando empiezas en Python es la diferencia entre parámetros y argumentos.

Entenderlo es más sencillo de lo que parece:

Imagina que creas una función que suma dos variables, la variable A y la B

def letras(A, B) 
   return A+B

A y B son parámetros, sin embargo cuando debes llamar la función o el  método para ejecutarlo necesitas dar valor a  los parámetros cuando los llamas

Si  A = 1, B=5

def letras(1, 5)

La  función hará lo que está establecido en su comportamiento sumar 1+5

Cuando creamos la clase Resultado al método solución se le pasaron tres parámetros, sin embargo al crear el objeto se pasaron cuatro argumentos, pues se añadió self.

self , es siempre el primer argumento de cualquier clase y hace referencia a ella misma.

Cuando una función es creada por un usuario, se declara siempre igual:

  • La palabra def y luego el nombre de la función,  después se añaden los parámetros de la función entre paréntesis y después  dos puntos,  para terminar la línea.
  • La acción que la funcion debe ejecutar..
  • Y la llamada a return para que nos devuelva algo. No colocar return provocará que la función devuelva un objeto none, el cual no admite que se ejecuten funciones sobre el.
def función(a, b): 
   c=a+b 
   return c

Existen diferentes tipos de argumentos

Los que son por defecto, los requeridos, los argumentos keyword y los  variables.

Argumentos por defecto

Son que les asigna un valor mediante el operador =

def menos(a,b,d=3): 
   return a-b-d

Esta función puede ser llamada con todos sus parámetros,  o solo con alguno de ellos.

#llamandola con 1 parametro  
menos(b=2)
#llamandola con todos los parametros 
menos( a=10,b=12,d=4)

Argumentos requeridos

Son aquellos que tiene que ser pasados a la función en el momento adecuado y en un orden dado para garantizar su ejecución

En la función menos() a, b y d son argumentos requeridos, los cuales deben pasarse en un momento dado (al inicio) y en un orden ( ya que a-b-d), cambiar ese orden alteraría el resultado.

Argumentos keyword

Este tipo de argumentos son llamados utilizando el parametro al que corresponde para identificarlo

def sol(a,b): 
   return a+b 
   
#llamando la función con el uso de keywords 
def sol(a=2, b=3)

 Cuando usamos las keywords, podemos cambiar el orden de los argumentos, sin que ello afecte el resultado

def sol(b=3,a=2)

Argumentos de número  variable

Se utiliza cuando no se sabe el numero de argumentos esperado, y para ello se utiliza la sintaxis *args

def  varios(*args):   
   return sum(args)  
   #ejecutando la función 
   varios(3,6,7)

El asterisco * , se coloca antes del nombre de la variable que soporta los argumentos multiples:

def  diferentes(*varnueva):  
   x=2  
   for i in varnueva:  
   x += i*2  
   return x

Variables

Las  variables en Python pueden ser locales o globales, las primeras son las que se definen dentro de las funciones, por tanto solo se puede acceder a ellas desde dentro de la función, mientras que las variables globales puede obtenerla cualquier función.

Return

Return es el encargado de  devolver el resultado, ya sea uno o múltiples valores, y su uso nos permite , ampliar las posibilidades  de nuestra función o método.

Cuando necesitamos que el return nos devuelva multiples valores, utilizaremos tuplas

Funciones anónimas

Son las funciones que en vez de declararse con def, son declaradas con la palabra lambda.

double = lambda x: x*3  
   double(5)

En este caso x es el argumento, y x*3 la instrucción que la función debe cumplir

Una función con dos argumentos podría ser

sum = lambda xmy:x+y  
   sum(4,2)

Las funciones anónimas pueden usarse por ejemplo, cuando se requieren funciones con un corto periodo de tiempo de vida, por ejemplo cuando se trabaja con maps(), filter() o reduce().

Main

La función main(), se usa comunenente en Python para agrupar los principales componentes de un sistema.

En un ejemplo sencillo podría ser algo asi:

def  main():  
   varios()  
   solucion() 
   main()

Existe un detalle a considerar, para llamar main() como clase, debe hacerse de esta forma:

__name__ ==’__main__’:

De lo contrario Python asumirá que estamos llamando a un modulo

main() también puede crearse utilizando __init__ para instanciar una clase o un objeto. El nuevo objeto instanciado es asignado al parámetro self

La estructura es esta:

class  nueva:  
""" Requires:  
   atrib_a 
   atrib_b 
"""
def  __init__ (self, atrib_a, atrib_b): 
   self.atrib_a =atrib_a 

 self.atrib_b = atrib_b 
 def  funcion1(self): 
 funcion1  = …acción…. 
 return funcion1 
 #llamando a main 
 if __name__ ==  ”__main__”: 
  solucion =  solucion(argumento1, argumento2) 
  funcion1  = solucion.funcion1() 
  print(funcion1) 

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

 ….un sueño es casi todo  y más que  nada, más que todo al soñarlo, casi nada después……