¿Cuándo debe colocar el tipo de datos Clave / Valor en su propia clase en lugar de utilizar una estructura genérica preconstruida, como a KeyValuePair
o a Tuple
?
Por ejemplo, la mayoría de los ComboBoxes que creo contienen un DisplayName y un Value. Este es el tipo de datos que estoy tratando de decidir cuándo incluir una nueva clase y cuándo usar un KeyValuePair.
Actualmente estoy trabajando en algo que usa iCalendar
, y los datos del usuario seleccionado finalmente se combinan en un key1=value1;key2=value2;
tipo de cadena. Comencé colocando los datos en a KeyValuePair<string,string>
, pero ahora me pregunto si esa debería ser su propia clase.
En general, estoy interesado en averiguar qué pautas se utilizan al decidir usar una estructura / clase existente como un objeto KeyValuePair
sobre dos propiedades, y en qué tipo de situaciones usaría una sobre otra.
fuente
tuple
tipo.iCalendar
y quería objetos paraBYDAY
yBYSETPOS
. Aparecen en los cuadros combinados, pero los datos reales se combinan en la cadena de regla recurrente, que es unkey=value;
tipo de cadenaRespuestas:
Por lo general, usaría un objeto en lugar de un KeyValuePair o Tuple en la mayoría de los casos. Primero, cuando vienes 6 meses después para hacer cambios, es mucho más fácil descubrir cuál era tu intención antes que preguntarte qué
Tuple t
es y por qué tiene esos valores divertidos. En segundo lugar, a medida que las cosas crecen y cambian, puede facilitar el comportamiento de sus objetos de transferencia de datos simples según sea necesario. ¿Necesita tener dos formatos de nombre? Fácil, solo agregue las sobrecargas ToString () apropiadas. ¿Lo necesita para implementar alguna interfaz? No hay problema. Finalmente, realmente hay casi cero gastos generales para crear un objeto simple, especialmente con propiedades automáticas y finalización de código.Protip de bonificación: si desea evitar que estos objetos contaminen su espacio de nombres, crear clases privadas dentro de las clases es una excelente manera de mantener las cosas en secreto y evitar dependencias extrañas.
fuente
La regla para definir una nueva clase es simple: se resume en "Navaja de Occam".
http://c2.com/cgi/wiki?OccamsRazor
No introduzca nuevas clases sin una buena razón. O use clases preconstruidas tanto como sea posible. O invente lo menos posible. Sin embargo, te sientes cómodo escribiendo menos código.
No puede usar una clase preconstruida si tiene que asignar una responsabilidad única al objeto y esa responsabilidad no está definida en la clase preconstruida. A menudo este es un método único.
A
tuple
oKeyValuePair
se prefiere.Hasta.
Necesita alguna funcionalidad que no sea parte de A
tuple
oKeyValuePair
. Entonces tienes que definir tu propia clase.fuente
tuple
oKeyValuePair
"? KeyValuePair al menos tiene alguna forma semántica limitada, pero las tuplas rara vez tienen (podría ser posible, según el contexto) imho. Introducir una nueva clase debería darle una semántica clara como algo natural.Si escribe su propia clase, tiene un lugar claro para colocar la documentación sobre cuáles son los dos valores. Sobre todo porque dos cadenas no es una definición muy clara. Sin embargo, podrías escribir algo como
fuente
MyPair
define cuáles son los valores de Tuple y para qué se usan.Item1
yItem2
! ¿No es tan fácil definir toda la clase?public class SideStrings { public string Left { get; set; } public string Right { get; set; } }
S.Lott escribió
Permítanme decir por qué tengo un problema grave con esto. Ya que
parece estar bien ... ¿KeyValue [string, KeyValue [string, KeyValuePair [string, string]]] también está bien? No sé qué dirá S.Lott a esto, pero mi jefe piensa que está bien.
Me atrevo a estar en desacuerdo. Y aquí está el por qué: reduce la legibilidad del código que seguirá. La función que llenará dicha estructura de datos será mucho más compleja y propensa a errores (err .. excepción) (solo imagine al menos algo de lógica comercial también). No discutí demasiado con mi jefe, pero lo diré aquí: la legibilidad supera el ahorro de espacio minuto (que fue su argumento). Entonces, ¿no sería un objeto de clase en el que hay algunos campos; pero algunos permanecen vacíos en algunas ocasiones ¿será mejor?
PD: Soy un Ultra_Noob, así que dime si estoy equivocado.
fuente
KeyValuePair<string,string>
está bien, suponiendo que las cosas puestas sean claves y valores. Aquí, reutilizar una clase existente es una ganancia, ya que guarda el código de escritura y gana interoperabilidad. OTOH, usar algo tan complicado como laKeyValuePair<string,KeyValuePair<string,string>>
mayoría de las veces es simplemente demasiado complicado para ser práctico. A veces puede ser correcto, cuando no necesita funcionalidad adicional, cuando el significado es obvio y cuando funciona bien con otras clases. YMMV, esto es solo ponderar los pros y los contras.Cuando decimos par clave / valor , generalmente pienso en tablas hash , matrices asociativas o simplemente un objeto KeyValuePair . Los uso todos y no hay diferencia en cuándo uso cuáles.
Creo que lo más importante de una lista de pares clave / valor es que las claves deberían ser únicas (ya que es una clave después de todo), y todas las estructuras antes mencionadas realmente me proporcionan esa funcionalidad.
Aparte de eso, quiero buscar por teclas o hacer acciones de estilo de lista (matriz) como push y pop.
Entonces, mi respuesta es NO , y no creo objetos explícitamente para pares clave / valor, ya que muchas estructuras incorporadas ya lo hacen por mí.
fuente
El capítulo seis de Clean Code tiene una buena descripción de cuándo usar una estructura de datos versus una clase. En pocas palabras, utiliza una estructura de datos cuando anticipa agregar nuevas funciones para operar con esos datos. Usas una clase cuando anticipas agregar nuevos tipos de datos para ser operados por las funciones existentes. Su ComboBox es un ejemplo de esto último. Tiene un conjunto de funciones (la implementación de ComboBox) que opera en muchos tipos de datos diferentes (diferentes tipos de datos para diferentes widgets).
fuente
Quizás estaría de acuerdo con Wilding aquí , pero también soy un poco novato en este tipo de cosas.
Sugeriría que los tipos incorporados son a menudo objetos de mecanismo . KeyValuePair, por ejemplo, es parte del mecanismo de un diccionario y tablas hash, lo que ayuda a garantizar claves únicas y tienen propiedades que tienen nombres significativos dentro del contexto del mecanismo en sí.
Por otro lado, el uso de objetos de datos personalizados proporciona una mejor representación de sus datos y proporciona muchos beneficios, incluida la legibilidad y la extensibilidad. No hay nada que deje de reutilizar el código existente en los objetos personalizados creados como Sign sugirió , pero trataría de ocultar la clase envuelta y evitaría la fuga de abstracción , para que pueda cambiar la implementación subyacente en un punto posterior sin afectar el resto de su código .
Entonces, la verdadera pregunta: ¿está representando datos o los está utilizando en un mecanismo? (y no recomendaría mezclar estos conceptos juntos).
En mi experiencia, no hay nada peor que ver pasar una Tuple [cadena, cadena] a un método y no tener una forma inmediata de saber qué se supone que son el Elemento1 y el Elemento2. Es mejor usar Tuples dentro de métodos o como miembros privados de una clase solamente.
fuente