绝大多数开发者理所应当地误以为操控性强化很繁杂,须要大批的实战经验和科学知识。好吧,无法说这是完全严重错误的。强化插件以获得最差操控性不是两件容易的事。但,这并不意味著如果你不具备那些科学知识,就无法做任何人事。
这里有11个更易遵从的提议和最差课堂教学能协助你建立一个操控性较好的插件。
大部份提议是特别针对Java的。但也有若干个提议是与词汇毫无关系的,能应用领域于大部份插件和C词汇。在探讨专门针对特别针对Java的操控性Listary基本功以后,让我们先来看看通用型基本功。
1.在你知道必要性以后不要强化
这可能是最重要的操控性调整基本功之一。你如果遵从常用的最差课堂教学作法并试著高效率地实现示例。但,这并不意味著在你断定必要以后,你如果更改任何人标准库或构筑繁杂的强化。
在绝大多数情况下,过早地强化不仅会挤占大批天数,而且会使标识符显得无法写作和保护。更差劲的是,那些强化通常不会带来任何人益处,因为你耗费大批天数来强化的是插件的Tumkur部份。
所以,你如何断定你须要强化一些东西呢?
首先,你须要表述插件标识符的速率得多快,比如,为大部份API初始化选定最大响应天数,或者选定在某一天数范围内要引入的历史记录数量。在完成那些之后,你就能量测插件的什么样部份很慢须要改良。然后,接著看第三个基本功。
2.使用解析器搜寻真正的困局
在你遵从第二个提议并确定了插件的这类部份须要改良后,所以从这儿开始呢?
你能用两种方法来解决问题:
查看你的代码,并从看起来可疑或者你觉得可能会产生问题的部份开始。
希望不须要我解释为什么如果始终遵从第二种方法的原因。
很明显,基于解析器的方法能让你更好地理解标识符的操控性影响,并使你能够专注于最关键的部份。如果你曾使用过解析器,所以你一定记得曾经你是多么惊讶于一下就找到了标识符的什么样部份产生了操控性问题。老实说,我第一次的猜测不止一次地导致我走错了方向。
3.为整个插件建立操控性测试套件
这是另一个通用型基本功,能协助你避免在将操控性改良部署到生产后经常会发生的许多意外问题。你如果总是表述一个测试整个插件的操控性测试套件,并在操控性改良以后和之后运行它。
这些额外的测试运行将协助你识别更改的功能和操控性副作用,并确保不会导致弊大于利的更新。如果你工作于被插件若干个不同部份使用的组件,如数据库或缓存,所以这一点就尤其重要。
4.首先处理最大的困局
在建立测试套件并使用解析器分析插件之后,你能列出一系列须要解决以提高操控性的问题。这很好,但它仍然无法回答你如果从这儿开始的问题。你能专注于速效方案,或从最重要的问题开始。Java 程序员必须清楚的 7 个操控性指标,这个你也必须会。
速效方案一开始可能会很有吸引力,因为你能很快显示第二个成果。但有时,可能须要你说服其他团队成员或管理层认为操控性分析是值得的——因为暂时看不到效果。
但总的来说,我提议首先处理最重要的操控性问题。这将为你提供最大的操控性改良,而且可能再也不须要去解决其中一些为了满足操控性需求的问题。
常用的操控性调整基本功到此结束。下面让我们仔细看看一些某一于Java的基本功。
5.使用StringBuilder以编程方式连接String
有很多不同的选项来连接Java中的String。比如,你能使用单纯的+或+ =,以及StringBuffer或StringBuilder。String 真的是不可变的吗?
所以,你如果选择哪种方法?
答案取决于连接String的标识符。如果你是以编程方式添加新内容到String中,比如在for循环中,所以你如果使用StringBuilder。它很容易使用,并提供比StringBuffer更好的操控性。但请记住,与StringBuffer相比,StringBuilder不是线程安全的,可能不适合大部份示例。StringBuffer 和 StringBuilder 的 3 个区别,这个你必须清楚。
你只须要实例化一个新的StringBuilder并初始化append方法来向String中添加一个新的部份。在你添加了大部份的部份之后,你就能初始化toString()方法来检索连接的String。
下面的标识符片段显示了一个单纯的例子。在每次迭代期间,这个循环将i转换为一个String,并将它与一个空格一起添加到StringBuilder sb中。所以,最后,这段标识符将在日志文件中写入“This is a test0 1 2 3 4 5 6 7 8 9”。
StringBuilder sb =newStringBuilder(“This is a test”);for(inti=0; i<10; i++) {sb.append(i);sb.append(” “);}log.info(sb.toString());
正如在标识符片段中看到的那样,你能将String的第二个元素提供给构造方法。这将建立一个新的StringBuilder,新的StringBuilder包含提供的String和16个额外字符的容量。当你向StringBuilder添加更多字符时,JVM将动态增加StringBuilder的大小。
如果你已经知道你的String将包含多少个字符,则能将该数字提供给不同的构造方法以实例化具有表述容量的StringBuilder。这进一步提高了效率,因为它不须要动态扩展其容量。
6.使用+连接一个语句中的String
当你用Java实现你的第二个插件时,可能有人告诉过你不如果用+来连接String。如果你是在插件逻辑中连接字符串,这是正确的。字符串是不可变的,每个字符串的连接结果都存储在一个新的String对象中。这须要额外的内存,会减慢你的插件,特别是如果你在一个循环内连接多个字符串的话。
在那些情况下,你如果遵从基本功5并使用StringBuilder。
但,如果你只是将字符串分成多行来改善标识符的可读性,那情况就不一样了。
Query q = em.createQuery(“SELECT a.id, a.firstName, a.lastName ”+ “FROM Author a ”+ “WHERE a.id = :id”);
在那些情况下,你如果用一个单纯的+来连接你的字符串。Java编译器会对此强化并在编译时执行连接。所以,在运行时,你的标识符将只使用1个String,不须要连接。
7.尽可能使用基元
避免任何人开销并提高插件操控性的另一个简便而快速的方法是使用基本类型而不是其包装类。所以,最好使用int来代替Integer,使用double来代替Double。这允许JVM将值存储在堆栈而不是堆中以减少内存消耗,并作出更有效的处理。
8.试着避免BigInteger和BigDecimal
既然我们在探讨数据类型,所以我们也快速浏览一下BigInteger和BigDecimal吧。尤其是后者因其精确性而受到大家的欢迎。但这是有代价的。
BigInteger和BigDecimal比单纯的long或double须要更多的内存,并且会显著减慢所有计算。所以,你如果须要额外的精度,或者数字将超过long的范围,所以最好三思而后行。这可能是你须要更改以解决操控性问题的唯一方法,特别是在实现数学算法的时候。金融系统中正确的金额计算及存储方式,这个你了解下。
9.首先检查当前日志级别
这个提议如果是显而易见的,但不幸的是,很多程序员在写标识符的时候都会大多会忽略它。在你建立调试消息以后,始终如果首先检查当前日志级别。否则,你可能会建立一个之后会被忽略的日志消息字符串。
这里有两个反面例子。
// don’t do thislog.debug(“User [” + userName + “] called method X with [” + i + “]”);// or thislog.debug(String.format(“User [%s] called method X with [%d]”, userName, i));
在上面两种情况中,你都将执行建立日志消息大部份必需的步骤,在不知道日志框架是否将使用日志消息的前提下。因此在建立调试消息以后,最好先检查当前的日志级别。
// do thisif(log.isDebugEnabled()) {log.debug(“User [” + userName + “] called method X with [” + i + “]”);}
10.使用Apache Commons StringUtils.Replace而不是String.replace
一般来说,String.replace方法工作正常,效率很高,尤其是在使用Java 9的情况下。但,如果你的插件须要大批的替换操作,并且没有更新到最新的Java版本,所以我们依然有必要性搜寻更快和更有效的替代品。
有一个备选答案是Apache Commons Lang的StringUtils.replace方法。正如Lukas Eder在他最近的一篇博客文章中所描述的,StringUtils.replace方法远胜Java 8的String.replace方法。
而且它只须要很小的改动。即添加Apache Commons Lang项目的Maven依赖项到插件pom.xml中,并将String.replace方法的大部份初始化替换为StringUtils.replace方法。
// replace thistest.replace(“test”, “simple test”);// with thisStringUtils.replace(test, “test”, “simple test”);
11.缓存昂贵的资源,如数据库连接
缓存是避免重复执行昂贵或常用标识符片段的流行解决方案。总的思路很单纯:重复使用那些资源比反复建立新的资源要便宜。
一个典型的例子是缓存池中的数据库连接。新连接的建立须要天数,如果你重用现有连接,则能避免这种情况。
你还能在Java词汇本身找到其他例子。比如,Integer类的valueOf方法缓存了-128到127之间的值。你可能会说建立一个新的Integer并不是太昂贵,但由于它经常被使用,以至于缓存最常用的值也能提供操控性优势。
但,当你考虑缓存时,请记住缓存实现也会产生开销。你须要耗费额外的内存来存储可重用资源,因此你可能须要管理缓存以使资源可访问,以及删除过时的资源。
所以,在开始缓存任何人资源以后,请确保实施缓存是值得的,也就是说必须足够多地使用它们。
总结
正如你所看到的,有时不须要太多工作就能提高插件的操控性。本文中的大部份提议只须要你稍作努力就能将它们应用领域于你的标识符。
但,最重要的还是那些与是什么C词汇毫无关系的基本功:
在你知道必要性以后不要强化
使用解析器搜寻真正的困局
首先处理最大的困局