Me gustaría agregar una respuesta a esta pregunta, ya que últimamente he estado avanzando a través de algunos Java buenos, malos pero en su mayoría feos, y tengo una gran cantidad de generalizaciones brutas sobre desarrolladores Java y Java vs.JS y Desarrolladores JS que en realidad podrían estar basados en algo vagamente parecido a una verdad útil.
Hay IDEs pero puede ser útil entender por qué no ha habido muchos
He estado probando Webstorm ahora que me siento atraído por el desarrollo de Node y no es lo suficientemente malo como para que lo haya comprado, pero todavía tiendo a abrir archivos js en Scite con más frecuencia que WS. La razón de esto es que puede hacer mucho más con mucho menos en JS, pero también porque el trabajo de la interfaz de usuario proporciona comentarios inmediatos, las herramientas de desarrollo del navegador (Chrome y Firebug en particular) son realmente excelentes y (teniendo en cuenta los contextos que no son del navegador ) volver a ejecutar el código alterado es rápido y fácil sin un paso de compilación.
Otra cosa de la que estoy bastante convencido es que los IDEs básicamente crean su propia demanda al habilitar un código descuidado que realmente no puede permitirse en JavaScript. ¿Quieres aprender cómo nos gestionamos en JS? Puede ser útil comenzar tratando de escribir algo no trivial en Java sin un IDE y prestar mucha atención a las cosas que debe comenzar a hacer y pensar para poder mantener / modificar ese código sin mover un IDE adelante. En mi opinión, esas mismas cosas siguen siendo críticas para escribir código mantenible, ya sea que tenga un IDE o no. Si tuviera que escribir un plan de estudios de programación de 4 años, no le permitiría tocar un IDE durante los primeros dos años con el interés de no torcer las herramientas y las dependencias.
Estructura
Los desarrolladores JS experimentados que trabajan con aplicaciones complejas pueden estructurar su código y lo hacen. De hecho, es algo en lo que tendemos a tener que ser mejores con una historia temprana que carecía de IDEs para leer el código por nosotros, pero también porque los lenguajes poderosamente expresivos pueden expresar poderosamente bases de códigos de desastres completamente imposibles de mantener muy rápidamente si no codifica cuidadosamente.
De hecho, tuve una curva de aprendizaje bastante empinada para comprender nuestra base de código Java recientemente hasta que finalmente me di cuenta de que nada de eso era una POO adecuada. Las clases no eran más que paquetes de métodos poco relacionados que alteran los datos disponibles a nivel mundial en beans o DTO o getters / setters estáticos. Esa es básicamente la misma bestia vieja que se suponía que OOP reemplazaría. Así que básicamente dejé de mirar y pensar en el código. Acabo de aprender las teclas de acceso directo y rastreé a través de los problemas y todo salió mucho más suavemente. Entonces, si aún no tiene el hábito, piense mucho más sobre OOD.
Una aplicación JS bien estructurada al más alto nivel tenderá a consistir en funciones complejas (por ejemplo, jQuery) y objetos que interactúan entre sí. Yo diría que la marca de una aplicación bien estructurada y fácil de mantener en cualquier idioma es que es perfectamente legible ya sea que la esté mirando con un IDE o Notepad ++. Es una de las principales razones por las que soy muy crítico con la inyección de dependencia y la primera prueba de TDD llevada al extremo.
Y finalmente, deja ir las clases. Aprende la herencia prototípica. En realidad, es bastante elegante, fácil de implementar cuando realmente necesita herencia. Sin embargo, creo que los enfoques de composición tienden a funcionar mucho mejor en JS, y personalmente empiezo a enfermarme y tengo terrores nocturnos EXTJS cada vez que veo más de uno o dos niveles de herencia en cualquier idioma.
Principios Básicos Primero
Me refiero a las cosas centrales de las que deberían derivarse todas las otras buenas prácticas: DRY, YAGNI, el principio del menor asombro, la separación limpia de dominios problemáticos, escribir en una interfaz y escribir código legible humano son mi núcleo personal. Cualquier cosa un poco más compleja que defienda el abandono de esas prácticas debe considerarse Kool Aid en cualquier idioma, pero especialmente en un lenguaje como JavaScript, donde es muy fácil dejar un legado de código muy confuso para el próximo tipo. El acoplamiento flojo, por ejemplo, es excelente hasta que lo llevas tan lejos que ni siquiera puedes saber dónde está ocurriendo la interacción entre los objetos.
No temas teclear dinámicamente
No hay muchos tipos principales en JavaScript. En su mayor parte, las reglas de conversión dinámicas son prácticas y directas, pero vale la pena aprenderlas para que pueda aprender mejor a administrar el flujo de datos sin conversiones innecesarias y rutinas de validación sin sentido. Créeme. Los tipos estrictos son excelentes para el rendimiento y detectar problemas en la compilación, pero no lo protegen de nada.
Aprenda la mierda de las funciones y cierres de JS
Las funciones de primera clase de JS son posiblemente la razón principal por la que JS ganó el premio "Solo un lenguaje que vale la pena tocar la web del lado del cliente". Y sí, en realidad hubo competencia. También son una característica central de JS. Construimos objetos con ellos. Todo tiene un alcance para las funciones. Y tienen características útiles. Podemos examinar los parámetros a través de la palabra clave argumentos. Podemos adjuntarlos temporalmente y dispararlos en el contexto de ser métodos de otros objetos. Y hacen que los enfoques basados en eventos de cosas obscenamente fáciles de implementar. En resumen, convirtieron a JS en una bestia absoluta para reducir la complejidad y adaptar diversas implementaciones de JS (pero principalmente la API DOM) directamente en la fuente.
Reevaluar patrones / prácticas antes de adoptar
Las funciones de primera clase y los tipos dinámicos hacen que muchos de los patrones de diseño más complejos sean completamente inútiles y engorrosos en JS. Sin embargo, algunos de los patrones más simples son increíblemente útiles y fáciles de implementar dada la naturaleza altamente flexible de JS. Los adaptadores y decoradores son particularmente útiles y he encontrado que los singletons son útiles para las complejas fábricas de widgets de interfaz de usuario que también actúan como gestores de eventos para los elementos de interfaz de usuario que construyen.
Siga la guía del idioma y haga más con menos
Creo que uno de los principales jefes de Java argumenta en alguna parte que la verbosidad es en realidad una característica positiva que hace que el código sea más fácil de entender para todas las partes. Bazofia. Si eso fuera cierto, la jerga legal sería más fácil de leer. Solo el escritor puede hacer que lo que ha escrito sea más fácil de entender y usted solo puede hacerlo poniéndose en el lugar del otro tipo ocasionalmente. Entonces abraza estas dos reglas. 1. Sea lo más directo y claro posible. 2. Llegar al maldito punto ya. La victoria es que el código limpio y conciso es de órdenes de magnitud más fáciles de entender y mantener que algo en lo que tienes que atravesar veinticinco capas para llegar desde el gatillo a la acción deseada real. La mayoría de los patrones que defienden ese tipo de cosas en lenguajes más estrictos son, de hecho, soluciones para limitaciones que JavaScript no tiene.
Todo es maleable y eso está bien
JS es probablemente uno de los lenguajes menos proteccionistas de uso popular. Abraza eso. Funciona bien. Por ejemplo, puede escribir objetos con variables "privadas" persistentes inaccesibles simplemente declarando variables regulares en una función de constructor y hago esto con frecuencia. Pero no es para proteger mi código o los usuarios del mismo "de sí mismos" (de todos modos, podrían reemplazarlo con su propia versión durante el tiempo de ejecución). Pero más bien es para señalar la intención porque la suposición es que el otro tipo es lo suficientemente competente como para no querer destrozar ninguna dependencia y verá que no está destinado a hacerlo directamente, tal vez por una buena razón.
No hay límites de tamaño, solo dominios problemáticos
El mayor problema que tengo con todas las bases de código Java que he visto es la abundancia de archivos de clase. En primer lugar, SOLID es solo una reiteración confusa de lo que ya debe saber sobre OOP. Una clase debe manejar un conjunto específico de problemas relacionados. No hay un problema con un método. Eso es solo tomar el viejo código de func-spaghetti C de encadenamiento solo con la adición de toda la sintaxis de clase sin sentido para arrancar. No hay límite de tamaño o método. Si tiene sentido agregar algo a una función, clase o constructor ya largo, tiene sentido. Toma jQuery. Es un conjunto completo de herramientas de longitud de biblioteca en una sola función y no hay nada de malo en eso. Si todavía necesitamos jQuery depende de un debate razonable, pero en términos de diseño,
Si Java es todo lo que sabe, incursione en algo con una sintaxis no basada en C
Cuando comencé a jugar con Python porque me gustó lo que estaba escuchando sobre Django, aprendí a separar la sintaxis del diseño del lenguaje. Como resultado, se hizo más fácil entender Java y C como una suma de sus partes de diseño de lenguaje en lugar de una suma de cosas que hacen de manera diferente con la misma sintaxis. Un buen efecto secundario es que cuanto más comprenda otros idiomas en términos de diseño, mejor comprenderá las fortalezas / debilidades del que mejor conoce a través del contraste.
Conclusión
Ahora, considerando todo eso, veamos todos los puntos problemáticos:
- No hay forma inmediata de encontrar el punto de entrada de una función (que no sea una búsqueda de texto sin formato, que luego puede resultar en búsquedas posteriores de métodos más arriba en la jerarquía de llamadas, después de dos o tres de los cuales ha olvidado dónde comenzó)
Chrome y Firebug realmente tienen seguimiento de llamadas. Pero vea también mis puntos sobre la estructura y mantener las cosas concisas y directas. Cuanto más pueda pensar en su aplicación como construcciones bien encapsuladas más grandes que interactúan entre sí, más fácil será averiguar de quién es la culpa cuando las cosas salen mal. Yo diría que esto también es cierto para Java. Tenemos constructores de funciones de clase que son perfectamente útiles para las preocupaciones tradicionales de OOP.
function ObjectConstructor(){
//No need for an init method.
//Just pass in params and do stuff inside for instantiation behavior
var privateAndPersistent = true;
//I like to take advantage of function hoisting for a nice concise interface listing
this.publicAndPointlessEncapsulationMurderingGetterSetter
= publicAndPointlessEncapsulationMurderingGetterSetter;
//Seriously though Java/C# folks, stop with the pointless getter/setters already
function publicAndPointlessEncapsulationMurderingGetterSetter(arg){
if(arg === undefined){
return privateAndPersistent;
}
privateAndPersistent = arg;
}
}
ObjectConstructor.staticLikeNonInstanceProperty = true;
var instance = new ObjectConstructor();//Convention is to capitalize constructors
En mi código, casi nunca uso los literales de objetos {}como componentes estructurales de la aplicación, ya que no pueden tener variables internas (privadas) y prefiero reservarlas para usarlas como estructuras de datos. Eso ayuda a establecer una expectativa que mantiene la claridad de la intención. (si ve curvas, son datos, no un componente de la arquitectura de la aplicación).
- Los parámetros se pasan a las funciones, sin forma de saber qué propiedades y funciones están disponibles en ese parámetro (aparte de ejecutar realmente el programa, navegar hasta el punto en el que se llama la función y usar console.logs para generar todas las propiedades disponible)
Nuevamente, vea las herramientas modernas del navegador. Pero también, ¿por qué es tan fastidioso volver a ejecutar el programa? La recarga es algo que un desarrollador web del lado del cliente generalmente golpea cada pocos minutos porque no le cuesta absolutamente nada hacerlo. Esto es otra vez, otro punto con el que la estructura de la aplicación puede ser útil, pero es una desventaja de JS que debes ejecutar tu propia validación cuando hacer cumplir los contratos es crítico (algo que solo hago en los puntos finales expuestos a otras cosas que mi base de código no hace) 't control). En mi opinión, la compensación vale la pena los beneficios.
- El uso común de funciones anónimas como devoluciones de llamada, que con frecuencia conduce a un espagueti de rutas de código confusas, que no puede navegar rápidamente.
Sí, eso es malo en cualquier cosa no trivial. No hagas eso. Nombra tus funciones niños. También es más fácil rastrear cosas. Puede definir, evaluar (necesario para asignar) y asignar una función trivial simple en línea con:
doSomethingWithCallback( (function callBack(){}) );
Ahora Chrome tendrá un nombre para ti cuando estés rastreando llamadas. Para funciones no triviales, lo definiría fuera de la llamada. También tenga en cuenta que las funciones anónimas asignadas a una variable siguen siendo anónimas.
- Y claro, JSLint detecta algunos errores antes del tiempo de ejecución, pero incluso eso no es tan útil como tener líneas onduladas rojas debajo de su código directamente en el navegador.
Nunca toco las cosas. Crockford le ha dado algunas cosas buenas a la comunidad, pero JSLint cruza la línea en preferencias estilísticas y sugiere que ciertos elementos de JavaScript son partes malas sin una razón particularmente buena, en mi opinión. Definitivamente ignore esa cosa sobre las clases regEx y negación seguidas de * o +. Los comodines funcionan peor y puedes limitar fácilmente la repetición con {}. Además, ignore todo lo que diga sobre los constructores de funciones. Puede envolverlos fácilmente en una función de fábrica si la nueva palabra clave le molesta. CSSLint (no el de Crockford) es aún peor en el frente de los malos consejos. Siempre lleve a las personas que hablan mucho con un grano de sal. A veces juro que solo buscan establecer autoridad o generar material nuevo.
Y nuevamente, debe desaprender lo que ha aprendido con esta preocupación de tiempo de ejecución que tiene. (es común que he visto con muchos desarrolladores de Java / C #) Si ver errores en el tiempo de ejecución aún te molesta 2 años después, quiero que te sientes y recargues el spam en un navegador hasta que se hunda. no es una división de tiempo de compilación / tiempo de ejecución (bueno, no es visible de todos modos, JS se ejecuta en un JIT ahora). No solo está bien descubrir errores en tiempo de ejecución, es muy beneficioso recargar y descubrir spam de manera tan barata y fácil en cada punto de parada.
Y aprovecha esas herramientas de desarrollo de Chrome. Están integrados directamente en webkit. Haga clic derecho en Chrome. Inspeccionar elemento. Explora las pestañas. Una gran capacidad de depuración con la capacidad de alterar el código en la consola durante el tiempo de ejecución es una de las opciones más potentes pero menos obvias. Genial para probar también.
En una nota relacionada, los errores son tus amigos. Nunca escriba una declaración catch vacía. En JS no ocultamos ni enterramos errores (o al menos no debemos toser YUI / tos ). Los atendemos. Cualquier cosa menos resultará en dolor de depuración. Y si escribe una declaración catch para ocultar posibles errores en la producción, al menos silenciosamente registre el error y documente cómo acceder al registro.