Clases de datos: getters y setters o diferentes métodos de diseño

7

He estado intentando diseñar una interfaz para una clase de datos que estoy escribiendo. Esta clase almacena estilos para caracteres, por ejemplo, si el carácter está en negrita, cursiva o subrayado. Pero también el tamaño de la fuente y la familia de la fuente. Así que tiene diferentes tipos de variables miembro. La forma más fácil de implementar esto sería agregar captadores y definidores para cada variable miembro, pero esto me parece mal. Se siente mucho más lógico (y más OOP) llamar a style.format(BOLD, true) en lugar de style.setBold(true) . Entonces, para usar métodos lógicos en lugar de getters / setters.

Pero me enfrento a dos problemas al implementar estos métodos: Necesitaría una declaración de cambio grande con todas las variables miembro, ya que no se puede acceder a una variable por el contenido de una cadena en C ++. Además, no puede sobrecargar por tipo de devolución, lo que significa que no puede escribir un getter como style.getFormatting(BOLD) (Sé que hay algunos trucos para hacer esto, pero estos no permiten parámetros, que obviamente necesitaría).

Sin embargo, si implementara captadores y definidores, también hay problemas. Tendría que duplicar bastante código porque los estilos también pueden tener estilos primarios, lo que significa que los captadores deben observar no solo las variables miembro de este estilo, sino también las variables de los estilos primarios.

Como no pude averiguar cómo hacer esto, decidí hacer una pregunta hace un par de semanas. Consulte Programación orientada a objetos: captadores / instaladores o nombres lógicos . Pero en esa pregunta no hice hincapié en que sería solo un objeto de datos y que no estoy creando un motor de procesamiento de texto, por lo que una de las personas que respondieron me sugirió que hiciera otra pregunta mientras lo aclaraba (porque solución, el patrón decorador, no es adecuado para mi problema). Por favor, tenga en cuenta que no estoy creando mi propio motor de procesamiento de texto, solo uso estas clases para almacenar datos.

Como todavía no he podido encontrar una solución a este problema, me gustaría volver a hacer esta pregunta: ¿cómo diseñar una clase de estilos como este? ¿Y por qué harías eso?

    
pregunta Frog 09.09.2012 - 14:03

3 respuestas

9

Parte 1

Esta es una buena pregunta de diseño. Usted es correcto en la detección de olor de código en relación con los captadores y setters. En general, indican un problema de diseño que expone los detalles de implementación de su objeto.

Intente pensar en términos de lo que deberían hacer sus objetos: decir, no preguntar:

Su primer problema puede ser que está intentando diseñar "clases de datos". En lugar de preocuparse por los datos (detalles de la implementación), piense en la funcionalidad. De nuevo, ¿qué deben hacer tus objetos? En tu caso, ¿qué quieres hacer con los estilos de personaje? ¿A quién (en cuanto a software) le importan los estilos de personajes? ¿Qué necesitan hacer?

Esperemos que te ayude a empezar. El desarrollo guiado por pruebas ayuda con este tipo de problemas de diseño. Te obliga a pensar en términos de función, no de datos.

Por el contrario, si todo lo que necesita es un contenedor de datos, escriba una clase de estructura de estilo C y vaya a la ciudad. No lo recomendaría, mantenerlo será $ @ #% #.

¡Buena suerte!

Parte 2

Lo que desea es una clase de datos simple: omita a los captadores y definidores por completo o desea crear una abstracción plataforma independiente que coloque una fachada (Patrón de fachada) delante del renderizado y configuración de estilo. Simplemente proporciona una interfaz para establecer estilos y renderizar. La implementación específica de su plataforma hace el trabajo sucio (usando NSTextView en su ejemplo).

El beneficio de la clase de datos simple es que es inicialmente simple de escribir. Su inconveniente es que le será difícil evitar una maraña gigante de afirmaciones if-else. También le faltará un lugar claro para que sea específico de la plataforma la prestación de llamadas que utiliza los estilos. A medida que la complejidad del sistema crece, puede ser más difícil decidir dónde irán los detalles de la implementación.

La fachada es un enfoque más abstracto. Los beneficios son que es más flexible y puede reutilizarse si decide realizar el traslado a otra plataforma. Sus inconvenientes son más tiempo de desarrollo inicial.

La interfaz pública de la fachada le proporcionará lo que necesita para establecer y eliminar estilos, así como para iniciar el procesamiento cuando llegue el momento.

Los detalles de cómo desea configurar los estilos dependen de usted. Use el sistema que se sienta mejor. Simple get ters y set ters o un genérico set y get que usa un diccionario también funciona internamente (vea los aumentos ptree si está usando C ++). Incluso podría tomar todos los estilos (o predeterminados) en el momento de la construcción. Podrías decidir no exponer a los mutadores en ese punto. Tu llamada. Tal vez usted decida que es importante controlar los estilos que admite y usar un sistema de configuración más el de fábrica (podemos agregar más detalles más adelante si eso es importante para usted). De hecho, diferentes implementaciones de la fachada podrían proporcionar diferentes maneras de abordar el problema. Podrías crear un prototipo de unos pocos y elegir qué funciona mejor.

La implementación específica de la plataforma de su abstracción de fachada utilizará el sistema de representación específico de la plataforma ( NSTextView en su caso) y los estilos que ha configurado para realizar las llamadas apropiadas al sistema. Simplemente inyecte las clases específicas de la plataforma en la construcción (inyección de dependencia), implemente su método render() y estará listo para comenzar.

Parte 3

Si el diseño de su sistema lo permite, puede tomar todos los estilos para un elemento en particular en el momento de la construcción. Esto podría permitirle evitar por completo a los captadores y establecedores si elige hacer que su elemento sea inmutable. Tu entonces tendrías una abstracción simple, limpia y posiblemente inmutable frente a tu sistema de estilos de personaje. El estado inmutable generalmente conduce a menos errores pero requiere que usted opere bajo la premisa de que no puede cambiar las cosas sin querer.

Llevando esto un paso más allá, un archivo de configuración puede definir las diferentes configuraciones de estilo que tiene. Una vez más, esto requeriría un conocimiento previo de los estilos que está configurando (similar a la construcción con los estilos anteriores). Indique el tipo de estilo que está buscando, diga "encabezado", puede obtener la configuración de los encabezados que especifique una fuente más grande y en negrita.

Estas son solo algunas ideas que me salen de la cabeza. Sin más recopilación de requisitos y casos de uso, será difícil ser más específico.

Espero que ayude. Buena suerte!

    
respondido por el hiwaylon 09.09.2012 - 15:56
2

Huelo una lista de atribución. Estoy de acuerdo en que debe establecer el formato y obtener el formato, excepto que usaría una lista. Una máscara de bits incluso si sus atributos lo permiten. De lo contrario, simplemente mantenga una matriz de objetos de formateador que utilicen IOC para formatear el campo si es posible. perdoname, no se c ++

Public abstract class IFormatter
{
.   public abstract void FormatText(TextField* fieldToFormat);
}

Public class BoldFormatter : IFormatter
{...}

Public class TextField
{
.   public void AddFormatter(IFormatter* formatterToAdd)
.   {...}

.   public IFormatter[] GetFormatters()
.   {...}

.   public void Render()
.   {
.       foreach(IFormatter formatter in formatters)
.       { formatter.FormatText(this); }
}
    
respondido por el Jimmy Hoffa 10.09.2012 - 23:14
2

Si todo lo que hacen es almacenar datos, ¿por qué molestarse con cualquier tipo de getter y setter? No tiene invariantes que aplicar, ninguna razón lógica para controlar los datos y ninguna razón para procesarlos ni impedir el acceso. La razón de ser de la clase es "almacenar datos". Así que haz que almacene algunos datos y déjalos así.

    
respondido por el DeadMG 10.09.2012 - 23:50

Lea otras preguntas en las etiquetas