¿Qué "mejores prácticas" populares no siempre son las mejores y por qué? [cerrado]

100

Las "mejores prácticas" están en todas partes en nuestra industria. Una búsqueda en Google sobre "mejores prácticas de codificación" arroja casi 1,5 millones de resultados. La idea parece traer consuelo a muchos; solo sigue las instrucciones y todo saldrá bien.

Cuando leo sobre una práctica recomendada , por ejemplo, acabo de leer varias de Clean Code recientemente, me pongo nervioso. ¿Significa esto que siempre debería usar esta práctica? ¿Hay condiciones adjuntas? ¿Hay situaciones en las que podría no ser una buena práctica? ¿Cómo puedo estar seguro hasta que haya aprendido más sobre el problema?

Varias de las prácticas mencionadas en Clean Code no me sentaron bien, pero honestamente no estoy seguro de si eso es porque son potencialmente malas, o si eso es solo mi prejuicio personal al hablar. Sé que muchas personas prominentes en la industria de la tecnología parecen pensar que no hay mejores prácticas , por lo que al menos mis dudas persistentes me colocan en buena compañía.

La cantidad de mejores prácticas sobre las que he leído son simplemente demasiado numerosas para enumerarlas aquí o hacer preguntas individuales, por lo que me gustaría expresar esto como una pregunta general:

¿Qué prácticas de codificación que se etiquetan popularmente como "mejores prácticas" pueden ser subóptimas o incluso dañinas en ciertas circunstancias? ¿Cuáles son esas circunstancias y por qué hacen que la práctica sea pobre?

Preferiría escuchar sobre ejemplos y experiencias específicos.

Aaronaught
fuente
8
¿Cuáles son las prácticas con las que no estás de acuerdo ?, solo curiosidad.
Sergio Acosta
Cualquiera puede escribir un libro, y no tengo que estar de acuerdo con él, es tan simple como eso.
Trabajo
Una cosa que me gusta del libro "Code Complete" de Steve McConnell es que respalda todos sus consejos con pruebas e investigaciones contundentes. Solo
digo
55
@Walter: Esto ha estado abierto durante meses, definitivamente es constructivo, ¿por qué cerrarlo?
Orbling
2
Al ver cómo se menciona mi nombre aquí, supongo que debería contribuir: creo que las respuestas aquí son valiosas, pero la pregunta podría reformularse en algo definitivamente menos parecido a una encuesta sin invalidar ninguna de las respuestas. Título del ejemplo: "¿Qué 'mejores prácticas' populares a veces pueden ser perjudiciales y cuándo / por qué?"
Aaronaught

Respuestas:

125

Creo que has dado en el clavo con esta declaración

Odiaría tomar las cosas al pie de la letra y no pensar en ellas críticamente

Ignoro casi todas las mejores prácticas cuando no viene con una explicación de por qué existe

Raymond Chen lo pone mejor en este artículo cuando dice

Los buenos consejos tienen una justificación para que pueda saber cuándo se convierten en malos consejos. Si no comprende por qué se debe hacer algo, entonces ha caído en la trampa de la programación de culto de carga, y seguirá haciéndolo incluso cuando ya no sea necesario o incluso se vuelva perjudicial.

Conrad Frix
fuente
44
Cita maravillosa
David Thornley
¡El siguiente párrafo de esa cita de Raymond Chen probablemente describa la notación húngara! La mayoría de las compañías que veo que lo usan no tienen una buena razón para explicarlo.
Craig
3
Sin embargo, espero que la gente no tome esto como una excusa para no buscar cuál es el razonamiento detrás de las mejores prácticas. ;) Desafortunadamente, he visto desarrolladores con esta actitud.
Vetle
3
La justificación es buena. La investigación es mejor.
Jon Purdy
77
Absolutamente cierto, y he dicho lo mismo antes. Quizás el primer estándar en cualquier documento de "Estándares" debería leer, "En el interés de compartir el conocimiento y proporcionar la información necesaria para rescindir los estándares en momentos posteriores, todos los estándares incluirán las razones de su existencia".
Scott Whitlock
95

También podría tirar esto al ring:

Premature optimization is the root of all evil.

No, no es.

La cita completa:

"Deberíamos olvidarnos de las pequeñas eficiencias, digamos alrededor del 97% del tiempo: la optimización prematura es la raíz de todo mal. Sin embargo, no debemos dejar pasar nuestras oportunidades en ese crítico 3%".

Eso significa que aprovecha las mejoras de rendimiento específicas y estratégicas a lo largo de su proceso de diseño. Significa que usa estructuras de datos y algoritmos que son consistentes con los objetivos de rendimiento. Significa que conoce las consideraciones de diseño que afectan el rendimiento. Pero también significa que no optimiza frívolamente al hacerlo, le dará ganancias menores a expensas de la mantenibilidad.

Las aplicaciones deben estar bien diseñadas, para que no se caigan al final cuando aplicas una pequeña carga sobre ellas, y luego terminas reescribiéndolas. El peligro con la cita abreviada es que, con demasiada frecuencia, los desarrolladores lo usan como una excusa para no pensar en el rendimiento hasta el final, cuando podría ser demasiado tarde para hacer algo al respecto. Es mejor desarrollar un buen rendimiento desde el principio, siempre que no se centre en las minucias.

Supongamos que está creando una aplicación en tiempo real en un sistema integrado. Eliges Python como lenguaje de programación, porque "la optimización prematura es la raíz de todo mal". Ahora no tengo nada en contra de Python, pero es un lenguaje interpretado. Si el poder de procesamiento es limitado, y se necesita realizar una cierta cantidad de trabajo en tiempo real o casi en tiempo real, y elige un idioma que requiere más poder de procesamiento para el trabajo que el que tiene, está realmente jodido, porque ahora tiene que comenzar de nuevo con un lenguaje capaz.

Robert Harvey
fuente
44
+1 para los fuertes No, no lo es.
Stephen
21
Pero si ya ha reconocido que una optimización en particular está dentro de ese crítico 3%, ¿es prematuro al optimizarla?
John
77
@Robert: Entonces, ¿cuál es el punto de desacuerdo con la afirmación de que "la optimización prematura es la raíz de todo mal"?
John
8
Nunca es prematuro optimizar el diseño de alto nivel y las decisiones técnicas como la elección del idioma. Sin embargo, a menudo, solo después de haber completado un diseño en su mayoría, las ineficiencias se vuelven aparentes, por lo que Fred Brooks dijo que la mayoría de los equipos escriben una versión desechable, ya sea que tengan la intención o no. Otro argumento para la creación de prototipos.
Dominique McDonnell
8
@Robert, la cita de Knuth se optimizó prematuramente ...
94

Un retorno por función / método.

iMacUwhAK
fuente
77
Iba a poner esto. Me encantan algunas declaraciones de devolución anticipada.
Carson Myers, el
44
¡Absolutamente! Las personas idean un flujo de programa bastante interesante para evitar una returndeclaración temprana . O bien estructuras de control profundamente anidadas o verificaciones continuas. Esto realmente puede hinchar un método cuando if returnrealmente podría simplificar este problema.
snmcdonald
44
Si necesita múltiples retornos en una función (aparte de los guardias), su función probablemente sea demasiado larga.
EricSchaefer
18
No tiene sentido tener una palabra clave de retorno a menos que esté destinada a aparecer en varios lugares. Regrese temprano, regrese a menudo. Solo servirá para simplificar aún más su código. Si las personas pueden entender cómo funcionan las declaraciones de interrupción / continuación, ¿por qué luchan con el retorno?
Evan Plaice
77
Creo que esta es una práctica recomendada muy anticuada. No creo que sea una mejor práctica moderna.
Skilldrick
87

No reinventar la rueda es un dogma muy mal utilizado. Su idea es que si existe una solución adecuada, úsela en lugar de crear la suya; Además de ahorrar esfuerzo, es probable que la solución existente esté mejor implementada (libre de errores, eficiente, probada) de lo que se le ocurriría inicialmente. Hasta aquí todo bien.

El problema es que rara vez existe una solución 100% adecuada. Puede existir una solución adecuada al 80%, y su uso probablemente esté bien. Pero, ¿qué tal un 60% adecuado? 40%? ¿Dónde se traza la línea? Si no dibuja la línea, podría terminar incorporando una biblioteca hinchada a su proyecto porque está utilizando el 10% de sus características, solo porque desea evitar "reinventar la rueda".

Si reinventa la rueda, obtendrá exactamente lo que desea. También aprenderás a hacer ruedas. Aprender haciendo no debe subestimarse. Y al final, una rueda personalizada puede ser mejor que una rueda genérica lista para usar.

revs Joonas Pulakka
fuente
3
Me ha pasado esto al revés. Construí mi propio componente de cuadrícula ajax porque en ese momento no había ninguno que hiciera lo que quería, pero luego lo reemplacé con cuadrículas Ext JS. Me ayudó que supuse desde el principio que la capa de visualización sería reemplazada.
Joeri Sebrechts
20
Convenido. Si nadie reinventara la rueda, todos estaríamos conduciendo nuestros autos con neumáticos de madera.
Aprendiz del Dr. Wily
66
Siempre me siento como tu ejemplo del 10% cuando agrego Boost a un proyecto C ++. Yo siempre necesito menos del 10% de la misma, directamente, pero, por supuesto, las funciones que necesito importar otros módulos que importan otros módulos que ...
Romano Starkov
3
+1: solo esta semana, reinventé la rueda (por ejemplo, reemplacé el complemento jquery hinchado pero popular que usamos por algo que se ajusta a nuestras necesidades pero modular) y resultó en enormes ganancias de rendimiento. Además, hay personas cuyo trabajo es literalmente reinventar la rueda: por ejemplo, Michelin, hacen I + D para mejorar los neumáticos.
wildpeaks
2
@Dr. Wily, esas ruedas no fueron reinventadas, ¡fueron refactorizadas!
78

"Prueba de unidad todo".

He oído decir a menudo que todo el código debe tener pruebas unitarias, un punto con el que no estoy de acuerdo. Cuando tiene una prueba para un método, cualquier cambio en la salida o estructura de ese método debe realizarse dos veces (una vez en el código, una vez en la prueba).

Como tal, las pruebas unitarias deberían ser, en mi opinión, proporcionales a la estabilidad estructural del código. Si estoy escribiendo un sistema en capas de abajo hacia arriba, mi capa de acceso a datos tendrá pruebas del wazoo; mi capa de lógica de negocios estará bastante bien probada, mi capa de presentación tendrá algunas pruebas y mis puntos de vista tendrán poca o ninguna prueba.

Fishtoaster
fuente
77
Sospecho que "Unit Test Everything" se ha convertido en un cliché, como la cita de "optimización prematura". En general, estoy de acuerdo con sus proporciones, y he visto muchos ejemplos de desarrolladores que realizan un esfuerzo monumental para burlarse de un objeto de capa de aplicación, esfuerzo que podría emplearse mejor haciendo pruebas de aceptación.
Robert Harvey
36
Si un cambio en la estructura de un método causa un cambio en sus pruebas, es posible que esté haciendo las pruebas incorrectamente. Las pruebas unitarias no deben verificar la implementación, solo el resultado.
Adam Lear
77
@ Anna Lear: Creo que estaba hablando de hacer cambios de diseño / estructurales (refactorización). Dado que el diseño no es lo suficientemente maduro, cuando encuentre la mejor manera de hacerlo, es posible que deba modificar muchas pruebas en el camino. Estoy de acuerdo en que cuando eres un probador más hábil, puedes notar más fácilmente dónde la prueba sería una mala idea (por esta razón y otras), pero si el diseño no es realmente maduro, lo más probable es que tengas algunas pruebas en el camino.
n1ckp
13
Creo que esta es también la razón por la cual la idea de "hacer la prueba primero" no funciona. Para hacer las pruebas primero debe tener el diseño correcto. Pero tener el diseño correcto requiere que pruebes cosas y veas cómo funcionan para que puedas mejorarlas. Por lo tanto, realmente no puede hacer las pruebas antes de tener el diseño, y obtener el diseño correcto requiere que codifique y vea cómo funciona. A menos que tenga un súper arquitecto realmente, no veo realmente cómo funcionará esa idea.
n1ckp
13
@ n1ck TDD no es en realidad un ejercicio de prueba tanto como es un ejercicio de diseño. La idea es que desarrolle su diseño a través de pruebas (ya que eso expone rápidamente una API razonable para sus cosas) en lugar de ajustar las pruebas a un diseño existente (que puede ser malo / insuficiente). Entonces no, no es necesario tener el diseño correcto para hacer las pruebas primero.
Adam Lear
57

Siempre programe para interfaces.

A veces solo habrá una implementación. Si demoramos el proceso de extracción de una interfaz hasta el momento en que vemos la necesidad, a menudo descubriremos que no es necesario.

Eric Wilson
fuente
44
De acuerdo, usted programa en una interfaz cuando necesita una interfaz (es decir, una API estable para trabajar).
Robert Harvey
45
En mi lectura, esta regla no se trata de interfaces como construcciones de lenguaje. Significa que no debe hacer suposiciones sobre el funcionamiento interno de una clase al llamar a sus métodos, y solo debe confiar en los contratos API.
Zsolt Török
2
Ok, aquí hay una pregunta interesante: soy principalmente un desarrollador de .NET, por lo que para mí mis interfaces se parecen a IBusinessManager o IServiceContract. Para mí, esto es extremadamente fácil de navegar (y generalmente mantengo mis interfaces en otro espacio de nombres [o incluso en otro proyecto]). Cuando utilicé Java, en realidad me pareció confuso (en general, las implementaciones de interfaz que he visto tienen el sufijo .impl, y las interfaces no tienen una delineación). Entonces, ¿podría ser un problema de estándares de código? Por supuesto, las interfaces en Java hacen que el código se vea desordenado: se ven exactamente iguales a las clases normales a primera vista.
Watson
55
@Watson: un costo es que cada vez que presiono F3 ('saltar a la declaración') en una llamada al método en Eclipse, salto a la interfaz, no a la implementación. Luego tengo que controlar-T, flecha hacia abajo, volver para llegar a la implementación. También bloquea algunas refactorizaciones automáticas; por ejemplo, no puede incorporar un método en una definición de interfaz.
Tom Anderson el
44
@Tom: Bueno señor, con mucho gusto lo involucraría en esa guerra, Eclipse vs. Intellij, sin embargo, tengo un código moral excepcional que me impide entrar en confrontaciones físicas con alguien que tiene una discapacidad obvia. AUGE. No estoy diciendo que Eclipse sea malo, estoy diciendo que si los poderes del Eje lo hubieran usado para construir o diseñar sus máquinas de guerra, la Segunda Guerra Mundial ahora se conocería como el "Kerfuffle de dos días". Sin embargo, en serio, descubrí que carece de algo de esmalte que obtengo en IDE disponibles (Intellij / VS + ReSharper). Me he encontrado luchando en más de una ocasión, que es demasiado.
Watson
46

No use nada de código abierto (o que no sea de Microsoft para sus desarrolladores de .NET)

Si Microsoft no lo desarrolló, no lo usamos aquí. Desea utilizar ORM - EF, desea utilizar IOC - Unity, desea iniciar sesión - bloque de aplicaciones de registro empresarial. Existen muchas mejores bibliotecas, pero siempre estoy atrapado ordenando desde el menú en dólares del mundo del desarrollo. Juro que cada vez que escucho las mejores prácticas de Microsoft pienso "Pautas nutricionales de McDonald's". Claro, probablemente vivirás si los sigues, pero también estarás desnutrido y con sobrepeso.

  • Tenga en cuenta que esta podría no ser su mejor práctica, pero es una práctica común en casi todos los lugares donde he trabajado.
Watson
fuente
13
Suena horrible ... = (Probablemente estoy demasiado del otro lado, sin embargo, evito M $ tanto como sea posible.)
Lizzan
Eso no debería ser así. Una biblioteca debe elegirse por su valor, no solo considerando quién la hizo. Por ejemplo, me encanta EF pero tuve una mala experiencia con Enterprise Library y encontré mejores herramientas para la validación y el registro, como FluentValidation, log4net y Elmah.
Matteo Mosca
44
No te despedirán por comprar IBM ^ wMicrosoft
Christopher Mahan
17
También existe la versión de imagen espejo, es decir, nunca use nada de Microsoft ni use nada por lo que tenga que pagar.
Richard Gadsden
55
Tengo la suerte de trabajar en una organización donde este no es un dogma generalizado, pero en los lugares donde hemos adoptado soluciones comerciales, seguro que hay mucho dolor. El problema surge cuando alguna parte de la solución comercial no funciona del todo. Cuando es de código abierto, puede mirar la fuente (La documentación definitiva) y descubrir qué está pasando mal. Con el código cerrado, debe pagar por el privilegio de acceder al conocimiento del soporte técnico que sabe aún menos sobre el producto que usted hace. Y esa es la única "solución" disponible.
SingleNegationElimination
40

Orientación a objetos

Existe la suposición, solo porque el código está "orientado a objetos", es mágicamente bueno. Por lo tanto, la gente sigue exprimiendo la funcionalidad en clases y métodos, solo para estar orientados a objetos.

LennyProgrammers
fuente
77
No me puedo imaginar construir un sistema de software de ningún tamaño significativo sin aprovechar la organización que proporciona la Orientación de Objetos.
Robert Harvey
18
Robert Unix no está orientado a objetos, y ciertamente califica como un sistema de software de tamaño significativo. También parece ser bastante popular (piense en Mac OSX, iPhone, teléfonos Android, etc.)
Christopher Mahan
77
Lo que quise decir es que creo que deberíamos usar la metodología más adecuada. He visto a personas usar métodos y clases donde es engorroso y no tiene mucho sentido, simplemente porque "está orientado a objetos". Eso es culto de carga.
LennyProgrammers
8
No hay bala de plata. La programación funcional (Haskell) es bastante exitosa sin estar orientada a objetos. Al final del día, tiene múltiples herramientas y es su trabajo elegir el mejor surtido para la tarea en cuestión.
Matthieu M.
99
Lo curioso es que, además de usar clases, polimorfismo y similares, la mayoría del código orientado a objetos es, de hecho, un código de procedimiento.
Oliver Weiler
35

Todo el código debe ser comentado.

No, no debería serlo. En algún momento tiene un código obvio, por ejemplo, los establecedores no deben comentarse, hasta que hagan algo especial. Además, ¿por qué debería comentar esto?

/** hey you, if didn't get, it's logger. */
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
Vladimir Ivanov
fuente
13
Todo el código debe ser entendible . Los comentarios son una herramienta importante en eso, pero lejos de ser la única.
Trevel
Absolutamente, el código debe ser comprensible. Pero no hay una sola razón para escribir un comentario que no agregue nada a, por ejemplo, el nombre del método. Si escribes /** sets rank. */ void setRank(int rank) { this.rank = rank; }, supongo que el comentario es estúpido. ¿Por qué está escrito?
Vladimir Ivanov
2
Documentación generada. Para eso es el /** */formato en lugar del /* */formato de comentario. O para .NET sería///
Berin Loritsch
10
El uso de }//end if, }//end for, }//end whileson el mejor ejemplo de despilfarro comentar que me he encontrado. He visto esto muchas veces donde la llave de apertura no está más de 2 líneas arriba. En mi humilde opinión, si necesita estos comentarios, entonces su código necesita re-factorizar ... o necesita pagar $ 20 y comprar un editor IDE / Text que resalte los corchetes coincidentes.
scunliffe
77
El código dice "cómo". Los comentarios deben decir "por qué".
32

Metodologías, particularmente scrum. No puedo mantener una cara seria cuando escucho a los adultos usar la frase "Scrum Master". Me canso tanto de escuchar a los desarrolladores protestar que algún aspecto de la Metodología X no está funcionando para su empresa, solo que Guru So-and-So me dijo que la razón por la que no funciona es que, de hecho, no son verdaderos profesionales de Metodología X. "Scrum más duro, debes, mi alumno Padawan!"

Hay pepitas de sabiduría en las metodologías ágiles, muchas de ellas, pero a menudo están mezcladas con tanto estiércol que no puedo combatir mi reflejo nauseoso. Toma este bit de la página de scrum de Wikipedia :

Una serie de roles se definen en Scrum. Todos los roles se dividen en dos grupos distintos: cerdos y pollos, según la naturaleza de su participación en el proceso de desarrollo.

De Verdad? ¿Cerdos y gallinas, dices? ¡Fascinante! No puedo esperar para lanzar este a mi jefe ...

evadeflow
fuente
Interesante. Estoy de acuerdo hasta cierto punto. Sin embargo, con esa última parte: llámalos como quieras, son mnemotécnicos, eso es todo.
Steven Evers
12
+1 ... tienes razón, es difícil tomar eso en serio. <gran voz en auge> * YO SOY EL SCRUMMASTER * </voice>
GrandmasterB
2
Y las parábolas. Me recuerda a los sermones de la iglesia, o el tipo de anécdotas por las que los gurús de la autoayuda (y los comediantes) son famosos: "Toma a mi amigo Steve. Steve discutía constantemente con su esposa Sheryl. Esos dos lo discutían por horas, para el punto donde su matrimonio estaba en peligro real. Entonces, un día ... "Este tipo de hilos didácticos no me molesta en otras esferas, pero odio verlos proliferar en las ciencias de la ingeniería.
evadeflow
2
¿Qué pasa con los Scrum Ninjas?
Berin Loritsch
1
No estoy de acuerdo con la comparación "Cerdo y pollo" ... vuela directamente frente al Manifiesto Ágil. A saber, "Colaboración del cliente sobre la negociación del contrato". Los clientes tienen tanto interés (si no más) en el éxito del proyecto como el equipo del proyecto. Llamar a algunos roles cerdos y otros roles pollos establece una mentalidad de "nosotros contra ellos" de que, en mi humilde opinión, es el obstáculo más grande para proyectos exitosos.
Michael Brown
25

Mapeo relacional de objetos ... http://en.wikipedia.org/wiki/Object-relational_mapping

No quiero que nunca me abstraigan de mis datos, ni quiero perder ese control y optimización precisos. Mi experiencia con estos sistemas ha sido extremadamente pobre ... Las consultas generadas por estas capas de abstracción son incluso peores que las que he visto en off-shoring.

Fosco
fuente
19
La optimización prematura es la fuente de todos los males. El código lento es, en la vida real, un problema increíblemente raro en comparación con el código que no se puede mantener. Use un ORM, luego corte la abstracción solo donde la necesite.
Fishtoaster
28
Los ORM son una herramienta 80-20. Están destinados a manejar el 80% de CRUD que se vuelve tan agotador para escribir todo ese código de plomería sin fin después de un tiempo. El otro 20% se puede hacer de formas más "convencionales", como usar procedimientos almacenados y escribir consultas SQL ordinarias.
Robert Harvey
18
@Fishtoaster: ¿No quiere decir: "Deberíamos olvidarnos de las pequeñas eficiencias, digamos alrededor del 97% del tiempo: la optimización prematura es la raíz de todo mal. Sin embargo, no debemos dejar pasar nuestras oportunidades en ese crítico 3%"?
Robert Harvey
55
@ Robert Harcey: Hay una razón por la que no utilicé una cita directa. Creo que la mayoría de los programadores se centran demasiado en la eficiencia: es un problema que pocos de ellos realmente necesitan resolver. Es cierto que hay ciertos dominios donde es más importante que otros, pero la capacidad de mantenimiento y la extensibilidad son un problema en todas partes. Otra cita modificada: "Haga que funcione, que sea mantenible, que sea legible, que sea extensible, que sea comprobable, y luego , si tiene tiempo y resulta que lo necesita, hágalo rápido".
Fishtoaster
12
@ Craig: ¿Cómo no reconociste la ironía en tu declaración? Necesitar un año para aprender cómo obtener un buen rendimiento de un ORM es un argumento excelente contra los ORM, como lo es la necesidad de "controlar" el SQL producido e inyectar procedimientos almacenados. Si tiene el conocimiento para eso, tiene el conocimiento para evitar el ORM por completo.
Nicholas Knight el
22

Escribir nombres de funciones como si fueran oraciones en inglés:

Draw_Foo()
Write_Foo()
Create_Foo()

etc. Esto puede verse bien, pero es un dolor cuando estás aprendiendo una API. ¿Cuánto más fácil es buscar un índice para "Todo lo que comienza con Foo"?

Foo_Draw()
Foo_Write()
Foo_Create()

etc.

Colen
fuente
2
Probablemente sea tan fácil como escribir Foo en la lista de funciones de TM.
Josh K
68
Suena como si realmente quisieras que sea Foo.Draw(), Foo.Write()y Foo.Create(), para que puedas hacerlo Foo.methods.sortoFoo.methods.grep([what I seek]).sort
Inaimathi
77
Comenzar con 'Obtener' es otro ejemplo.
JeffO
1
Vengo del mundo objetivo-c, y extraño mucho los nombres de métodos detallados y la notación de infijo cuando hago java (mi otra vida). Desde que la finalización del código comenzó a funcionar, tampoco he encontrado un problema al escribir extra.
2
@ Scott Whitlock: No es que fuera de fecha para algunos desarrolladores .NET, IIRC, VS 2008 no lo hizo. Sin embargo, 2010 sí, y es fantástico.
Steven Evers
22

MVC: a menudo encuentro que el problema de la creación de muchos problemas de diseño web en el enfoque MVC se trata más de hacer feliz un marco (rieles, etc.) que de la simplicidad o la estructura. MVC es un favorito de los "astronautas de la arquitectura" que parecen valorar el andamiaje excesivo sobre la simplicidad. ymmv.

OO basado en clases: en mi opinión, fomenta estructuras complejas de estado mutable. Los únicos casos convincentes que he encontrado para la OO basada en clases a lo largo de los años son los ejemplos curiosos de "forma-> rectángulo-> cuadrado" que forman el capítulo 1 de cualquier libro de OO

Brad Clawsie
fuente
44
He realizado desarrollo web en ASP.NET y ASP.NET MVC y, aunque MVC parece andamiaje, prefiero mucho más que ASP.NET, por muchas razones: simplicidad, facilidad de mantenimiento y control extremadamente fino sobre el marcado. Todo tiene su lugar y, aunque todo parece un poco repetitivo, es un placer mantenerlo. Es completamente personalizable, por lo que si no le gusta un comportamiento fuera de la caja, puede cambiarlo.
Robert Harvey
1
En lo que respecta a OO, hay formas buenas y malas de hacerlo. La herencia está sobrevalorada y se usa con más moderación en el mundo real de lo que la mayoría de los libros te hacen creer; Actualmente existe una tendencia hacia un estilo de desarrollo más funcional e inmutable, incluso en el mundo OO.
Robert Harvey
1
+1 por mencionar MVC. Si bien el concepto de MVC (separar la lógica de la capa de datos, la lógica de presentación y la lógica de fondo es una buena idea) separarlos físicamente en una jerarquía de carpetas compleja con una mezcla de archivos que contienen fragmentos de código es estúpido. Culpo todo este fenómeno a la falta de soporte de espacio de nombres de PHP y a los desarrolladores novatos que glorifican las técnicas de décadas como 'lo más nuevo'. Es simple, cree un espacio de nombres para los accesos a la base de datos, la GUI y la lógica de fondo (y subespacios de nombres donde sea necesario).
Evan Plaice
3
En cuanto a OO, realmente no verá sus beneficios hasta que su proyecto crezca a un tamaño donde la complejidad de gestión se vuelva importante. Siga el principio de responsabilidad única siempre que sea posible y si su código está accesible públicamente (por ejemplo, para un .dll), oculte la implementación interna de clases / métodos / propiedades siempre que sea posible para que el código sea más seguro y simplifique la API.
Evan Plaice
1
Personalmente, considero que el ejemplo de forma-> rectángulo-> cuadrado es uno de los argumentos más elegantes contra oop. por ejemplo, para Square(10).Draw()eso es suficiente Rectangle(10, 10).Draw(). así que supongo que eso significa que el cuadrado es una subclase de rectángulo. Pero no mySquare.setWidthHeight(5,10)tiene sentido (es decir, falla el principio de sustitución de Liskov), un cuadrado no puede tener diferentes alturas y anchos, aunque un rectángulo sí puede, de modo que eso implica que el rectángulo es una subclase de cuadrado. Esto se conoce en otros contextos como el "problema del círculo, elipse"
SingleNegationElimination
22

YAGNI

( No lo vas a necesitar )

Este enfoque me ha costado horas y horas cuando tuve que implementar características en una base de código existente, donde una planificación cuidadosa habría incluido estas características de antemano.

Las ideas mías a menudo han sido rechazadas por YAGNI, y la mayoría de las veces alguien tuvo que pagar por esa decisión más tarde.

(Por supuesto, uno podría argumentar que una base de código bien diseñada también permitiría agregar características más adelante, pero la realidad es diferente)

Sean Patrick Floyd
fuente
15
Estoy de acuerdo con YAGNI, pero veo a qué te refieres. El objetivo de YAGNI es tratar con personas que desean planificar todo desde el principio hasta el más mínimo detalle. Sin embargo, nueve de cada diez veces se usa como una excusa para no usar el código de ingeniero o para saltear por completo la planificación.
Jason Baker el
12
P.Floyd, @Jason Baker: +1 Absolutamente correcto. El viejo dicho se aplica aquí "meses en el laboratorio pueden ahorrar horas en la biblioteca"
Steven Evers
Una especificación a menudo (y en su mayoría debería) dejar la mayor parte de la implementación, y parte de la interfaz abierta. todo lo que no está en la especificación directamente, pero que se requiere para implementar la especificación, ya sea una decisión de implementación, una interfaz visible para el usuario o cualquier otra cosa, también es un requisito indirecto de la especificación. Si una característica no está en la especificación, y no está implícita en la especificación, entonces no la necesita. ¿Cómo puede esto ser confuso?
SingleNegationElimination
1
@TokenMacGuy el aspecto crucial es el implícito en la parte de especificaciones . Ahí es donde las opiniones difieren mucho.
Sean Patrick Floyd
20

Para SQL

  1. No uses disparadores
  2. Ocultar siempre las tablas detrás de las vistas

En orden:

  1. Son una característica que tiene su lugar. ¿Tiene varias rutas de actualización a una tabla o requiere una auditoría del 100%?

  2. ¿Solo porque? Lo haría si estuviera refactorizando para mantener un contrato, pero no cuando he leído que la gente cambia la vista para que coincida con los cambios de la tabla

Editar:

Número 3: Evitar * con EXISTS. Prueba 1/0. Funciona. La lista de columnas no se evalúa según el estándar SQL. Página 191

revs gbn
fuente
3
# 2 es una mejor práctica?
Hogan
1
@Hogan: una vista que simplemente refleja una tabla base no agrega seguridad sobre el uso directo de la tabla base. Si se une a una tabla de usuario de seguridad, o enmascara algunas columnas, entonces es lo suficientemente justo. Pero SELECCIONE cada columna de la tabla o vista: no hay diferencia. Personalmente, de todos modos uso procs almacenados.
gbn 27/10/10
3
@Hogan: Sé algo sobre SQL Server :-) stackoverflow.com/users/27535/gbn Lo que quiero decir es que GRANT SELECT en la tabla no es diferente a GRANT SELECT ON VIEW si la vista es SELECT * FROM TABLE
gbn
1
@gbn: estoy de acuerdo. No hay diferencia allí. Creo que podríamos estar diciendo lo mismo. Supongo que mi comentario original ("¿El # 2 es una práctica recomendada?") Se basó más en mi experiencia personal de que las vistas (como los desencadenantes) se usan con mayor frecuencia de forma incorrecta que se usan correctamente. Por lo tanto, esta mejor práctica solo conduciría al abuso, no a la mejora. Si se considera una práctica recomendada, tiene 100% de razón, es una mala.
Hogan
20

Patrones de diseño en su mayoría. Están sobreutilizados y subutilizados.

Geek
fuente
13
+1 Todavía no veo cómo los Patrones de diseño son soluciones hermosas o elegantes. Son soluciones a las deficiencias del lenguaje, nada más.
Oliver Weiler
2
Solo míralo como un esfuerzo por erradicar el olor del lenguaje usando el lenguaje mismo.
Filip Dupanović
15

El principio de responsabilidad única

("cada clase debe tener una sola responsabilidad; en otras palabras, cada clase debe tener una, y solo una, razón para cambiar")

Estoy en desacuerdo. Creo que un método debería tener una sola razón para cambiar, y todos los métodos en una clase deberían tener una relación lógica entre sí , pero la clase en sí misma podría hacer varias cosas (relacionadas).

En mi experiencia, este principio con demasiada frecuencia se aplica con demasiado entusiasmo, y terminas con muchas clases pequeñas de un método. Ambas tiendas ágiles en las que he trabajado han hecho esto.

¡Imagínese si los creadores de la API .Net hubieran tenido este tipo de mentalidad: en lugar de List.Sort (), List.Reverse (), List.Find () etc., tendríamos las clases ListSorter, ListReverser y ListSearcher!

En lugar de seguir discutiendo en contra del SRP (que en sí mismo no es terrible en teoría) , compartiré algunas de mis experiencias anecdóticas:


En un lugar donde trabajé, escribí un solucionador de flujo máximo muy simple que constaba de cinco clases: un nodo, un gráfico, un creador de gráficos, un solucionador de gráficos y una clase para usar el creador de gráficos / solucionadores para resolver un problema del mundo real Ninguno fue particularmente complejo o largo (el solucionador fue, con mucho, el más largo con ~ 150 líneas). Sin embargo, se decidió que las clases tenían demasiadas "responsabilidades", por lo que mis compañeros de trabajo comenzaron a refactorizar el código. Cuando terminaron, mis 5 clases se habían ampliado a 25 clases, cuyas líneas de código totales eran más del triple de lo que eran originalmente. El flujo del código ya no era obvio, ni el propósito de las nuevas pruebas unitarias; Ahora me resultaba difícil descubrir qué hacía mi propio código.


En el mismo lugar, casi todas las clases tenían un solo método (su única "responsabilidad"). Seguir el flujo dentro del programa era casi imposible, y la mayoría de las pruebas unitarias consistían en probar que esta clase llamaba código de otra clase , cuyo propósito era igualmente un misterio para mí. Había literalmente cientos de clases donde debería haber (IMO) solo docenas. Cada clase hizo solo una "cosa" , pero incluso con convenciones de nomenclatura como "AdminUserCreationAttemptorFactory" , fue difícil distinguir la relación entre las clases.


En otro lugar (que también tenía la mentalidad de clases-debería-tener-solo-un-método ), estábamos tratando de optimizar un método que ocupaba el 95% del tiempo durante una determinada operación. Después (optimistamente) de optimizarlo un poco, volví mi atención hacia por qué se llamaba un millón de veces. Se llamaba en un bucle en una clase ... cuyo método se llamaba en un bucle en otra clase ... que también se llamaba en un bucle ...

En total, hubo cinco niveles de bucles repartidos en 13 clases (en serio). Lo que estaba haciendo cualquier clase en realidad era imposible de determinar con solo mirarlo: había que dibujar un gráfico mental de qué métodos llamaba, y qué métodos llamaban esos métodos, y así sucesivamente. Si todo se hubiera agrupado en un solo método, solo habría tenido unas 70 líneas con nuestro método problemático anidado dentro de cinco niveles de bucles inmediatamente obvios.

Mi solicitud para refactorizar esas 13 clases en una sola clase fue denegada.

BlueRaja - Danny Pflughoeft
fuente
66
Parece que alguien tiene "Fiebre de patrón" o en este caso "Fiebre principal" en ese trabajo. La clase de lista no viola SRP. Todas sus funciones tienen un propósito, manipular una colección de objetos. Tener una sola función en una clase me parece una exageración. El principio detrás de SRP es que una unidad de código (ya sea método, clase o biblioteca) debe tener una única responsabilidad que se pueda establecer de manera sucinta.
Michael Brown
3
He empezado a ver este tipo de locura en personas a las que les resulta imposible escribir código funcional puro. Demasiada educación para que cada problema del mundo pueda resolverse con un libro de patrones. No hay suficiente pensamiento sobre el pragmatismo. Como usted, he visto un código OO basado en clases que es tan horrible que seguirlo es completamente imposible. Y es enorme e hinchado.
rapid_now
3
Segundo comentario aquí. Muchos "principios" se aplican en exceso. Hay muchas cosas que son buenas ideas, donde hacer lo contrario es a veces apropiado. Los buenos programadores saben cuándo rompen las reglas. Debido a que las reglas no son "reglas", son declaraciones de "buenas prácticas la mayor parte del tiempo, excepto cuando es una idea realmente tonta".
rápidamente_ahora
"Imagínese si los creadores de la API .Net hubieran tenido este tipo de mentalidad: en lugar de List.Sort (), List.Reverse (), List.Find () etc., tendríamos las clases ListSorter, ListReverser y ListSearcher ! ". Esto es exactamente lo que se hace en C ++, y es maravilloso . Los algoritmos están separados de las estructuras de datos, por lo que si escribo mi propio contenedor, todos los algoritmos que funcionan con la biblioteca estándar solo funcionan con mi nuevo contenedor. Debe ser horrible en tierra .Net, escribir una nueva función de clasificación para cada nuevo contenedor que desee clasificar.
Mankarse
14

Ahora que mencionó Clean Code, aunque contiene algunas buenas ideas, creo que su obsesión por refactorizar todos los métodos en submétodos y aquellos en submétodos, etc., se lleva demasiado lejos. En lugar de un par de métodos de diez líneas, se supone que prefiere veinte (supuestamente bien nombrados) frases ingeniosas. Obviamente, alguien piensa que está limpio, pero para mí parece mucho peor que la versión original.

Además, reemplazando cosas elementales simples como

0 == memberArray.length

dentro de una clase con una llamada al método propio de la clase, como

isEmpty()

es una cuestionable "mejora" en mi humilde opinión. Adición: La diferencia es que la primera verificación hace exactamente lo que dice: comprueba si la longitud de la matriz es 0. Ok, también isEmpty()puede verificar la longitud de la matriz. Pero también podría implementarse así:

return null != memberArray ? 0 == memberArray.length : true;

Es decir, ¡incluye una verificación nula implícita! Este puede ser un buen comportamiento para un método público: si la matriz es nula, entonces algo está vacío, pero cuando hablamos de elementos internos de clase, esto no es tan bueno. Si bien la encapsulación hacia el exterior es imprescindible, los componentes internos de la clase deben saber exactamente lo que está sucediendo dentro de la clase. No puede encapsular la clase de sí misma . Explícito es mejor que implícito.


Esto no quiere decir que romper métodos largos o comparaciones lógicas involucradas no sea bueno; por supuesto que lo es, pero hasta qué punto hacerlo , donde está el punto dulce, es obviamente una cuestión de gustos. Romper un método largo da como resultado más métodos, y eso no es gratis. Tienes que saltar el código fuente para ver lo que realmente está sucediendo, cuando puedes verlo de un vistazo si todas esas cosas estuvieran en un solo método.

Incluso iría tan lejos como para decir que en algunos casos un método de 1 línea es demasiado corto para merecer ser un método.

revs Joonas Pulakka
fuente
66
Raramente veo esto como un problema. Principalmente es porque generalmente veo demasiado en un solo método, no muy poco. Sin embargo, según algunos estudios, la muy baja complejidad en los métodos también tiene una tasa de error ligeramente mayor que la complejidad moderadamente baja. enerjy.com/blog/?p=198
MIA
Sí, este es definitivamente un problema solo en Clean Code. En la vida real, los métodos tienden a ser demasiado largos, como dijiste. ¡Pero es interesante ver esa curva! De hecho, las cosas deben hacerse lo más simple posible, pero no más simple.
Joonas Pulakka
1
Encuentro su segundo ejemplo eminentemente más legible, y esa forma (o algo similar, como una propiedad de Longitud en la clase en sí) es imprescindible si lo está haciendo público.
Robert Harvey
@Robert Harvey: El segundo ejemplo es un buen método público, pero llamarlo desde la propia clase es cuestionable, porque no sabes exactamente lo que hace antes de ver cómo se implementa. Podría verificar nulo, por ejemplo. Vea mi adición arriba.
Joonas Pulakka
@Joonas: lo suficientemente justo.
Robert Harvey
13

"Sé liberal con los comentarios"

Los comentarios son definitivamente algo bueno, pero demasiados son igual de malos, si no peores que insuficientes. ¿Por qué? Bueno, las personas tienden a ignorar los comentarios si ven demasiados innecesarios. No digo que pueda tener un código perfectamente autodocumentado, pero es preferible un código que necesite comentarios para su explicación.

Jason Baker
fuente
1
El código autodocumentado es definitivamente agradable. Aunque, me gusta tener comentarios al lado de algo como cálculos simples (para expresar cuál es el tipo de retorno o el valor devuelto). Sin embargo, si sus comentarios necesitan más palabras que el código en sí, probablemente sea hora de volver a escribir el código.
sova
66
Tengo que estar de acuerdo con la forma en que Sova lo puso. El código limpio es preferible a los comentarios.
Riwalk
44
¡Aún necesitas el "por qué" que está ahí!
Prefiero tener comentarios que expliquen por qué. Significa que tengo que PENSAR menos en ingeniería inversa la intención del código cuando lo miro.
rápidamente_ahora
12

GoTo Considerado Nocivo

Si está implementando una máquina de estado, una declaración GOTO puede tener más sentido (legibilidad y código eficiente) que un enfoque de "programación estructurada". Realmente preocupaba a algunos compañeros de trabajo cuando el primer código que escribí en un nuevo trabajo incluía no solo una, sino varias declaraciones. Afortunadamente, fueron lo suficientemente inteligentes como para darse cuenta de que en realidad era la mejor solución en este caso particular.

Cualquier "mejor práctica" que no permita excepciones sensatas y documentadas a sus reglas es simplemente aterradora.

MZB
fuente
16
Voy a programar durante nueve años sin una sola declaración goto (incluidas varias máquinas de estado, como mencionaste). Expande tu mente a nuevas ideas.
Riwalk
3
@Mathieu M. - estuvo de acuerdo - mezclar GOTO con declaraciones de control estructuradas no es sensato. (Esto era puro C y no fue un problema.
MZB
1
@ Stargazer2: con un simple FSM, depende de si poner el estado en una variable y usarlo como índice para llamar a un procedimiento (¿no es lo mismo que un GOTO calculado?) Proporciona un código más claro / rápido que usar el contador del programa como el estado FSM. No estoy abogando por esto como la mejor solución en la mayoría de las circunstancias, solo la mejor solución en algunas circunstancias. Expande tu mente a enfoques alternativos.
MZB
55
@MZB, ¿no estaría de acuerdo en que una llamada a la función también es solo un GOTO calculado? Lo mismo ocurre con las construcciones for / while / if / else / switch, entre otras. Los diseñadores de idiomas abstraen los cambios directos en el contador del programa por una razón. No uses goto.
Riwalk
3
La implementación directa de una máquina de estado es probablemente un antipatrón. Hay muchas maneras de tener una máquina de estados sin expresar los estados y las transiciones literalmente. por ejemplo,import re
SingleNegationElimination
12

Los sacrificios que hacemos para que el código sea comprobable

Salto muchos aros para hacer que mi código sea comprobable, pero no pretendo que no lo haría si tuviera la opción. Sin embargo, a menudo escucho a personas presionando la idea de que estas son "mejores prácticas". Estas prácticas incluyen (escrito en el idioma de .Net, pero también se aplica a otros idiomas) :

  • Creando una interfaz para cada clase. Esto duplica el número de clases (archivos) a tratar y duplica el código. Sí, la programación de la interfaz es buena, pero para eso están destinados los especificadores públicos / privados.
  • Cada clase no instanciada al inicio necesita una fábrica. Claramente, new MyClass()es mucho más simple que escribir una fábrica, pero ahora el método que lo crea no se puede probar de forma aislada. Si no fuera por este hecho, solo haría 1/20 del número de clases de fábrica que hago ahora.
  • Haga que cada clase sea pública, lo que anula el propósito de tener especificadores de acceso en las clases. Sin embargo, no se puede acceder a las clases no públicas (y, por lo tanto, probarlas) desde otros proyectos, por lo que la única otra opción es mover todo el código de prueba al mismo proyecto (y así liberarlo con el producto final).
  • Inyección de dependencia. Claramente, al tener que dar a cualquier otra clase, uso un campo y un parámetro constructor es mucho más trabajo que simplemente crearlos cuando los necesito; pero ya no puedo probar esta clase de forma aislada.
  • El principio de responsabilidad única, que me ha causado tantos dolores de cabeza, lo he trasladado a su propia respuesta .

Entonces, ¿qué podríamos hacer para solucionar esto? Necesitaríamos un cambio drástico en la arquitectura del lenguaje:

  • Necesitaríamos la capacidad de burlarnos de las clases
  • Necesitaríamos la capacidad de probar métodos privados de clases internas, desde otro proyecto (esto puede parecer una vulnerabilidad de seguridad, pero no veo un problema si el examinado se ve obligado a nombrar sus clases de probadores) .
  • La inyección de dependencia (o la ubicación del servicio), así como algo equivalente a nuestro patrón de fábrica existente, debería ser una parte central del lenguaje.

En resumen, necesitamos un lenguaje diseñado desde cero con la capacidad de prueba en mente .

BlueRaja - Danny Pflughoeft
fuente
¿Supongo que nunca has oído hablar de TypeMock ? Permite burlas, clases privadas, estadísticas (fábrica), cualquier cosa.
Allon Guralnek
@Allon: Sí, pero está lejos de ser gratuito , por lo que no es una opción para la mayoría de las personas.
BlueRaja - Danny Pflughoeft
Si tiene que escribir muchas clases de fábrica, entonces está haciendo algo mal. Las bibliotecas Smart DI (p. Ej., Autofac para C #) pueden utilizar Func <T>, Lazy <T>, Delegados, etc. para las fábricas, sin escribir ningún boilerplate.
gix
10

Separar aplicaciones en niveles; Capa de datos, capa empresarial, capa de interfaz de usuario

La razón principal por la que no me gusta esto es que la mayoría de los lugares que siguen este método, usan marcos muy frágiles para hacerlo. IE UI Layer está codificada a mano para tratar con objetos de capa empresarial, los objetos de capa empresarial están codificados a mano para tratar con reglas de negocios y bases de datos, la base de datos es SQL y ya es bastante frágil y está administrada por el grupo "DBA" que no le gusta el cambio.

¿Por qué es esto malo? Es probable que la solicitud de mejora más común sea "Necesito un campo en la pantalla X que tenga Y". ¡Explosión! Solo tiene una nueva característica que afecta a cada capa individual, y si separa las capas con diferentes programadores, se convierte en un gran problema que involucra a múltiples personas y grupos, para un cambio muy simple.

Además, no sé cuántas veces he estado en argumentos que van más o menos así. "El campo de nombre está limitado a una longitud máxima de 30, ¿se trata de un problema de capa de interfaz de usuario, de negocio o de datos?" Y hay cien argumentos, y no hay una respuesta correcta. La respuesta es la misma, afecta a todas las capas, no desea hacer la interfaz de usuario tonta y tener que pasar por todas las capas, y fallar en la base de datos, solo para que el usuario descubra que su entrada es demasiado larga. Si lo cambia, afecta a todas las capas, etc.

Las "capas" también tienden a gotear; Si alguna capa está físicamente separada por los límites del proceso / máquina (interfaz de usuario web de IE y lógica de backend empresarial), las reglas se duplican para que todo funcione razonablemente bien. Es decir, parte de la lógica empresarial termina en la interfaz de usuario, a pesar de que es una "regla de negocios", porque el usuario necesita que la interfaz de usuario sea receptiva.

Si el marco utilizado, o la arquitectura utilizada, es resistente a pequeños cambios y fugas, es decir, se basa en metadatos y se ajusta dinámicamente a través de todas las capas, puede ser menos doloroso. Pero la mayoría de los frameworks es un problema real, ya que requiere cambios en la interfaz de usuario, cambios en la capa empresarial y cambios en la base de datos, para cada pequeño cambio, y causa más trabajo y menos ayuda de la que se supone que produce la técnica.

Probablemente me critiquen por esto, pero ahí está :)

Arrendajo
fuente
¡+1, suena como mi último lugar de trabajo hasta el más mínimo detalle! Respeto las aplicaciones escalonadas por principio, sin embargo, demasiadas personas lo tratan como una bala de plata cuando no tiene sentido. La mayoría del software empresarial tiene una cantidad asombrosamente baja de lógica empresarial y lo que tiene es relativamente simple. Esto puede hacer que la lógica de negocios en capas sea una pesadilla del código repetitivo. Muchas veces las líneas pueden quedar borrosas entre el acceso a los datos y la lógica empresarial porque la consulta ES la lógica empresarial.
maple_shaft
... además, la mayoría de las tiendas fallan absolutamente al reconocer la lógica de la interfaz de usuario o la lógica de presentación. Debido a que no entienden cuán poca lógica de negocios existe en una aplicación CRUD típica, sienten que deben estar haciendo algo mal cuando la mayoría de su lógica reside en la capa de presentación como lógica de presentación. Se identifica falsamente como lógica de negocios y luego las personas lo envían al servidor para otra llamada al servidor. Un Thin Client puede y debe tener una lógica de presentación, por ej. (Ocultar textField2 si se selecciona la opción1 en dropDown3).
maple_shaft
7

Historias de usuarios / Casos de uso / Personas

 

Entiendo la necesidad de estos cuando está programando para una industria con la que no está familiarizado, pero creo que cuando se implementan con toda su fuerza se vuelven demasiado corporativos y se convierten en una pérdida de tiempo.

Riwalk
fuente
7

80 límites de caracteres / líneas son tontos

Entiendo que se deben hacer algunos compromisos para que coincida con el ritmo del corredor más lento en el lado de la GUI (limitaciones de resolución de pantalla, etc.) pero, ¿por qué esa regla se aplica al formato de código?

Ver ... Hubo esta pequeña invención llamada barra de desplazamiento horizontal que se creó para administrar el espacio de la pantalla virtual fuera del límite de píxeles más a la derecha. ¿Por qué los desarrolladores, que han logrado crear excelentes herramientas para mejorar la productividad, como el resaltado de sintaxis y el autocompletado, lo usan?

Claro, hay editores de CLI utilizados religiosamente por los dinosaurios * nix que siguen las viejas y cansadas limitaciones de sus terminales VT220, pero ¿por qué el resto de nosotros tenemos el mismo estándar?

Yo digo, joder el límite de 80 char. Si los dinosaurios son lo suficientemente épicos como para hackear emacs / vim todo el día, ¿por qué no deberían ser capaces de crear una extensión que envuelva líneas automáticamente o brinde capacidades de desplazamiento horizontal a sus IDE CLI?

Los monitores de 1920x1080 píxeles eventualmente se convertirán en la norma y los desarrolladores en todo el mundo todavía viven bajo las mismas limitaciones sin tener en cuenta por qué lo hacen, excepto que eso es lo que les dijeron sus mayores cuando recién comenzaban a programar.

Los límites de 80 caracteres no son una práctica recomendada, sino una práctica de nicho para una minoría de programadores y deben tratarse como tales.

Editar:

Es comprensible que a muchos desarrolladores no les guste la barra de desplazamiento horizontal porque requiere un gesto del mouse, así que ... ¿Por qué no aumentar el límite de ancho de columna a un número mayor (que 80) para aquellos de nosotros que usamos pantallas modernas?

Cuando los monitores de computadora 800x600 se convirtieron en la norma para la mayoría de los usuarios, los desarrolladores web aumentaron el ancho de su sitio web para acomodar a la mayoría ... ¿Por qué los desarrolladores no pueden hacer lo mismo?

Evan Plaice
fuente
1
@Orbling La lógica de Nice GWB con ___ es un mal ángulo. Entonces detesta el hScroll, ¿tiene alguna razón válida por la que el ancho de columna debe limitarse a 80 caracteres? ¿Por qué no 160 o 256? Creo que todos podemos suponer que la mayoría de los desarrolladores han retirado sus terminales VT220 y los han reemplazado con puTTY para que puedan extender el ancho mediante programación de todos modos.
Evan Plaice
44
Prefiero que nos mantengamos en el límite de 80 char. Tan pronto como me des más espacio horizontal, intentaré abrir documentos adicionales junto con el resto. Odiaría tener que desplazarme de cuatro maneras. Además, he notado a menudo que me veo obligado a escribir código más legible con el límite de 80 caracteres.
Filip Dupanović
2
¿Cómo lo imprimirías?
55
Lo siento, tengo que estar en desacuerdo con esto. Realmente odio las largas y largas líneas: requiere más movimiento de los ojos, requiere gestos del mouse para desplazarse, es más difícil ver cosas colgantes sutilmente pequeñas al final de una línea. En aproximadamente el 99% de los casos, hay formas claras de hacer que las cosas pasen por varias líneas (más cortas), lo que es más claro y fácil de leer. 80 Los caracteres pueden ser arbitrarios y "porque era así en los días de tarjetas perforadas", pero sigue siendo un marco razonable para trabajar en el interior, la mayoría de las veces, por las razones anteriores.
rapid_now
3
Sangría por 2 espacios. Y use un editor con un rastreador automático de sangría. Lo he hecho así durante años, no es gran cosa. (Emacs con los modos correctos ayuda aquí.)
rápidamente_ahora
5

Medida, medida, medida

Muy bien, mida, pero para aislar errores de rendimiento, la medición funciona, así como la eliminación sucesiva. Aquí está el método que uso.

He estado tratando de localizar la fuente de la "sabiduría" medida-medida. Alguien con una caja de jabón lo suficientemente alta lo dijo, y ahora viaja.

Mike Dunlavey
fuente
5

Mi maestro me exige que comience todos mis identificadores (sin incluir constantes) con letras minúsculas, por ejemplo myVariable.

Sé que parece algo menor, pero muchos lenguajes de programación requieren variables para comenzar con letras mayúsculas. Valoro la coherencia, por lo que es un hábito mío comenzar todo con letras mayúsculas.

Maxpm
fuente
99
Tenía un maestro que requería camelCase porque insistía en que eso era lo que la gente usaba en el mundo real ... Al mismo tiempo, estaba programando en dos grupos diferentes en mi trabajo; ambos grupos insistían en las puntuaciones inferiores. Lo que importa es lo que usa su grupo. Podría haberse definido a sí mismo como el programador principal y todo estaría bien en mi libro, seguimos sus convenciones, pero siempre daba su opinión como "la forma en que se hacen las cosas en el mundo real", como si no hubiera otro válido camino.
xnine
@xnine Todavía no tengo suficiente representante en este sitio para calificar tu comentario, así que solo responderé con este comentario de aprobación.
Maxpm
55
El caso de camello (primera letra en minúscula) es una convención bastante común, así como el caso de Pascal (primera letra de cada palabra en mayúscula). En la mayoría de los idiomas, camelCase se usa en variables privadas / internas donde PascalCase se usa en clases, métodos, propiedades, espacios de nombres, variables públicas. No es una mala práctica acostumbrarse a estar listo para proyectos que pueden usar un esquema de nomenclatura diferente.
Evan Plaice
2
Solo un FYI. Algunos idiomas infieren significado si la primera letra de una variable es mayúscula o no. En uno de esos idiomas, si la primera letra es mayúscula, la variable se trata como una constante; cualquier intento de cambiarla arrojará un error.
Berin Loritsch
1
En Go , los métodos públicos y los miembros de las clases comienzan con una letra mayúscula; privadas con una letra minúscula.
Jonathan Leffler
5

Use Singletons

Cuando solo deberías tener una instancia de algo. No puedo estar más en desacuerdo . Nunca use un singleton y solo distribúyalo una vez y pase el puntero / objeto / referencia según sea necesario. No hay absolutamente ninguna razón para no hacer esto.

usuario2528
fuente
2
Eso es un montón de cosas negativas que me han dejado bastante confundido en cuanto a su postura real sobre los singletons.
Paul Butcher
1
@Paul Butcher: Odio los singletons y nunca debería usarse
1
@rwong: Personalmente, no creo que ningún motivo sea legítimo. Solo escríbelo como una clase normal. Realmente, no hay ninguna razón para usar un singleton que no sea la pereza y para promover malos hábitos o diseño.
66
¿Quién dice que usar Singeltons es la mejor práctica?
Phil Mander
2
Los Singletons tienen su lugar, especialmente en los casos en que una estructura operativa se asigna y se llena en el inicio, luego básicamente se convierte en lectura solo durante el tiempo de ejecución del programa. Sin embargo, en ese caso, solo se convierte en un caché en el otro lado de un puntero.
Tim Post
5

Usando unsigned int como iterador

¿Cuándo aprenderán que usar el signo int es mucho más seguro y menos propenso a errores? ¿Por qué es tan importante que el índice de matriz solo pueda ser un número positivo, que todos estén contentos de pasar por alto el hecho de que 4 - 5 es 4294967295?

AareP
fuente
Bien, ahora tengo curiosidad, ¿por qué dices eso? Me siento un poco tonto. ¿Puede proporcionar algunos ejemplos de código para respaldar sus declaraciones?
Paul Nathan
44
@Paul Nathan: en lo que respecta a los errores, aquí hay un ejemplo: for (unsigned int i = 0; i <10; i ++) {int crash_here = my_array [max (i-1,0)];}
AareP
@AareP: Sin duda, ¿supongo que hace referencia al hecho de que cuando un int sin signo 0disminuye 1, en realidad termina con el valor positivo máximo que puede almacenar un int sin signo?
Adam Paynter
1
@ Adam Paynter: sí. Esto puede parecer normal para los programadores de c ++, pero seamos sinceros, "unsigned int" es una mala "implementación" de números positivos solamente.
AareP
No es una buena idea en máquinas pequeñas incrustadas: las entradas con frecuencia sin firmar generarán un código más pequeño y más rápido. Depende del compilador y procesador.
rápidamente_ahora
4

Los métodos no deberían ser más largos que una sola pantalla

Estoy completamente de acuerdo con el principio de responsabilidad única, pero ¿por qué las personas perciben que significa "una función / método no puede tener más que una responsabilidad única en el nivel más fino de granularidad lógica"?

La idea es simple. Una función / método debe cumplir una tarea. Si parte de esa función / método se puede usar en otro lugar, córtelo en su propia función / método. Si pudiera usarse en otro lugar del proyecto, muévalo a su propia clase o una clase de utilidad y haga que sea accesible internamente.

Tener una clase que contiene 27 métodos auxiliares que solo se llaman una vez en el código es tonto, una pérdida de espacio, un aumento innecesario de complejidad y un sumidero de tiempo masivo. Suena más como una buena regla para las personas que quieren verse ocupadas refactorizando código pero no producen mucho.

Aquí está mi regla ...

Escribir funciones / métodos para lograr algo

Si se encuentra a punto de copiar / pegar algún código, pregúntese si sería mejor crear una función / método para ese código. Si una función / método solo se llama una vez en otra función / método, ¿hay realmente un punto en tenerla en primer lugar (se llamará con más frecuencia en el futuro)? ¿Es valioso agregar más saltos dentro / fuera de funciones / métodos durante la depuración (es decir, el salto agregado hace que la depuración sea más fácil o más difícil)?

Estoy completamente de acuerdo en que las funciones / métodos de más de 200 líneas deben ser analizadas, pero algunas funciones solo realizan una tarea en tantas líneas y no contienen partes útiles que puedan resumirse / usarse en el resto del proyecto.

Lo veo desde una perspectiva de desarrollo de API ... Si un nuevo usuario mirara el diagrama de clase de su código, cuántas partes de ese diagrama tendrían sentido dentro de la mayor parte del proyecto y cuántas existirían únicamente como ayudantes a otras partes internas del proyecto.

Si tuviera que elegir entre dos programadores: el primero tiende a escribir funciones / métodos que intentan hacer demasiado; el segundo divide cada parte de cada función / método al mejor nivel de granularidad; Yo elegiría las primeras manos. El primero lograría más (es decir, escribir más contenido de la aplicación), su código sería más fácil de depurar (debido a menos saltos dentro / fuera de funciones / métodos durante la depuración), y perdería menos tiempo haciendo un trabajo ocupado perfeccionando cómo el código se ve vs perfeccionando cómo funciona el código.

Limite las abstracciones innecesarias y no contamine el autocompletado.

Evan Plaice
fuente
Esta. Una vez reorganicé alguna función larga en varias, solo para darme cuenta de que casi todas necesitaban casi todos los parámetros del código original. El manejo de los parámetros fue tan difícil que fue más fácil volver al código anterior.
l0b0
3
Creo que un argumento contrario a esto es que refactorizar partes de un método grande en llamadas separadas puede hacer que el método más grande sea más fácil de leer. Incluso si el método solo se llama una vez.
Jeremy Heiler
1
@Jeremy ¿Cómo? ¿De qué manera, resumir una sección de código y colocarla en su propio método lo hace más legible que simplemente colocar un comentario de una línea en la parte superior de ese fragmento de código que describe lo que hace? Suponiendo que el bloque de código solo se usa una vez en esa sección de código. ¿Es realmente tan difícil para la mayoría de los programadores descomponer las partes de trabajo del código mientras lo leen y / o colocar algunos comentarios de una línea para recordarles lo que hace si no pueden?
Evan Plaice
44
@Evan: poner piezas de código en funciones efectivamente les da un nombre , con suerte explicando bien qué hace esa pieza de código. Ahora, siempre que ese trozo de código se llama, se puede ver el nombre de explicar lo que hace el código , en lugar de tener que analizar y comprender el propio algoritmo. Si se hace bien, esto puede facilitar enormemente la lectura y comprensión del código.
sbi
1
+1 y daría más si pudiera. No hay nada de malo en un conjunto de código C que tiene 1000 líneas en una sola función (por ejemplo, un analizador con un interruptor masivo ()), siempre que la intención sea clara y simple. Romper todas las pequeñas piezas y llamarlas solo hace que la cosa sea más difícil de entender. Por supuesto, esto también tiene límites ... el juicio sensato lo es todo.
rápidamente_ahora