Foros del Web » Programando para Internet » PHP »

Consejo en uso de Classes, por favor.

Estas en el tema de Consejo en uso de Classes, por favor. en el foro de PHP en Foros del Web. Saludos colegas. Tengo años de programar en PHP pero no tanto de basar mi desarrollos en el uso de Objetos, se me viene encima un ...
  #1 (permalink)  
Antiguo 06/05/2017, 11:48
 
Fecha de Ingreso: noviembre-2009
Mensajes: 11
Antigüedad: 15 años, 1 mes
Puntos: 1
Consejo en uso de Classes, por favor.

Saludos colegas. Tengo años de programar en PHP pero no tanto de basar mi desarrollos en el uso de Objetos, se me viene encima un proyecto grande y quiero su consejo para ver si esta es la forma correcta de hacerlo.
Voy a simplificarlo con el siguiente ejemplo.

Código PHP:
class Auto {
  public 
$TanqueGasolina = new TanqueGasolina();
  public 
$Motor = new Motor();

  
// Funciones del Auto
}

class 
TanqueGasolina extends Auto {
  public 
$Gasolina 100;

  
// Funciones del Tanque de gas
}

class 
Motor extends Auto {
  public 
$Estado "Apagado";
  
  public function 
Encender() {
    
// AQUI EMPIEZAN MIS DUDAS
  

Supongamos que para "Encender()" el motor, necesito comprobar que el tanque tenga gasolina, puedo acceder a ese valor con algo como:
Código PHP:
 $this->TanqueGasolina->Gasolina
(Creo... la verdad es que ya ise tantas pruebas que traigo un nido de ideas en la cabeza)

¿Esta es la forma correcta de hacerlo?
Por que, si hago un print_r() de Auto, las dos sub-classes cargan de nuevo los valores del padre, y no se si eso sea bueno para el rendimiento, tampoco me queda claro que pasa si modifico un valor "padre" desde un "hijo", ¿repercute en todas las sub-classes?

La otra opción es manejar cada cosa como una Clase individual, pero si hago eso, no puedo acceder a los valores de otra si no es pasandolos en cada función. Tendria que ser algo como:
Código PHP:
$this->Motor->Enceder($this->TanqueGasolina->Gasolina); 
El problema de esto, es que cada clase tendra tantas funciones y atributos que dependen unos de otros, que esto lo veo muy complicado a la hora de mantener (o tratar de) "orden" en el código.

Les voy a agradecer infinitamente su ayuda o consejos, si saben de alguna literatura que deba de leer sobre un modelo de código, o algún consejo basado en experiencia... cualquier cosa es bienvenida. No quisiera iniciar el desarrollo y toparme en seco por estructurar mal desde un inicio.

Perdón por la biblia de explicación, pero es lo mas simple que se me ocurre. Saludos y de antemano, gracias.
  #2 (permalink)  
Antiguo 06/05/2017, 14:22
alvaro_trewhela
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Consejo en uso de Classes, por favor.

Primero, no se que tan necesario serían esos extends.
Segundo, en tu clase Auto no se puede instanciar clases de ese modo te arrojará error, la correcta forma sería:

Código PHP:
Ver original
  1. class Auto {
  2. public $tanque;
  3. public $motor;
  4.     function Auto(){
  5.     $this->tanque = new TanqueGasolina();
  6.     $this->motor = new Motor();
  7.     }
  8. }

Tercero, de la forma en que estás trabajando te encajonas tu mismo, y claro no queda otra que pasar por parámetro y ver....

Código PSEUDO:
Ver original
  1. encender(gas){
  2.     if(gas > 0){
  3.     encender
  4.     }
  5. }

Entonces:

Código PHP:
Ver original
  1. $auto = new Auto();
  2. $auto->motor->encender($auto->tanque->gasolina);

dejame darle una vuelta....

Por mientras te dejo mi código:

Código PHP:
Ver original
  1. <?php
  2.  
  3. class Auto {
  4. public $tanque;
  5. public $motor;
  6.     function Auto(){
  7.     $this->tanque = new TanqueGasolina();
  8.     $this->motor = new Motor();
  9.     }
  10. }
  11.  
  12. class TanqueGasolina{
  13. public $gasolina = 100;
  14. }
  15.  
  16. class Motor{
  17. public $encendido = "Apagado";
  18.  
  19.     public function encender($gas){
  20.         if($gas > 0){
  21.         $this->encendido = "Encendido";
  22.         return "Encendido!!";
  23.         }
  24.     }
  25. }
  26.  
  27. $auto = new Auto();
  28. echo $auto->motor->encender($auto->tanque->gasolina);
  29.  
  30.  
  31. ?>

Falta encapsulamiento de todas maneras!!! jajaja

Edito, porque lo otro sería usar la funcion encender derechamente en auto:

Código PHP:
Ver original
  1. class Auto {
  2. public $tanque;
  3. public $motor;
  4.     function Auto(){
  5.     $this->tanque = new TanqueGasolina();
  6.     $this->motor = new Motor();
  7.     }
  8.    
  9.     public function encender(){
  10.         if($this->tanque->gasolina > 0){
  11.         $this->motor->encendido = "Prendido";
  12.         }
  13.     }
  14. }

Pero no es la idea cierto?

Última edición por alvaro_trewhela; 06/05/2017 a las 15:05
  #3 (permalink)  
Antiguo 06/05/2017, 17:09
 
Fecha de Ingreso: noviembre-2009
Mensajes: 11
Antigüedad: 15 años, 1 mes
Puntos: 1
Respuesta: Consejo en uso de Classes, por favor.

Antes que nada, te agradezco el tiempo y el interes en ayudarme. Tienes razón, usando los extends me encajono solo, y no, no es que los considere necesarios, solo que estube leyendo sobre "subclases", y todo lo que encontre indicaba ese camino. Pero me da igual si son clases normales o con extends.

Realmente, creo que mis problemas se solucionarian si desde la clase "$motor" pudiera hacer algo como:
Código PHP:
$parent->tanquegasolina->gasolina 
Pero hasta donde he leido, eso no es posible, si sabes de alguna forma de hacerlo, me cambiarias la vida.

Si no, no me queda mas que, sentarme, pensar bien como va a funcionar todo el sistema y ni hablar, a pasar variables.

Tengo tiempo, voy a seguir haciendo pruebas un par de dias mas y a darle mas vueltas en la cabeza, si se te ocurre en estos dias, te voy a agradecer mucho me lo compartas.

Nuevante, muchisimas gracias, sin tu aclaracion con los extends probablemente acabaria enredandome mas y mas.
  #4 (permalink)  
Antiguo 06/05/2017, 17:17
alvaro_trewhela
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Consejo en uso de Classes, por favor.

Claro lo que sucede con extends, es que esto haces:



Con las flechitas me refiero a que le entregas a cada cual las propiedades de auto.

Edito, más aun, cuando extiendes y haces estas instancias de las clases queda asì:



No es que si haces esa mezcla entre extender y llamar haga que sea posible la conexión entre las clases

Última edición por alvaro_trewhela; 06/05/2017 a las 17:46
  #5 (permalink)  
Antiguo 06/05/2017, 17:48
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 11 años, 5 meses
Puntos: 379
Respuesta: Consejo en uso de Classes, por favor.

Código PHP:
class Auto {
  public 
$TanqueGasolina = new TanqueGasolina();
  public 
$Motor = new Motor();

  
// Funciones del Auto

El primer problema que tienes es que la clase carro crea las instancias de tanque y motor esto genera un poco de acoplamiento para ciertos casos.
Código PHP:
class TanqueGasolina extends Auto {
  public 
$Gasolina 100;

  
// Funciones del Tanque de gas
}

class 
Motor extends Auto {
  public 
$Estado "Apagado";
  
  public function 
Encender() {
    
// AQUI EMPIEZAN MIS DUDAS
  

El problema en esta parte es que estas intentando usar la herencia como forma de reutilización en clases que no tiene nada en común, a esto se le conoce como Refused bequest para resolver esto puedes usar composición o delegar la responsabilidad en otras clases. Por otro lado, algo que pasaste por alto es que estas explicando el problema que tienes pero no lo que realmente quieres hacer, pero con la información que proporcionaste y viendo el código puedes hacer algo como lo siguiente.
Código PHP:
Ver original
  1. class Tank {
  2.    
  3.     private $level = 0;
  4.    
  5.     public function level() {
  6.         return $this->level;
  7.     }
  8.    
  9.     public function fill($quantity) {
  10.         $this->level = $quantity;
  11.     }
  12. }
  13.  
  14. class Engine {
  15.    
  16.     private $state = 'off';
  17.    
  18.     private $tanke = null;
  19.    
  20.     public function __construct(Tank $tank) {
  21.         $this->tank = $tank;
  22.     }
  23.    
  24.     public function turnOn() {
  25.        
  26.         if ($this->tank->level()) {
  27.             $this->state = 'on';
  28.         } else {
  29.             $this->state = 'off';
  30.         }
  31.        
  32.         return $this->state;
  33.     }
  34.    
  35.     public function turnOff() {
  36.         $this->state = 'off';
  37.     }
  38.    
  39. }
  40.  
  41. class Car {
  42.    
  43.     private $tank;
  44.    
  45.     private $engine;
  46.    
  47.     public function __construct(Tank $tank, Engine $engine) {
  48.         $this->tank = $tank;
  49.         $this->engine = $engine;
  50.     }
  51.    
  52.     public function turnOn() {
  53.         return $this->engine->turnOn();
  54.     }
  55.    
  56.     public function turnOff() {
  57.         return $this->engine->turnOff();
  58.     }
  59.    
  60.     public function fillGas($quantity) {
  61.         $this->tank->fill($quantity);
  62.     }
  63.    
  64. }
  65. //ejemplo
  66. $tank = new Tank();
  67. $tank->fill(100);
  68. $engine = new Engine($tank);
  69. $car = new Car($tank, $engine);
  70. var_dump($car->turnOn());
  71. $car->turnOff();
  72. $car->fillGas(0);
  73. var_dump($car->turnOn());
Este ejemplo tiene mucho que mejorar pero la idea de utiliza delegación te simplifica el problema y obtienes un api mas sencilla de usar ademas cada objeto ya tiene su propia responsabilidad.
Si estas comenzando con la POO te aconsejo que leas sobre los principios GRASP para que aprendas como signar responsabilidades entre clases, un buen libro que habla sobre el tema es el de craig larman
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.

Última edición por hhs; 06/05/2017 a las 18:40 Razón: agregue referencia
  #6 (permalink)  
Antiguo 07/05/2017, 17:27
 
Fecha de Ingreso: noviembre-2009
Mensajes: 11
Antigüedad: 15 años, 1 mes
Puntos: 1
Respuesta: Consejo en uso de Classes, por favor.

Hola hhs. Antes que nada, al igual que a alvaro_trewhela, agradecer tu ayuda y tiempo.
Ya leí sobre los principios GRASP, por lo pronto de la Wikipedia, por que desconocía el termino (es lo que pasa cuando aprendes a programar sin universidad), voy a buscar el libro que mencionas para comprarlo en la primera oportunidad.

La idea final es/era tener algo como:
Código PHP:
$Auto1 = new Auto();
$Auto2 = new Auto();
.... 
Y que cada "Auto" tenga todos sus componentes, "Tanque, Motor, etc.."
Probablemente lo pudiese resolver con solo una clase, la clase Auto, y ahi toooodas las funciones y atributos.
Pensé en utilizar varias clases para tener "orden" pero veo que lo plantee mal desde un inicio y de ahi todos los problemas. Pero sus codigos y consejos ya me dejan mas en claro cual es la forma correcta de hacerlo.

Una ultima pregunta, veo que en los constructores de las classes utilizas algo como:
Código PHP:
 __constructor(Tank $tank
Nunca lo habia usado en PHP, es igual que en C? para forzar que la variable enviada sea una instancia de Tank o tiene otra funcion?
  #7 (permalink)  
Antiguo 08/05/2017, 13:05
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 11 años, 5 meses
Puntos: 379
Respuesta: Consejo en uso de Classes, por favor.

Cita:
Iniciado por LordMOY Ver Mensaje
Hola hhs. Antes que nada, al igual que a alvaro_trewhela, agradecer tu ayuda y tiempo.
Ya leí sobre los principios GRASP, por lo pronto de la Wikipedia, por que desconocía el termino (es lo que pasa cuando aprendes a programar sin universidad), voy a buscar el libro que mencionas para comprarlo en la primera oportunidad.
En realidad la universidad solo te da algunas bases la mayor parte lo aprendes en el camino, así que no te preocupes si no tienes estudios formales.
Cita:
La idea final es/era tener algo como:
Código PHP:
$Auto1 = new Auto();
$Auto2 = new Auto();
.... 
Y que cada "Auto" tenga todos sus componentes, "Tanque, Motor, etc.."
Probablemente lo pudiese resolver con solo una clase, la clase Auto, y ahi toooodas las funciones y atributos.
Pensé en utilizar varias clases para tener "orden" pero veo que lo plantee mal desde un inicio y de ahi todos los problemas. Pero sus codigos y consejos ya me dejan mas en claro cual es la forma correcta de hacerlo.
Lo facil seria hacer una sola clase como comentas, pero en realidad debes de crear un modelo de objetos que resuelva el problema que tienes, si vas a tener autos con diferentes motores , tipo de tanques, etc. entonces tienes que buscar la forma de que tus objetos puedan hacer eso y es probable que no lo resuelvas con una sola clase. Al punto al que voy es que tu tienes que resolver el problema de acuerdo a los requisitos de tu proyecto si en esos requisitos una sola clase resuelve el problema que bien por tí, pero si no es así, entonces vas a tener que crear todo lo que se requiera para resolver esos requisitos.
Cita:
Una ultima pregunta, veo que en los constructores de las classes utilizas algo como:
Código PHP:
 __constructor(Tank $tank
Nunca lo habia usado en PHP, es igual que en C? para forzar que la variable enviada sea una instancia de Tank o tiene otra funcion?
Si, es para forzar que los métodos o funciones solo acepten ciertos tipos en sus argumento. Puedes ver mas en el manual: http://php.net/manual/es/functions.a...pe-declaration
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #8 (permalink)  
Antiguo 08/05/2017, 21:33
jhonnyalexander_91
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Consejo en uso de Classes, por favor.

Mi sugerencia es que use un "Framework" actualizado para realizar su desarrollo entendiendo primero las recomendaciones y buenas prácticas del mismo, este le guiará para que desarrolle aplicaciones robustas sin que tenga muchos problemas de seguridad y a la vez pueda tener un desarrollo escalable.

Le sugiero también que use el método de desarrollo orientado a pruebas y que entienda el concepto de Inyección de Dependencias.

Etiquetas: classes
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 03:35.