A medida que programamos, todos desarrollamos prácticas y patrones que usamos y en los que confiamos. Sin embargo, con el tiempo, a medida que cambia nuestra comprensión, madurez e incluso el uso de la tecnología, nos damos cuenta de que algunas prácticas que alguna vez pensamos que eran excelentes no lo son (o ya no se aplican).
Un ejemplo de una práctica que usé una vez con bastante frecuencia, pero que he cambiado en los últimos años, es el uso del patrón de objetos Singleton .
A través de mi propia experiencia y largos debates con colegas, me he dado cuenta de que los singleton no siempre son deseables ; pueden hacer que las pruebas sean más difíciles (inhibiendo técnicas como burlarse) y pueden crear acoplamientos no deseados entre partes de un sistema. En su lugar, ahora uso fábricas de objetos (generalmente con un contenedor de IoC) que ocultan la naturaleza y la existencia de singletons de partes del sistema que no les importa, o necesitan saber. En cambio, dependen de una fábrica (o localizador de servicios) para obtener acceso a dichos objetos.
Mis preguntas a la comunidad, en un espíritu de superación personal, son:
- ¿Qué patrones o prácticas de programación ha reconsiderado recientemente y ahora trata de evitar?
- ¿Con qué decidiste reemplazarlos?
fuente
Puntos de retorno únicos.
Una vez preferí un único punto de retorno para cada método, porque con eso podía asegurarme de que no se pasara por alto cualquier limpieza necesaria para la rutina.
Desde entonces, me he movido a rutinas mucho más pequeñas, por lo que la probabilidad de pasar por alto la limpieza se reduce y, de hecho, se reduce la necesidad de limpieza, y descubrí que las devoluciones tempranas reducen la complejidad aparente (el nivel de anidamiento) del código. Los artefactos del único punto de retorno (mantener las variables de "resultado" alrededor, mantener las variables de marca, cláusulas condicionales para situaciones que aún no se han hecho) hacen que el código parezca mucho más complejo de lo que realmente es, lo hace más difícil de leer y mantener. Las salidas anticipadas y los métodos más pequeños son el camino a seguir.
fuente
En una palabra, sobreingeniería .
fuente
Notación húngara (tanto formas como sistemas). Solía prefijar todo. strSomeString o txtFoo. Ahora uso someString y textBoxFoo. Es mucho más legible y más fácil para alguien nuevo que venga y recoja. Como beneficio adicional, es trivial mantenerlo consistente: camelCase el control y agregue un nombre útil / descriptivo. El húngaro de formularios tiene el inconveniente de que no siempre es coherente y el húngaro de sistemas no te beneficia mucho. Agrupar todas sus variables juntas no es realmente tan útil, especialmente con los IDE modernos.
fuente
La arquitectura "perfecta"
Se me ocurrió LA arquitectura hace un par de años. Me empujé técnicamente tanto como pude para que hubiera capas 100% sueltas, uso extensivo de delegados y objetos livianos. Fue un paraíso técnico.
Y fue una mierda. La pureza técnica de la arquitectura solo ralentizó a mi equipo de desarrollo con el objetivo de lograr la perfección sobre los resultados y casi logré un completo fracaso.
Ahora tenemos una arquitectura mucho más simple y menos técnicamente perfecta y nuestra tasa de entrega se ha disparado.
fuente
El uso de cafeína. Una vez me mantuvo despierto y en un glorioso humor de programación, donde el código voló de mis dedos con una fluidez febril. Ahora no hace nada, y si no lo tengo me duele la cabeza.
fuente
Comentar el código. Solía pensar que el código era precioso y que no se pueden eliminar esas hermosas gemas que elaboraste. Ahora elimino cualquier código comentado que encuentre a menos que haya un TODO o una NOTA adjunta porque es demasiado peligroso dejarlo. A saber, me he encontrado con clases antiguas con grandes porciones comentadas y realmente me confundió por qué estaban allí: ¿fueron comentados recientemente? ¿Es este un cambio de entorno de desarrollo? ¿Por qué hace este bloqueo no relacionado?
Considere seriamente no comentar el código y simplemente eliminarlo. Si lo necesita, todavía está en control de fuente. YAGNI aunque.
fuente
El uso excesivo / abuso de las directivas #region. Es solo una pequeña cosa, pero en C #, anteriormente usaba directivas #region por todas partes para organizar mis clases. Por ejemplo, agruparía todas las propiedades de la clase en una región.
Ahora miro hacia atrás en el código antiguo y sobre todo me molestan. No creo que realmente aclare las cosas la mayor parte del tiempo y, a veces, simplemente te ralentizan. Así que ahora he cambiado de opinión y siento que las clases bien diseñadas son en su mayoría más limpias sin directivas regionales.
fuente
El desarrollo de la cascada en general, y en específico, la práctica de escribir especificaciones funcionales y de diseño completas y completas que de alguna manera se espera que sean canónicas y luego esperar una implementación de las mismas que sean correctas y aceptables. Lo he visto reemplazado por Scrum, y bueno, digo. El simple hecho es que la naturaleza cambiante de las necesidades y deseos del cliente hace que cualquier especificación fija sea efectivamente inútil; la única forma de abordar el problema de manera realmente adecuada es con un enfoque iterativo. No es que Scrum sea una panacea, por supuesto; Lo he visto mal utilizado y abusado muchas, muchas veces. Pero supera a la cascada.
fuente
Nunca chocar.
Parece una muy buena idea, ¿no? A los usuarios no les gustan los programas que fallan, así que escribamos programas que no fallan, y a los usuarios les debería gustar el programa, ¿verdad? Así es como empecé.
Hoy en día, me inclino más a pensar que si no funciona, no debería fingir que funciona. Falla tan pronto como puedas, con un buen mensaje de error. Si no lo hace, su programa se bloqueará aún más con solo unas pocas instrucciones más tarde, pero con un error de puntero nulo indescriptible que le llevará una hora depurar.
Mi patrón favorito de "no chocar" es este:
Ahora, en lugar de pedirles a sus usuarios que copien / peguen el mensaje de error y enviárselo, tendrá que sumergirse en los registros para tratar de encontrar la entrada del registro. (Y dado que ingresaron una ID de usuario no válida, no habrá entrada de registro).
fuente
null
o la cadena vacía).Pensé que tenía sentido aplicar patrones de diseño cada vez que los reconocía.
Poco sabía que en realidad estaba copiando estilos de lenguajes de programación extranjeros, mientras que el lenguaje con el que estaba trabajando permitía soluciones mucho más elegantes o fáciles.
El uso de varios idiomas (muy) diferentes me abrió los ojos y me hizo darme cuenta de que no tengo que aplicar mal las soluciones de otras personas a problemas que no son míos. Ahora me estremezco cuando veo el patrón de fábrica aplicado en un lenguaje como Ruby.
fuente
Pruebas obsesivas. Solía ser un apasionado defensor del desarrollo de prueba primero. Para algunos proyectos tiene mucho sentido, pero me he dado cuenta de que no solo es inviable, sino que es perjudicial para muchos proyectos adherirse servilmente a la doctrina de escribir pruebas unitarias para cada pieza de funcionalidad.
Realmente, adherirse servilmente a cualquier cosa puede ser perjudicial.
fuente
Esto es algo pequeño, pero: preocuparse por dónde van las llaves (¿en la misma línea o en la siguiente?), Longitudes máximas de código sugeridas, convenciones de nomenclatura para variables y otros elementos de estilo. Descubrí que todo el mundo parece preocuparse más por esto que yo, así que me dejo llevar por la corriente de quienquiera que esté trabajando hoy en día.
Editar: La excepción a esto es, por supuesto, cuando soy el que más se preocupa (o el que está en condiciones de establecer el estilo para un grupo). En ese caso, ¡hago lo que quiero!
(Tenga en cuenta que esto no es lo mismo que no tener un estilo coherente. Creo que un estilo coherente en una base de código es muy importante para la legibilidad).
fuente
Quizás la "práctica de programación" más importante sobre la que he cambiado de opinión es la idea de que mi código es mejor que el de los demás. Esto es común para los programadores (especialmente los novatos).
fuente
Bibliotecas de utilidades. Solía llevar un ensamblado con una variedad de métodos y clases de ayuda con la teoría de que podría usarlos en otro lugar algún día.
En realidad, acabo de crear un enorme espacio de nombres con muchas funciones mal organizadas.
Ahora, simplemente los dejo en el proyecto en el que los creé. Es muy probable que no los necesite, y si lo hago, siempre puedo refactorizarlos en algo reutilizable más adelante. A veces los marcaré con un // TODO para una posible extracción en un ensamblado común.
fuente
Diseñando más de lo que codifiqué. Después de un tiempo, se convierte en parálisis del análisis.
fuente
El uso de un DataSet para realizar la lógica empresarial. Esto vincula demasiado el código a la base de datos, además, el DataSet generalmente se crea a partir de SQL, lo que hace que las cosas sean aún más frágiles. Si el SQL o la base de datos cambia, tiende a filtrarse a todo lo que toca el DataSet.
Realización de cualquier lógica empresarial dentro de un constructor de objetos. Con la herencia y la capacidad de crear constructores sobrecargados tienden a dificultar el mantenimiento.
fuente
Abreviando variable / método / tabla / ... Nombres
Solía hacer esto todo el tiempo, incluso cuando trabajaba en idiomas sin límites obligatorios en la longitud de los nombres (bueno, probablemente eran 255 o algo así). Uno de los efectos secundarios fue una gran cantidad de comentarios esparcidos por todo el código que explican las abreviaturas (no estándar). Y por supuesto, si los nombres se cambiaran por cualquier motivo ...
Ahora prefiero llamar a las cosas como realmente son, con buenos nombres descriptivos. incluyendo abreviaturas estándar solamente. No es necesario incluir comentarios inútiles, y el código es mucho más legible y comprensible.
fuente
Foo(int arg0, String arg1, float arg2)
etcEnvolviendo los componentes de acceso a datos existentes, como la biblioteca empresarial, con una capa personalizada de métodos auxiliares.
fuente
Escuché por primera vez sobre la programación orientada a objetos mientras leía sobre Smalltalk en 1984, pero no tuve acceso a un lenguaje oo hasta que usé el compilador cfront C ++ en 1992. Finalmente pude usar Smalltalk en 1995. Había anticipado ansiosamente oo tecnología y se comprometió con la idea de que salvaría el desarrollo de software.
Ahora, solo veo oo como una técnica que tiene algunas ventajas, pero es solo una herramienta en la caja de herramientas. Hago la mayor parte de mi trabajo en Python y, a menudo, escribo funciones independientes que no son miembros de la clase y, a menudo, recopilo grupos de datos en tuplas o listas donde en el pasado habría creado una clase. Todavía creo clases cuando la estructura de datos es complicada o necesito un comportamiento asociado con los datos, pero tiendo a resistirme.
De hecho, estoy interesado en trabajar un poco en Clojure cuando tenga tiempo, lo que no proporciona facilidades oo, aunque puede usar objetos Java si entiendo correctamente. No estoy listo para decir algo como oo está muerto, pero personalmente no soy el fan que solía ser.
fuente
En C #, se usa
_notation
para miembros privados. Ahora creo que es feo.Luego cambié a
this.notation
para miembros privados, pero descubrí que era inconsistente al usarlo, así que lo dejé también.fuente
this
oMe
(C # y VB.NET respectivamente) al llamar a métodos y propiedades. En mi opinión, hace que mi código sea más fácil de leer y comprender más adelante, especialmente cuando hay cuatro o más objetos dentro de ese ámbito en particular.Dejé de seguir el método de diseño recomendado por la universidad antes de la implementación. Trabajar en un sistema caótico y complejo me ha obligado a cambiar de actitud.
Por supuesto, sigo investigando el código, especialmente cuando estoy a punto de tocar un código que nunca antes había tocado, pero normalmente trato de concentrarme en implementaciones tan pequeñas como sea posible para que algo funcione primero. Este es el objetivo principal. Luego, refina gradualmente la lógica y deja que el diseño aparezca por sí solo. La programación es un proceso iterativo y funciona muy bien con un enfoque ágil y con mucha refactorización.
El código no se verá en absoluto como pensó en un principio. Pasa todo el tiempo :)
fuente
Solía ser un gran aficionado al diseño por contrato. Esto significó poner una gran cantidad de verificación de errores al comienzo de todas mis funciones. Los contratos siguen siendo importantes, desde la perspectiva de la separación de preocupaciones, pero en lugar de intentar hacer cumplir lo que mi código no debería hacer, trato de usar pruebas unitarias para verificar lo que hace.
fuente
Usaría estática en muchos métodos / clases ya que es más conciso. Cuando comencé a escribir exámenes, esa práctica cambió muy rápidamente.
fuente
Excepciones marcadas
Una idea asombrosa en papel: define el contrato claramente, no hay lugar para errores u olvidarse de verificar alguna condición de excepción. Me vendieron cuando me enteré por primera vez.
Por supuesto, resultó ser un desastre en la práctica. Hasta el punto de tener bibliotecas hoy como Spring JDBC, que tiene como una de sus principales características ocultar las excepciones comprobadas heredadas.
fuente
Que todo lo que valía la pena solo estaba codificado en un idioma en particular. En mi caso, creía que C era el mejor lenguaje de todos los tiempos y nunca tuve ninguna razón para codificar nada en ningún otro idioma ... nunca.
Desde entonces, he llegado a apreciar muchos idiomas diferentes y los beneficios / funcionalidad que ofrecen. Si quiero codificar algo pequeño, rápidamente, usaría Python. Si quiero trabajar en un proyecto grande, codificaría en C ++ o C #. Si quiero desarrollar un tumor cerebral, lo codificaría en Perl .
fuente
Cuando necesité hacer un poco de refactorización, pensé que era más rápido y más limpio comenzar de inmediato e implementar el nuevo diseño, arreglando las conexiones hasta que funcionaran. Luego me di cuenta de que es mejor hacer una serie de pequeñas refactorizaciones para avanzar lenta pero confiablemente hacia el nuevo diseño.
fuente
Quizás lo más importante que ha cambiado en mis prácticas de codificación, así como en otras, es la aceptación de clases externas y bibliotecas descargadas de Internet como base para los comportamientos y la funcionalidad de las aplicaciones. En la escuela, en el momento en que asistí a la universidad, nos animaron a descubrir cómo mejorar las cosas a través de nuestro propio código y confiar en el lenguaje para resolver nuestros problemas. Con los avances en todos los aspectos de la interfaz de usuario y el consumo de servicios / datos, esto ya no es una noción realista.
Hay ciertas cosas que nunca cambiarán en un idioma, y tener una biblioteca que envuelve este código en una transacción más simple y en menos líneas de código que tengo que escribir es una bendición. La conexión a una base de datos siempre será la misma. La selección de un elemento dentro del DOM no cambiará. El envío de un correo electrónico a través de un script del lado del servidor nunca cambiará. Tener que escribir esto una y otra vez es una pérdida de tiempo que podría estar usando para mejorar mi lógica central en la aplicación.
fuente
Inicializando todos los miembros de la clase.
Solía inicializar explícitamente cada miembro de la clase con algo, generalmente NULL. Me he dado cuenta de que esto:
fuente
Al igual que usted, también he adoptado los patrones de IoC para reducir el acoplamiento entre varios componentes de mis aplicaciones. Facilita mucho el mantenimiento y el intercambio de piezas, siempre que pueda mantener cada componente lo más independiente posible. También estoy utilizando más marcos relacionales de objetos como NHibernate para simplificar las tareas de administración de bases de datos.
En pocas palabras, estoy usando marcos "mini" para ayudar a crear software de manera más rápida y eficiente. Estos mini frameworks ahorran mucho tiempo y, si se hacen bien, pueden hacer que una aplicación sea muy simple de mantener en el futuro. ¡Plug 'n Play para ganar!
fuente