Los consejos contradictorios que has leído tienen sentido de alguna manera, pero todos hacen suposiciones (diferentes) o frases ambiguas. Es uno de esos tipos de distinciones que dicen "decir lo mismo con palabras diferentes".
un método solo debe ser estático si no modifica un estado
Tenga en cuenta la ambigüedad de "modificar un estado". El siguiente ejemplo viola esta regla (literalmente), pero conserva el espíritu (figurativo) de la regla:
public static void SetUserNameToBob(User u)
{
u.Name = "Bob";
}
Esto modifica el estado del User
objeto, por lo que, de hecho, "modifica un estado".
Sin embargo, este método no se basa en un estado interno particular para decidir su propio flujo lógico (por ejemplo u.Name = currentlySelectedDefaultName()
, sería una violación ya que el nombre seleccionado es un estado seleccionado). Y creo que eso es lo que significa: no se modifica ningún estado interno .
[un método solo debe ser estático si] su resultado depende solo de los parámetros que se le proporcionan
Mira el artículo anterior, este dice más o menos lo mismo. Lo que significa es que esto:
public static string currentlySelectedDefaultName;
public static void SetUserNameToBob(User u)
{
u.Name = currentlySelectedDefaultName;
}
no debe ser estático, ya que el nombre "actual predeterminado" es un estado y, por lo tanto, no debe ser una variable / método global.
Piense en lo que sucede si se están ejecutando dos subprocesos separados: uno de ellos quiere usar el valor predeterminado "Bob", el otro quiere usar el valor predeterminado "Jim". Terminarán peleando por el valor, lo que puede crear problemas de depuración masiva y comportamiento inesperado.
Sin embargo, si cada hilo tiene su propio DefaultNameSetter
objeto, entonces no pelean por el mismo recurso.
Sin embargo, la respuesta más votada en esta publicación establece que los métodos estáticos deben usarse siempre que sea posible.
Esto es como hacer cumplir una regla al intentar / fallar. ¿ Podemos configurar este método como estático?
- Si
=>
bueno! ¡Déjalo de esa forma!
- No
=>
Esto prueba que el código depende de un valor no estático en algún lugar y, por lo tanto, no debe hacerse estático.
Para citar indirectamente a Jeff Goldblum en Jurassic Park , no debe argumentar la necesidad de hacer algo simplemente demostrando que se puede hacer.
Nuevamente, el enfoque no es necesariamente (o siempre) incorrecto, pero asume ciegamente que los métodos ya están escritos para ser tan independientes del estado como sea lógicamente posible, lo cual simplemente no es el caso.
Incluso si se suscribe a este enfoque metodológico, solo puede aplicarlo cuando un proyecto ya no está en desarrollo. Si el proyecto aún está en desarrollo, los métodos actuales pueden ser marcadores de posición para la implementación futura. Puede ser posible hacer Foo()
estática hoy, pero no mañana, si la lógica dependiente del estado simplemente no se ha implementado todavía.
Muchas de las respuestas en esta publicación dicen que uno debe hacer lo que sea más lógico.
Bueno, no están equivocados; pero, ¿no es solo una pequeña frase de decir "haz lo correcto"? Ese no es un consejo realmente útil, a menos que ya sepa cuándo usar las estadísticas y cuándo evitarlas. Es una trampa 22.
Entonces, ¿cuándo deberías usar estadísticas?
Como habrás notado, no todos están de acuerdo con la regla, o al menos con la forma de formular la regla. Agregaré otro intento aquí, pero tenga en cuenta que esto está creando efectivamente otro estándar :
Mantenlo en mente.
La estática son verdades universales.
Ese es el propósito de un espacio de nombres global: cosas que son correctas en toda la capa de aplicación.
Aquí hay un argumento de pendiente resbaladiza. Algunos ejemplos:
var myConfigKey = ConfigurationManager.AppSettings["myConfigKey"];
Este es un ejemplo muy claro. La configuración de la aplicación implica inherentemente que la configuración es global para la aplicación y, por lo tanto, se garantiza un método statis.
bool datesOverlap = DateHelper.HasOverlap(myDateA_Start, myDateA_End, myDateB_Start, myDateB_End);
Este método es universalmente correcto. No le importa qué fechas estás comparando. Al método no le importa el significado de las fechas. Si son fechas de empleo, fechas de contrato, ... no importa el algoritmo del método.
Tenga en cuenta la similitud semántica entre contextual y de estado . Ambos tipos se refieren a un estado "no universal". Esto demuestra que las diferencias contextuales, por lo tanto , dependen del estado y no son adecuadas para hacerse estáticas.
var newPersonObject = Person.Create();
Esto es una verdad universal. El mismo proceso de creación se utiliza en toda la aplicación.
Sin embargo, esta línea puede volverse borrosa:
var newManager = Person.CreateManager();
var newJanitor = Person.CreateJanitor();
Desde una perspectiva técnica, nada ha cambiado. El administrador (y los conserjes) se crean de la misma manera en toda la aplicación. Sin embargo, esto ha creado sutilmente un estado (gerente / conserje), que lenta pero constantemente resta valor a lo universal que es realmente la verdad.
Se puede hacer? Desde una perspectiva técnica; Sí .
¿Debería hacerse? Es una cuestión de si está discutiendo el principio puro o si tiene en cuenta que se deben hacer compromisos para no luchar sin sentido por la perfección lógica. Entonces diría que si no crea un problema mayor que el que el problema intenta resolver .
A medida que se expanden las opciones (gerentes, conserjes, contadores, vendedores, ...), el problema crece. Para un problema suficientemente grande, es deseable un patrón de fábrica .
Si solo tiene dos opciones y no tiene ninguna razón para sospechar que la lista de opciones crecerá, puede argumentar que los métodos de creación estática son suficientes. Algunos podrían estar en desacuerdo, y también veo su punto. Pero tiendo a ser práctico y no demasiado perfeccionista en mi enfoque.