Pepito, el arquitecto de software que vive en mi cabeza, ha irrumpido en mi pensamiento vociferando - ¡ Esto es insostenible !
Al parecer ha clonado nuestro bonito proyecto y ha encontrado flagrantes fallos de diseño. He tratado de explicarle que tenía muchas ganas de sacar adelante las primeras versiones, que las cosas no salen perfectas a la primera, le he reconocido que hay margen de mejora, y que tengo varias cosas apuntadas en mi libreta para retocar. Él seguía enfurecido. - ¡ No puedes enseñar esto al público, qué van a pensar !
En la eterna pugna entre desarrollador y arquitecto, siempre el arquitecto tiene la razón (¿o no? jjj)
Me encantaría que fueran Uds. mismos queridos lectores quienes me propusieran mejoras y alternativas para la plataforma de test, lamentablemente este blog es de muy reciente creación, y no creo que ello vaya a ocurrir, así que de momento nos arreglaremos Pepito y yo solos. No obstante les animo una y otra vez a participar activamente.
Recuerden que disponen del proyecto completo en GitHub
Enigma Software - ZM LABS
Uso correcto de la herencia y la suplantación de métodos.
Cada uno de los Test que definamos van a constituir una clase, con su lógica particular. Pero hemos definido una clase base para cada uno de los test, que contará con el método Start() y las propiedades Estado y Mensajes.
En el objeto test_object.ExecutionProperties hemos definido una propiedad genérica de tipo Object para asociar la clase asociada al test seleccionado. Sin embargo, estábamos asociando la clase derivada, en este caso test1_multithreading_vs_singlethreading, lo que nos obligaba a usar la cláusula CASE para saber a que tipo de dato corresponde la propiedad.
En lugar de esto, la mejor opción en asociar a la propiedad genérica la clase base a la que hemos llamado test_exec
La asignación de la propiedad genérica queda igual que estaba:
_treeelem.TestObject.execution.OBJ = test_types.GetObject(_test_functions, _type);
..pero modificamos el método GetObject para instanciar un objeto del tipo base test_exec y su correspondiente clase derivada.
public static Object GetObject(test_functions _functions, ZmLabsObjects.enumTestTypes _type) { test_exec res = new test_exec(_functions); switch (_type) { case ZmLabsObjects.enumTestTypes.test1_multithreading_vs_singlethreading: res = new test1_multithreading_vs_singlethreading(_functions); break; } return res; }
Poca diferencia, pero trascendente, ya que a la hora de ejecutar el test ya no necesitamos hacer un SWITCH según el tipo de objeto instanciado como antes, sino que invocamos el método virtual Start() sea cual sea la clase derivada:
public static void HiloNegocio() { var negobject = (test_exec)_testobject.execution.OBJ; negobject.Start(); //switch (_testobject.execution.TestType) //{ // case enumTestTypes.test1_multithreading_vs_singlethreading: // var obj2 = (test1_multithreading_vs_singlethreading)_testobject.execution.OBJ; // obj2.Start(); // break; //} }
Del mismo modo, en la lectura de las propiedades Estado y Mensajes ya no es necesario dicho SWITCH que evaluaba el tipo de test que se estaba ejecutando, sino que leemos las propiedades de la clase base, heredadas por la clase del test específico:
test_exec execObject = (test_exec)_testobject.execution.OBJ; _estadoProceso = execObject.Estado; lstMensajes = execObject.Mensajes.Where(msg => msg.leido == false).ToList(); foreach (var msg in lstMensajes) { execObject.SetMsgLeido(msg.id); } //_testobject.execution.OBJ = execObject; //switch (_testobject.execution.TestType) //{ // case enumTestTypes.test1_multithreading_vs_singlethreading: // var obj2 = (test1_multithreading_vs_singlethreading)_testobject.execution.OBJ; // _estadoProceso = obj2.Estado; // lstMensajes = obj2.Mensajes.Where(msg => msg.leido == false).ToList(); // foreach (var msg in lstMensajes) // { // obj2.SetMsgLeido(msg.id); // } // _testobject.execution.OBJ = (test1_multithreading_vs_singlethreading)obj2; // break; //}
Una de las ventajas de la herencia es la posibilidad de reutilizar métodos genéricos en todas las clases derivadas, y aquí tenemos un ejemplo magnífico. Se trata del método SetMsgLeido. En este momento el método en cuestión se encuentra implementado en la clase derivada test1_multithreading_vs_singlethreading. Ello nos obligaría a repetir esta funcionalidad en cada uno de los test. Ahora por orden de Pepito voy a trasladar el método a la clase base test_exec, de modo que se convertirá en un método reutilizable en todas las clases derivadas test1_, test2_, etc.
Les mostraré pues como han quedado las clases base y derivada:
public class test_exec { public test_types.enumEstadoProceso Estado; public List<test_types.mensajes> Mensajes = new List<test_types.mensajes>(); public test_functions _testobject; public test_exec(test_functions p_testobject) { _testobject = p_testobject; } public virtual void Start() { } public void SetMsgLeido(Guid id) { Mensajes.Where(idx => idx.id == id).First().leido = true; } private void SetMsg(string Msg) { this.Mensajes.Add(new test_types.mensajes() { id = Guid.NewGuid(), mensaje = Msg, leido = false }); } }
public class test1_multithreading_vs_singlethreading : objects.test_exec { public static List<objects.process_control> _lst_process_control = new List<objects.process_control>(); public test1_multithreading_vs_singlethreading(test_functions p_testobject) : base(p_testobject) { } public override void Start() { this.Estado = test_types.enumEstadoProceso.Ejecutando; //-->> cosas this.Estado = test_types.enumEstadoProceso.Finalizado; } #region Cases public TestCases MultithreadingCase(TestCases _test) { //-->> cosas } private static void CalcFibo1(int index) { //-->> cosas } public TestCases SinglethreadingCase(TestCases _test) { //-->> cosas } public TestCases HybridCase(TestCases _test) { //-->> cosas } private static void CalcFibo2(int index) { //-->> cosas } #endregion }
Recuerden amigos dejar cuantos comentarios les parezcan oportunos.
Comentarios
Publicar un comentario