Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Estas en el tema de Duda: Como inicializar propiedades públicas (filtradas) de un objeto en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Hola a todos. Últimamente me estoy poniendo en serio con POO en PHP5 —hasta hace poco casi todo el código en mis aplicaciones era PHP5 ...
  #1 (permalink)  
Antiguo 30/12/2008, 03:39
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Hola a todos.

Últimamente me estoy poniendo en serio con POO en PHP5 —hasta hace poco casi todo el código en mis aplicaciones era PHP5 al estilo de PHP4, y quiero que eso cambie—, y hoy me ha surgido una duda: ¿Cual es la forma óptima de inicializar una propiedad pública, pero filtrada, de un objeto?

Es decir, yo tengo este código:

Código PHP:
class Prueba{
    
    private 
$a//Debe ser una cadena, por ejemplo.
    
    
public function __construct($arg 'Default'){
        
        
$this -> $arg;
        
    }
    
    public function 
__set($var$value){
        
        switch(
$var){
            
            case 
'a':
            
                if (
is_string($value)) $this -> $value;
                else throw new 
MyException('foo');
            
            default:
                
                throw new 
MyException02('foo02');
            
        }
        
    }
    

Pero no funciona, ya que el $this -> a = $arg; del constructor define la propiedad directamente, sin pasar por el __set, pues no importa que sea privada ya que es el propio objeto el que hace la llamada.

Otra opción:

Código PHP:
class Prueba{
    
    private 
$a//Debe ser una cadena, por ejemplo.
    
    
public function __construct($arg 'Default'){
        
        
$this -> __set('a'$arg);
        
    }
    
    public function 
__set($var$value){
        
        switch(
$var){
            
            case 
'a':
            
                if (
is_string($value)) $this -> $value;
                else throw new 
MyException('foo');
            
            default:
                
                throw new 
MyException02('foo02');
            
        }
        
    }
    

Esta no me acaba de gustar, pues me parece que empeora un poco el rendimiento de la clase, ya que introduce un salto en el código (una llamada a un método) por cada propiedad a inicializar desde el constructor... ¿a vosotros qué os parece?

Otra:

Código PHP:
class Prueba{
    
    private 
$a//Debe ser una cadena, por ejemplo.
    
    
public function __construct($arg 'Default'){
        
        
$this -> setA($arg);
        
    }
    
    public function 
__set($var$value){
        
        switch(
$var){
            
            case 
'a':
            
                
$this -> setA($value);
            
            default:
                
                throw new 
MyException02('foo02');
            
        }
        
    }
    
    private function 
setA{
        
        if (
is_string($value)) $this -> $value;
        else throw new 
MyException('foo');
        
    }
    

Esta me gusta menos, ya que hace que el código crezca muchísimo (¿¿un método privado por cada propiedad??). Además, creo que es aún menos eficiente ya que introduce un nuevo salto en el código: Mantiene el del constructor, y añade un salto si el programador decide cambiar la propiedad (ya que incorpora una función al __set, en lugar de estar en él el código).

Y lo último que se me ocurre es duplicar el código en el constructor:

Código PHP:
class Prueba{
    
    private 
$a//Debe ser una cadena, por ejemplo.
    
    
public function __construct($arg 'Default'){
        
        if (
is_string($arg)) $this -> $arg;
        else throw new 
MyException('foo');
        
    }
    
    public function 
__set($var$value){
        
        switch(
$var){
            
            case 
'a':
            
                if (
is_string($value)) $this -> $value;
                else throw new 
MyException('foo');
            
            default:
                
                throw new 
MyException02('foo02');
            
        }
        
    }
    

Lo cual creo que es lo más óptimo desde el punto de vista del rendimiento... pero me gustaría saber si existe una diferencia práctica entre este y el primero, ya que este no me gusta nada pues lo de duplicar código para el mantenimiento del programa es fatídico.

¿Cual es vuestra opinión acerca de este problema? ¿O es simplemente que tengo un error en mi planteamiento sobre objetos y clases?

Gracias por vuestro tiempo.
  #2 (permalink)  
Antiguo 30/12/2008, 04:16
 
Fecha de Ingreso: octubre-2004
Mensajes: 2.627
Antigüedad: 19 años, 6 meses
Puntos: 48
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Olvidate del rendimiento. La optimizacion dejala para cuando la necesites, y descubras exactamente lo que require optimizacion (analizando la aplicacion en funcionamiento real). ¿Cuantas veces vas a llamar al set por script? ¿1, 2, 3? ¿Cual crees que puede ser la diferencia de tiempo entre un salto o 2 saltos en una llamada?

Tu primer objetivo es hacer codigo facil de mantener. Optimizar por optimizar es malgastar el tiempo.
  #3 (permalink)  
Antiguo 30/12/2008, 04:48
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Entonces casi elegiríamos la segunda opción (la primera de las que funcionan), ¿no?
  #4 (permalink)  
Antiguo 30/12/2008, 05:01
 
Fecha de Ingreso: octubre-2004
Mensajes: 2.627
Antigüedad: 19 años, 6 meses
Puntos: 48
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Para empezar esta bien. Recuerda que el codigo evoluciona, intentar que el codigo incial sea correcto al 100% es malgastar el tiempo. Con un ejemplo abstracto no se pueden ver necesidades que te pueden salir. Y programar para necesidades que no vas a necesitar tambien es perder el tiempo.

Por ejemplo, ahora usas un switch. Mañana puede ser que veas mas practico usar funciones de array combinado con funciones (por ejemplo, un array donde almacenas el nombre de la propiedad y una coleccion de filtros standards a aplicar en el orden indicado).
  #5 (permalink)  
Antiguo 30/12/2008, 06:10
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Últimamente me estoy poniendo en serio con POO en PHP5 —hasta hace poco casi todo el código en mis aplicaciones era PHP5 al estilo de PHP4, y quiero que eso cambie—,
Ahora ahora lo que vi no es muy serio Estaría bueno que vieras otros manuales de POO genéricos y no solo el manual de PHP5, ya que es un manual técnico y de sintaxis, no de programación y conceptos.

Cita:
y hoy me ha surgido una duda: ¿Cual es la forma óptima de inicializar una propiedad pública, pero filtrada, de un objeto?
¿Optimizar? ¡Si aún no es funcional!

Pregunta: ¿conoces el principio KISS? Veo que lo violas constantemente

Lo que intentas hacer debe solucionarse directamente y de forma simple, mi sugerencia personal es que evites los __set y __get de PHP5 que no aportan nada bueno a un diseño POO (en la mayoría de los casos terminan generando el mismo efecto que si fueran atributos públicos), que existan tampoco quiere decir que los debas usar por defecto.

La solución debería ser así:

Código PHP:
class Prueba
{
    
   private 
$_a;
    
   public function 
__construct($a)
   {        
        
$this->_a = (string)$a;
        
   }      

Listo, no abuses de las excepciones, solo son para casos "excepcionales", no para cualquier situación.

Sugerencia: lee sobre getter / setter, todo esto ya está inventado hace mucho tiempo y perder tiempo en reinventar la rueda no es muy productivo.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #6 (permalink)  
Antiguo 30/12/2008, 10:01
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

DarkJ, muchas gracias por tu respuesta .

Enriqueplace;

Cita:
¿Optimizar? ¡Si aún no es funcional!
Suelo buscar la mejor forma de hacer las cosas desde el principio, desde la base, y creo que es como debe hacerse.

Con tu ejemplo no respondes a mi pregunta, pues lo que yo pretendo es conocer vuestra opinión acerca de cual es la mejor forma para filtrar una variable que desde fuera es vista como pública pero que internamente tiene un control. Quizá el ejemplo que puse es demasiado simple, no obstante, creo que quedó claro a lo que me refiero: Un caso en el que sea necesario hacer una comprobación al valor que se pasa a una propiedad de un objeto, teniendo en cuenta que el mismo se puede pasar al constructor y también es accesible como una propiedad pública.

Cita:
Listo, no abuses de las excepciones, solo son para casos "excepcionales", no para cualquier situación.
Me gustan los lenguajes fuertemente tipados, como C++, por eso las excepciones si se intenta pasar argumentos del tipo incorrecto. Creo que es mejor eso que hacer un typecast implícito y transparente y seguir como si tal cosa.

De todas formas muchísimas gracias por tu tiempo, pero es que simplemente tu respuesta no me convence.
  #7 (permalink)  
Antiguo 30/12/2008, 10:41
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

El problema de usar __set es que solo es activado como bien dices, cuando lees la variable desde forma publica, por lo que al querer pasarla por el constructor no se va a activar, en ese caso lo que puedes hacer es checar el tipo de variable en el constructor y también en el __set, o crear un método que se dedique solamente a checar los tipos de variables y lo llamas desde el constructor y desde el __set.

Saludos.
  #8 (permalink)  
Antiguo 30/12/2008, 10:47
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Suelo buscar la mejor forma de hacer las cosas desde el principio, desde la base, y creo que es como debe hacerse.
Siempre hay más de una.

Cita:
Con tu ejemplo no respondes a mi pregunta, pues lo que yo pretendo es conocer vuestra opinión acerca de cual es la mejor forma para filtrar una variable que desde fuera es vista como pública pero que internamente tiene un control.
Mmm... partamos entonces que:
  • Los atributos públicos están prohibidos (99,99% de los casos)
  • La forma de inicializar es a través del constructor y/o métodos get/set
  • Posteriormente la validación la podrás hacer a través de un método privado de la propia clase, manteniendo la simplicidad en el constructor y en los set/get.
Cita:
Un caso en el que sea necesario hacer una comprobación al valor que se pasa a una propiedad de un objeto, teniendo en cuenta que el mismo se puede pasar al constructor y también es accesible como una propiedad pública.
Usa el mismo método privado para validarla.

Cita:
Me gustan los lenguajes fuertemente tipados, como C++, por eso las excepciones si se intenta pasar argumentos del tipo incorrecto. Creo que es mejor eso que hacer un typecast implícito y transparente y seguir como si tal cosa.
Usa C++, PHP no es tipado fuerte, pero puedes usarlo en la POO.

Cita:
De todas formas muchísimas gracias por tu tiempo, pero es que simplemente tu respuesta no me convence.
No sé de qué habría de convencer , es que me parece que tu pregunta es por un problema tan trivial y es mi impresión es que estás complicando exageradamente la solución de un problema simple.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #9 (permalink)  
Antiguo 31/12/2008, 09:10
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Los atributos públicos están prohibidos (99,99% de los casos)
La forma de inicializar es a través del constructor y/o métodos get/set
Estamos totalmente de acuerdo.

Cita:
Posteriormente la validación la podrás hacer a través de un método privado de la propia clase, manteniendo la simplicidad en el constructor y en los set/get.
En esto no. He leído un artículo tuyo al respecto, en el cual comentas que
Cita:
Otro error común es agregarle más lógica que asignar un valor o retornar el valor del atributo. Si necesitas agregarle lógica, ya dejan de ser "get / set", lo cual es mejor que cambiemos de nombre y lo dejemos con los demás métodos comunes de nuestra clase.

(...)

Nota: esto es muy a nivel personal, hay opiniones encontradas sobre tener una lógica elemental dentro de un set/get o hacerlo tan extenso como necesitemos. Claramente yo estoy en el primer grupo.
Yo estoy en un grupo intermedio... creo que se les puede añadir lógica, pero dependerá mucho de los casos, y de cómo sea esa lógica.

También he leído un artículo de Allen Holub en el que dice que los getters/setters deben evitarse a toda costa... y el mayor argumento que leo —o al menos así lo comprendo yo— es la necesidad de mantener el ocultamiento de la implementación interna del objeto. Estoy de acuerdo, pero... ¿qué gano al utilizar otro tipo de métodos en lugar de un getter? Por ejemplo, él dice que

Cita:
What if you need to change the accessed field's type? You also have to change the accessor's return type. You use this return value in numerous places, so you must also change all of that code. I want to limit the effects of a change to a single class definition. I don't want them to ripple out into the entire program.
y estoy de acuerdo con él... pero, ¿como lo soluciono? Si yo quiero saber la nota del examen de Febrero de un alumno que se abstrae en un objeto $alumno de la clase Alumno...

Cita:
If X was an int, but now must be a long, you'll get 1,000 compile errors.
Sigo de acuerdo... y si yo implemento el acceso a la nota del alumno como un getter que devuelve un int y luego lo tengo que cambiar a un float, por ejemplo, obtendría errores —en un lenguaje fuertemente tipado, claro—... pero... es que ese problema no tiene nada que ver con el getter-en-sí, el problema está con el hecho de devolver valores, ya que si implemento un método nota que me permita obtener la nota del alumno, voy a tener el mismo problema...

Lamento si me he enrollado demasiado y... si no te gusta debatir sobre el sexo de los ángeles, lo dejamos y espero a que alguien se interese por el tema —o que quedo con mis propias conclusiones, si no hay nadie que me las rebata.

Nota: Me disculpo de antemano por si a alguien le molestan los contenidos en inglés, si es necesario los traduzco.
  #10 (permalink)  
Antiguo 31/12/2008, 09:48
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
También he leído un artículo de Allen Holub en el que dice que los getters/setters deben evitarse a toda costa...
Justamente lo comento en el mismo artículo, al final:

"También quiero destacar que a pesar de existir esta técnica, no quiere decir que deba ser usada o que su uso esté completamente permitido. Hay que entender que la POO no debería hacer uso de de los getter y setters ya que tendríamos acceso de forma directa al "estado del objeto" (la información que tienen los atributos de un objeto) y permitir el acceso o modificación genera el mismo efecto de manipulación que si fuera una operación de "corazón abierto".

Nuestro objeto debería estar protegido del exterior y no permitir tener acceso directo a sus atributos, y trabajar siempre sobre sus métodos ("los métodos definen el comportamiento del objeto"). En caso de no poder hacerlo, se podría priorizar disponer de "get" (obtener valor de un atributo de forma directa) y no "set" (modificar un valor directo de un atributo), y
en el peor de los casos, tener un uso muy controlado de los "set"."

Cita:
y estoy de acuerdo con él... pero, ¿como lo soluciono? Si yo quiero saber la nota del examen de Febrero de un alumno que se abstrae en un objeto $alumno de la clase Alumno...
Haces simplemente un método, común y corriente, pero no "conceptualmente" un get/set.

Es conceptual, getter/setter como forma alternativa de acceder a los atributos, pero si necesitas hacer algo más complejo, no uses el "concepto get/set", crea un método que haga lo que necesites y no importa si inicia con la palabra "get" (eso no lo define como un getter).

Ejemplo:

Si tienes un atributo "nombre", tendrías:

Código PHP:
$alumno->getNombre();
$alumno->setNombre(); 
Esos son get/set (tienes un atributo "nombre"), pero perfectamente podrías hacer:

Código PHP:
$alumno->getNotaExamen(); 
Y no quiere decir que sea un "getter", es un método común y corriente, no lo usas para tratar de acceder a un atributo privado.

¿Se entiende la diferencia?

Complica todo lo que quieras (validaciones etc) los métodos comunes, pero evita hacerlo en los getter y setter, la idea es una forma de "solucionar" la necesidad de acceder a un dato de un atributo evitando que este sea público, por eso sugiero que definan estas reglas:
  1. atributos privados
  2. usa métodos comunes y no getter/setter
  3. Si no te queda otra, usa solo getter
  4. Si no te queda otra, usa setter
  5. trata de evitar getter y setter a la vez (efecto "atributo público")
¿Queda más claro ahora?
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #11 (permalink)  
Antiguo 31/12/2008, 10:02
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Te entiendo perfectamente... pero no acabo de encontrar un argumento válido para no usar los getters/setters, más que el púramente dogmático. Y oye, con los dogmatismos no-argumentados no me llevo nada bien, de ahí mis dudas —dudaba de si era algo puramente dogmático o había alguna razón que a mí se me escapaba.
  #12 (permalink)  
Antiguo 31/12/2008, 14:11
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Iniciado por Sanva Ver Mensaje
Te entiendo perfectamente... pero no acabo de encontrar un argumento válido para no usar los getters/setters, más que el púramente dogmático. Y oye, con los dogmatismos no-argumentados no me llevo nada bien, de ahí mis dudas —dudaba de si era algo puramente dogmático o había alguna razón que a mí se me escapaba.
¿"Un argumento válido"? ¿"dogmatismos no-argumentados""? No te bases en una sola opinión, esta discusión es de los orígenes de la POO y no de un solo autor.

Si razonas un poco te darás cuenta que usar getter/setter, en el peor de los casos, es lo mismo que usar "atributos públicos" (Si usas set o get, ya tienes el 50% de un atributo público) y esto rompe una de las bases de la POO (fuente wikipedia):

"Principio de ocultación: Cada objeto está aislado del exterior, es un módulo natural, y cada tipo de objeto expone una interfaz a otros objetos que especifica cómo pueden interactuar con los objetos de la clase. El aislamiento protege a las propiedades de un objeto contra su modificación por quien no tenga derecho a acceder a ellas, solamente los propios métodos internos del objeto pueden acceder a su estado. Esto asegura que otros objetos no pueden cambiar el estado interno de un objeto de maneras inesperadas, eliminando efectos secundarios e interacciones inesperadas. Algunos lenguajes relajan esto, permitiendo un acceso directo a los datos internos del objeto de una manera controlada y limitando el grado de abstracción. La aplicación entera se reduce a un agregado o rompecabezas de objetos."
__________________
Blog phpsenior.com Cursos a Distancia surforce.com

Última edición por enriqueplace; 31/12/2008 a las 14:17
  #13 (permalink)  
Antiguo 01/01/2009, 19:59
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

No estoy de acuerdo:

Si utilizas un getter/setter sin lógica interna (simplemente asignar el valor a la variable, y listo) es verdad, pero si utilizas una lógica interna, un getter/setter sólo se diferencia en la sintaxis utilizada para acceder al valor. No se si me explico...

Código PHP:
$a -> nombre 'Sanva'
es exactamente lo mismo que

Código PHP:
$a -> definirNombre('Sanva'); 
. No violas el principio de ocultación, ya que nadie sabe cómo funciona el getter/setter de forma interna.

Última edición por Sanva; 01/01/2009 a las 20:00 Razón: Añadir formato
  #14 (permalink)  
Antiguo 01/01/2009, 21:55
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Iniciado por Sanva Ver Mensaje
No estoy de acuerdo:

Si utilizas un getter/setter sin lógica interna (simplemente asignar el valor a la variable, y listo) es verdad, pero si utilizas una lógica interna, un getter/setter sólo se diferencia en la sintaxis utilizada para acceder al valor. No se si me explico...

Código PHP:
$a -> nombre 'Sanva'
es exactamente lo mismo que

Código PHP:
$a -> definirNombre('Sanva'); 
. No violas el principio de ocultación, ya que nadie sabe cómo funciona el getter/setter de forma interna.
No estás entendiendo el punto ni el principio. El principio de ocultación habla de evitar el acceso o modificación de los atributos del objeto desde el exterior, no tiene nada que ver con los setter y getter, estos aparecen después con la existencia de situaciones que te imposibilitan poder cumplir estrictamente con el principio.

En el mundo ideal, deberíamos tener SOLO atributos privados / protegidos y para comunicarnos con el exterior únicamente métodos públicos.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #15 (permalink)  
Antiguo 02/01/2009, 08:32
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
No estás entendiendo el punto ni el principio.
Una cosa es que tengas una idea u opinión formada, otra muy diferente es que asumas que tienes razón. Entiendo perfectamente el Español, y el principio de ocultación está muy bien explicado en la Wikipedia, y creo que no hay ningún tipo de error en mis argumentaciones al respecto.

Si el tema es de autores, es decir, cada uno piensa de una forma o según una corriente distinta, lo dejamos aquí y punto.

Saludos, y gracias por vuestro tiempo.
  #16 (permalink)  
Antiguo 02/01/2009, 09:04
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Iniciado por Sanva Ver Mensaje
Una cosa es que tengas una idea u opinión formada, otra muy diferente es que asumas que tienes razón. Entiendo perfectamente el Español, y el principio de ocultación está muy bien explicado en la Wikipedia, y creo que no hay ningún tipo de error en mis argumentaciones al respecto.

Si el tema es de autores, es decir, cada uno piensa de una forma o según una corriente distinta, lo dejamos aquí y punto.

Saludos, y gracias por vuestro tiempo.
Hay claramente errores en tus argumentaciones:

"No violas el principio de ocultación, ya que nadie sabe cómo funciona el getter/setter de forma interna."

Y tu ejemplo es claro, no estás entendiendo el punto del principio ni la diferencia con los getter /setter (el postulado anterior es incorrecto).

Es más simple de lo que parece, vuelvo al principio, te estás complicando exageradamente desde el planteo de tu duda y cómo abordas la implementación.

Y estamos hablando solo de asignación de valores a atributos! No quiero ver en temas más complejos.

Busca simplicidad, no te compliques con estas cosas, no le puedes dar tanta vuelta a algo tan simple.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com

Última edición por enriqueplace; 02/01/2009 a las 19:12
  #17 (permalink)  
Antiguo 03/01/2009, 07:36
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Es más simple de lo que parece, vuelvo al principio, te estás complicando exageradamente desde el planteo de tu duda y cómo abordas la implementación.
Bueno, eso es circunstancial... es lo que tienen las discusiones, que tienden a complicarse.

Cita:
Y tu ejemplo es claro, no estás entendiendo el punto del principio ni la diferencia con los getter /setter (el postulado anterior es incorrecto).
Aquí es donde tú y yo no estamos de acuerdo, y nuestra discusión tiene sentido: Tú dices que un getter/setter no debe tener lógica interna, que es simplemente una asignación a una propiedad del objeto. Desde tu punto de vista mis argumentaciones son erróneas, puesto que realmente sí estoy violando el principio de ocultación al revelar los nombres de las propiedades del objeto, y al permitir una asignación a una propiedad privada —lo que la convertiría en pública, y haría que los getter/setter sean una absoluta estupidez.

Sin embargo mi punto de vista es otro: Yo sí creo que los getter/setter deben tener una lógica interna. Y teniendo en cuenta eso, lo que yo expongo al usuario es una propiedad del objeto con un determinado nombre, pero que internamente su nombre puede ser totalmente distinto, de hecho puede tener una lógica asignada y una sola asignación de propiedad puede ser internamente una asignación doble. Por ejemplo:

Código PHP:
class Prueba{
    
    private 
$_t;
    private 
$_f;
    
    public function 
__construct($arg 37){
        
        
$this -> __set('temperatura'$arg);
        
    }
    
    public function 
__set($var$value){
        
        switch(
$var){
            
            case 
'temperatura':
            
                if (
$value 35 || $value 43$this -> _t $value;
                else throw new 
MyException('Temperatura imposible');
                
                if (
$value 37$this -> _f true;
                else 
$this -> _f false;
                
                break;
            
            default:
                
                throw new 
MyException02('Error');
            
        }
        
    }
    
    public function 
__get($var){
        
        switch(
$var){
            
            case 
'temperatura':
            
                return 
$this -> _t;
            
            default:
                
                throw new 
MyException02('Error');
            
        }
        
    }
    
    public function 
tieneFiebre(){
        
        return 
$this -> _f;
        
    }
    

Ahí creo que se ve claramente lo que quiero explicar. El API del objeto indicará que se puede acceder a una propiedad temperatura, la cual admite asignación de enteros desde el 36 al 42. Además de eso, existe un método tieneFiebre para comprobar si el sujeto tiene o no fiebre. Bien, pero ese es el API pública, internamente el objeto no tiene una propiedad pública —ni privada-pública por acción de los getter/setter— llamada temperatura, no, lo que tiene son dos propiedades privadas llamadas _t y _f, las cuales son definidas según una lógica interna, y que pueden cambiar —tanto sus nombres como sus tipos internos en el caso de ser un lenguaje tipado, y también la lógica que establece si el sujeto tiene o no fiebre, o una nueva propiedad/método, según proceda, que permita determinar la especie del sujeto por si se quiere ampliar la funcionalidad de la clase base (esto es, sin herencias, por lo que sea) y establecer otras reglas para determinar si el sujeto tiene o no fiebre, según su pertenencia a una u otra especie.

Creo que ahora me he explicado al completo, y creo que nuestras discrepancias no son acerca de que los getter/setter se puedan utilizar de forma general o no... la discusión está en si pueden o no llevar una lógica interna: Si pueden, se pueden usar pues no violas el principio de ocultación... si no pueden, no se pueden usar porque sí lo violas.

Y la discrepancia en si se puede o no se puede usar lógica interna creo que ya pertenece al área de las opiniones personales.
  #18 (permalink)  
Antiguo 03/01/2009, 08:02
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Te cambio el ejemplo:

Código PHP:
class Paciente
{    
   private 
$_temperatura;

   const 
FIEBRE 38;
   const 
MAX_TEMPERATURA 43;
   const 
MIN_TEMPERATURA 35;

   public function 
asignarTemperatura($grados)
   {
      if (
$grados self::MIN_TEMPERATURA || $grados self::MAX_TEMPERATURA){
         throw new 
MyException('Temperatura fuera de rango');
      }
      
$this->_temperatura $grados;
   }    
   public function 
tieneFiebre()
   {
      return 
$this->_temperatura >= self::FIEBRE             
   
}
    

Como te argumentaba al principio:
  • Te estás complicando innecesariamente, se puede hacer mucho más sencillo.
  • Trata de evitar los __set y __get, por lo general terminan creando el efecto "atributos públicos"
  • No uses/evita (conceptualmente) los getter/setter, usa métodos simples (si los set/get son parches, no tienes por qué estar obligado a usarlos).
  • El principio se aplica de acuerdo a la exposición de los atributos, justamente, en el uso de get/set (y así lo estás haciendo). Por lo tanto, no los uses, usa métodos y coloca la lógica que quieras.
El problema es conceptual, get/set es conceptual, usar un método común es conceptual.

Con este código creo que se acabó la discusión.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #19 (permalink)  
Antiguo 03/01/2009, 08:14
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

xD ok, terminamos la discusión. Y si bien tu código está perfecto (de hecho me gusta más que el mío, que era un burdo ejemplo ilustrativo en donde sobraban propiedades), no se diferencia en nada del mío en cuanto al principio de ocultación, que era de lo que iba últimamente el hilo.
  #20 (permalink)  
Antiguo 03/01/2009, 08:17
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Hay un dicho que dice "No es que la tortuga sea lenta, es que no quiere ir".

Para aprender hay que dejar el orgullo de lado.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #21 (permalink)  
Antiguo 03/01/2009, 08:30
 
Fecha de Ingreso: diciembre-2005
Ubicación: Redondela (Galicia)
Mensajes: 368
Antigüedad: 18 años, 4 meses
Puntos: 1
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Bueno, eso ya me ha parecido totalmente fuera de tono.

¿Me quieres decir exactamente en dónde expongo los atributos privados en mi último ejemplo? Otra cosa es que tú asumas que tienes razón, y que soy yo el que entiende mal el principio de ocultación y no tú. Yo intento argumentar, no hago oídos sordos todo el rato basándome en que tengo razón y punto. Yo no se si la tengo, yo creo que la tengo, y para tratar de tenerla, argumento.

Y no, repetir que no se pueden usar los getter/setter porque expones los atributos justo después de que yo te demuestre empíricamente —con un ejemplo— que eso no es así, no es argumentar.
  #22 (permalink)  
Antiguo 24/01/2009, 08:20
Avatar de Lord Kazuky  
Fecha de Ingreso: junio-2006
Ubicación: 7F.00.00.01
Mensajes: 123
Antigüedad: 17 años, 10 meses
Puntos: 5
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Enrique, cuando dices:

"No uses/evita (conceptualmente) los getter/setter, usa métodos simples (si los set/get son parches, no tienes por qué estar obligado a usarlos)."

¿Es por cuestión de diseño? a que te refieres con 'conceptualmente'?

Segun el ejemplo que pones 'asignarTemperatura' y 'tieneFiebre' son nombres que dicen más de lo que hacen que solo 'get'. ¿A eso te refieres?
__________________
Saludos.
"Cualquier tonto puede escribir código que un computador entiende. Los buenos programadores escriben código que los humanos pueden entender. ;)"
  #23 (permalink)  
Antiguo 24/01/2009, 09:32
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Cita:
Iniciado por Lord Kazuky Ver Mensaje
Enrique, cuando dices:

"No uses/evita (conceptualmente) los getter/setter, usa métodos simples (si los set/get son parches, no tienes por qué estar obligado a usarlos)."

¿Es por cuestión de diseño? a que te refieres con 'conceptualmente'?

Segun el ejemplo que pones 'asignarTemperatura' y 'tieneFiebre' son nombres que dicen más de lo que hacen que solo 'get'. ¿A eso te refieres?
Estimado Lord, pensé que todo el hilo de la discusión había sido suficientemente claro

Un getter/setter no es más que una "convención de nombres y uso" para un método, por ejemplo:
  • si pides datos, get y nombre del atributo que entregas datos, ej: getNombre()
  • si es para asignar datos, inica el nombre con set y el atributo, ej: setNombre($valor);
Y conceptualmente, es simplemente para suplir que no hagas atributos públicos pero que quieres/necesitas de alguna forma aplicar una "excepción" (evita que todo lo sea)... si lo razonas verás que si aplicas set/get siempre a tus atributos, es lo mismo que si fueran públicos... y esa no es la idea, los objetos (en su uso tradicional) no deben tener atributos públicos.

Es conceptual, tu perfectamente puedes tener métodos que se llamen "getAlgo" y no sean getter/setter, simplemente porque te queda más cómodo que decir "obtenerValorDeAlgo"; nadie dice que no puedes usar en otros ámbitos la preposición "get"... por eso también la discusión que un método getter/setter tiene que ser simple, como si fuera un atributo público... si hacemos métodos quilométricos, yo diría que se pierde la esencia, usa entonces métodos comunes y no digas que son getter/setter.

Lo "conceptual" es que deberías evitar acceder directamente a datos de un atributo desde el exterior ("principio de ocultamiento") y trabajar con métodos comunes que retornen información procesada.

Ese es el concepto, de ahí que lo puedas aplicar siempre y de forma pura, es lo más difícil.

Por eso mi sugerencia en ese orden, trata de evitar los getter/setter, pero si no puedes, usa ese orden.

¿Queda más claro ahora?
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #24 (permalink)  
Antiguo 26/01/2009, 08:11
Avatar de Lord Kazuky  
Fecha de Ingreso: junio-2006
Ubicación: 7F.00.00.01
Mensajes: 123
Antigüedad: 17 años, 10 meses
Puntos: 5
De acuerdo Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Hombre muchas gracias!

A manera de ejemplo y creo ya que para terminar. Digamos que en un diseño, en donde quiero acceder a datos de un Modelo para mostrarlos en un formulario. ¿Podria utilizar los metodos getter para leer cada uno de ellos (construyendolos como métodos sencillos)? ¿Cualquier otro metodo que se llame 'obtenerAlgo' no vendria haciendo el mismo papel del getter? ¿Como hago para evitar metodos así si necesito mostrar esa información? ¿Deberia crear mejor un metodo nose.. 'llenarFormulario' que me reciba el objeto formulario y lo llene con los datos del objeto actual?

Que pena, ya debes estar cansado de repetir tantas cosas... Deberia haber una especie de FAQ de estos conceptos bien documentados para remitirnos todos ahi cuando tengamos dudas o sencillamente para no estar preguntando lo mismo todas las veces.
__________________
Saludos.
"Cualquier tonto puede escribir código que un computador entiende. Los buenos programadores escriben código que los humanos pueden entender. ;)"

Última edición por Lord Kazuky; 26/01/2009 a las 09:07 Razón: Aun hay dudas :S
  #25 (permalink)  
Antiguo 26/01/2009, 16:03
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 18 años, 11 meses
Puntos: 32
Respuesta: Duda: Como inicializar propiedades públicas (filtradas) de un objeto

Ten cuidado con la edición de las respuestas, me llegó por email una y de casualidad entré a este hilo para verlo y vi que le agregaste preguntas.

Cita:
A manera de ejemplo y creo ya que para terminar. Digamos que en un diseño, en donde quiero acceder a datos de un Modelo para mostrarlos en un formulario. ¿Podria utilizar los metodos getter para leer cada uno de ellos (construyendolos como métodos sencillos)?
No eres claro... para acceder "datos"? Por lo que vengo explicando, getter/setter se aplica a atributos, si haces ambos, generas el mismo efecto que un atributo público.

Que no es lo mismo que si tienes "métodos comunes" que inician con la preposición "get" o "set" (aunque se estile que todo lo que sea "set" o "get" es un método getter / setter, pero no necesariamente es así).

Por ejemplo

Código PHP:
class Persona
{
   private 
$_fechaNacimiento;

   public function 
__construct($fechaNacimiento)
   {
      
$this->_fechaNacimiento $fechaNacimiento;
   }
   public function 
getEdad()
   {
       
/* calcular edad */

      
return $edad;
   }


Aquí tenemos un "método común" getEdad pero no existe un atributo "edad", tampoco estoy usando un método setter, ya que creo el objeto pasando todos los datos que necesita a su constructor.

Distinto sería si tuvieras un método getFechaNacimiento():


Código PHP:
class Persona
{
   private 
$_fechaNacimiento;

   public function 
getFechaNacimiento()
   {
      return 
$this->_fechaNacimiento;
   }


¿Se ve la sutil diferencia? Lo que se sugiere que es no crear setter/getter a diestra y siniestra para todos los atributos de una clase. En lo posible creen solo métodos que "esconden" el detalle del trabajo con los atributos y se concentran en resolver los problemas concretos. No expongan innecesariamente el interior del objeto.

Cita:
Que pena, ya debes estar cansado de repetir tantas cosas... Deberia haber una especie de FAQ de estos conceptos bien documentados para remitirnos todos ahi cuando tengamos dudas o sencillamente para no estar preguntando lo mismo todas las veces.
Mmm.. una forma es usar el buscador del foro, otra, hay un faq, pero estos temas a veces son muy largos de explicar y surgen discusiones al respecto, la otra, esperar que termine de escribir mi libro
__________________
Blog phpsenior.com Cursos a Distancia surforce.com

Última edición por enriqueplace; 27/01/2009 a las 06:27
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

SíEste tema le ha gustado a 2 personas




La zona horaria es GMT -6. Ahora son las 07:05.