language-agnostic - the - strategy pattern uml
Convención de nomenclatura para métodos no virtuales y abstractos. (7)
Con frecuencia me encuentro creando clases que usan este formulario (A):
abstract class Animal {
public void Walk() {
// TODO: do something before walking
// custom logic implemented by each subclass
WalkInternal();
// TODO: do something after walking
}
protected abstract void WalkInternal();
}
class Dog : Animal {
protected override void WalkInternal() {
// TODO: walk with 4 legs
}
}
class Bird : Animal {
protected override void WalkInternal() {
// TODO: walk with 2 legs
}
}
En lugar de esta forma (B):
abstract class Animal {
public abstract void Walk();
}
class Dog : Animal {
public override void Walk() {
// TODO: do something before walking
// custom logic implemented by each subclass
// TODO: walk with 4 legs
// TODO: do something after walking
}
}
class Bird : Animal {
public override void Walk() {
// TODO: do something before walking
// custom logic implemented by each subclass
// TODO: walk with 2 legs
// TODO: do something after walking
}
}
Como puede ver, lo bueno de la forma A es que cada vez que implementa una subclase, no necesita recordar incluir la lógica de inicialización y finalización. Esto es mucho menos propenso a errores que la forma B.
¿Qué es una convención estándar para nombrar estos métodos?
Me gusta nombrar el método público Walk
desde entonces puedo llamar a Dog.Walk()
que se ve mejor que algo como Dog.WalkExternal()
. Sin embargo, no me gusta mi solución de agregar el sufijo "Interno" para el método protegido. Estoy buscando un nombre más estandarizado.
Por cierto, ¿hay un nombre para este patrón de diseño?
Por cierto, ¿hay un nombre para este patrón de diseño?
Su primer ejemplo utiliza aspectos del patrón de Método de plantilla y es similar a lo que Herb Sutter llama el "Idioma de interfaz no virtual":
Buena pregunta. El patrón es válido y lo uso mucho. También estoy de acuerdo en que WalkInternal
no es un nombre ideal.
En este ejemplo creo que no estás enmarcando el problema correctamente.
En lugar de cambiar el nombre del método ''interno'', observe su método público ''externo''. Se llama Walk
, pero tiene fragmentos de código ( //do something before walking
y //do something after walking
) que muestra claramente que contiene algo más que la lógica de "Caminar". Tal vez este método debería llamarse Exercise
o GoToTheShops
, o cualquier nombre de creatividad que se le ocurra que describa lo que está haciendo. Cualquiera que sea el método, definitivamente es un superconjunto de Walking + algunas otras acciones pre / post walking.
Un ejemplo similar que he desarrollado recientemente tenía un método público llamado Complete
y un virtual llamado Save
, por lo que:
- Cada clase necesita ''Completar''
- Diferentes implementaciones tendrían su propio método ''Guardar''
- ''Completar'' también realizaría alguna validación, notificación, etc.
En resumen, el método abstracto debe llamarse Walk
, y en su lugar, debe cambiar el nombre de su método público a algo que describa con mayor precisión el proceso de "hacer algo / Caminar / hacer algo".
edición: si la clase Walk
no agrega ningún valor significativo o lógica a la clase WalkInternal
, entonces me preguntaría si es necesario. Si agrega lógica, debe cambiar su nombre para reflejar su nueva función.
Los métodos son medios para tomar medidas e ir por esa regla. Los nombres de los métodos deben ser frases verbales o verbales. Y son aplicables a los métodos independientemente de donde se declaren. El método es más una pauta que un patrón de diseño :). Si usted es un tipo .Net, entonces recomendaré el libro "Framework Design GuideLines" de Brad Adam y Krzystof Cwalina, que aborda claramente estos problemas.
No estoy seguro si existe una convención de nomenclatura estándar para esto. Además de WalkInternal
, otras alternativas pueden ser DoWalk
o WalkImpl
.
Para un método que proporciona el comportamiento principal de un método de plantilla, uso nombres como WalkOverride
. La clase base lo implementa como un método protected abstract
(se requiere que la clase derivada proporcione la implementación) o como uno protected virtual
vacío / no vacío protected virtual
(la clase derivada puede opcionalmente proporcionar / anular la implementación). Se pueden encontrar ejemplos en los distintos marcos XAML de Microsoft con métodos como MeasureOverride
y ArrangeOverride
. (El patrón de WalkCore que menciona @Jehof se usa allí para nombrar el método de la plantilla en sí).
Para los "eventos" a los que la clase derivada puede responder opcionalmente para sus propios fines (en lugar de definir el comportamiento del método de la plantilla), uso nombres como OnWalking
y OnWalked
. Cada uno de estos se implementa generalmente en la clase base como un método protected virtual
con un cuerpo de método vacío.
Prefiero nombrar mis métodos virtuales o abstractos con el sufijo Core
, para indicar que el método debe contener la lógica central para hacer algo.
Todos los argumentos comprueban y provocan posibles eventos que hago en el método, que llama a los Core-Methods.
abstract class Animal {
public void Walk() {
// TODO: do something before walking
// possible Argument checks and event raising
// custom logic implemented by each subclass
WalkCore();
// TODO: do something after walking
}
protected abstract void WalkCore();
}
class Dog : Animal {
protected override void WalkCore() {
// TODO: walk with 4 legs
}
}
class Bird : Animal {
protected override void WalkCore() {
// TODO: walk with 2 legs
}
}
Creo que no hay una directriz oficial para nombrar esto, y depende de usted. Pero debe ser consistente para todas las clases y métodos virtuales / abstractos que defina.
Las "Pautas de diseño del marco" sugieren utilizar el sufijo Core si sigue el Método de plantilla y desea proporcionar puntos de extensibilidad.
Utilizo la convención de un caso resaltado en mayúsculas para anulaciones abstractas, por lo tanto, Dog._Walk, aunque más que de vez en cuando me pregunto si no había una mejor manera.
Me gusta DoWalk mejor que WalkInternal; es más corto y transmite la idea de que es una anulación rápida y directa. Sin embargo, "hacer" cualquier cosa me frota de la manera equivocada, algo así como el "Mi" objeto. Me gusta mi subrayado seguido de la convención de mayúsculas mejor, todavía.
Buena pregunta de la vida real aunque
Aclamaciones,
Berryl