oop architecture code-reuse library-design

oop - Arquitectura de algún código reutilizable



architecture code-reuse (3)

¿Por qué no hacer que el framework invoque tu código personalizable? Entonces su cliente crea un objeto y lo inyecta en el marco. El marco inicializa, llama a setup() etc., y luego llama al código de su cliente. Al finalizar (o incluso después de una excepción lanzada), el marco llama a cleanup() y sale.

Entonces su cliente simplemente implementaría una interfaz como (en Java)

public interface ClientCode { void runClientStuff(); // for the sake of argument }

y el código de marco está configurado con una implementación de esto, y llama a runClientStuff() siempre que sea necesario.

Por lo tanto, no deriva del marco de aplicación, sino que simplemente proporciona una clase conforme a un contrato en particular. Puede configurar la configuración de la aplicación en tiempo de ejecución (por ejemplo, qué clase el cliente proporcionará a la aplicación) ya que no se deriva de la aplicación y, por lo tanto, su dependencia no es estática.

La interfaz anterior puede ampliarse para tener múltiples métodos, y la aplicación puede llamar a los métodos requeridos en diferentes etapas del ciclo de vida (por ejemplo, para proporcionar una configuración / limpieza específica del cliente), pero ese es un ejemplo de desplazamiento de característica :-)

Estoy escribiendo una serie de aplicaciones pequeñas y simples que comparten una estructura común y necesitan hacer algunas de las mismas cosas de la misma manera (por ejemplo, registro, configuración de conexión de base de datos, configuración del entorno) y estoy buscando algunos consejos para estructurar el componentes reutilizables. El código está escrito en un lenguaje fuerte y estáticamente tipado (por ejemplo, Java o C #, he tenido que resolver este problema en ambos). Por el momento tengo esto:

abstract class EmptyApp //this is the reusable bit { //various useful fields: loggers, db connections abstract function body() function run() { //do setup this.body() //do cleanup } } class theApp extends EmptyApp //this is a given app { function body() { //do stuff using some fields from EmptyApp } function main() { theApp app = new theApp() app.run() } }

¿Hay una mejor manera? Tal vez de la siguiente manera? Estoy teniendo problemas para sopesar las concesiones ...

abstract class EmptyApp { //various fields } class ReusableBits { static function doSetup(EmptyApp theApp) static function doCleanup(EmptyApp theApp) } class theApp extends EmptyApp { function main() { ReusableBits.doSetup(this); //do stuff using some fields from EmptyApp ReusableBits.doCleanup(this); } }

Una compensación obvia es que con la opción 2, el ''marco'' no puede envolver la aplicación en un bloque try-catch ...


Recuerde, la herencia es solo una buena opción si todos los objetos que se heredan reutilizan el código duo a sus similitudes. o si desea que las personas que llaman puedan interactuar con ellos en la misma fisión. si lo que acabo de mencionar se aplica a usted, en base a mi experiencia siempre es mejor tener la lógica común en su clase base / abstracta.

así es como volvería a escribir su aplicación de muestra en C #.

abstract class BaseClass { string field1 = "Hello World"; string field2 = "Goodbye World"; public void Start() { Console.WriteLine("Starting."); Setup(); CustomWork(); Cleanup(); } public virtual void Setup() {Console.WriteLine("Doing Base Setup.");} public virtual void Cleanup() {Console.WriteLine("Doing Base Cleanup.");} public abstract void CustomWork(); } class MyClass : BaseClass { public override void CustomWork() {Console.WriteLine("Doing Custome work.");} public override void Cleanup() { Console.WriteLine("Doing Custom Cleanup"); //You can skip the next line if you want to replace the //cleanup code rather than extending it base.Cleanup(); } } void Main() { MyClass worker = new MyClass(); worker.Start(); }


Siempre he favorecido la reutilización a través de la composición (su segunda opción) en lugar de la herencia (su primera opción).

La herencia solo debe usarse cuando existe una relación entre las clases en lugar de la reutilización del código.

Entonces, para su ejemplo, tendría varias clases de ReusableBits cada una haciendo 1 cosa que cada aplicación haga uso de / cuando sea necesario.

Esto permite que cada aplicación reutilice las partes de su marco que son relevantes para esa aplicación específica sin verse forzado a tomar todo, lo que permite una mayor libertad de las aplicaciones individuales. La reutilización a través de la herencia a veces puede ser muy restrictiva si tiene algunas aplicaciones en el futuro que no encajan exactamente en la estructura que tiene en mente hoy.

También encontrará las pruebas unitarias y el desarrollo impulsado por pruebas mucho más fácil si divide su marco en servicios separados.