收藏!这些IDE使用技巧,你都知道吗

简介: 欲善其事,先利其器。对于研发同学,在日常的开发工作中,我们与之打交道最多的便是编程的IDE。能否高效和灵活的使用IDE,将对我们的工作效率起着举足轻重的作用。

 

一 、背景

1 、目的

欲善其事,先利其器。对于研发同学,在日常的开发工作中,我们与之打交道最多的便是编程的IDE。能否高效和灵活的使用IDE,将对我们的工作效率起着举足轻重的作用。

研发同学在开发中最主要做的两件事分别是架构设计和编码,前者主要取决于大量的项目经验积累和个人的思考深度,也是作为研发的核心竞争力,短时间内很难快速求成;后者主要取决于日常的编码练习和一定程度的IDE信息差,能够通过下文中介绍的一系列技巧进行能力的快速补齐和巩固加强。

本文的主要目的有两方面:

  • 一方面,对IDE的快捷操作和高效技巧,结合自己多年的实践和理解,进行一次系统性的总结和梳理。
  • 另一方面,希望通过本文系统性的梳理,能够帮助更多的同学提高研发效率,无论你是刚入手不久的新人,还是有着多年开发经验的专家,相信你都能够在本文中发现一片新天地,让你能够有更多的时间和精力去做更有意义的事情。

2 、定位

网上很多技术网站和个人博客,对于IDE各种技巧和便捷操作总结得非常具体且详细,对于单点的详尽程度都是极具参考和学习价值的。但其对应的问题是,这些很多很优秀的文章,出自于不同的手笔,有各自的行文风格,且分散在各个网站的散点,难以系统化。

我对本文的定位是,将各种技巧以大分类的形式进行收拢和聚合,以帮助大家构建和完善整体的知识体系,大幅度提高开发效率。对于每个分类点到即止,替代咀嚼式灌输方式的是,尽量使用渐进式引导的方式。

3 、普适性

JetBrains系列的IDE产品众多,除了下图之外,还有其他未列入的,如Google二次开发的Android Studio等。虽然归为多个产品实例,但这些IDE的内核都是一样的,只是在内核的基础上额外添加了各自的语言特性。本文将以使用量最高的一款IDE——IDEA为例进行展开,文中提到的绝大多数能力和技巧,在其他IDE均同样适用,一通则百通。

 

二、 Postfix Completion

1 、介绍

Postfix Completion (下称Postfix) 是一种通过 . + 模板Key 来对当前已经输出的表达式,添加和应用预设代码模板的编码增强能力。

其核心要解决的问题是,将编码过程中一些通用的代码结构范式进行抽象和沉淀,并能在同类型的场景下,通过 . + 模板Key 的方式进行唤醒和复用。

举个例子,现在需要完成下面一段代码的编写,为了对name参数进行判空保护:

if (name != null) {}

在普通文本编辑器中,其中 if 2次,name 4次,(){}!= 共6次,再加空格Tab和光标切换,一共需要按键23次。

在IDEA编辑器中,不使用Postfix时,一共需要按键20次,不考虑代码格式化的情况可以减少到16次。

在IDEA编辑器中,使用Postfix时,只需要8次,如下图:

 

在这个例子中,可以对比出使用Postfix前后的效果,使用之后在编码中减少了一半的手动按键操作,且生成的代码是自带格式化的。在实际的编码过程中,各项目大小和复杂度差异性虽然很大,但细化到这种基本单位的编程范式时,它们都是融会贯通的。

与上例中nn并列的Postfix,IDEA给我们预设的还有很多,下面对一些非常高频使用的Postfix进行梳理。

2 、梳理

var

快速定义一个局部变量,自带IDE的类型推断

 

notnull

快速进行NPE的判空保护:

 

nn

同notnull,是它的简写,推荐用这个,更加便捷:

 

try catch

快速对当前语句添加try catch异常捕获,同时IDE还会对catch中的Exception自动做类型推断:

 

cast

快速实现类型强转,不需要反复使用()包裹和光标切换;配合instanceof使用时还能自动实现cast类型的推断:

 

if

快速实现if判断的代码范式:

 

throw

快速实现抛异常:

 

for

快速实现集合或数组的迭代:

 

fori

快速实现集合或数组的带索引值迭代;同时对整型数字也支持:

 

sout/soutv

快速实现(不带参数/带参数)的打印功能:

 

return

快速实现方法中的值返回逻辑:

 

format

快速实现字符串格式化:

 

3 、高级用法

担心系统预设的Postfix不足以满足我们的编码需求,IDEA还提供了Postfix的自定义功能。

这里我以自定义一个对集合判空的代码范式,来举例说明自定义Postfix的流程:

1)进入IDE设置界面,然后依次进入Editor => General => Postfix Completion => 面板左下角加号 => Java:

 

2)在弹起的页面中,按照下图进行配置,然后保存退出设置页。

 

此时我们自定义的 isempty 这个Postfix即完成了,下面来看下实际使用的效果:

 

在实际开发过程中,对于根据已经输入的表达式就能决定接下来代码格式的功能,我们都能使用这种自定义方式进行代码的抽象和复用。

接下来介绍IDE中一种跟Postfix功能很相像,但灵活度更高的能力——Live Template。

三、 Live Template

1、 介绍

介绍之前可以先看一段简短的编码过程:

 

上面这段编码中,我先后使用了Live Template的以下三个模板能力:

  • psfs:定义字符串常量
  • main:添加入口函数
  • sout:实现日志输出

这里我们将其和上面提到的Postfix对比来看,两者都是提供代码级别模板的功能。不同的是,Postfix需要一个已经输入的表达式和 . + 模板Key 来进行触发,而Live Template不需要这些,它仅仅需要 模板Key 即可触发。

Live Template提供的预设模板要比Postfix要高出一个数量级,因此这里我就不进行一一演示,我们可以进行设置面板,然后按照Editor => Live Templates的路径自行查看,如下图:

 

2 、高级用法

和Postfix一样,Live Template也支持自定义模板,但它的自定义模板相对来说更加灵活和开放,甚至支持我们直接植入脚本。鉴于Live Template的高度灵活性,单独介绍这块会占据大量的篇幅,因此这里我将从几个实际的案例场景来开拓一下思路,而具体自定义拓展过程就不详细展开介绍了。

Key值映射

将DB中查询到 List 结构的数据,根据Key值映射转化为 Map<K, T> 结构的数据,以便于进行后续的数据填充逻辑:

 

DB批量查询

在数据查询时,我们会有根据ID主键进行批量DB数据查询的诉求,如下:

List<User> users = userMapper.queryUserByIds(userIds);

这种写法会有一个弊端,就是当 userIds 大到一定的量级时,该查询会变得非常耗时。

对于该问题其中一个解法是,将这个大的 userIds 拆分成多个批次,然后让这多个批次异步并行去查询。这里便使用Live Template来抽取一个针对该场景的代码模板,如下:

 

按照该模板,我们的查询语句将变成这样:

List<User> users = batchQuery(userIds, 100, userMapper::queryUserByIds, null);

可以看到,和之前相比,多传一个分批的size参数,同时还支持指定的异步任务调度器的自定义配置,而返回结果和之前的查询方式保持完全一致,不需要外部有额外的适配工作。

脚本植入

这个功能是我非常看好Live Template的主要原因,它的灵活性和拓展性也主要来源于这里。它支持我们通过一个 模板Key 来唤起和执行一段脚本,这也就意味着,我们的自定义的Live Template模板是可编程的,极大程度提高了该模板的拓展性。

单描述功能会有些空洞,这里我结合一个实际案例进行介绍,我们来实现一个跨电脑的代码共享功能:

1)首先,使用python的flask框架写一个极简的服务端应用并启动,提供最简单的 push 和 pull 的能力,如下:

from flask import Flask, requestDEFAULT = 'nothing'
code = DEFAULTapp = Flask(__name__)@app.route('/push')
def push():global codecode = request.args.get('code', DEFAULT)return 'Success'@app.route('/pull')
def pull():return codeapp.run()

2)然后,我们来通过groovy脚本实现一个代码 pull 的模板,这里应用了Live Template的 groovy script 能力,对应脚本如下:

def url = new URL('http://127.0.0.1:5000/pull');
def conn = url.openConnection() as HttpURLConnection;
def result = conn.inputStream.text;
return result

3)最后,再实现代码push的模板,脚本如下(下面的代码入参,是通过剪切板赋值传递过来的):

def code = _1;
def url = new URL('http://127.0.0.1:5000/push?code=' + new URLEncoder().encode(code));
def conn = url.openConnection() as HttpURLConnection;
def result = conn.inputStream.text;
return result

此时就已经完成了跨设备的代码分享功能,为方便演示,这里就用 People1 和 People2 两个类来模拟两台独立的电脑。People1 将自己的一段代码复制到剪切板中,然后通过 push 模板调用 push 接口来将这段代码上传到Python服务应用中;People2 再通过 pull 脚本来调用服务端的 pull 接口,访问到 People1 上传的代码并输入到当前的代码编辑器中,实现效果如下图:

 

这里的代码共享只是一个引子,除此之外,我们还能写很多有意思的脚本,比如在IDE中查天气、通过IDE聊天等等,自行脑补拓展。

介绍完Live Template之后,接下来介绍文件级别的模板——File Template。

四 、File Template

1 、介绍

File Template,顾名思义,对应文件级别的模板。对于该模板,我们使用脚本的主要在于两个场景,分别是文件头和文件的自定义,下面结合案例依次展开。

2 、自定义文件头

按照下图的路径,来更改文件头的格式,IDE就会在我们新建一个类或接口时,根据这里的配置格式来自动生成对应的文件注释头。

 

3 、抽象通用Controller

看下面一段代码,这是一个针对于User这个domain的增删改查接口类:

package com.alibaba.ide.code.controller;import com.alibaba.ide.code.entity.Result;
import com.alibaba.ide.code.entity.User;
import com.alibaba.ide.code.service.Condition;
import com.alibaba.ide.code.service.UserService;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;/*** @author puke* @version 2021/2/9*/
@RestController
@RequestMapping("api/user")
public class UserController {@Resourceprivate UserService userService;@PostMappingpublic Result<User> create(@RequestBody User record) {User user = userService.insert(record);return Result.success(user);}@PutMappingpublic Result<User> update(@RequestBody User record) {User user = userService.update(record);return Result.success(user);}@DeleteMapping("{id}")public Result<Void> deleteById(@PathVariable Serializable id) {boolean success = userService.deleteById(id);return success ? Result.success() : Result.fail();}@GetMapping("{id}")public Result<User> queryById(@PathVariable Serializable id) {User user = userService.queryById(id);return Result.success(user);}@GetMappingpublic Result<List<User>> queryByCondition(Condition<User> condition) {List<User> list = userService.queryByCondition(condition);return Result.success(list);}
}

仔细看这段代码会发现,如果基于该接口再新增另一个domain对应的Controller接口类,代码中的基本结构和逻辑都是可以复用的。此时,便是File Template排上用场的地方,我们定义一个通用的 Controller 模板,将共性的部分抽象到模板里,再将差异性的部分通过模板入参 Subject 变量传入进来(注,这里需要用到Velocity 模板[1]的知识)。

#set($SubjectOfLowerFirst = ${Subject.substring(0,1).toLowerCase()} + $Subject.substring(1))
package ${PACKAGE_NAME};import com.alibaba.ide.code.entity.Result;
import com.alibaba.ide.code.entity.${Subject};
import com.alibaba.ide.code.service.Condition;
import com.alibaba.ide.code.service.${Subject}Service;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;#parse("File Header.java")
@RestController
@RequestMapping("api/${SubjectOfLowerFirst}")
public class ${Subject}Controller {@Resourceprivate ${Subject}Service ${SubjectOfLowerFirst}Service;@PostMappingpublic Result<${Subject}> create(@RequestBody ${Subject} record) {${Subject} ${SubjectOfLowerFirst} = ${SubjectOfLowerFirst}Service.insert(record);return Result.success(${SubjectOfLowerFirst});}@PutMappingpublic Result<${Subject}> update(@RequestBody ${Subject} record) {${Subject} ${SubjectOfLowerFirst} = ${SubjectOfLowerFirst}Service.update(record);return Result.success(${SubjectOfLowerFirst});}@DeleteMapping("{id}")public Result<Void> deleteById(@PathVariable Serializable id) {boolean success = ${SubjectOfLowerFirst}Service.deleteById(id);return success ? Result.success() : Result.fail();}@GetMapping("{id}")public Result<${Subject}> queryById(@PathVariable Serializable id) {${Subject} ${SubjectOfLowerFirst} = ${SubjectOfLowerFirst}Service.queryById(id);return Result.success(${SubjectOfLowerFirst});}@GetMappingpublic Result<List<${Subject}>> queryByCondition(Condition<${Subject}> condition) {List<${Subject}> list = ${SubjectOfLowerFirst}Service.queryByCondition(condition);return Result.success(list);}
}

模板定义完成,接下来来看一下实际的使用效果:

 

这里使用 Goods 作为新的domain对象,可以看到,生成的 Controller 代码已经具备 UserController 的全部能力,并且生成的代码全部都是 Goods 相关的api,这样就实现了File Template的横向迁移能力。

五、 低频高效快捷键

1、 介绍

IDEA中的快捷键多达上百个,我们很难把每个都记清楚,网上也有很多对应的总结。这里我主要梳理一些,大家使用相对比较低频,但又非常高效的快捷键。

2 、梳理

选择重复元素:Control + G

通常情况下,我们可以使用 Shift + F6 对类名、方法名和变量名进行批量更改,但对于其他元素进行批量更改时,该快捷键特别合适,且不限编程语言。

 

批量框选:Option + 鼠标左键拖拽

对于"对齐"的代码进行批量更改的最优解,没有之一:

 

整行移动:Option + Shift + ↑/↓

快速调整代码执行顺序,免除繁琐的剪切粘贴过程:

 

整行/块复制:Command + D

对于整行/块的复制,效率远高于纯手动的复制粘贴:

 

展开/收起:Command + . or Command + Shift + +/-

前者,快速显示/隐藏当前方法体;后者,快速概览当前类的所有方法:

 

 

修改方法签名:Command + F6

在方法被多文件或多处调用时,该方式替换效率极高:

 

查看历史剪切板:Command + Shift + V

开发中经常会出现需要复制多个文本的诉求,而PC默认的剪切板只能保存一个,该功能专门用来解决这个痛点:

 

代码抽取

代码抽取主要用在代码重构的时候,以最快速度达到我们抽取一个变量、方法的目的。

1)抽局部变量:Command + Option + V

 

2)抽成员变量:Command + Option + F

 

3)抽静态常量:Command + Option + C

 

4)抽方法入参:Command + Option + P

 

5)抽方法:Command + Option + M

 

六、 代码调试

代码调试在开发中使用的非常多,常规的单步、多步、进入、跳出操作这里也不特殊说明了。

有一点值得说的就是,利用条件断点来实现运行期的代码植入功能,先看下图:

 

可以看到,Debug模式运行时,我们能动态改变 age 变量的值,本来被赋值为 20 的,结果输出出来却是 10。

这个是我在开发中无意间发现的一个功能,算是一个Trick了。但这个功能在实际的开发过程中特别有用,尤其针对于一些代码改动后再次运行的成本比较高的场景。比如Android开发过程中,能够在不重新打整包的情况下,动态修改页面中各个元素的样式、接口的请求、数据的内容等等;再比如服务端场景中,如果我们的应用支持Debug模式,则可以通过该功能实现应用无需重新部署的情况下,进行动态更改上下文逻辑的操作。

七、 写在最后

跬步至千里,小流成江海,开发工作有大小,业务需求有缓急,但终究要落到眼下,从一砖一瓦的基石开始,从一行一列的编码开始,希望本文中能帮助到更多的研发同学。

作者:开发者小助手_LS

原文链接

本文为阿里云原创内容,未经允许不得转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/514157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做安全操作系统,这位技术老兵是认真的!

受访者 | 王文东 记者 | 伍杏玲 出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09; 近年来国际形势变化莫测&#xff0c;基础软件作为建设国家信息系统的核心&#xff0c;其自主研发能力备受关注与热议。作为企业和个人开发者&#xff0c;我们如何打破当前…

快手基于 Flink 的持续优化与实践

简介&#xff1a; 快手基于 Flink 的持续优化与实践的介绍。 一、Flink 稳定性持续优化 第一部分是 Flink 稳定性的持续优化。该部分包括两个方面&#xff0c;第一个方面&#xff0c;主要介绍快手在 Flink Kafka Connector 方面做的一些高可用&#xff0c;是基于内部的双机房读…

平台建设的7大问题:蚂蚁AI平台实践深度总结

简介&#xff1a; 在支持蚂蚁几乎所有核心业务运行和发展的过程中&#xff0c;我们在平台建设、业务支持、平台运营、AI创新以及AI整体运营等各个方面做了很多尝试&#xff0c;有了不少的收获和感悟&#xff0c;在此分享给大家。 过去几年&#xff0c;我和团队一直在负责蚂蚁集…

知乎热问:进入内核态究竟是什么意思?

‍‍知乎上有一个问题&#xff1a;进入内核态究竟是什么意思&#xff1f;暂且忘记这个问题&#xff0c;让我们从另一个问题出发&#xff0c;一步步引出这个问题的答案。特权指令问题现代计算机里面&#xff0c;同时运行了很多程序&#xff0c;比如Office软件、浏览器、QQ、还有…

我在阿里云做云开发平台

简介&#xff1a; 你体验过云上的研发模式了没&#xff1f; 各大云厂商今年在开发者阵地侧逐渐开始向“云”化开发发展&#xff0c;最为显著的产品就是Cloud IDE&#xff0c;催生出来的趋势就是云端开发。云开发现阶段尽管在各大公司内部无法作为日常开发工具普遍推广&#xff…

mysql 事务日志备份_事务日志备份与恢复 5

14.5 用Bak文件恢复到故障点的奥秘如果数据库被损坏&#xff0c;我们就只能利用备份集文件(通常扩展名为BAK)来恢复数据库&#xff0c;如果备份集中包含了尾日志备份&#xff0c;我们同样能将数据库恢复到故障点。前面我们已经介绍了使用restore headeronly命令可以查看备份集文…

从no-code到low-code:企业级hpaPaaS的未来

简介&#xff1a; 本文将简单谈一谈基于 no-code > low-code > pro-code 渐进式思路的研发体系。 引子 宜搭负责人骁勇给我举过一个例子&#xff0c;我们小时候逢年过节穿的衣服&#xff0c;都是去裁缝店选一下材料、量一下尺寸&#xff0c;等个半个来月&#xff0c;讨回…

“解救”外卖骑手,美团首次公开算法规则!

整理 | 郑丽媛出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;相信大家点外卖的时候都会注意到“预估到达时间”这一栏&#xff0c;那你是否好奇过这个时间是怎么得出来的呢&#xff1f;简单用距离除以速度&#xff1f;还是结合送餐距离、出餐时间和天气情况等更多…

Serverless 极致弹性解构在线游戏行业痛点

简介&#xff1a; 本文将通过剖析一个个具体的场景案例&#xff0c;以期望给相关的游戏开发同学带来共鸣&#xff0c;同时也希望能给非游戏行业的同学带来一些启发。 一、前言 1. 游戏客户上云关注点 游戏行业是一个富有创意又竞争激烈的市场&#xff0c;被称为第九艺术。游戏…

ACK正式支持对基于Alibaba Cloud Linux操作系统的集群进行等保加固

简介&#xff1a; 我们对基于Alibaba Cloud linux操作系统的ACK集群进行等保加固&#xff0c;意味着阿里云在云产品开发和交付的过程中将安全作为重要组成部分&#xff0c;将合规融入到产品的“血液”中&#xff0c;把安全植入产品的“骨髓”里&#xff0c;能够帮助有等保诉求的…

华为一口气发布十余款新品,HarmonyOS用户过亿

9月13日19:30&#xff0c;华为在线上举办了智慧办公新品发布会。本次发布会带来了华为MateBook 13s笔记本电脑、华为MateBook 14s笔记本电脑、华为MateStation X一体机、华为PixLab X1打印机、华为MateView GT 27英寸曲面屏显示器以及华为MatePad Pro 12.6英寸套装版等十余款新…

labelme实例分割_MaskRCNN在多个实例数据集上实践

刚刚开通付费功能&#xff0c;好奇心驱使我试试效果&#xff0c;这不&#xff0c;前两天试了一下&#xff0c;感觉也没啥新奇的。我的公众号使命是记录和分享个人学习经历&#xff0c;不会使用付费功能的。在此也非常感谢之前给我付费的小伙伴哈&#xff0c;哈哈&#xff0c;话…

技术干货 | 阿里云数据库PostgreSQL 13大版本揭秘

简介&#xff1a; 阿里云RDS PostgreSQL是一款兼容开源PostgreSQL的全托管云数据库产品&#xff0c;自2015年首次发布以来&#xff0c;根据用户需求不断升级迭代&#xff0c;已支持9.4、10、11、12等多个版本&#xff0c;覆盖了高可用版、基础版、只读实例等多种形态&#xff0…

国家能源集团携手华为首次部署矿鸿操作系统,开创工控新纪元

9月14日&#xff0c;由国家能源集团携手华为公司共同举办的“矿鸿操作系统”发布会在北京圆满举行。矿监局、工信部、科技部、能源局、煤炭工业协会、国家能源集团、华为等政府机构与企业代表出席&#xff0c;共同见证了“矿鸿操作系统”的正式发布。面对煤矿数字化、智能化的快…

MaxCompute在电商场景中如何进行漏斗模型分析

简介&#xff1a; 本文以某电商案例为例&#xff0c;通过案例为您介绍如何使用离线计算并制作漏斗图。 背景 漏斗模型其实是通过产品各项数据的转化率来判断产品运营情况的工具。转化漏斗则是通过各阶段数据的转化&#xff0c;来判断产品在哪一个环节出了问题&#xff0c;然后…

ado.net mysql 事务_ADO.NET事务

在发布System.Transaction命名空间之前&#xff0c;可以直接用ADO.NET创建事务&#xff0c;也可以通过组件、特性和COM运行库(位于System.EnterpriseServices命名空间中)进行事务处理。本文如题所示&#xff0c;介绍在这些传统事务处理方式中较为简单的“ASP.NET事务”。在传统…

这可能是大型复杂项目下数据流的最佳实践

简介&#xff1a; 实际项目中沉淀的数据流最佳实践。 数据流是前端一直以来都存在的一个问题&#xff0c;我们项目沉淀了一套最佳实践&#xff0c;如有问题&#xff0c;欢迎探讨 在旧的 Done 项目中&#xff0c;代码复杂度高&#xff0c;已经到了“牵一发而动全身”&#xff0c…

淘宝推荐、视频搜索背后的检索技术竟是它!深度揭秘达摩院向量检索引擎Proxima

简介&#xff1a; 淘宝搜索推荐、视频搜索的背后使用了什么样的检索技术&#xff1f;非结构化数据检索&#xff0c;向量检索&#xff0c;以及多模态检索&#xff0c;它们到底解决了什么问题&#xff1f;今天由阿里巴巴达摩院的科学家从业务问题出发&#xff0c;抽丝剥茧&#x…

ipython和jupyter哪个好_对Python开发者而言,IPython仍然是Jupyter Notebook的核心

如果你不明白 Jupyter 是什么&#xff0c;这么说吧&#xff0c;它拥有和 IPython 同样的代码&#xff0c;并且是由同一批人开发的&#xff0c;只不过取了一个新名字、安了一个新家。下面这个注脚进一步说明了这一点&#xff1a;我从声明中解读出来的信息是&#xff0c;“Jupyte…

这个高薪行业正在大量招人,你会考虑吗?

作者 | 侯淼淼 出品 | 《新程序员》当人们提及“程序员”这一职业的时候&#xff0c;大多数人的第一想法往往是高薪。然而近年来&#xff0c;随着造车势力的兴起&#xff0c;新一轮的高薪岗位抢人大战正式打响。2021年以来&#xff0c;一汽、东风等传统车厂招聘岗位数量持…