¿Deben las Startups realmente preocuparse por producir código reutilizable y bien mantenible o sería mejor para ellos hacerlo funcionar y luego preocuparse por la refactorización? ¿Qué piensas y por qué?

El código reutilizable tiene un valor casi cero, el código fácil de mantener tiene un valor inmenso. Intentar hacer que su código sea reutilizable lo hará menos mantenible.

El problema con toda la filosofía de “hacer que funcione y luego preocuparse por la calidad” es que realmente no lo hará funcionar. Una de las características clave de un código terrible es que las cosas comienzan a romperse después de que su proyecto llega a un cierto tamaño, y cuando arregla una cosa, rompe otra cosa.

Si comienza con la intención y la capacidad de crear un código de calidad, sus posibilidades de llegar a un producto exitoso son mucho mayores. No importa qué tan rápido llegues allí, si “allí” apesta.

Si su código es lo suficientemente complejo como para que necesite comentarios de código, probablemente esté escribiendo un código demasiado complejo: escriba un código que un interno pueda entender, porque un interno probablemente le hará cambios en algún momento. Escriba código que sea hermoso y escriba pruebas unitarias como locas.

Tenga cuidado al agregar funciones, los cambios frenéticos causados ​​por los cambios de funciones inducidos por la administración pueden romper su código en pedazos: no permita que eso suceda, piense cuidadosamente sobre lo que se agrega y asegúrese de que el equipo de administración conozca el impacto de cualquier cambio solicitado .

Sin embargo, refactorizar como loco: a menudo hago reescrituras completas de mi código cuando tengo una idea de cómo las cosas podrían ser masivamente mejores de lo que son ahora. Comienzo desde cero y uso mi antigua base de código como una pila de bloques de construcción para cortar y pegar para el nuevo calor.

Si. Código bien escrito y refactorización constante == desarrollo sostenible rápido.

La práctica de “simplemente hacer que funcione” y “cortar esquinas” es una pendiente resbaladiza que rápidamente conduce a un atolladero. Y por rápido no me refiero a meses, sino a semanas desde el desarrollo inicial.

El código desordenado y no probado se vuelve frágil y exponencialmente más difícil de trabajar y ampliar. Y progresivamente más difícil refactorizar y agregar un conjunto de pruebas adecuado después del hecho.

La ilusión inicial de velocidad se reemplaza rápidamente por la entrega lenta y lenta, y se dedica MUCHO tiempo a la depuración. La depuración se vuelve más difícil porque el código no se ha probado y es muy difícil de leer. Se comienzan a gastar muchas horas hombre solo para descubrir qué se suponía que debía hacer un fragmento de código y cómo afectaba al resto.

Las felicitaciones que los equipos de desarrollo obtienen inicialmente por sacar ese prototipo por la puerta se olvidan, reemplazadas por la creciente presión de la gerencia por más de la misma “velocidad” inicial percibida.

No importa cuánto el CTO o el desarrollador principal les recuerde a los otros gerentes la compensación que se hizo inicialmente (que se renueva a medida que pasa el tiempo, ya que el tiempo de “detener todo para refactorizar y agregar pruebas” nunca llega), con la bendición y, a veces, la imposición de este último, la culpa de la velocidad más lenta percibida recae cada vez más en el equipo de desarrollo. Después de todo, ahí es donde está el cuello de botella, ¿verdad?

Eso puede, y a menudo lo lleva, a un conflicto político que se agrava rápidamente. Más gastos generales. Y la infelicidad general … Y los desarrolladores descontentos, que además del mal código con el que tienen que lidiar, tienen una compañía entera mirándolos como si fueran holgazanes, a menudo después de muchas noches y fines de semana, todo por el pago del mercado secundario. .

Los desarrolladores descontentos comienzan a partir hacia pastos más verdes. Y luego tienes un problema de puerta giratoria. Encontrar nuevos desarrolladores, y luego ponerlos al día … Una caja negra de código base, frágil, no probado, funcionando en vivo en producción. Ah, y ese genio desarrollador que escribió el código tan “rápidamente” no está allí para explicar cómo llegó a ese punto. Y no hay documentos, ya que eso es … solo una esquina para cortar, ¿verdad?

Vuelve a la cima y comienza de nuevo. Es un bucle sin fin que generalmente termina en un choque, o al menos mucho estrés para todos los involucrados. Y un pésimo producto.

Las startups deberían optimizar solo una cosa: la velocidad de desarrollo. Menos tiempo dedicado a escribir código, más tiempo dedicado a validar el producto y las características.

Escribir código mantenible no es barato. Requiere un enfoque basado en pruebas y requiere comentarios y documentación. Gran parte del código se descartará o reescribirá a medida que se eliminen o modifiquen las características y, junto con esto, las pruebas, los comentarios y la documentación que escribió también se eliminarán.

En lugar de adoptar un enfoque basado en pruebas para producir código que se pueda mantener, adopte un enfoque basado en API.

Deje que el servidor solo sirva JSON en lugar de HTML. En efecto, construir una API interna. Construya la aplicación web sobre esta API, renderizó el HTML en el lado del cliente utilizando los datos JSON devueltos por los puntos finales de la API.

Esto lo coloca en una buena posición para desarrollar rápidamente las inevitables aplicaciones móviles para su producto, ya que no necesita agregar nada al servidor para que las aplicaciones móviles funcionen. Lo mismo para el sitio web móvil y para la API pública, todo lo cual se puede construir sobre la API interna.

De hecho, está reutilizando mucho código, solo que a un nivel más alto que hacer que las clases y funciones sean lo más genéricas posible.

Una vez más, optimice la velocidad de desarrollo.

En caso de que esté interesado en leer algunas estrategias para aumentar la velocidad de desarrollo, escribí un blog sobre ellas aquí: desarrollo centrado en la velocidad

Escribir un código reutilizable que se pueda mantener bien puede reducir la probabilidad de llegar tarde a su producto vendible mínimo y el seguimiento de los lanzamientos, lo que es especialmente importante para las startups con límites de tiempo impuestos por las finanzas.

Cada producto tiene una barra de calidad mínima aceptable. Hago software de sistemas para aplicaciones críticas de negocios donde perder o corromper los datos de los clientes sería malo: las compañías celulares quieren facturar a los clientes por cada llamada, al menos una de las principales redes de cable despediría al ingeniero de turno al momento de una interrupción, y los clientes empresariales Realmente quiero que sus copias de seguridad funcionen. Lo malo es malo para los negocios: un colega que trabajaba para una empresa con prácticas de prueba deficientes arruga la nariz cuando habla de los clientes que devuelven el producto y sé de una startup B2B a la que se le rescindieron sus fondos en parte porque los clientes no estaban contentos con la calidad y cuán lentas e impredecibles fueron las versiones de corrección de errores.

Hacer software se trata de enviar productos y ventas que se mantengan, lo que requiere cruzar esa barra de calidad.

En la práctica, Test-Driven Development es el camino más rápido y confiable hacia ese objetivo. Aunque el tiempo para alcanzar el hito arbitrario de “código completo” puede ser mayor, pasa menos tiempo total haciendo algo que puede enviar. Al darse cuenta de la mejora de la calidad a través del desarrollo impulsado por pruebas: los resultados y las experiencias de cuatro equipos industriales, Microsoft e IBM llegaron a esa conclusión con puntos de datos como 20-25% más largos para codificar con un 91% menos de densidad de defectos y 15% más con 76% menos de defectos densidad versus organizaciones comparables que no usan TDD.

El diseño requerido para las pruebas incrementales tiende a producir componentes de software más pequeños que son inherentemente más fáciles de mantener y más propensos a ser reutilizables porque la especialización ocurre más arriba en la pila.

Los efectos se vuelven exponencialmente más significativos a medida que itera a través de pivotes (las cinco nuevas empresas para las que he trabajado lo hicieron al menos una vez) y complementos (conté 120 opciones después de que mi producto actual evolucionó durante 3 años) donde el tamaño del componente y Las API limpias entre ellas tienden más a la complejidad total lineal que a la combinatoria en función del tamaño de la base de código.

El código reutilizable conducirá automáticamente a un código bien mantenible. Lo cual es realmente importante en el inicio, ya que tendemos a cambiar o agregar características rápidamente y el requisito cambiará muy a menudo.

Por otro lado, el inicio solo tiene una cantidad muy limitada de tiempo y dinero, que tenemos que gastar ambos con mucho cuidado. Como todos sabemos, construir software de alta calidad es muy costoso.

Afortunadamente, el mundo se está volviendo más abierto, existen muchos proyectos de código abierto y servicios de buena calidad. Las startups típicas pueden usar muchos servicios de código abierto y de terceros para acelerar su desarrollo sin comprometer la calidad de su propio código. Ahorrará mucho tiempo (y dinero). Es posible que aún necesite escribir su propia solución cuando llegue al punto en que lo necesite, pero eso es después de validar su idea.

Entonces obtienes código bien mantenible y un desarrollo rápido.

Necesitas encontrar un equilibrio. No tiene el tamaño del equipo, el presupuesto o el tiempo masivos para que las cosas pasen de la planificación de requisitos a la operativa como lo hace una entidad establecida.

En el extremo de un lado, tiene la opción de un desorden de código descuidado que se junta en una estructura monolítica gigante porque “funciona”, lo que realmente significa que es una prueba de concepto. ¿Pero realmente funciona en el sentido de ser robusto y escalable con el proyecto? ¿Se manejan las excepciones, se aclaran los casos de prueba y se mitigan los errores? ¿Cuánto tiempo llevará agregar una nueva característica a esto si un cliente pregunta? ¿Puede un nuevo desarrollador entrar y leer el código y realmente darle sentido de alguna manera? ¿Es eficiente y funciona bien? Si es necesario, ¿hay controles de seguridad y acceso adecuados en el código?

En el extremo opuesto vas con el marco de microservicios; sobregenie todo para que esté lo más optimizado posible para el rendimiento y la memoria; documentas cada cosa; escribe pruebas automatizadas para cada escenario posible; considera cosas como la escalabilidad y el mantenimiento de modo que pueda automatizar su proceso de prueba, compilación e implementación; Te esfuerzas por hacer que todo sea lo más modular y reutilizable posible de la manera más estricta posible. Te tomas el tiempo para asegurarte de que los datos y el código seguros sean parte del proceso de desarrollo todo el tiempo. Muchas de estas cosas son ideales, pero hacerlo con un equipo pequeño, las limitaciones de tiempo y el presupuesto serán difíciles.

Con el escenario anterior, puede obtener algo que funciona, pero corre el riesgo de no poder desarrollar nuevas funciones de manera oportuna sin introducir nuevos errores en el sistema. Un sistema con errores o uno que no se puede actualizar para acomodar nuevas solicitudes de funciones de manera oportuna hará que pierda su base de clientes. En el último escenario, pasará demasiado tiempo siendo un perfeccionista y corre el riesgo de superar las limitaciones de presupuesto / tiempo y / o perder la oportunidad para la base de clientes que pueden ir a otro lado.

Entonces priorizas. Por lo general, las optimizaciones pueden posponerse para las fases de refactorización posteriores (bueno, nuestro sistema funcionó muy bien antes, ¡pero ahora es aún más rápido!). Intente asegurarse de que el código esté lo suficientemente limpio como para que se pueda refactorizar fácilmente y asegúrese de documentar las piezas difíciles / complejas para que otra persona (o incluso usted mismo) pueda leerlo en unos pocos meses y saber lo que está haciendo. Básicamente, intenta comprender hacia dónde crecerá su sistema y qué necesidades tendrá en el futuro, y lo hace funcionar por ahora con diseño para que pueda construirse más adelante. No tiene sentido construir un sistema a escala para 10 millones de usuarios antes de que tenga un solo usuario actualmente, pero puede intentar obtener la base allí para que pueda escalar rápidamente si tiene la suerte de tener tales demandas. Por supuesto, esto es solo una opinión generalizada: la fase de ingeniería de requisitos de cualquier proyecto de codificación determinará las prioridades que tendrá a corto y largo plazo.

Realmente depende de tu objetivo.

Si su objetivo es crear una empresa que construya un producto real, es decir, que está construyendo una empresa para administrar, entonces la calidad es importante. Las esquinas cortadas al principio, aunque a veces son necesarias, le costarán más adelante.

Dicho esto, no desea establecer un alcance tan grande que no pueda hacerlo. Debe comprender claramente su alcance para hoy y tal vez dos o tres años fuera y construir para eso. Debe crear un código bien construido, legible, confiable y fácil de mantener (lo que también significa que está completamente documentado).

Después de tres años, es probable que esté haciendo algo lo suficientemente diferente como para tener que volver a escribir posiciones importantes de todos modos.

Por otro lado, si como muchas “startups esbeltas” de hoy en día, realmente está jugando el esquema de hacerse rico rápidamente para tratar de construir una empresa para vender lo antes posible, entonces continúe y escriba basura ya que venderá la empresa o abandone la idea mucho antes de que llegue a casa para posarse.

Creo que una empresa que intenta despegar necesita despegar.

También creo que un negocio necesita tener un ojo en estas cosas y ser pragmático.

He visto algunos problemas de software bastante horribles, debido a las malas actitudes … hodge-podge, lo que sea, tirarlo juntos … y luego nada se limpia, un desastre lleva a otro, y las cosas pueden comenzar a romperse fácilmente.

En particular, un negocio que una vez tuvo problemas creció rápidamente y se convirtió en efectivo. El propietario era justificadamente frugal dado los años anteriores con poco flujo de caja. Pero, el negocio aún estaba creciendo y no podía seguir el ritmo de la demanda debido a la pobre infraestructura de código. ( Y las demandas eran bastante altas, siempre esperando / queriendo más, pero sin escuchar los problemas, la mayoría de ellos causados ​​por esta falta histórica de prestar atención en primer lugar. Es un ciclo desagradable y vicioso de malas actitudes que debe ser comprobado antes de que las cosas lleguen a este nivel. )

En un momento, se vuelve pragmático establecer estándares y escribir un buen código por el bien del crecimiento organizacional (de lo contrario, se pasa demasiado tiempo limpiando un desorden cuando algo sale mal, o algo cambia, etc.).

Las empresas suelen ser sobre eficiencia (o * debería ser *) … ¿por qué? Cuando estás en el negocio para ganar dinero, los desordenes o las actitudes que te detienen ( menos que los políticos / conversadores / burócratas pragmáticos ) tienden a reducir las ganancias, y ese es el otro lado del desastre que aborrezco … la gente quiere hacer dinero, pero tenga actitudes tan complacientes y mediocres hacia hacer las cosas de tal manera que beneficie al negocio y, por lo tanto, a ellos mismos.

Mi regla general es que la línea de tiempo para cualquier inversión que valga la pena que realice mientras construye una startup debería ser aproximadamente su próximo hito de financiamiento. Esto es cierto para cualquier inversión significativa que realice, no solo en la calidad del código.

es decir, si necesita recaudar dinero en 12 meses, no tiene sentido hacer una inversión que solo dará sus frutos en 18 meses. Concéntrese en lograr el próximo hito de financiamiento.

Para mí, lograr el equilibrio correcto entre la optimización prematura (sobre inversión) y el cowboy (bajo inversión) es una de las “artes” clásicas de construir una startup.

Más allá de eso, creo que el enfoque correcto es tratar de escribir la menor cantidad de código posible: cada línea de código que escriba crea una responsabilidad. Es por eso que debe hacer que cada característica luche por su existencia y la respuesta predeterminada a cualquier solicitud de nueva característica debe ser “no”. Este enfoque lo obliga a centrarse en el valor central absoluto que está tratando de proporcionar a sus usuarios / clientes y obtener comentarios lo antes posible.

La gente de desarrollo ágil y basado en pruebas tiene buenos consejos. Si comienza escribiendo un conjunto de casos de prueba, que, por supuesto, su código no escrito aún no pasa, entonces escriba solo el código que necesita para pasar las pruebas, pero nada generalizado más allá de lo que necesita, luego pase a un buen comienzo. El código reutilizable generalmente no es lo que realmente necesita. El código mantenible es vital. Si observa el código que pasa las pruebas y se da cuenta de que las pruebas no capturaron algo que cree que es un requisito, invente una nueva prueba y vea si el código realmente falla. Enjabonar, enjuagar, repetir …

El punto principal de Agile es que obtienes algo construido para que el usuario pueda ver lo que hace y obtener comentarios sobre lo que realmente quiere que haga. Es completamente posible que, dados los nuevos requisitos, tenga que desechar el diseño anterior y comenzar de nuevo, pero debería encontrar esa necesidad rápidamente en lugar de después de tener años de desarrollo ligados a su proyecto.

Cada situación es diferente, no hay una respuesta correcta. Cual es el producto? por ejemplo, si está relacionado con la infraestructura (por ejemplo, una nueva base de datos), las mejores prácticas de ingeniería estarían en orden y el esfuerzo se financiaría para tener esto en cuenta. Si se trata de juegos, esa sería otra historia. ¿Cuál es el objetivo del negocio? ¿Estás apuntando a tener entusiasmo y vender? Centrarse en el corto plazo, entonces. ¿Quiénes son los fundadores? Si el fundador tiene una sólida formación técnica, es posible que vea más prácticas recomendadas (no busque más que Quora para obtener un excelente ejemplo). Si el fundador no es técnico (por ejemplo, un ex banquero de inversiones), es probable que “lo que está bajo el capó” no esté en el plan.

Personalmente, me gusta que el estado de un negocio sea un producto bien construido que utiliza automatizaciones de prueba. Hay mucho trabajo en las startups que tienen un nido de ratas con una base de código y están en el punto donde ya no pueden mantenerlo, por lo que en ese momento contratan un conjunto de habilidades que pueden adaptarse a las mejores prácticas / automatizaciones.

Quién sabe … es realmente una situación caso por caso, no existe una fórmula mágica, si la hubiera, todos la estaríamos usando.

No es mi intención no elegir una respuesta por completo, pero una buena guía que trato de seguir es “nunca hay un mejor momento que ahora”. Lo que quiero decir es que, a menudo, durante el desarrollo, sabes de una mejor implementación que tomaría más tiempo. Debido a la escasez de tiempo actual, usted dice “Lo haré así y volveré y lo arreglaré cuando haya un tiempo después”. Sin embargo, el problema con esto es que nunca hay tiempo para volver, o simplemente no lo haces. Creo firmemente que si SABES que hay una mejor manera de hacer algo que puede llevar más tiempo, tómate el tiempo y hazlo bien la primera vez para que no tenga que corregirse más tarde.

Antes de PMF, debes golpearlo lo más rápido posible cortando todas las esquinas. Planee tirar grandes porciones de código que no se combinaron con PMF y suponga que necesitará refactorizar lo que queda más adelante.

No intente hacerlo perfecto en este momento porque tiene un costo muy alto.

Solo manténgalo claro y viable.

Digamos que tenemos 3 opciones:
1. Código de calidad 10, costo 1 año
2. Código de calidad 7, costo 3 meses
3. Código de calidad 5, costo 1 semana.

Para el inicio, creo que la opción 2 es una buena opción.

Puesta en marcha: un esfuerzo que parte de una idea vaga y se convierte en un producto pragmático. Código bien mantenible: código que se puede batir sin romper. Duh?