您好,登录后才能下订单哦!
本篇内容主要讲解“优秀程序员都在注意的点有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“优秀程序员都在注意的点有哪些”吧!
很多事情并不难,只是缺乏多走半里路的习惯!
反例
public boolean isInValid(String str) { if (str == null || str.trim().length() == 0) { return true; } return false; }
多走一步,海阔天空
public boolean isInValid(String str) { return (str == null) || (str.trim().length() == 0); }
是个程序员都知道哪个更好!
还有一种见过很多次的代码:
public boolean isEmptyName() { return StringUtils.isEmpty(name)? true: false; }
难道不感觉到多余吗?
再走半步,山清水秀
public boolean isEmptyName() { return StringUtils.isEmpty(name); }
NullPointException,让我们防不胜防;尤其是使用第三方API,如果抛出这个异常,会让人有骂街的冲动。所以:若不想踩坑,请先别给别人挖坑。
理想要求:我们生产的所有public带返回值的方法体中,不应该出现“return null”字样。空对象就是这一思想的落地实现。
案例:查询并返回一个名字为steven的老师或者学生。
public static SearchFilter name(String name) { return human -> human.getName().equalsIgnoreCase(name); } public Human find(SearchFilter filter) { for (Human human : humans) { if (filter.isMatched(human)) { return human; } } return new NullHuman(); //如果你返回NULL,总有一天你会挨骂! } //Test assertFalse(edu.find(name("steven")).isNull());
谈起设计模式,很多人会觉得高大上,于是当学会了其中一个时,便会不加节制的使用。
单例,GOF中最简单的一个设计模式,很好用、也非常方便,但说实话很多人在滥用。我们的系统中随处可见,但用前请叩问自己该类真的是在系统当中有并且只能有一个实例吗?
否则请拒绝单实例。太多的单实例会给你的自动化测试带来无穷的烦恼。
枚举有一些比较强大的特性容易被忽视,比如枚举对象本身也可以携带变量;这一特性让枚举在更多的场合发挥不可替代的功用。
举例:不同武器具有不同的杀伤力,杀伤力变量可以携带到武器的枚举值中。
public enum EquipmentEnum { Staff(20), Hammer(10); double playerRisedAbility; EquipmentEnum(double playerRiseAbility) { this.playerRisedAbility = playerRiseAbility; } public double getRaiseAbility(double originalAbility) { return Double.sum(originalAbility, playerRisedAbility); } }
30%的代码注释比的时代已经成为过去,最好的注释的就是无需注释,程序员应该致力于通过命名让注释消失。
大量的实践证明,随着重构频率越来越高,重构过程中随着代码的变更同步更新注释的可能性几乎为零。久而久之,注释与代码就是南辕北辙。
好的命名能够愉悦读者的心情,让人有想一睹作者真面目的冲动!
案例:
一个房地产开发商一个新的楼盘开盘,原价80万每套,有如下优惠策略,但优惠政策可能随着楼盘存量情况会不一样,为开发商写一个房款计算程序
老客户买二套房可优惠4%,可累加
一次性全款客户可优惠3%,可累加
public class Customer { Benefiter benefit = new NullBenefiter(); public void is(Benefiter benefits) { //原本的set方法,重命名会带来意想不到的效果。 this.benefit = benefits; } public double shouldPay(double srcPrice) { return srcPrice - benefit.benefit(srcPrice); } } @FunctionalInterface public interface Benefiter { abstract double benefit(double srcPrice); default Benefiter and(final Benefiter otherPolicy) { return srcPrice -> (benefit(srcPrice) + otherPolicy.benefit(srcPrice)); } }
受益于良好命名,客户代码语义跃然纸上:customer.is(oldCustomer().and(fullPay()));
数组是任何一门相对高级的机器语言的必备数据结构,但是对面向对象开发人员而言,似乎对它有所忽略。
在一些特定的场景下,它能起到意想不到的效果。
案例:美元、法郎、人民币三币种间换算。其中美元:法郎=1:2;美元:人民币=1:8;
public class ExchangeRate { public static final int DOLLAR = 0; public static final int FRANC = 1; public static final int YMB = 2; private static final double[][] rates = { //二维数组定义币种之间的汇率,简单高效 {1.0d, 2.0d, 8.0d}, {0.5d, 1.0d, 4.0d}, {0.125d, 0.25d, 1.0d} }; public static double getRateOf(Currency src, Currency tgt) { return rates[src.ID][tgt.ID]; } } public class Cash { private double value; private Currency unit; public Cash(double value, Currency unit) { this.value = value; this.unit = unit; } @Override public boolean equals(Object obj) { if (obj instanceof Cash) { Cash other = (Cash) obj; return value == other.value * getRateOf(other.unit, unit); } return false; } }
如果汇率的二维数组使用配置文件定义并初始化,那还可以将设计提升一个新的高度——易于扩展,甚至不需修改任何Java代码即可完成币种的扩展。
当我们调用外部API时,最理想的就是零入参,即便有入参也希望是类型明确且范围可枚举的,这样会让我们使用这个API时更具安全感!心同此理,当你把一个函数声明为public时,请谨慎地定义它的入参。
如果把上述案例中获取两种币种之间的汇率函数:
public static double getRateOf(Currency src, Currency tgt) { return rates[src.ID][tgt.ID]; }
定义为
public static double getRateOf(int src, int tgt) { return rates[src][tgt]; }
虽然函数实现简单了一些,但可想而知,这个API会让使用者很忌惮!数组越界异常肯定是经常发生。
相反通过枚举规约了入参的类型和范围,给用户一些固定选项,使用者少了很多顾虑,而我们的程序也更加安全。
所以:我们对外提供的API入参类型尽量少用String、Int这种基本类型,给使用者发挥的空间越大,犯错的可能越大,因为你把风险暴露在不受控的用户手里。
你是否为反复地编写类似“if (tasks != null && tasks.size() > 0)”或者“if (name != null && (!name.isEmpty()))”的代码而心浮气躁,其实你完全可以解救自己。
封装一下
public class CollectionUtil { public static boolean isEmpty(Collection collection) { return collection == null || collection.isEmpty(); } }
以及
public class StringUtil { public static boolean isEmpty(String context) { return context == null || context.isEmpty(); } }
一切变得非常简单,心情好了,效率也就高了!
我们的系统充斥着if/else的逻辑,因为它逻辑“简单”、易用!但随着时间推移、需求的扩展,有一天你会发现自己都看不懂自己写的if/else。
所以一开始就要学会拒绝这种逻辑的嵌套,又或者是当你看嵌套的复杂逻辑,大胆的对它进行重构。
案例:输入一个1-1000的数值N,如果N是3或者3的倍数时,返回“FIZZ”;如果N是5或者5的倍数时, 返回“BUZZ”;既是3的倍数又是5的倍数时, 返回“FIZZBUZZ”;其他的则输出N。
public String say(int input) throws Exception { if ( input < 1 || input > 1000){ throw new Exception("Invalid input"); } if (input % 15 == 0) { return "FIZZBUZZ"; } if (input % 5 == 0) { return "BUZZ"; } if (input % 3 == 0) { return "FIZZ"; } return String.valueOf(input); }
嗅一嗅其中的坏味道,如果将来需求扩展,比如引进7的倍数。照此逻辑,继续添加if,问题是解决了,但总有一天你会怀疑人生!
public String say(int input) throws Exception { if (input < 1 || input > 1000) { throw new Exception("Invalid input"); } DefaultParser defaultParser = new DefaultParser(null); MultiOfThreeParser multiOfThreeParser = new MultiOfThreeParser(defaultParser); MultiOfFiveParser multiFiveParser = new MultiOfFiveParser(multiOfThreeParser); MultiOfFifteenParser fifteenPaser = new MultiOfFifteenParser(multiFiveParser); return fifteenPaser.parse(input); } public abstract class Parser { abstract boolean isFixedResponsibility(int inputContext); abstract String response(int inputContext) throws Exception; public String parse(int inputContext) throws Exception { if (isFixedResponsibility(inputContext)) { return response(inputContext); } if (nextParser != null) { return nextParser.parse(inputContext); } return NULL; } } public class MultiOfFifteenParser extends Parser { public MultiOfFifteenParser(Parser nextParser) { super(nextParser); } @Override public String response(int inputContext) throws Exception { return FLAG_FOR_MULIT_OF_FIFTEEN; } @Override boolean isFixedResponsibility(int inputContext) { return inputContext % 15 == 0; } }
看起来好多了,但感觉好像还有哪儿不太对劲!
敏锐的读者可能还会发现上述改进还存在细微的小问题,那就是say方法里面的异常分支处理。怎么还存在一个if,对于一个完美主义强迫症患者而言,它的存在就是一个灾难。继续改进一下:
public String say(int input) throws Exception { DefaultParser defaultParser = new DefaultParser(null); MultiOfThreeParser multiOfThreeParser = new MultiOfThreeParser(defaultParser); MultiOfFiveParser multiOfFiveParser = new MultiOfFiveParser(multiOfThreeParser); MultiOfFifteenParser FifteenPaser = new MultiOfFifteenParser(multiOfFiveParser); InvalidNumberParser invalidNumberPaser = new InvalidNumberParser(FifteenPaser); return invalidNumberPaser.parse(input); } public class InvalidNumberParser extends Parser { public InvalidNumberParser(Parser nextParser) { super(nextParser); } @Override String response(int inputContext) throws Exception { throw new Exception("Invalid input"); } @Override boolean isFixedResponsibility(int inputContext){ return (inputContext < L_THRESHOLD) || (inputContext > H_THRESHOLD); } }
到此,相信大家对“优秀程序员都在注意的点有哪些”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。