Problemas esquecidos,
Correndo parado
Injetado por robôs
Homem feliz!
Do filme "Exterminador da infância" "Eletrônica de Aventura"
Olá, hoje vamos falar sobre desempenho novamente. Sobre a produtividade dos desenvolvedores.
Vou falar sobre como bombear essa habilidade através das Ideias. Espero que minhas dicas sejam úteis, comentários e melhorias sejam bem-vindos. Vamos lá!
Um desenvolvedor comum gasta uma parte considerável de seu dia útil em atividades rotineiras. Até recentemente, eu também atuava. E então alguns pensamentos simples e óbvios surgiram na minha cabeça:
- raramente escrevemos algo realmente novo e incomum
- uma parte significativa do tempo de trabalho, o desenvolvedor escreve o código do modelo
- muitas das construções simples que usamos são facilmente formalizáveis e, em nossas cabeças, as expressamos com algumas palavras
Como a maior parte do tempo em que trabalho com o Spring Booth / Hibernate, a maioria dos modelos e geração de código os preocupa, embora a abordagem seja universal e você possa facilmente fazer melhorias semelhantes nos seus projetos.
O teatro começa com um cabide e o aplicativo Spring Booth começa com as configurações. Geralmente eles são assinados no arquivo application.yml
/ application.properties
, mas também acontece que alguns beans / configurações precisam ser descritos com o código:
@Configuration @EnableSwagger2 class SwaggerConfig { @Bean Docket documentationApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } }
Essa configuração inclui o Swagger (um item útil na fazenda). Pense no que pode ser automatizado? Os desenvolvedores sabem que @Configuration
é colocado acima da classe de configurações. I.e. você pode criar uma espécie de espaço em branco - um modelo da classe de configuração e criá-lo com um movimento do pulso. A opção "Idéia" pronta para uso oferece ao usuário a oportunidade de personalizar os modelos existentes:

O que vamos usar:
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end import org.springframework.context.annotation.Configuration; @Configuration class ${NAME} { }
Para desenvolvedores experientes, tudo está claro aqui; para iniciantes, eu explicarei:
Linha 1: uma linha como essa será adicionada ao código da classe recém-criada
package com.example.-;
Linha 2: conecte a anotação desejada
Linha 3: classe corporal.
Observe que a variável ${NAME}
se transformará em uma janela pop-up onde precisaremos inserir o nome da classe.
Total:

Esse modelo evita a necessidade de escrever @Configuration
em uma classe com nossas @Configuration
mãos e resolver a importação. Não é muito, mas é importante começar e obter alguma experiência.
Apenas uma classe de configurações vazia vale pouco. Vamos aprender a criar beans sem esforço extra. Para fazer isso, em Editor> Modelos de arquivo e código , acesse Editor> Modelos dinâmicos . Aqui você pode descrever padrões reconhecidos digitando. No meu ambiente de desenvolvimento, defini uma subespécie separada para uso no Spring. Nele, criamos um modelo:
@Bean public $CLASS_NAME$ $mthdName$() { return new $CLASS_NAME$($END$); }
A variável CLASS_NAME
é definida pelo usuário em uma janela pop-up e, além da atribuição direta, é usada para criar um nome de método:

A variável mthdName
usa o método camelCase()
, que recebe o valor de CLASS_NAME
. A configuração ocorre em Editar variáveis :

A variável $END$
significa a posição do ponteiro após a renderização. Nosso bean provavelmente possui dependências (implementadas por meio do construtor), portanto, você precisa torná-los argumentos para o método que retorna nosso bean:

Agora, vamos examinar o aplicativo de cima para baixo e ver quais outras tarefas diárias podem ser aceleradas de maneira tão simples.
Serviço
O senso comum sugere que esse método será mais útil nos casos em que temos uma grande quantidade de código que vagueia de um lugar para outro. Por exemplo, um serviço regular de primavera provavelmente depende dos repositórios (o que significa que é necessário transacional), faz algum tipo de registro e as dependências são implementadas pelo construtor. Para não listar todas as anotações sobre a classe recém-criada a cada vez, descrevemos o modelo:
#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} { }
Em ação:

Em seguida, vem a odiosa lista de dependências. Acima, usamos o método camelCase()
para descrever o nome do método que retorna a lixeira. Eles também podem criar nomes de campos:

private final $CLASS_NAME$ $fieldName$; $END$
Para não pressionar Ctrl + Alt + L (alinhamento) a cada vez, ative a caixa de seleção Reformatar de acordo com o estilo e o ambiente fará tudo por você:

Repositórios e Entidades
Mesmo nas entidades mais simples, temos muitas anotações de importação. Você pode criar um modelo muito eficaz para eles:
#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; }

Em 2019, se você usar o Hibernate, certamente também usará a Data da Primavera e, nesse caso, precisará criar repositórios. Vamos acelerar a criação deles:
#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}>{ }

Seria ótimo se, ao definir o cursor na entidade (a classe marcada @Entity
e @Table
) e pressionar Alt + Enter, a “Idéia” sugerisse a criação imediata de um repositório, mas não é tão inteligente :). Atualmente, os usuários não têm a capacidade de alterar / adicionar intenções ( Editor> Intenções ), mas você pode escrever seu próprio plugin:

Teste
Em geral, quanto mais modelos forem construídos no seu código, maior será o ganho de automação. Um dos trabalhos mais repetidos são os testes. Quem assistiu ao relatório de Cyril Tolkachev, “A Maldição do Teste da Primavera”, sabe que existe uma maneira fácil de fazer o contexto subir apenas uma vez para todos os testes: criando uma classe abstrata e herdando todos os testes dela.
Descrevendo 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 facilmente fazer com que todos os testes recém-criados herdem o BaseTest
. Para fazer isso, você precisa alterar o modelo que cria o teste padrão:

No 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 seguir, descrevemos as dependências. Eu não quero discar toda vez
@Autowired private MyService service;
portanto, na seção Editor> Modelos ao vivo, escreva
@Autowired private $CLASS_NAME$ $fieldName$; $END$
A variável $fieldName$
descrita exatamente da mesma maneira que no exemplo de criação de um bean, com uma exceção: para imediatamente após a criação de um campo, o cursor não muda para ele, é necessário marcar Ignorar se definido :

Basicamente, o @Autowired
necessário apenas para os campos da classe, portanto, defina Declaração no menu suspenso Aplicável :

Nós olhamos:

A propósito, como estamos criando um teste para uma determinada classe, nada nos impede de introduzir a dependência necessária imediatamente quando ela é criada ( toCamelCase()
não funciona aqui, então o Velocity é usado):
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} }

Minha experiência sugere que, sempre que possível, todos os testes devem ser transversais. Mesmo que seja verificado um serviço que retira a entidade e corta parte de um de seus campos, ainda é melhor obter a entidade honestamente, ou seja, do banco de dados. Portanto, na maioria dos testes, pego dados honestos de um dos ambientes e os carrego antes de executar o teste usando o @Sql
.
A amostragem de dados precisa ser feita manualmente para cada tarefa, mas vinculá-los ao teste desejado pode ser facilmente automatizado. Novamente, vá para Editor> Modelos ao vivo , a seção JUnit e escreva:
@Sql("/sql/$CLASS_NAME$.sql") $END$

Agora, digitando sql
, obtemos um menu suspenso com 1 registro, selecionando o que obtemos:
@Sql("/sql/MyEntityRepositoryTest.sql") class MyEntityRepositoryTest extends BaseTest { }
Observe que o arquivo ao qual estamos nos referindo ainda não existe; portanto, quando você executa o teste no formato bruto, ele certamente trava. No entanto, a partir da versão 193.1617 , o Idea destaca um arquivo inexistente e, o mais importante, sugere criá-lo!

Postfixes
Uma das ferramentas mais poderosas é a criação / adição de código usando expressões postfix (terminações). O exemplo mais simples:

Há muitas conclusões, você pode vê-las na seção Editor> Geral> Conclusão do Postfix :

Também há espaço para vários tipos de experimentos. Por mim, fiz uma conclusão para substituir uma variável em uma expressão de teste baseada em AssertJ :

Na vida, fica assim:

Links úteis
Se você deseja melhorar suas habilidades com a idéia, verifique dois ótimos relatórios:
Anton Arkhipov - trabalho eficaz com o IntelliJ IDEA
Tagir Valeev - Refatoração atômica no IntelliJ IDEA: dobramos o IDE para nós mesmos
Isso é tudo, raramente se distrai e lembre-se de que o tempo é o nosso único recurso verdadeiramente não renovável.