2010-04-08 14 views
26

frecuencia me encuentro creación de clases que utilizan esta forma (A):convención de nombres para los métodos no virtuales y abstractas

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 del formulario 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 el formulario 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 al Dog.Walk() que se ve mejor que algo así como Dog.WalkExternal(). Sin embargo, no me gusta la solución de agregar el sufijo "Interno" para el método protegido. Estoy buscando un nombre más estandarizado.

Btw, ¿hay algún nombre para este diseño?

+0

Buena pregunta; Yo hago esto todo el tiempo, también. –

+0

@Robert: ¿qué has estado llamando los métodos internos? – Senseful

+0

Impl como en WalkImpl .... No mejor que Internal. –

Respuesta

11

No estoy seguro si hay una convención de nomenclatura estándar para esto. Además de WalkInternal, otras alternativas pueden ser DoWalk o WalkImpl.

+0

Otra alternativa que vi es * MakeWalk * – Leyu

-2

Los métodos son medios de acción y siguiendo esa regla, los nombres de los métodos deben ser verbos o verbos. Y es aplicable a los métodos independientemente de dónde se declaren.Para mí Dog.Walk parece más natural que Dog.WalkInternal. Y sí, nombrar el método es más una pauta que un patrón de diseño :). Si eres un chico de .Net, te recomendaré el libro "Framework Design GuideLines" de Brad Adam y Krzystof Cwalina, que aborda claramente estos problemas.

+1

¿Cómo aborda esto la pregunta específica? Si "WalkInternal" es malo, entonces ¿qué es * bueno *? –

+0

La pregunta no es Dog.Walk() vs Dog.WalkInternal(). Quiero que el método expuesto se denomine "Walk" porque, como dices, parece más natural. La pregunta es cómo llamar a este método interno que maneja la lógica personalizada principal para cada subclase cada vez que se llama al método Walk(). Gracias por la respuesta sin embargo. – Senseful

+0

Como el método interno no es visible para el mundo exterior, puede asignarle un nombre según su preferencia. Lo que he notado en algunos lugares es nombrar el método con la palabra "Ayudante" con el sufijo del nombre del método. En ese caso, su "WalkInternal" "se convertirá en" WalkHelper ". –

10

Btw, ¿hay algún nombre para este diseño?

Su primer ejemplo utiliza aspectos del patrón Template Method y es similar a lo que Herb Sutter llama la "Interfaz de Idioma no virtual":

+0

Este es exactamente el mismo patrón de diseño al que me refería. Para otros interesados, Herb Sutter usa el prefijo "Do" para los métodos internos (por ejemplo, DoWalk() en lugar de WalkInternal()). Y, otra razón por la que recomienda este formulario es para separar las preocupaciones de la interfaz y la implementación. – Senseful

3

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á 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 muestran claramente que contiene algo más que la lógica de 'Caminar'. Tal vez este método se llame Exercise o GoToTheShops, o el 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 + y otras acciones previas y posteriores.

Un ejemplo similar que recientemente he desarrollado tenía un método público llamado Complete, y una virtual llamado Save, de modo que:

  • Cada clase necesaria para 'completo'
  • Diferentes implementaciones tendrían su propio método 'Guardar'
  • 'completa' que también llevan a cabo una validación, notificación, etc

En resumen, el yo abstracto thod debe llamarse Walk, y en su lugar debe cambiar el nombre de su método público a algo que describa con más precisión el proceso 'hacer algo/Walk/do something'.


de edición: Si la clase Walk no añade ningún valor significativo o la lógica de la clase WalkInternal entonces me gustaría cuestionar si es necesario. Si agrega lógica, entonces debe renombrarse para reflejar su nueva función.

8

Prefiero poner nombre a 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 plantean 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 de nomenclatura oficial para esto, y depende de usted. Pero debe ser consistente para todas las clases y métodos virtuales/abstractos que defina.

El "Framework Design Guidelines" sugiere utilizar el sufijo Core si sigue el Método de plantilla y desea proporcionar puntos de extensibilidad.

+0

+1 para referencia de "Framework Design Guidelines". –

2

Uso la convención de mayúsculas y minúsculas para mayúsculas y minúsculas abstractas, así que Dog._Walk, aunque me pregunto más de vez en cuando si no había una forma mejor.

Me gusta más DoWalk que WalkInternal - es más corto & transmite la idea de que es una anulación rápida y directa. "Hacer" cualquier cosa me frota por el camino equivocado, algo así como "Mi" objeto lo hace. Me gusta mi guión bajo seguido de la convención de mayúsculas, mejor aún.

Buena pregunta la vida real, aunque

Cheers,
Berryl

0

Para un método que proporciona un comportamiento principal de un método de la plantilla, lo uso como nombres WalkOverride. La clase base implementa, ya sea como un protected abstract método (clase derivada es requiere para proporcionar aplicación) o un protected virtual uno vacío/no vacío (clase derivada puede opcionalmente proporcionar aplicación/override). Se pueden encontrar ejemplos en los diversos frameworks XAML de Microsoft con métodos tales como MeasureOverride y ArrangeOverride. (El patrón WalkCore @Jehof mentions se usa allí para nombrar el método de la plantilla en sí.)

Por "eventos" a la que la clase derivada puede opcionalmente responden para sus propios fines (en contraposición a la definición de comportamiento del método de la plantilla), utilizo 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.

Cuestiones relacionadas