¿Es suficiente distinguir los métodos solo por el nombre del argumento (no el tipo) o es mejor nombrarlo más explícitamente?
Por ejemplo T Find<T>(int id)
vs T FindById<T>(int id)
.
¿Hay alguna buena razón para nombrarlo más explícitamente (es decir, agregar ById
) en lugar de mantener solo el nombre del argumento?
Una razón por la que puedo pensar es cuando las firmas de los métodos son las mismas pero tienen un significado diferente.
FindByFirstName(string name)
y FindByLastName(string name)
T Find<T>(string name)
o(int size)
¿cómo planea resolver los problemas inevitables?ID
objeto opaco y no solo unint
. De ese modo, compruebe en tiempo de compilación que no utiliza una identificación para int o viceversa en alguna parte de su código. Y con eso puedes tenerfind(int value)
yfind(ID id)
.Respuestas:
Claro que hay una buena razón para nombrarlo más explícitamente.
No es principalmente la definición del método la que debe explicarse por sí misma, sino el uso del método . Y mientras
findById(string id)
yfind(string id)
se explican por sí mismos, hay una gran diferencia entrefindById("BOB")
yfind("BOB")
. En el primer caso, usted sabe que el literal aleatorio es, de hecho, un Id. En el último caso, no está seguro: en realidad podría ser un nombre de pila o algo completamente diferente.fuente
findById(id)
vsfind(id)
. Puedes ir en cualquier dirección en esto.double Divide(int numerator, int denominator)
que se utiliza en un método:double murdersPerCapita = Divide(murderCount, citizenCount)
. No puede confiar en dos métodos que usan el mismo nombre de variable, ya que hay muchos casos en los que ese no es el caso (o cuando es el caso, es un mal nombre)Ventajas de FindById () .
A prueba de futuro : si comenzar con
Find(int)
, y luego tener que agregar otros métodos (FindByName(string)
,FindByLegacyId(int)
,FindByCustomerId(int)
,FindByOrderId(int)
, etc), la gente como yo tienden a pasar las edades buscandoFindById(int)
. No es realmente un problema si se puede y va a cambiarFind(int)
a laFindById(int)
vez que se hace necesario - el futuro es a prueba sobre estos si s.Más fácil de leer .
Find
está perfectamente bien si la llamada parecerecord = Find(customerId);
Sin embargo,FindById
es un poco más fácil de leer si lo esrecord = FindById(AFunction());
.La consistencia . Puede aplicar constantemente el patrón
FindByX(int)
/ enFindByY(int)
todas partes, peroFind(int X)
/Find(int Y)
no es posible porque entran en conflicto.Ventajas de Find ()
Find
es simple y directo, y juntooperator[]
con uno de los 2 nombres de funciones más esperados en este contexto. (Algunas alternativas populares que songet
,lookup
ofetch
, dependiendo del contexto).FindById(int id)
, podemos eliminar fácilmente la redundancia cambiándola aFind(int id)
, pero hay una compensación: perdemos algo de claridad.Alternativamente, puede obtener las ventajas de ambos utilizando Ids fuertemente tipados:
Implementación de
Id<>
: Escribiendo valores de ID en C #Los comentarios aquí, así como en el enlace anterior, plantearon múltiples preocupaciones con respecto a las
Id<Customer>
que me gustaría abordar:CustomerId
yOrderID
son diferentes tipos (customerId1 = customerId2;
=> bueno,customerId1 = orderId1;
=> malo), pero su implementación es casi idéntica, por lo que podemos implementarlos con copiar y pegar o con metaprogramación. Si bien hay un valor en una discusión sobre exponer u ocultar lo genérico, la metaprogramación es para qué sirven los genéricos.DoSomething(int customerId, int orderId, int productId)
. Los ID fuertemente tipados también evitan otros problemas, incluido el que se le preguntó a OP.int aVariable
. Es fácil decir que se retiene un IDId<Customer> aVariable
, e incluso podemos decir que es un ID de cliente.String
es solo una envolturabyte[]
. La envoltura, o encapsulación, no está en conflicto con la tipificación fuerte.operator==
yoperator!=
también, si no desea confiar exclusivamente enEquals
:.
fuente
Otra forma de pensar en esto es usar la seguridad de tipo del idioma.
Puede implementar un método como:
Donde FirstName es un objeto simple que envuelve una cadena que contiene el nombre y significa que no puede haber confusión en cuanto a lo que está haciendo el método, ni en los argumentos con los que se llama.
fuente
string name = "Smith"; findById(name);
.que es posible si utiliza tipos generales no descriptos.DWORD
LPCSTR
clones, etc. y piensan "es un int / string / etc.", llega al punto en el que pasas más tiempo apuntalando tus herramientas de las que realmente diseñas el código .int
menudo se suman, multiplican, etc., lo que no tiene sentido para las ID; por lo que me gustaría hacerID
distinto deint
. Esto puede simplificar una API, al reducir lo que podemos hacer dado un valor (por ejemplo, si tenemos unID
, solo funcionaráfind
, no por ejemplo,age
ohighscore
). Por el contrario, si nos encontramos convirtiendo mucho, o escribiendo la misma función / método (pfind
. Ej. ) Para varios tipos, es una señal de que nuestras distinciones son demasiado finasVoy a votar por una declaración explícita como FindByID ... El software debe ser creado para el cambio. Debe estar abierto y cerrado (SÓLIDO). Entonces, la clase está abierta para agregar un método de búsqueda similar como digamos FindByName ... etc.
Pero FindByID está cerrado y su implementación está probada por unidad.
No sugeriré métodos con predicados, esos son buenos a nivel genérico. ¿Qué sucede si en función del campo (ByID) tiene una metodología diferente?
fuente
Me sorprende que nadie sugiera usar un predicado como el siguiente:
Con este enfoque, no solo reduce la superficie de su API, sino que también le da más control al usuario que la usa.
Si eso no es suficiente, siempre puede ampliarlo a sus necesidades.
fuente