Esta pregunta es subjetiva, pero tenía curiosidad por saber cómo la mayoría de los programadores abordan esto. El siguiente ejemplo está en pseudo-C #, pero esto también debería aplicarse a Java, C ++ y otros lenguajes OOP.
De todos modos, cuando escribo métodos auxiliares en mis clases, tiendo a declararlos como estáticos y simplemente pasar los campos si el método auxiliar los necesita. Por ejemplo, dado el siguiente código, prefiero usar la Llamada de método n. ° 2 .
class Foo
{
Bar _bar;
public void DoSomethingWithBar()
{
// Method Call #1.
DoSomethingWithBarImpl();
// Method Call #2.
DoSomethingWithBarImpl(_bar);
}
private void DoSomethingWithBarImpl()
{
_bar.DoSomething();
}
private static void DoSomethingWithBarImpl(Bar bar)
{
bar.DoSomething();
}
}
Mi razón para hacerlo es que deja en claro (al menos a mis ojos) que el método auxiliar tiene un posible efecto secundario sobre otros objetos, incluso sin leer su implementación. Me parece que puedo asimilar rápidamente métodos que utilizan esta práctica y, por lo tanto, me ayudan a depurar cosas.
¿Qué prefieres hacer en tu propio código y cuáles son tus razones para hacerlo?
Respuestas:
Esto realmente depende. Si los valores con los que operan sus ayudantes son primitivos, entonces los métodos estáticos son una buena opción, como señaló Péter.
Si ellos son complejos y, a continuación SÓLIDO aplica, más concretamente, el S , el I y el D .
Ejemplo:
Esto sería sobre tu problema. Usted puede hacer que
makeEveryBodyAsHappyAsPossible
un método estático, que se llevará en los parámetros necesarios. Otra opción es:Ahora
OurHouse
no es necesario conocer las complejidades de las reglas de distribución de cookies. Solo debe ser ahora un objeto, que implementa una regla. La implementación se abstrae en un objeto, cuya única responsabilidad es aplicar la regla. Este objeto se puede probar de forma aislada.OurHouse
se puede probar con el uso de un simple simulacro deCookieDistributor
. Y puede decidir fácilmente cambiar las reglas de distribución de cookies.Sin embargo, tenga cuidado de no exagerar. Por ejemplo, tener un sistema complejo de 30 clases actúa como la implementación de
CookieDistributor
, donde cada clase simplemente cumple una pequeña tarea, realmente no tiene sentido. Mi interpretación del SRP es que no solo dicta que cada clase solo puede tener una responsabilidad, sino que una sola clase debe llevar a cabo una sola responsabilidad.En el caso de las primitivas u objetos que usa como primitivas (por ejemplo, objetos que representan puntos en el espacio, matrices o algo), las clases auxiliares estáticas tienen mucho sentido. Si tiene la opción, y realmente tiene sentido, entonces podría considerar agregar un método a la clase que representa los datos, por ejemplo, es sensato
Point
tener unadd
método. De nuevo, no exagere.Entonces, dependiendo de su problema, hay diferentes maneras de solucionarlo.
fuente
Es un lenguaje bien conocido declarar métodos de clases de utilidad
static
, por lo que tales clases nunca necesitan ser instanciadas. Seguir este modismo hace que su código sea más fácil de entender, lo cual es algo bueno.Sin embargo, hay una seria limitación a este enfoque: tales métodos / clases no pueden ser fácilmente burlados (aunque AFAIK al menos para C # hay marcos de trabajo que pueden lograr incluso esto, pero no son comunes y al menos algunos de ellos son comercial). Por lo tanto, si un método auxiliar tiene una dependencia externa (por ejemplo, una base de datos) que hace que, por lo tanto, sus llamantes, sean difíciles de probar, es mejor declararlo como no estático . Esto permite la inyección de dependencia, lo que hace que los llamadores del método sean más fáciles de realizar pruebas unitarias.
Actualizar
Aclaración: lo anterior se refiere a clases de utilidad, que contienen solo métodos auxiliares de bajo nivel y (típicamente) ningún estado. Los métodos auxiliares dentro de las clases con estado sin utilidad son un problema diferente; disculpas por malinterpretar el OP.
En este caso, percibo un olor a código: un método de clase A que opera principalmente en una instancia de clase B puede tener un mejor lugar en la clase B. Pero si decido mantenerlo donde está, prefiero la opción 1, ya que es más simple y fácil de leer.
fuente
Prefiero # 1 (
this->DoSomethingWithBarImpl();
), a menos que, por supuesto, el método auxiliar no necesite acceso a los datos / implementación de la instanciastatic t_image OpenDefaultImage()
.La interfaz pública y la implementación privada y los miembros están separados. los programas serían mucho más difíciles de leer si optara por el n. ° 2. con # 1, siempre tengo los miembros y la instancia disponibles. en comparación con muchas implementaciones basadas en OO, tiendo a usar mucha encapsualización y muy pocos miembros por clase. En cuanto a los efectos secundarios, estoy de acuerdo con eso, a menudo hay una validación de estado que extiende las dependencias (por ejemplo, argumentos que uno tendría que pasar).
# 1 es mucho más simple de leer, mantener y tiene buenos rasgos de rendimiento. por supuesto, habrá casos en los que puede compartir una implementación:
Si el # 2 fuera una buena solución común (por ejemplo, la predeterminada) en una base de código, me preocuparía la estructura del diseño: ¿las clases están haciendo demasiado? ¿No hay suficiente encapsulación o no hay suficiente reutilización? ¿Es el nivel de abstracción lo suficientemente alto?
Por último, # 2 parece redundante si está utilizando lenguajes OO donde se admite la mutación (por ejemplo, un
const
método).fuente