Escribir los nombres, los verbos y los adjetivos es un gran enfoque, pero prefiero pensar en el diseño de la clase como una pregunta qué datos deben ocultarse ?
Imagina que tienes un Query
y un objeto Database
objeto:
El Query
le ayudará a crear y almacenar una consulta -- almacenar, es la clave aquí, ya que una función podría ayudarle a crear una con la misma facilidad. Tal vez usted podría quedarse: Query().select('Country').from_table('User').where('Country == "Brazil"')
. No importa exactamente la sintaxis -- ¡ese es su trabajo! -- la clave es que el objeto te ayude esconder algo , en este caso los datos necesarios para almacenar y dar salida a una consulta. El poder del objeto proviene de la sintaxis de su uso (en este caso un encadenamiento inteligente) y de no necesitar saber lo que almacena para hacerlo funcionar. Si se hace bien, el Query
puede generar consultas para más de una base de datos. Internamente almacenaría un formato específico, pero podría convertir fácilmente a otros formatos cuando la salida (Postgres, MySQL, MongoDB).
Ahora pensemos en la Database
objeto. ¿Qué esconde y almacena esto? Bueno, claramente no puede almacenar todo el contenido de la base de datos, ¡ya que para eso tenemos una base de datos! Entonces, ¿cuál es el objetivo? El objetivo es ocultar el funcionamiento de la base de datos de las personas que utilizan el Database
objeto. Las buenas clases simplificarán el razonamiento al manipular el estado interno. Para ello Database
podría ocultar cómo funcionan las llamadas de red, o las consultas o actualizaciones por lotes, o proporcionar una capa de almacenamiento en caché.
El problema es el siguiente Database
objeto es ENORME. Representa la forma de acceder a una base de datos, por lo que bajo las cubiertas podría hacer cualquier cosa y todo. Claramente, la conexión en red, el almacenamiento en caché y la creación de lotes son bastante difíciles de manejar dependiendo de su sistema, por lo que ocultarlos sería muy útil. Pero, como mucha gente notará, una base de datos es increíblemente compleja, y cuanto más lejos de las llamadas a la base de datos en bruto te encuentres, más difícil es ajustar el rendimiento y entender cómo funcionan las cosas.
Este es el compromiso fundamental de la POO. Si eliges la abstracción correcta, hace que la codificación sea más sencilla (String, Array, Dictionary), si eliges una abstracción demasiado grande (Database, EmailManager, NetworkingManager), puede llegar a ser demasiado compleja para entender realmente cómo funciona, o qué esperar. El objetivo es ocultar la complejidad pero es necesaria una cierta complejidad. Una buena regla general es empezar evitando Manager
y en su lugar crear clases que sean como structs
-- todo lo que hacen es mantener los datos, con algunos métodos de ayuda para crear/manipular los datos para hacer su vida más fácil. Por ejemplo, en el caso de EmailManager
comienzan con una función llamada sendEmail
que toma un Email
objeto. Este es un punto de partida sencillo y el código es muy fácil de entender.
En cuanto a tu ejemplo, piensa en los datos que deben estar juntos para calcular lo que buscas. Si quisieras saber qué distancia recorre un animal, por ejemplo, podrías tener AnimalStep
y AnimalTrip
(colección de AnimalSteps). Ahora que cada Viaje tiene todos los datos de los Pasos, entonces debería ser capaz de averiguar cosas sobre él, quizás AnimalTrip.calculateDistance()
tiene sentido.