工作机器人-快乐的人

被遗忘的烦恼
跑步停止
由机器人注入
快乐的人!


电影中 “童年终结者” “冒险电子”


嗨,今天我们再谈性能。 关于开发人员的生产力。


我将讨论如何通过“创意”提升这项技能。 希望我的提示有用,欢迎提出评论和改进。 走吧


普通的开发人员将大部分工作时间都花在日常活动上。 直到最近,我也表演了。 然后我脑中浮现出一些简单而明显的想法:


  • 我们很少会写一些新奇的东西
  • 在工作时间的很大一部分中,开发人员编写了模板代码
  • 我们使用的许多简单构造都易于形式化,在我们的脑海中,我们用几句话来表达它们

我使用Spring Booth / Hibernate的时间最多,因此大多数代码生成和模板都与它们有关,尽管这种方法是通用的,并且您可以轻松地为项目进行类似的改进。


剧院从衣架开始,而Spring Booth应用程序从设置开始。 通常,它们是在文件application.yml / application.properties中签名的,但是也有一些bean /配置必须用代码来描述:


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

此设置包括Swagger(服务器场上的一个有用项目)。 考虑什么可以自动化? 开发人员知道@Configuration位于settings类的上方。 即 您可以创建一种空白-配置类的模板,并轻轻一挥即可创建它。 开箱即用的“想法”为用户提供了为自己定制现有模板的机会:



我们将使用:


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

对于有经验的开发人员,这里的内容很清楚,对于初学者,我将解释:


第1行:将这样的行添加到新创建的类的代码中


 package com.example.-; 

第2行:连接所需的注释
第三行:身体课。


请注意,变量${NAME}将变成一个弹出窗口,我们需要在其中输入类名。


总计:


此模板使我们不必手动在类上编写@Configuration并解决导入问题。 数量不多,但是对于我们来说开始并获得一些经验很重要。


一个空的设置类就没有什么价值。 让我们学习如何轻松创建bean。 为此,请从“ 编辑器”>“文件和代码模板” ,转到“ 编辑器”>“实时模板” 。 在这里,您可以描述通过键入识别的模式。 在开发环境中,我定义了与Spring一起使用的单独的亚种。 在其中,我们创建一个模板:


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

CLASS_NAME变量由用户在弹出窗口中设置,除直接分配外,还用于创建方法名称:



变量mthdName使用内置方法camelCase() ,该方法将传递CLASS_NAME的值。 设置发生在Edit变量中



变量$END$表示指针在渲染后的位置。 我们的bean可能具有依赖性(通过构造函数实现),因此您需要使它们成为返回我们的bean的方法的参数:



现在,让我们从上到下浏览应用程序,看看可以用这种简单的方式来加速其他日常任务。


服务专区


常识表明,这种方法在我们有大量代码会在不同地方徘徊的情况下最有用。 例如,常规的spring服务可能依赖于存储库(这意味着需要事务性),进行某种日志记录,并且依赖项是通过构造函数实现的。 为了不每次都列出新创建的类上的所有注释,我们描述模板:


 #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} { } 

实际上:



接下来是令人讨厌的依赖项列表。 上面,我们使用了内置的camelCase()方法来描述返回bin的方法的名称。 他们还可以创建字段名称:



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

为了不每次都按Ctrl + Alt + L (对齐),请启用“ 根据样式重新设置格式”复选框,环境将为您做所有事情:



储存库和实体


即使在最简单的实体中,我们也有许多导入注释。 您可以为他们创建一个非常有效的模板:


 #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; } 


在2019年,如果您使用的是Hibernate,那么当然也要使用Spring Date,如果是这样,则需要创建存储库。 让我们加快其创建速度:


 #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}>{ } 


如果将光标放在实体上(标记为@Entity@Table的类)并按Alt + Enter,则 “ Idea”会建议立即创建存储库,但这不是那么聪明: 当前,用户无法更改/添加意图( Editor> Intentions ),但是您可以编写自己的插件:



测试中


通常,代码中模板构造的数量越多,自动化收益就越大。 测试是重复性最高的工作之一。 那些看过Cyril Tolkachev “春季测试的诅咒”的报告的人知道,有一种简单的方法可以使所有测试的上下文只出现一次:创建一个抽象类,并从该类继承所有测试。


描述类似


 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 { } 

我们可以轻松地使所有新创建的测试继承BaseTest 。 为此,您需要更改创建默认测试的模板:



在代码中:


 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} } 

接下来,我们描述依赖性。 我不想每次都拨打


 @Autowired private MyService service; 

因此,在“ 编辑器”>“实时模板 ”部分中编写


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

变量$fieldName$描述与创建Bean示例中的描述完全相同,但有一个例外:要在创建字段后立即将光标不切换到该字段,您需要检查Skip如果已定义



基本上,@ @Autowired仅用于类字段,因此请确保在“ 适用于”下拉列表中设置“声明”



我们看:



顺便说一下,由于我们正在为某个类创建测试,因此没有什么阻止我们在创建它时立即引入必要的依赖项( toCamelCase()在这里不起作用 ,因此使用了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} } 


我的经验表明,只要有可能,所有测试都应贯穿于各个领域。 即使选中了一项服务以取出实体并切断其一部分字段的服务,还是最好诚实地获取实体,即 从数据库中。 因此,对于大多数测试,我使用一种环境从诚实的数据中获取一种数据,并在使用@Sql进行测试之前加载它们。


每个任务都需要手工完成数据采样,但是将它们链接到所需的测试可以轻松实现自动化。 再次,转到编辑器>实时模板JUnit部分,然后编写:


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


现在,输入sql ,我们将获得一个包含1条记录的下拉列表,并选择以下内容:


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

请注意,我们所指的文件尚不存在,因此当您以原始格式运行测试时,它肯定会崩溃。 但是,从版本193.1617开始,该Idea突出显示了一个不存在的文件,最重要的是,它建议创建它!



后缀


最强大的工具之一是使用后缀表达式(终止)来创建/添加代码。 最简单的例子:



有很多全,您可以在“ 编辑器”>“常规”>“后缀完成”部分中看到所有补全



也有各种实验的范围。 我自己完成了将变量替换为基于AssertJ的测试表达式的工作:



在生活中,它看起来像这样:



有用的链接


如果您打算通过Idea来提高自己的技能,请务必查看两个出色的报告:


Anton Arkhipov-与IntelliJ IDEA的有效合作
Tagir Valeev-IntelliJ IDEA中的原子重构:我们自己弯曲IDE


仅此而已,很少会分心,请记住,时间是我们唯一真正不可再生的资源。

Source: https://habr.com/ru/post/zh-CN465433/


All Articles