¿Por qué se debe evitar la herencia de forma?

9

Recuerdo haber aprendido VB4 y arrastrar un botón a un formulario, hacer doble clic en ese botón y escribir código en el controlador de eventos con el que acababa de ser bendecido mágicamente. Viniendo de QBASIC Me encantó la "V" en "VB", el diseñador visual fue literalmente lo mejor desde el pan rebanado.

Por supuesto, podrías hacer todo eso programáticamente, pero la magia de la "V" era tan atractiva que no podías evitar arrastrar ese botón. Nos animaron a tomar esa ruta.

Pero hace unos años, comencé a aprender sobre C # y el marco .net y me fascinó la forma en que todo lo que creía saber acababa de salir por la ventana. Hay mucha magia en VB6 que se revela completamente en .net: tome los constructores y el InitializeComponentsmétodo, por ejemplo. En este último, encontrará todas las instancias de control que ha arrastrado desde la caja de herramientas, todos los eventos que ha registrado y las propiedades que ha establecido en el diseñador.

Y eso está bien ... supongo. Es solo que siento que no soy "dueño" de lo que está sucediendo, este código que solo puedo modificar a través del diseñador me molesta muchísimo. Cada vez que copia un botón que dice "Ok" de un formulario a otro (a veces junto con su hermano "Cancelar"), en realidad está duplicando el código, y eso es un pecado, ¿no? SECO, no te repitas, dice el Papa .

Dejando de lado las religiones y las escuelas de pensamiento, con toda objetividad, ¿no deberíamos derivar formas de las formas básicas en su lugar, y tener el botón "Ok" (y todos sus amigos) vivir en la forma base? Algo así como FormBasede donde se deriva a DialogFormBase; todas las clases creadas en muy poco tiempo ... escribiendo código. Los botones se crean dependiendo de cómo se instancia la clase (es decir, un argumento enum constructor determina qué botones se crearán), los controles se colocan dentro de una disposición de paneles divididos y paneles de diseño de flujo, inyectados en el formulario comoContentque encaja en el panel de contenido principal. ¿No es esto lo que ASP.net hace con páginas maestras y marcadores de posición de contenido? Derivaría un formulario cuando necesito una nueva "página maestra", pero esta nueva "página maestra" aún se deriva de una clase de formulario base, por lo que las imágenes son consistentes en toda la aplicación.

Para mí, eso es mucho más reutilización de código que cualquier otra cosa que haya hecho con el diseñador en WinForms, y ni siquiera fue difícil, y el código no está abarrotado con un método de 200 líneas sobre el que no tengo control, puedo pon comentarios donde me gusta, un diseñador no los sobrescribirá. Supongo que es solo una cuestión de patrones y arquitectura, que es lo que me trajo a este enlace: el mejor diseño para formularios de Windows que compartirá una funcionalidad común , donde me di cuenta de que estaba en lo cierto, excepto la respuesta allí, sugiere exactamente lo que soy haciendo, pero está aconsejando contra la herencia de formularios debido a consideraciones de diseño. Esa es la parte que no entiendo .debido a consideraciones de estructura de código, especialmente en lo que respecta a la herencia de forma y control, que no veo ninguna razón para evitar, aparte de que rompe el diseñador .

No todos podemos ser flojos, entonces, ¿qué parte me estoy perdiendo?

Mathieu Guindon
fuente
No entiendo. ¿Estás insinuando que no deberíamos usar diseñadores visuales y escribir todo el código GUI a mano?
Eufórico
Pre .NET ¿dónde estaba el código que controlaba todos los objetos arrastrados en el formulario?
JeffO
1
@JeffO a juzgar por el código heredado con el que he tratado, diría que en el formulario, en algún lugar entre SQL en línea ad-hoc y lógica de negocios. El punto es que WinForms es .net; así que si el diseñador está trabajando bien con lo que hoy en día huele a "mal código" y "malos hábitos de codificación" y en realidad se rompe cuando comienza a estructurar las cosas, le digo que deje el diseñador y trate los formularios como lo que son (¡clases!). . y, de todos modos, ¿cómo es la codificación de una capa de interfaz de usuario en C # tan diferente de la codificación de una capa de interfaz de usuario en ExtJS? Es "tedioso" hacer eso en WinForms porque "oye, hay un diseñador". ¿Es tedioso codificar una interfaz de usuario ExtJS?
Mathieu Guindon
Voy a citar a otro usuario: CodeCaster; Un controlador de eventos está destinado a conectar la GUI a la lógica de su negocio. Si tiene un cuadro de texto para ingresar el nombre de un usuario y un botón Agregar, hacer clic en el botón Agregar simplemente debe llamar a _userRepository.AddUser (UsernameTextbox.Text). No desea lógica empresarial en los controladores de eventos. stackoverflow.com/questions/8048196/…
Pieter B
@Pieter, ¿eso no pone una dependencia DAL en su capa de presentación?
Mathieu Guindon el

Respuestas:

9

Me opondré con un paradigma diferente: favorecer la composición sobre la herencia.

Incluso cuando comience a escribir código GUI a mano y use la herencia para compartir comportamientos y visuales entre formularios, encontrará el mismo problema que el diseño normal de OOP. Digamos que tiene DialogForm, que tiene botones Aceptar / Cancelar y GridForm, que tiene cuadrícula. Deriva todos los cuadros de diálogo de DialogForm y todos los formularios con Grid de GridForm. Y luego descubres que quieres forma con ambos. ¿Cómo lo resolverías? Si está utilizando la herencia de formularios, entonces no hay forma de resolverlo. Por otro lado, si está utilizando UserControls, simplemente puede poner GridControl en su formulario y listo. Y aún puede usar el diseñador con UserControls, por lo que no tiene que perder el tiempo escribiendo tedioso código GUI.

Eufórico
fuente
Bueno, el formulario base simplemente tiene un SplitContainer con Panel2 fijo, que contiene un FlowLayoutPanel llamado BottomPanely que aloja los comportamientos comunes Ok / Cancel / Apply / Close; Panel1 contiene un SplitContainer con Panel1 fijo (para alojar etiquetas comunes de "instrucciones", o menús, barras de herramientas, todo lo que está en la parte superior) y Panel2 con un Panel protegido llamado MainContent; cada implementación real decide cómo llenarla. Todo el contenido se puede inyectar en la implementación y sí, este puede ser un control de usuario realizado con el diseñador para ahorrar tiempo, buen punto ... pero ¿qué pasa con el formulario en sí?
Mathieu Guindon el
El problema aquí es la escala. Cuando acepta una solicitud con 10 formularios, tener un formulario común no es gran cosa. Los problemas comienzan cuando tiene una aplicación con docenas o cientos de formularios. Luego, tendrá formas que tienen piezas comunes, pero nunca suficientes para crear una forma base. En su caso, puede suceder que desee usar un diseño diferente o botones diferentes, pero mantenga todo lo demás igual. Y ahí es cuando comienzan los problemas.
Eufórico
2
El 'problema con la escala "no existe si tiene un diseño medio decente. Tenemos un proyecto en el que trabajo con unos cientos de formularios. Utilizamos la herencia de formularios en gran medida para proporcionar coherencia y funcionalidad común, y nunca hemos tenido ningún problema con ella.
Mason Wheeler
2
@MasonWheeler Tuve exactamente experiencia opuesta. Intentamos usar la herencia de formularios en una de nuestras aplicaciones, y cada vez que hicimos un pequeño cambio en los formularios base, todo se descompuso y tuvimos que arreglar manualmente todos los demás formularios. Además, el diseñador se comporta de manera extraña cuando trabaja con forma heredada.
Eufórico
1
@Euphoric: ¿Qué diseñador? Usamos Delphi, y su diseñador funciona bien con formas heredadas. Y de nuevo, no tienes estos problemas si tienes un buen diseño . Si no planea nada, por supuesto, todo será frágil y se romperá cada vez que lo toque, pero eso no es diferente de cualquier otro código.
Mason Wheeler
2

Gran parte de esto está vinculado a la pila de tecnología de elección.

WinForms y WPF pueden ser marcos de trabajo de interfaz de usuario de .NET, pero varían mucho en la forma de lograr el objetivo final. Ciertos paradigmas se mueven bien entre tecnologías, pero otros no, y no deberías intentar forzar un paradigma simplemente porque sientes que está destinado a existir en cada marco. Hay una razón por la que MVVM está orientado a WPF / SL y MVC es un concepto separado en ASP.NET de WebForms, etc. Ciertas tecnologías funcionan mejor con ciertos paradigmas.

Tenga en cuenta que el código generado generalmente debe eliminarse de sus preocupaciones DRY. Si bien es aplicable en algunos casos, la mayoría de las veces se debe ignorar. Los conceptos DRY sin duda deberían seguir siendo un foco fuera de su capa de Presentación, pero en la capa de Presentación, el código generado es a menudo un subproducto del marco en el que está trabajando. Esto no quiere decir que no pueda aplicar los principios DRY en su enfoque, sino que siga siendo cauteloso. ¿Podría crear un formulario base y heredarlo indefinidamente? Si. ¿Podría arrastrar y soltar componentes en un nuevo formulario cada vez que lo necesite? Si. Manténgase enfocado en el objetivo final, evitando posibles defectos, facilitando la refactorización aguas abajo y la escalabilidad mientras trabaja dentro de los límites de la pila de tecnología de elección.

Aaron McIver
fuente
0

Usted puede utilizar la herencia que le proporciona encapsular correctamente sus campos y rellenar en consecuencia. Si estuviera interesado en usar la herencia, mi sugerencia sería tener la forma base y un Modelo correspondiente para esa forma, y ​​para cada derivación derivar tanto la forma como el Modelo.

Una alternativa mucho mejor sería agrupar los controles relacionados en uno o más controles de UserControl. Solo necesita un poco de lógica para poner los datos relevantes en él.

Sam
fuente
0

Estoy totalmente de acuerdo con Mason Wheeler, aunque en tres años tal vez incluso él mismo había cambiado de opinión.

Estoy tratando de buscar alternativas para migrar desde los ejecutables de Delphi a la WEB.

Hasta ahora me decidí por UNIGUI, porque todavía puedo usar la herencia de formularios. Me gustaría que Delphi tuviera Mixins como Dart, ya que me permitiría tener menos antepasados. Pero siento que la gente escribe mucho más código en MVC que con la herencia de formularios visuales, ya que la mayoría de la navegación, llama a las reglas de validación en el módulo de datos (applyupdates), criterios de filtrado sql, buscando en el conjunto de datos del cliente, todo está escrito en 5 quizás 6 Forma antepasados.

Incluso el "Con MVC será más fácil para ti dejar a Delphi en la función" para mí no funciona como argumento, ya que la gente invitó a OOP, todo son clases, propiedades, métodos. Entonces, todo lo que necesito es un traductor. Realmente no pude encontrar ninguna ventaja, tal vez para sitios web que son mucho menos complicados pero cambian en una base diaria.

usuario3145857
fuente