2011-12-31 19 views
7

Tengo un sitio de arcade y en los últimos años se han agregado muchas características, hasta el punto en que la programación de procedimientos parece demasiado complicada y agrega nuevas características o simplifica las modificaciones de diseño pueden ser muy difíciles.Elegir qué clases usar en un diseño OOP de php

Por lo tanto, he decidido tratar de recodificar el sitio desde cero con las mismas características pero en formato OOP.

El problema que tengo es elegir las clases, entiendo OOP y cómo debería funcionar, pero siempre parece tener problemas para comenzar. No estoy seguro si debería intentar hacer funciones para clases como una clase de usuario con función de usuario de inicio de sesión o si la clase de usuario debería ser solo agregar/actualizar/mostrar detalles de usuario y la parte de inicio de sesión sería mejor en un sistema ¿clase?

Por el momento comencé con la siguiente clase y funciones pero ¿encajan en esta categoría?

<? 
class User { 

    var $userId, 
     $username, 
     $userRole, 
     $userEmail; 

    function isLoggedIn(){ 

    } 

    function login($postusername, $postpassword) 
    { 

    } 

    function increaseLoginCount(){ 

    } 

    function logout(){ 

    } 
} 
?> 

entonces yo podría tener algo como lo siguiente en una page.php .. (conecte clase no se muestra)

<? 
$db = new Connect; 
$db->connect(); 

$user = new User; 

if(!$user->isLoggedIn()) 
{ 
    echo "Please Log In."; 

    if($_POST['user']) 
    { 
     $user->login($_POST['username'], $_POST['password']); 
    } 
} 
else 
{ 
    if($_POST['logout']) 
    { 
     $user->logout(); 
     exit; 
    } 

    echo $user->username." Logged In.<br />"; 
} 
?> 

Pero entonces el sitio tendría páginas para mostrar sus categorías de juegos y I don' ¿Sabes dónde cabría la función displayGames() ya que no es un juego único por lo que no entraría en la clase 'Game'?

He tratado de encontrar ejemplos del 'mundo real', pero el código php que me muestra cómo hacer un cambio de color elefante o la danza realmente no ayuda ...

+0

tengo las funciones codificadas pero para simplificar este ejemplo se quitaron. – Dan

Respuesta

9

Vamos a empezar con un poco de análisis textual, destacados por mí:

corro un sitio arcada y sobre los últimos años

pensar en cuánto usted son capaces de hacer frente y con lo que está tratando.También entiendo que a lo largo de los años ha ganado conocimiento específico aproximadamente ejecutando el sitio de arcade. Has ganado profesión en tu área. Nunca subestimes tu posición y tus activos, es la base desde la que estás operando y en la que introducirás cambios. Esto incluye la base de usuarios de su sitio.

que ha tenido muchas características añaden, tiene hasta el punto en la programación de procedimiento sólo se ve demasiado complicado y adición de nuevas características o hacer modificaciones de diseño simples pueden ser muy complicado.

Si los sistemas crecen, se vuelven cada vez más complicados. Eso es no específico para programación de procedimientos solamente, es una cuestión de hecho. Como está ejecutando el sitio ahora durante muchos años, usted sabe cómo cambiaron las cosas, especialmente en el área en que el usuario interactúa con su sitio.

Por lo tanto he decidido intentar y recodificar el sitio desde cero con las mismas características pero en un formato de programación orientada a objetos.

Se dice que podría ser posible utilizar técnicas de OOP para hacer que el software reutilizable, hay (y no puede haber) ninguna prueba de esto.

Pero solo hay muy pocos ejemplos en el desarrollo de software comercial donde volver a escribir toda la aplicación desde cero fue un éxito. Muy pocos. Las reglas del desarrollo de software comercial pueden no aplicarse en su caso específico, así que solo digo.

Piense dos veces antes de volver a codificar el sitio. Hacer mucho trabajo solo para lograr lo mismo es algo infructuoso y puede ser decepcionante. En lugar de eso, probablemente vea más específicamente cuál de su diseño actual está presentando el mayor problema que le gustaría cambiar.

Es posible con PHP para mezclar de procedimiento y el estilo orientado a objetos, que puede ser especialmente útil cuando se tiene código heredado (una definición común de código legado es un código w/o pruebas automáticas).

El problema que tengo es recoger las clases,

trato de expresarlo de otro modo: Por lo escribir clases de?

Yo entiendo programación orientada a objetos y cómo debería funcionar, pero parece que siempre haber problemas para empezar.

El comienzo es siempre el paso más difícil. Estás en posición de tomar decisiones ahora, pero no puedes mirar hacia el futuro. Reduzca el riesgo eliminando la parte más arriesgada. Probablemente haya empezado a hacer una pregunta aquí para obtener algunos comentarios en los que basar sus decisiones, pero eso probablemente no reducirá la carga y podría generar confusión.Sin embargo, obtener educación es a menudo una buena cosa.

estoy seguro si debería ser tratando para hacer funciones para las clases como una clase de usuario con registro en función del usuario o si la clase de usuario debe ser sólo para añadir/actualizar/mostrar detalles del usuario y la parte de inicio de sesión sería mejor en una clase de sistema?

Eso depende en gran medida de la naturaleza de su aplicación y la naturaleza del usuario. Probablemente la mayor parte de su script solo necesite saber si un usuario es concreto o anónimo (un usuario anónimo no se ha conectado), es su ID, nombre o apodo.

La aplicación debe proporcionar ese usuario a cualquier componente consumidor, por lo que cada comando/script no necesita tratar a) obtener información de usuarios y manejar usuarios (como iniciar sesión), b) verificar si el componente es válido para el usuario (control de acceso). Eso debería ubicarse en otro lugar, p. en el application controller­PofEAA.

Cada uno de sus scripts/comandos que tiene el objeto del controlador de la aplicación, puede preguntar al usuario y simplemente interactuar con el usuario.

Sin embargo, esto es solo técnicamente hablando. Ocúpate del hecho de que no estás seguro, trabaja con esa información. Intente formular mejor su problema concreto, enumere los pros y los contras de una forma específica de resolverlo, evite el código concreto antes de comenzar a codificar. Luego compara pros y contras. Intenta hacer las cosas más simples y menos complicadas.

Probablemente escriba en palabras simples lo que debería estar sucediendo en lugar de escribir el código.

Por el momento He empezado con la siguiente clase y funciones pero sí que encajan en esta categoría ** **

Su código es bastante básico, así que es difícil para decir mucho al respecto, especialmente porque no sé cuál es tu sitio de arcade (y sobre qué categoría escribes). Todavía es bueno para un ejemplo, probablemente. Lo que se puede ver en tus clases es que integras estrechamente todo con los demás.

Por ejemplo, comienza con la base de datos. Eso es común, porque el DB es un componente central para cualquier aplicación. La aplicación necesita el DB para operar. Sin embargo, desea mantener las cosas juntas para que todos sus comandos puedan ejecutarse con algún otro DB o un nuevo objeto de usuario que esté conectado con algún otro DB más que el resto de los objetos de datos de su aplicación.

$application->getDB(); 

Como el usuario es un tema central en cada aplicación, debe tener una interfaz muy simple. Todos los detalles acerca de la autenticación de gloria, la recuperación de las propiedades de los usuarios, etc., deben ser objeto de delegación en otra clase/componente, para que pueda cambiar la implementación en la que se almacenan los usuarios y cómo se autentican:

/** 
    * @package command.modules.games 
    */ 
function ListGamesCommand(Request $request, Response $response) 
{ 
    $application = $request->getApplication(); 
    $user = $application->getSession()->getUser(); 
    $games = $application->getModels()->build('games'); 
    $games = $games->findByUser($user); 
    $response->setProp('games', $games); 
} 

Como muestra este ejemplo , puede agregar la funcionalidad cuando la necesite. P.ej. siempre que su aplicación no necesite iniciar sesión en usuarios, ¿por qué preocuparse por cómo está escrita ahora?

Crear una fábrica que está produciendo el usuario para el objeto de la aplicación - lo que necesita ahora o en el futuro (ver dos montones de objetos en The Clean Code Talks — Inheritance, Polymorphism, & Testing). Si luego necesita la autenticación, agréguela al objeto de sesión o a la interfaz del objeto del usuario.

La autenticación en sí misma se implementaría en una clase propia de todos modos, el Authenticator. Para que pueda revisar sus interfaces más adelante también, moviendo la invocación de la autenticación de la sesión al usuario o lo que sea. Solo una fracción de sus comandos deberá ocuparse de estas tareas específicas y, como todos los códigos nuevos se someten a pruebas automáticas, ya que desea reescribir y beneficiarse de OOP, se ha asegurado de que todos los lugares estén cubiertos y se vuelvan a factorizar adecuadamente.

Lo mismo es cierto para acceder a las variables de solicitud. Si desea hacer uso de los beneficios de OOP, que está altamente conectado con la indirección (y cada capa de indirección tiene un precio), primero debe hacer que sus clases base operen con datos específicos y no con datos (como globales y superglobales, he visto $_POST en su código de ejemplo).

Así que permitirá a su nuevo código para operar sobre una solicitud y entregar una respuesta (Entrada - Procesamiento - Salida):

$request = new Request($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV); 
$response = new Response; 

Ejemplo tomado de la BankAccount - Sample application used for PHPUnit training

Ahora todo por debajo de este puede operar en un Request y un Response objeto - entrada de proceso y convertirlo en salida. El comando de dominio (sus scripts/comandos que hacen la cosa) ya no necesita preocuparse por extraer entradas de la solicitud HTTP, como usar $_POST o $_GET, pueden tomarlo directamente del Request, o si escribe una clase de comandos propios, esto puede ser aún más personalizado. Y algunos comandos pueden operar en solicitudes y respuestas propias.

El siguiente gran tema es la interfaz de usuario. Usted escribe que deseas:

he decidido tratar de recodificar el sitio desde el principio con las mismas características pero en un formato de programación orientada a objetos.

Ya escribí que tal cosa puede ser infructuosa. Tener un beneficio del código OOP significaría que la próxima vez que cambie su código, aún podrá volver a usar los componentes. Como el software cambia constantemente, esta vez ahora ya es la próxima vez. Entonces, ya quiere reutilizar el código existente. Supongo que una parte de tu código actual es la lógica de salida. Por lo tanto, la lógica de salida existente debe interactuar con los ejemplos Request y Response anteriores.

Apuesto a que te encantan los sitios web. Te encanta hacer que funcionen y se vean geniales. Ha construido su sitio a lo largo de los años e incluso no todo es como usted quisiera, no quiere dejarlo. Por lo tanto, es crucial para su nueva escritura que no destruya todo, pero puede conservar su forma de trabajo desde ahora hasta el futuro (consulte también Preserve a Working Application; last point of the list).

En webapps la vista es una parte tan crucial. Si pierde la vista, su sitio perderá su identidad.Si cambia demasiado, su sitio perderá usuarios que se sienten cómodos con su uso hoy.

Si lo rompe,

  1. va a siquiera se dará cuenta?
  2. ¿Puedes arreglarlo?

Por otra parte usted quiere que su código de aplicación (las características, la funcionalidad) a no ser que fuertemente unido a ella por más tiempo tener un beneficio en volver a escribir el código de. Como desea volver a escribir su solicitud, vamos a echar un vistazo:

 .---------.       .-------------. 
    | website | ---> [interface in ] ---> | application | 
    | user | <--- [interface out] <--- |    | 
    `---------´       `-------------´ 

Como este esquema muestra, para hacer su aplicación más independiente que sea cual sea la interacción se parece a (puede ser un sitio web, una interfaz gráfica de usuario (teléfono inteligente) o la sistema de ticketing), el código de la aplicación debe ser reemplazable. No desea codificar la lógica para obtener juegos de un usuario, por ejemplo, para cada tipo de interfaz de usuario en el nuevo código de la aplicación, pero lo hizo en el código de la aplicación anterior.

Tomando el objeto User como ejemplo aquí. Cómo se autentica y dónde se almacena no debería ser algo que preocupe a su nuevo código de comandos de aplicación. Está ahí solo si el comando lo necesita. No globalmente, pero específicamente si el comando lo solicita.

Mientras que los procedimientos de registro y contraseña perdida son parte de su aplicación existente y continúan existiendo.

Ahora debe juntar el código anterior y el nuevo.

Por lo que probablemente comenzará con una interfaz para solicitudes HTTP y una respuesta HTTP. La vista entra en acción con Interface Out. Usted asigna/pasa todos los datos necesarios para la vista a través de esa interfaz, su aplicación no conoce la vista. No maneja ningún código CSS, Javascript o HTML dentro del código de su nueva aplicación. Eso es solo el azúcar en la parte superior para la producción. Su aplicación también debe interactuar a través de consola/telnet en texto plano o como un servicio XMLRPC remoto, punto final AJAX, lo que sea.

Así que probablemente solo pueda generalizar su código de vista e inyectarle variables. Escribir una capa de vista podría ser tan simple como incluir un archivo PHP. Opera en variables que están disponibles dentro de su alcance. Puede hacer uso de las funciones de "ayuda" (macros de plantilla) que están disponibles en su alcance. Puede hacer uso de ver objetos modelo. Incluso es posible escribir su propio idioma para la vista (lenguaje de plantillas, un lenguaje específico de dominio (DSL)).

Pero esto solo es posible si crea una interfaz que permita que el código de la aplicación lo haga.

Lo que debes hacer ahora es alejar el HTTP/HTML/CSS/JS de tu aplicación a un adaptador propio. Ese adaptador puede formular el comando genérico que se puede pasar a cualquier aplicación a través de la interfaz en.

La aplicación solo se encargará de ejecutar el comando y entregar su respuesta a través de la interfaz . Entonces tiene dos dominios ahora: su aplicación y el sitio web.

Puede comenzar a crear estos dos nuevos dominios y luego ofrecer una interfaz de entrada y salida para su código heredado y otro para su nuevo código.

También tiene "dos" aplicaciones una al lado de la otra. Finalmente están unidos (invisibles en su propio código) con su base de datos, que se ocupa de que los datos de su sitio estén en orden. Y para eso es la base de datos. Separe los datos de su código, para que pueda cambiar su código a lo largo del tiempo.

Además, si desea volver a codificar, dibuje un borde entre el código existente y el nuevo.

¡Buena suerte! Y espero que leer esto te muestre algunas opciones para tu caso específico. También tenga en cuenta que no convierta sus controladores en solo otra fachada de la base de datos. Probablemente obtenga los mejores beneficios (no conozca su mayor problema concreto) mediante el uso de una abstracción de HTTP liviana y una capa de vista solo porque podría ser que su aplicación solo sea para sitios web.

Debido a que en HTTP/PHP:

[Interface In] Plain Text HTTP request 
[Application] Free to go 
[Interface Out] Plain Text HTTP response 

Normalmente sólo necesitan algunas funciones se analiza la entrada y construir la salida.

Además, el hecho de no usar modelos de grasa tiene la ventaja de que accede a sus datos de forma rápida y secuencial, p. si no necesita pasar la salida de una vez (en búfer, un bloque), puede aprovechar el beneficio para transmitir la salida al servidor.

Debería decidir qué partes son importantes para refactorizar para su aplicación, no OOP o no. Al igual que los procedimientos, OOP necesita hacerse bien también. Si hoy tiene problemas al escribir el código de procedimiento, es posible que el código OOP no sea la respuesta a su problema. La necesidad de escribir un mejor código de procedimiento podría ser. Simplemente diciendo, no es fácil refactorizar una aplicación y primero debes identificar el problema real.

  1. Si lo rompes, ¿lo notarás?
  2. Si lo rompes, ¿puedes arreglarlo?

La parte crucial es que puedes notarlo y que tienes todo a mano para solucionarlo.

Obtenga su sitio web bajo prueba, por lo que puede decir si el cambio de código aquí o en realidad está funcionando bien. Ser capaz de rechazar cualquier cambio si sale a la luz no está funcionando (mejor).

Eso hecho puede decidir fácilmente sobre una nueva característica o no. Siempre que no necesite presentar nuevas funciones, no es necesario cambiar nada en la forma en que escribe las características. Y hasta allí, no puedes planificar las nuevas funciones.

Así que mejor piénselo dos veces antes de volver a escribir su aplicación. Como está escrito, esto puede matar el proyecto.


Ver también:How to implement MVC style on my PHP/SQL/HTML/CSS code?­SO Q&A

0

Todos los miembros de la clase de usuario como la mirada ellos pertenecen allí. Es importante separar el código GUI de otro código, pondría displayGames() en algún tipo de clase de GUI.

7

OOP tiene que ver con la identificación de áreas de responsabilidad y la construcción de unidades autónomas de código destinadas a manejar una y solo una de esas áreas. Una regla general es que cada objeto en su sistema debe incorporar un objeto o concepto equivalente en el mundo real, pero eso no siempre es cierto ya que también debe preocuparse por las cosas abstractas que son necesarias para que su sistema funcione (me refiero a abstracto aquí en el sentido de que no representan un elemento de la lógica de negocios, pero todavía se necesitan para que el sistema funcione. No me refiero a las clases abstractas, que es algo completamente distinto).

Por ejemplo, en su sitio de juegos, es probable que tenga que tratar con juegos, usuarios, moderadores, cuentas, comentarios, comentarios, etc. Cada uno de estos debe ser una clase en sí misma, y ​​cada instancia de esa clase debe representar un usuario, juego, comentario, etc. particular.

Pero las clases tienen áreas de responsabilidad, y como se mencionó anteriormente, una clase debe ocuparse de su área de responsabilidad y nada más. Renderizar una página no es responsabilidad de ninguna de las clases de objetos mencionadas anteriormente. Aquí es donde entran las clases que no representan las entidades de su sistema. Probablemente necesitará una clase para una página, una clase para una sesión, una clase para conexiones de bases de datos (aunque PHP ya lo cubrió con PDO) y algunos de los otros módulos DB como mysqli).

Para representar una página, debe usar una instancia de una clase de página. Le pasará una referencia al objeto de usuario conectado, referencias a cualquier objeto del juego que desee que se muestre, y así sucesivamente. Entonces tendrías que renderizar el HTML real. La clase de página no necesita saber nada sobre el funcionamiento interno de los objetos por los que lo pasa, aparte de las API que esos objetos exponen (conocidos en círculos de OOP como el protocolo del objeto, en otras palabras sus métodos y propiedades públicas).Una clase de página (muy básico) podría tener este aspecto:

class Page 
{ 
    private $user = NULL; 
    private $games = array(); 

    public function setUser (User $user) 
    { 
     $this -> user = $user; 
    } 

    public function getUser() 
    { 
     return ($this -> user); 
    } 

    public function addGame (Game $game) 
    { 
     $this -> games [] = $game; 
    } 

    public function getGames() 
    { 
     return ($this -> games); 
    } 

    public function generate() 
    { 
     $user = $this -> getUser(); 
     $games = $this -> getGames(); 

     $pageFile = '/path/to/a/php/script/representing/the/page/markup.php'; 
     require ($pageFile); 
    } 

    public function __construct (User $user, array $games) 
    { 
     $this -> setUser ($user); 
     foreach ($games as $game) 
     { 
      $this -> addGame ($game); 
     } 
    } 
} 

El guión markup.php real probablemente se vería algo como esto:

<html> 
    <head> 
     <title>Games page for <?php echo ($this -> user -> getName()); ?> 
    </head> 
    <body> 
    <p>Hello, <?php echo ($this -> user -> getName()), here are your games.</p> 
    <?php if (count ($this -> games)) { ?> 
    <ul> 
     <?php foreach ($this -> games as $game) { ?> 
     <li><?php echo ($game -> getName()); ?>: your best score is <?php echo ($game -> getHighScore ($this -> user)); ?></li> 
     <?php } ?> 
    </ul> 
    <?php } ?> 
    </body> 
</html> 

Como se habrán dado cuenta, si se utiliza este enfoque entonces los módulos de su aplicación tenderán a caer en una de tres categorías. Su lógica de negocios se opone a usuarios y juegos, su lógica de visualización como el archivo markup.php, y el tercer grupo que sirve como una forma de lógica de cola y coordinación como la clase de página.

Si bien en este caso particular es específico de su sitio, si generalizara este enfoque, entraría en un patrón de diseño conocido como MVC, que significa Modelo, Vista, Controlador (bueno, en realidad está más cerca de un patrón) llamado PAC para presentación, abstracción, controlador, pero casi siempre se llama MVC en la comunidad PHP por alguna razón, así que solo diremos MVC por ahora). Un patrón es una generalización de una clase de problemas con los que los programadores se topan de manera bastante regular que es útil tener un conjunto de herramientas de soluciones prefabricadas.

En el caso de su aplicación de juegos, Usuario y Juego son modelos, Page es un controlador y markup.php es una vista. Si sustituye un script markup.php diferente en este código, puede usarlo para presentar exactamente los mismos datos de una manera completamente diferente, por ejemplo, como un archivo XML. También podría usar los mismos modelos con un controlador diferente para hacer que hagan cosas diferentes. Lo importante a tener en cuenta aquí es que los modelos no deben preocuparse por cómo se usan, de esa forma se pueden usar de diferentes maneras dependiendo de lo que el controlador necesite lograr.

Como MVC es un patrón, ya existen kits de herramientas para crear aplicaciones MVC (aunque en realidad no son MVC;)) en PHP. Estos se llaman marcos. Hay mucho para elegir, como Symfony, CodeIgnitor, Zend Framework, etc. El marco más popular en estos días es Zend, aunque personalmente no soy fanático de él. (Diría que las versiones beta de Zend Framework 2 se ven mucho mejor que la versión actual del framework).

Espero que esto haya sido útil para usted. Sé que OOP puede ser desalentador al principio. Requiere que cambies tu forma de pensar como programador, pero no te preocupes, llegará con suficiente práctica.

+1

+1 Gran comentario sobre MVC en PHP. Siempre me molesta que se haya convertido en el término común ahora donde no se ajusta realmente al paradigma de PHP (ciertamente no en un entorno impulsado por solicitudes). Me pregunto si Zend es el marco más popular: http://www.google.co.uk/trends?q = zend + framework% 2Csymfony – liquorvicar

+0

Estaba basando ese comentario sobre la popularidad en mi experiencia reciente en la búsqueda de un mejor trabajo. Todos parecían querer la experiencia de Zend. :) – GordonM

+0

Bastante justo. Dudo que alguien pueda decir con toda confianza que es definitivamente el marco PHP más popular. Desde donde estoy sentado, Symfony2 parece ser "el indicado", pero luego admitiré que no he profundizado en ZF2. – liquorvicar

0

La publicación de GordonM es una buena idea para comenzar. Sin duda, recomendaría utilizar un marco establecido para comenzar: hacen mucho trabajo pesado por ti y te ayudarán a acostumbrarte a OOP dentro de PHP. Personalmente, si está utilizando PHP5.3 recomendaría Symfomy2 pero eso es puramente una preferencia personal. Lo que también sugeriría es que consigas una copia de the "Gang of Four" book. Es una lectura bastante esencial y, aunque proviene principalmente de un entorno de entorno no orientado a la solicitud, muchos de los patrones siguen siendo relevantes en PHP.

Cuestiones relacionadas