Pregunta

Estoy un poco confundido acerca de un párrafo en el libro completo código.

En la sección "Clases para evitar" se lee:

"clases Evita el nombre de verbos Una clase que sólo tiene un comportamiento pero no hay datos en general, no es realmente una clase. Considere convertir una clase como DatabaseInitialization () o StringBuilder () en una rutina en alguna otra clase"

Mi código se compone principalmente de las clases verbales sin datos. Hay invoicereaders, pricecalculators, etc. messagebuilders hago esto para concentrar las clases para cada una de las tareas. Luego agregar dependencias a otras clases de otras funcionalidades.

Si entiendo correctamente el párrafo debería usar un código como

class Webservice : IInvoiceReader, IArticleReader {
    public IList<Invoice> GetInvoices();
    public IList<Article> GetArticles();
}

en lugar de

class InvoiceReader : IInvoiceReader {
    public InvoiceReader(IDataProvider dataProvider);
    public IList<Invoice> GetInvoices();
}

class ArticleReader : IArticleReader {
    public ArticleReader(IDataProvider dataProvider);
    public IList<Article> GetArticles();
}

Editar Gracias por todas las respuestas.

Mi conclusión es que mi código actual es más que SRP OO sino que también sufre de la "modelo de dominio anémico".

Estoy seguro de tesis ideas me ayudarán en el futuro.

¿Fue útil?

Solución

Los nombres de clases como InvoiceReader, PriceCalculator, MessageBuilder, ArticleReader, InvoiceReader no son en realidad verbo nombres. Ellos son realmente los nombres de clase "sustantivo agente sustantivo". Ver sustantivos agente .

Un verbo nombre de la clase sería algo así como Validar, operar, administrar, etc. Obviamente, estas se utilizan mejor como métodos y sería bastante incómodo como nombres de clase.

El mayor problema con los nombres de clase "sustantivo agente sustantivo" es que pueden dar muy poco sentido de lo que realmente hace la clase (por ejemplo UserManager, DataProcessor etc). Como resultado, son más propensos a ser hinchado y perder cohesión interna. (Véase Responsabilidad Individual Principio ).

Por lo tanto la clase WebService con las interfaces IInvoiceReader y IArticleReader es probablemente el diseño más claro y más significativa OO.

Esto le da la simple, nombre de la clase del sustantivo obvia "WebService", junto con "sustantivo agente sustantivo" nombres de interfaz que anuncian claramente lo que la clase WebService puede hacer por las personas que llaman.

Se podría probablemente también dar más sentido a la clase real anteponiendo otro sustantivo, por ejemplo PaymentWebService.

Sin embargo, las interfaces son siempre mejor que una sola clase de nombres a describir más específicamente lo que la clase puede hacer por las personas que llaman. A medida que la clase se hace más compleja, nuevas interfaces también se pueden agregar con nombres significativos.

Otros consejos

Me ignorar esta "regla", en lo personal. El propio .NET Framework está lleno de "verbo" clases: TextReader, BinaryWriter, XmlSerializer, CodeGenerator, StringEnumerator, HttpListener, TraceListener, ConfigurationManager, TypeConverter, RoleProvider ... si usted piensa que el marco está mal diseñado, entonces por todos los medios, no utilice nombres como estos.

intención de Steve es comprensible. Si usted se encuentra la creación de clases sobre docenas y docenas sólo para realizar una tarea específica, lo más probable es un signo de una dominio anémica modelo, donde los objetos que deben ser capaz de hacer estas cosas por sí mismos no lo son. Pero en algún punto hay que hacer una elección entre programación orientada a objetos "puro" y el SRP .

Mi sugerencia sería la siguiente: Si usted se encuentra la creación de un "verbo" clase que actúa sobre una sola clase "sustantivo", piensan honestamente acerca de si es o no la clase "nombre" puede realizar la acción por sí mismo. Pero no empezar a crear Dios Objetos o subir con sentido / engañosa nombres con el único propósito de evitando la clase verbo.

No siga los consejos a ciegas. Estos son sólo directrices.

Dicho esto, Los sustantivos hacen muy buenos nombres de marcas , siempre y cuando modelar objetos lógicos. Puesto que la clase "Persona" es un modelo para todos los objetos de "persona", que calificó de "Persona" es muy útil, ya que le permite a la razón de esta manera: "Voy a crear a una persona desde la entrada del usuario, pero primero tiene que para validarlo ... "

Tenga en cuenta el uso de la palabra "evitar". No es erradicar o eliminar, o quemar en el infierno si alguna vez se utilicen.

Lo que el autor quiere decir es que si te encuentras con un montón de clases todas con nombres de verbos y todo lo que sucede a hacer es crear estáticamente clases ver estos, llamar a una función y olvidarse de ellos, probablemente no es una señal de que está separar un poco las preocupaciones de clase demasiado.

Sin embargo, hay situación en la creación de clases para implementar una acción es una cosa buena como cuando se tienen diferentes estrategias para la misma acción. Un muy buen ejemplo es IComparer <>. Todo lo que hace es comparar dos cosas, pero hay varias manera de comparar cosas.

Como sugiere el autor, en esos casos, una buena manera de hacerlo es mediante la creación de una interfaz y su aplicación. IComparer <> viene a la mente de nuevo.

Otra situación común es cuando la acción tiene un estado pesado, como la carga de archivos. Podría ser justificados para encapsular el estado en una clase.

En esencia lo que el libro está diciendo es que el diseño orientado a objetos es acerca de cómo extraer los objetos (los nombres) y la identificación de las operaciones (los verbos) que ocurren en y entre esos objetos.

Los sustantivos se convierten en los objetos, los verbos se convierten en los métodos que operan sobre estos objetos.

La idea es que el

  

más cerca de los modelos de programas de la verdadera   problema del mundo, mejor será el programa de   será.

En términos prácticos lo útil con un objeto es que puede representar un estado particular. A continuación, puede tener varias instancias diferentes de esta clase cada uno con un estado diferente para representar algún aspecto del problema.

En el caso de la clase InvoiceReader

  • sólo se le va a crear una instancia
  • el único estado que representa es la de que contiene un dataProvider
  • sólo contiene un método

no hay ninguna ventaja de colocarlo en un objeto.

La declaración Una clase que sólo tiene un comportamiento pero no hay datos en general, no es realmente una clase. es un error normal.

La extracción de comportamiento en una clase separada es una buena cosa común y hacer en la refactorización. Puede tener estado, sino que también no tiene que tener uno. Es necesario tener las interfaces limpias, y ponerlas en práctica de todas formas que encuentre necesario.

Además, las clases sin estado son grandes para los cálculos que necesitas sólo por un corto período de tiempo. Se les crean instancias (o, solicita una fábrica de algún tipo para conseguirlos), hacer los cálculos necesarios, y luego tirarlos a la basura. Puede tener la adecuada "versión" de su comportamiento disponible en cualquier lugar, en cualquier momento.

Por lo general, me parece que las diferentes implementaciones de una interfaz tienen algún estado (juego en el constructor, por ejemplo), pero a veces el tipo de su clase puede determinar su comportamiento completamente.

Por ejemplo:

public interface IExporter
{
    /// <summary>
    /// Transforms the specified export data into a text stream.
    /// </summary>
    /// <param name="exportData">The export data.</param>
    /// <param name="outputFile">The output file.</param>
    void Transform(IExportData exportData, string outputFile);
}

puede ser implementado como

class TabDelimitedExporter : IExporter { ... }
class CsvExporter : IExporter { ... }
class ExcelExporter : IExporter { ... }

Para llevar a cabo la exportación desde IExportData (cualquiera que sea) a un archivo CSV, es probable que no necesita ningún estado en absoluto. ExcelExporter, por el contrario, podría tener varias propiedades de opciones de exportación, pero también podría ser sin estado.

[Editar]

Moving GetInvoices y GetArticles en la clase WebService significa que atar su aplicación al tipo de servicio Web. Tenerlos en clases separadas le permitirá tener diferentes implementaciones para ambas facturas y artículos. En general, parece mejor tener separados.

centrarse menos en el nombre. La regla sobre el nombre es sólo un indicador de la regla empírica para una práctica pobre. El punto importante es la siguiente:

  

Una clase que sólo tiene un comportamiento pero no hay datos en general, no es realmente una clase

En su caso, parece como si sus clases tienen tanto los datos como la conducta, y que pueden así ser llamados "Factura" y "artículo".

Depende. Una gran cantidad de clases de existir el nombre de lectura y escritura verbos porque las clases también crean, mantienen y representan una conexión con la fuente de datos que están leyendo o escribiendo a partir. Si sus clases están haciendo eso, es probable que sea mejor para mantenerlos separados.

Si el lector sólo contiene objetos de análisis de la lógica, a continuación, girar las clases en métodos de utilidad es el camino a seguir. Me gustaría ir con un nombre más descriptivo que a pesar de servicio web.

Creo que el libro sugiere un diseño similar a la siguiente:

class Article : IIArticleReader
{
    // Article data...

    public IList<Article> GetArticles(); 
}

Aquí hay una toma clásica de 'verbo vs sustantivo' en OO:

http: // Steve-Yegge .blogspot.com / 2006/03 / ejecución-en-reino-de-nouns.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top