Robots de trabajo - hombre feliz

Problemas olvidados
Ejecución detenida
Inyectado por robots
Hombre feliz!


De la pelicula "Terminador de la infancia" "Electrónica de aventura"


Hola, hoy volveremos a hablar sobre el rendimiento. Sobre la productividad de los desarrolladores.


Hablaré sobre cómo impulsar esta habilidad a través de las Ideas. Espero que mis consejos sean útiles, comentarios y mejoras son bienvenidos. Vamos!


Un desarrollador ordinario pasa una parte considerable de su jornada laboral en actividades de rutina. Hasta hace poco, también actué. Y luego surgieron algunos pensamientos simples y obvios en mi cabeza:


  • con poca frecuencia escribimos realmente algo nuevo e inusual
  • Una parte importante del tiempo de trabajo, el desarrollador escribe código de plantilla
  • Muchas de las construcciones simples que utilizamos son fácilmente formalizables, y en nuestras cabezas las expresamos con unas pocas palabras.

La mayor parte del tiempo que trabajo con Spring Booth / Hibernate, por lo que la mayor parte de la generación de código y las plantillas les conciernen, aunque el enfoque es universal y puede realizar fácilmente mejoras similares para sus proyectos.


El teatro comienza con una percha, y la aplicación Spring Booth comienza con la configuración. Por lo general, se firman en el archivo application.yml / application.properties , pero también sucede que algunos beans / configuraciones deben describirse con el código:


 @Configuration @EnableSwagger2 class SwaggerConfig { @Bean Docket documentationApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } } 

Esta configuración incluye Swagger (un elemento útil en la granja). ¿Piensa en lo que se puede automatizar? Los desarrolladores saben que @Configuration se coloca por encima de la clase de configuración. Es decir puede crear una especie de espacio en blanco: una plantilla de la clase de configuración y crearla con un simple movimiento de la muñeca. Fuera de la caja, "Idea" le da al usuario la oportunidad de personalizar las plantillas existentes para sí mismo:



Lo que usaremos:


 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end import org.springframework.context.annotation.Configuration; @Configuration class ${NAME} { } 

Para desarrolladores experimentados, todo está claro aquí, para principiantes explicaré:


Línea 1: una línea como esta se agregará al código de la clase recién creada


 package com.example.-; 

Línea 2: conecte la anotación deseada
Línea 3: clase corporal.


Tenga en cuenta que la variable ${NAME} se convertirá en una ventana emergente donde necesitaremos ingresar el nombre de la clase.


Total:


Esta plantilla nos evita tener que escribir @Configuration en una clase con nuestras @Configuration manos y resolver la importación. No mucho, pero es importante para nosotros comenzar y adquirir algo de experiencia.


Una clase de configuración vacía solo vale poco. Aprendamos a crear frijoles sin esfuerzo adicional. Para hacer esto, desde Editor> Plantillas de archivos y códigos , vaya a Editor> Plantillas en vivo . Aquí puede describir patrones reconocidos al escribir. En mi entorno de desarrollo, definí una subespecie separada para usar con Spring. En él creamos una plantilla:


 @Bean public $CLASS_NAME$ $mthdName$() { return new $CLASS_NAME$($END$); } 

El CLASS_NAME variable CLASS_NAME en una ventana emergente y, además de la asignación directa, se usa para crear un nombre de método:



La variable mthdName utiliza el método camelCase() , al que se le pasa el valor de CLASS_NAME . La configuración tiene lugar en Editar variables :



La variable $END$ significa la posición del puntero después de la representación. Nuestro bean probablemente tiene dependencias (implementadas a través del constructor), por lo que debe hacer que sean argumentos para el método que devuelve nuestro bean:



Ahora veamos la aplicación de arriba a abajo y veamos qué otras tareas diarias se pueden acelerar de una manera tan simple.


Servicio


El sentido común sugiere que este método será más útil en los casos en que tengamos una gran cantidad de código que va de un lugar a otro. Por ejemplo, un servicio de primavera regular probablemente depende de los repositorios (lo que significa que se necesita una transacción), realiza algún tipo de registro y las dependencias se implementan a través del constructor. Para no enumerar todas las anotaciones sobre la clase recién creada cada vez, describimos la plantilla:


 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse("File Header.java") import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; @Log4j2 @Service @Transactional @RequiredArgsConstructor public class ${NAME} { } 

En acción:



Luego viene la odiosa lista de dependencias. Arriba, utilizamos el método incorporado camelCase() para describir el nombre del método que devuelve el bean. También pueden crear nombres de campo:



 private final $CLASS_NAME$ $fieldName$; $END$ 

Para no presionar Ctrl + Alt + L (alineación) cada vez, active la casilla de verificación Reformatear según el estilo y el entorno hará todo por usted:



Repositorios y Entidades


Incluso en las entidades más simples, tenemos muchas anotaciones de importación. Puede crear una plantilla muy efectiva para ellos:


 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse("File Header.java") import lombok.Getter; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Getter @Table @Entity public class ${NAME} { @Id private Long id; } 


En 2019, si usa Hibernate, seguramente también use Spring Date, y si es así, entonces necesita crear repositorios. Aceleremos su creación:


 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse("File Header.java") import org.springframework.data.jpa.repository.JpaRepository; public interface ${Entity_name}Repository extends JpaRepository<${Entity_name}, ${Key}>{ } 


Sería genial si, al establecer el cursor en la entidad (la clase marcada @Entity y @Table ) y presionar Alt + Enter, la "Idea" sugiriera crear inmediatamente un repositorio, pero no es tan inteligente :). Actualmente, los usuarios no tienen la capacidad de cambiar / agregar intenciones ( Editor> Intenciones ), pero puede escribir su propio complemento:



Prueba


En general, mientras más construcciones de plantillas haya en su código, mayor será la ganancia de automatización. Una de las piezas de trabajo más repetidas son las pruebas. Los que vieron el informe de Cyril Tolkachev "La maldición de la prueba de primavera" saben que hay una manera fácil de hacer que el contexto se levante solo una vez para todas las pruebas: crear una clase abstracta y heredar todas las pruebas de ella.


Describiendo algo como


 package com.example; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; import org.springframework.test.context.junit.jupiter.SpringExtension; @Transactional @SpringBootTest @ExtendWith(SpringExtension.class) public abstract class BaseTest { } 

podemos hacer fácilmente que todas las pruebas recién creadas hereden BaseTest . Para hacer esto, debe cambiar la plantilla que crea la prueba predeterminada:



En código:


 import com.example.BaseTest; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; #parse("File Header.java") class ${NAME} extends BaseTest { ${BODY} } 

A continuación describimos las dependencias. No quiero marcar cada vez


 @Autowired private MyService service; 

por lo tanto, en la sección Editor> Plantillas en vivo, escriba


 @Autowired private $CLASS_NAME$ $fieldName$; $END$ 

La variable $fieldName$ describe exactamente de la misma manera que en el ejemplo de creación de un bean, con una excepción: para inmediatamente después de crear un campo, el cursor no cambia a él, debe marcar Omitir si está definido :



Básicamente, @Autowired solo @Autowired necesario para los campos de clase, así que asegúrese de establecer la Declaración en el menú desplegable Aplicable :



Buscamos:



Por cierto, dado que estamos creando una prueba para una determinada clase, nada nos impide introducir la dependencia necesaria inmediatamente cuando se crea ( toCamelCase() no funciona aquí, por lo que se usa Velocity ):


 import com.example.demo.BaseTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; #parse("File Header.java") class ${NAME} extends BaseTest { #set($bodyLength = $NAME.length() - 4) #set($field = $NAME.substring(0, 1).toLowerCase() + $NAME.substring(1, $bodyLength)) @Autowired private ${CLASS_NAME} ${field}; ${BODY} } 


Mi experiencia sugiere que, siempre que sea posible, todas las pruebas deben ser transversales. Incluso si se verifica un servicio que elimina a la entidad y corta parte de uno de sus campos, es mejor obtener la entidad con honestidad, es decir. de la base de datos. Por lo tanto, para la mayoría de las pruebas, tomo datos honestos de uno de los entornos y los cargo antes de ejecutar la prueba usando @Sql .


El muestreo de datos debe hacerse a mano para cada tarea, pero vincularlos a la prueba deseada puede automatizarse fácilmente. Nuevamente, vaya a Editor> Plantillas en vivo , la sección JUnit y escriba:


 @Sql("/sql/$CLASS_NAME$.sql") $END$ 


Ahora, escribiendo sql , obtenemos un menú desplegable con 1 registro, seleccionando cuál obtenemos:


 @Sql("/sql/MyEntityRepositoryTest.sql") class MyEntityRepositoryTest extends BaseTest { } 

Tenga en cuenta que el archivo al que nos referimos aún no existe, por lo que cuando ejecuta la prueba en forma cruda, sin duda se bloqueará. Sin embargo, a partir de la versión 193.1617 , la Idea resalta un archivo inexistente y, lo más importante, ¡sugiere crearlo!



Postfixes


Una de las herramientas más poderosas es la creación / adición de código usando expresiones postfix (terminaciones). El ejemplo más simple:



Hay muchas finalizaciones, puedes verlas todas en la sección Editor> General> Finalización de postfix :



También hay margen para varios tipos de experimentos. Por mi parte, realicé una sustitución para sustituir una variable en una expresión de prueba basada en AssertJ :



En la vida, se ve así:



Enlaces utiles


Si va a mejorar sus habilidades con la Idea, asegúrese de revisar dos excelentes informes:


Anton Arkhipov - trabajo efectivo con IntelliJ IDEA
Tagir Valeev - Refactorización atómica en IntelliJ IDEA: doblamos el IDE por nosotros mismos


Eso es todo, rara vez se distrae y recuerde que el tiempo es nuestro único recurso verdaderamente no renovable.

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


All Articles