Todas las personas no saben escribir código

En vísperas de Moscú Python Conf ++, hablamos con Nikita Sobolev, CTO de la compañía We Do Services, sobre el problema global de administrar la complejidad del código en el contexto del desarrollo de lenguajes de programación. Y también sobre por qué aquí con el tiempo la situación solo empeora. Además, le preguntaron por qué necesitaba crear su propia peluquería.




- Cuéntanos algunas palabras sobre ti y tu trabajo.

Soy el director técnico de "Hacemos servicios". Hablando el nombre de la empresa, generalmente hago la pregunta: "¿Qué piensas, qué estamos haciendo?". De hecho, nos especializamos en desarrollo web: frontend y backend para clientes corporativos. Y trabajamos de acuerdo con nuestra propia metodología, que estamos mejorando en paralelo con el desarrollo de la empresa: proceso de desarrollo de software repetible (RSDP).

- En Moscow Python Conf ++ hablarás, incluso sobre tu propio linter. ¿Cómo se relaciona su trabajo con la auditoría y la gestión de la complejidad del código?

En general, tenemos dos áreas principales: el desarrollo en sí y todo lo que lo rodea: consultoría, elaboración de requisitos y, en particular, auditoría, durante el cual veo mucho código de otras personas. El código es completamente diferente: el que ahora está en desarrollo y el legado, que nadie solucionará; y el código que escriben los especialistas del cliente, y el que ordenaron a un lado. Y en todas las versiones del código hay muchos problemas: iguales y diferentes.

- Hablarás con los desarrolladores específicamente en Python. ¿Python tiene alguna característica en términos de gestión de la complejidad del código?

Por supuesto!

En primer lugar, todos los idiomas con tipeo dinámico sufren en mayor medida la complejidad injustificada, al menos debido a la falta de contexto adicional al leer el código. Y se te permite más suciedad.

En segundo lugar, Python se está desarrollando activamente. Tiene nuevos elementos de sintaxis, nuevos conceptos y módulos en bibliotecas estándar que rompen todo lo que era antes.

- ¿Qué tan malo es todo en Python? Después de todo, hay otros lenguajes en desarrollo activo, por ejemplo, JavaScript, que a menudo se critica por esto. ¿JavaScript es mejor?

No Incluso diría que en términos de complejidad, Python es bastante bueno con respecto a otros lenguajes. JavaScript es realmente malo por una simple razón: en el código del proyecto JS, varias entidades que no están relacionadas con el lenguaje en sí se mezclan a la vez: complementos y bibliotecas de terceros que se utilizan para construir el proyecto. Por ejemplo, si usa Webpack, puede escribir la función `import ()`, que carga los módulos de forma asincrónica. Resulta que el recopilador inserta parte de su interior en su lenguaje de programación, y al final generalmente no está claro qué está sucediendo.

Administrar la complejidad es difícil cuando el idioma cambia al instalar Babel o sus complementos. Y para comprender cómo funcionan, debe seguir los estándares del idioma, la implementación específica, etc.

En Python, la situación es mucho mejor. El lenguaje se está desarrollando de manera bastante sistemática, y este desarrollo tiene hitos comprensibles. En él, no puede cambiar radicalmente la sintaxis con dos líneas en la configuración. Y esto sigue siendo un back-end, al que estamos acostumbrados a hacer mayores demandas que a la interfaz. Sin embargo, en mi opinión, en Python hay bastantes cambios nuevos que rompen lo que era antes, trayendo beneficios dudosos.

- Es decir, con el desarrollo del lenguaje, ¿todo empeora?

Si recuerdas que apareció AsyncIO, esencialmente un segundo idioma dentro de Python, por supuesto, la complejidad ha crecido mucho. De hecho, ahora hay dos lenguajes de programación completamente independientes con una sintaxis similar: Python y Python + AsyncIO. Es decir, Python como entidad se ha vuelto más complicado el doble, porque tiene dos descendientes separados que trabajan de acuerdo con diferentes reglas.

La opinión de que estos son lenguajes de programación diferentes no es popular. Sin embargo, cuando le pide a los opositores de esta opinión, por ejemplo, que ejecuten una función asincrónica a partir de un código sincrónico, fallan. Las bibliotecas también son completamente diferentes. Quiere utilizar una biblioteca síncrona para trabajar con la base de datos, por favor. Y quieres asíncrono, no lo es.

Pero en Python, que se escribió hace cinco años, nada cambió realmente, e incluso viceversa, aparecieron herramientas que simplificaron el código, por ejemplo, anotaciones y verificación de tipos.

- ¿La gestión de la complejidad afecta el hecho de que en la programación ahora hay muchas personas con una base técnica débil?

Por supuesto Para esas personas, incluso se les ocurrió un lenguaje de programación especial. Se llama Go. No estoy bromeando De hecho, el objetivo de crear el lenguaje Go fue un intento de involucrar a los estudiantes y pasantes de Google que no pueden aprender C ++ al escribir código. Python no les convenía en rendimiento, necesitaban algo más, y Google ideó Go. Al final resultó que, muchas personas están listas para escribir en él, porque es muy simple. ¿Pero a qué costo se ha logrado esta simplicidad? No nos dan un lenguaje de programación normal, sino su versión muy truncada: prácticamente no hay conceptos complicados por diseño en él. No hay genéricos, no hay excepciones, etc. Y hay muchos fanáticos de este enfoque.

Pero hay otros desarrolladores, y para ellos el problema es que hay lenguajes en los que no hay equilibrio: puedes hacer cosas simples simplemente y no puedes hacer cosas complejas en absoluto. O al menos a través del dolor: tienes que luchar con una herramienta para hacer algo. Aquí, me parece, está el problema de manejar la complejidad.

- ¿Cuáles son los problemas típicos del código de otra persona?

Por lo general, se dividen en dos partes.

El primero son los problemas asociados con el hecho de que las personas no pueden ponerse de acuerdo sobre dónde colocar las comas condicionales. Usted lee un código y ve comas en un lugar, cambia a otro archivo y ve comas en otro lugar. Esto complica la percepción, como si leyera un libro impreso en un lugar en negrita y en otro en cursiva. Esto distrae del contenido, porque el cerebro tiene que reconocer que es una forma diferente de escribir lo mismo.

Cuando corrige la sintaxis, comienza a prestar atención a la semántica, porque las personas escriben conceptualmente de manera diferente. Desafortunadamente, no hay forma de ponerse de acuerdo en este nivel: es imposible llegar a un acuerdo de que resolvamos tales problemas de esta manera, pero son tales. No es posible cubrir todos los casos inicialmente. Este proceso ocurre durante una revisión de código de una tarea inmediata: cuando se explica al desarrollador por qué no se puede tomar su decisión. Si se aplica la práctica de revisión de código y los revisores son buenos, cortan las curvas de solución y no hay problemas en el código. Pero generalmente llegamos a la auditoría donde dicho proceso no está establecido. Y los problemas de semántica y arquitectura son mucho más difíciles de resolver, porque a veces son difíciles de formular y definir por sí mismos.

- ¿Y cómo se ve en la práctica?

Por ejemplo, las personas pueden resolver el mismo problema en plantillas, en vistas o en modelos. Y no existe una comprensión generalmente aceptada de dónde exactamente se debe resolver esta tarea: no hay documentación o patrones aplicables específicamente a este proyecto (por ejemplo, aquí usamos modelos gruesos y ponemos toda la lógica en ellos, pero aquí usamos modelos delgados; buenos o malos, ahora no importa, pero lo acordamos).

"¿Cuál es la razón principal por la que estos problemas existen?"

Todas las personas no saben cómo escribir código.

Esta tesis se descifra de la siguiente manera: el problema es que somos personas. Y, en general, es muy difícil para nosotros escribir algo estructurado y lógico. Y aquí también tenemos dos tipos diferentes de destinatarios. En primer lugar, esta es la persona que leerá este código y, en segundo lugar, esta es la máquina que debe ejecutarlo. El código para la máquina debe crearse de acuerdo con los criterios de rendimiento, consumo de memoria y tiempo de CPU, y el código para la persona debe basarse en los principios de legibilidad, inteligibilidad, etc. Estas son dos tareas opuestas. Y una persona que, de hecho, no puede resolver completamente ni siquiera uno de ellos, se ve obligada a resolver ambas tareas contradictorias al mismo tiempo.

"¿Pero el uso de diferentes patrones de programación es esencialmente una búsqueda de ingeniería?" ¿Es realmente malo?

Por supuesto, la investigación de ingeniería es importante y necesaria. Pero también debe ser manejable. Antes de cada tarea de este tipo, es necesario establecer criterios y limitaciones claros: de acuerdo con el tiempo empleado, los requisitos comerciales, las prácticas y herramientas de ingeniería.

Es mucho más probable que observe búsquedas creativas. No existen tales restricciones, validación de los resultados obtenidos tampoco. La calidad, como en el arte contemporáneo, no se puede medir.

Casi todos los clientes que recurren a nosotros para una auditoría sufren una situación típica: alguien les hizo algo, contrataron a un desarrollador para que de alguna manera desarrolle una solución, pero él vino y extendió sus manos: "No sé qué aquí para hacer, reescribamos todo ". ¿Sería bueno reescribir? No será Cuando decides reescribir, pisas exactamente el mismo rastrillo: confías la tarea a otro desarrollador que comete otros errores, pero al final todo resulta exactamente igual.

- ¿Necesitas algún otro enfoque?

Si Durante la auditoría, tratamos de encontrar la causa de los problemas con el código: por qué alguien no tomó e infló el módulo hasta el punto de que sería difícil desplazarse, y por qué se tomó inicialmente la decisión incorrecta. Y estamos tratando de automatizar o simplificar tanto como sea posible las decisiones correctas dentro de los límites establecidos.

Le daré un pequeño detalle al informe. Todos entienden que el código consiste en líneas: esta es la entidad más simple en la que puede consistir. Cada línea se puede escribir como

x = 1

o tal vez como

x = Math.median(forecast_data) if forecast_data else compute_probability(default_model) .

Hay una gran diferencia entre estas dos líneas, porque entiendes fácilmente la primera y mucha lógica se concentra en la segunda. Es necesario ejecutarlo en la cabeza en paralelo con el intérprete. Por lo tanto, debe comenzar a controlar cómo escribe el código, con el control de una sola línea de código. Además, la línea se convierte en conceptos más complejos: funciones, clases, módulos, etc. Pero las reglas que aceptas deben ser una.

Como resultado, no prohibimos que se hagan muchas cosas. Porque la gestión se trata de prohibiciones impuestas.

- ¿Te has encontrado con cosas divertidas en el código de otra persona?

Por supuesto Incluso tengo un repositorio donde recopilo tales ejemplos de código.

El ejemplo más aterrador que vi me mostró que dentro de un ciclo de cien iteraciones, puedes definir una función. Para ser sincero, cuando lo miré, dentro de mi intérprete se rompió. Supuse que no sabía que era posible.

Hubo un caso en el que vimos muchos comentarios divertidos en el código. Alguien se quejó de la vida, del trabajo, hubo quienes escribieron: "Entiendo que estoy escribiendo tonterías, pero el cliente me obliga a hacerlo". Sin embargo, los clientes generalmente no lo obligan a escribir un código incorrecto. Piden resolver su problema, y ​​qué código escribes allí, no les importa.

- Linter, revisión de código: ¿no guardar?

Tengo dos respuestas Sí lo hacen. No, no guardan. Ayuda si sigue estrictamente las reglas y regulaciones que le otorgan las linternas alineadas (aquellas que hacen un trabajo duro por usted: compruebe las funciones para ver la complejidad, la semántica del código, etc.). Este artículo debe estar bloqueando. No puedes simplemente ejecutar el linter a veces para ver el resultado. Si no cumplió con estas reglas, no debería liberar el código en producción.

Pero, de hecho, no ahorran. Porque esos proyectos que lo usan son raros.

Por cierto, a menudo me preguntan: ¿cómo presentar esto? Y respondo: es muy simple, pones una línea en CI - verifica mi código - y si falla, eso es todo, lo implementaste. Solo queda refactorizar todo. Afortunadamente, ahora hay autoformadores y la capacidad de refactorizar código por archivo. La siguiente pregunta es tradicional: ¿cómo explicarle al negocio que esto es importante?

- ¿Hay alguna respuesta general a esta pregunta?

Para cada caso, las respuestas son diferentes, por lo que en el caso general es difícil de formular (debe pensar en eso, en esto ...). Pero por lo general, las empresas que se ocupan de este problema provienen del lado técnico. Es decir Los expertos en tecnología nos preguntan, ya que las personas que saben hablar de negocios y de tecnología entienden cómo explicar esto a las empresas en su caso particular. Con tal declaración del problema, esto simplemente funciona. Cuando vienes, todo ya está mal, y todos entienden esto. Una conversación con los negocios comienza así: "¿Probablemente piensas que tus programadores están sentados y no hacen nada?" Y el negocio asiente. Y dices que ese no es el punto. Los programadores son buenos tipos que intentan resolver tus problemas. Pero sin un enfoque integrado para la gestión de proyectos, todo cae en el caos, y esto es normal.

Y proponemos proponer reglas para evitar ciertos problemas. Consideramos el costo de introducir diferentes piezas, y luego evaluamos las pérdidas reales (logradas) por el hecho de que todavía no existen tales piezas. Por ejemplo, los programadores han estado reparando un error durante un mes que no existe o que se puede encontrar en 30 segundos, si utiliza un enfoque y una herramienta específicos. Los números convencen bien.

- Al final, ¿es esto un problema administrativo?

Por supuesto Estoy convencido de que los programadores quieren escribir un buen código. Pero hay varios obstáculos. Alguien no sabe cómo por falta de experiencia. Alguien ha perdido la motivación, porque a todos no les importa. Alguien no sabe qué es exactamente un buen código por la razón, por ejemplo, el lanzamiento creativo. Presionan a alguien: él quiere y puede escribir, pero le dicen que debería ser mañana. Y en lugar de construir asociaciones con empresas y explicar por qué esto no sucederá mañana (o si sucede, entonces será necesario gobernar por otros tres días), lo hace de todos modos. Y tales asociaciones son interesantes para el negocio en sí. También necesita que funcione durante mucho tiempo y que sea económico de mantener.

Es decir, todos los problemas se resuelven aquí: no hay contradicciones insolubles.

- Hay un estilo de código - PEP 8. ¿No ayuda entender rápidamente qué es bueno?

En términos de comas, ayuda. Pero, ¿qué sentido tiene poner las comas correctas y todo lo demás es malo?

- ¿Te faltan algunas cosas conocidas de alto nivel?

En teoría, hay algunas mejores prácticas de ingeniería. Pero son desconocidos o ignorados. Cuando pregunta por qué el desarrollador no siguió esta práctica, dice que escuchó que este es un buen tema, pero el código funciona así. Cuando el código deja de funcionar, le preguntas si entendió de dónde vino la mejor práctica correspondiente y por qué seguirla. No, no lo entiendo. Él cree que simplemente se equivocó.

Es bastante difícil explicarle a una persona que cometer errores es normal. Todos están equivocados, todos somos humanos. Pero la mejor práctica de ingeniería fue inventada para salvarte de un error o protegerte de las consecuencias. Es decir Es una herramienta de seguridad, como en las empresas. Solo está escrito no con sangre, sino con tiempo y dinero abandonados.

En general, nuestra tarea global inalcanzable es automatizar la revisión de código para que Python mismo (si estamos hablando de nuestro caso) sepa cómo escribirlo. Esta debería ser una herramienta que brinde no solo oportunidades, sino también limitaciones para los desarrolladores.

- ¿Por qué estás desarrollando una pelusa? ¿Es posible usar (o desarrollar) los existentes?

De hecho, lo hacemos. Nuestro linter, de hecho, es un complemento para Flake8. Simplemente lo posicionamos como una herramienta completa, y no solo como un complemento.

¿Por qué Flake8 y no Pylint? Pylint hace mucho de lo que el linter no debe hacer. Por ejemplo, implementa una gran cantidad de verificaciones de tipo, aunque el verificador de tipo debe ocuparse de los tipos. Además, produce una gran cantidad de errores, que en realidad no lo son. Y no me gusta su documentación, y tengo miedo de su propia implementación de ast. Es difícil de configurar. Al habilitar la configuración, está permitiendo que las personas tomen las decisiones equivocadas. Por lo tanto, nuestra tarea es hacer una herramienta que no se pueda configurar. Así que lo pones, eso es todo.

- ¿Qué guías formaron la base de este linter? ¿O es solo tu propia experiencia aquí?

Ahora se basa en las reglas que hemos estado formulando para nosotros en la revisión del código durante muchos años. Algunas reglas fueron portadas de otras linters: ESLint, Pylint, SonarQube, Credo. Mucho se ha tomado del excelente trabajo de CognitiveComplexity . Siempre miraba hacia la billetera de Miller. Reglas separadas: esta es mi visión, que apareció después de evaluar una gran cantidad de código de otras personas. Es decir, en esta etapa es un "batiburrillo".

- ¿De qué hablarás en Moscow Python Conf ++?

En primer lugar, sobre la gestión de la complejidad . Este tema es cercano y comprensible para todos los desarrolladores. Analizaremos diferentes métricas, sobre formas de transferir complejidad desde el código de componente más simple - líneas - al módulo más complejo. Y luego hablaremos sobre la parte holivaria, donde presentaré mi visión de cómo escribir o no escribir en Python, y pediré a los usuarios que voten sobre lo que les gusta y lo que no. Para muchos desarrolladores, las restricciones (hacer A, pero no hacer B) son un intento en su espacio creativo, por lo que reaccionan muy violentamente a esto. Y justo aquí puedes comenzar una discusión interesante.

- ¿En quién se enfoca el informe?

Creo que estos todavía son desarrolladores establecidos, porque los programadores novatos aún no han formado su opinión clara. Aunque será interesante para ellos escuchar y hablar. Definitivamente son nuestros usuarios.



, , Moscow Python Conf++ . . , .

Source: https://habr.com/ru/post/es424393/


All Articles