1.注解尽量全面性,写有象征意义的注解
USB方式、类、繁杂的销售业务方式论,都假如加进有象征意义的注解
对USB方式的注解,假如包涵详尽的入参和结论表明,有极度放出的情形也要详尽描述类的注解假如包涵类的机能表明、译者和修正者。假如是销售业务方式论很繁杂的标识符,吗十分有必要性写确切注解。确切的注解,更有助于前面的保护。
2.工程项目分拆科学合理的产品目录内部结构
提过读理工学院那会,会弹做各式各样的信息系统,都是用MVC商业模式,也是controller、service、mapper、entity。假如今后销售业务扩充,你没分拆销售业务内部结构不然,很可能将就会辨认出,一个service包下,有上千个服务工程项目。。。
恰当的作法,假如服务工程项目过多,假如依照相同的销售业务展开分割,比如说订货、进占、点数之类
总之,你也能依照相同的销售业务分割组件,比如说建一个moudles包,接着按订货、进占等销售业务分割,每一销售业务都有他们的controller、service、mapper、entity。
他们分拆的目地,是让工程项目内部结构更明晰,时效性大列佩季哈区,更容易保护而已。
3. 不在循环里远程调用、或者数据库操作,优先考虑批量展开。
远程操作或者数据库操作都是比较耗网络、IO资源的,所以尽量不在循环里远程调用、不在循环里操作数据库,能批量一次性查回来尽量不要循环多次去查。(但是呢,假如是操作数据库,也不要一次性查太多数据哈,能分批500一次酱紫)。
正例:
remoteBatchQuery(param);反例:
for(int i=0;i<n;i++){ remoteSingleQuery(param) }4. 封装方式形参
假如你的方式参数过多,要封装一个对象出来。反例如下:
public void getUserInfo(String name,String age,String sex,String mobile,String idNo){ // do something … }假如参数很多,做新老USB兼容处理也比较麻烦。建议写个对象出来,如下:
public void getUserInfo(UserInfoParamDTO userInfoParamDTO){ // do something … } class UserInfoParamDTO{ private String name; private String age; private String sex; private String mobile; private String idNo; }5. 封装通用模板
一个杰出的前端合作开发,假如具有封装通用模板的编码能力。
他们来看一个销售业务需求:假设他们有这么一个销售业务场景:内部系统相同商户,调用他们系统USB,去跟外部第三方系统交互(http方式)。走类似这么一个流程,如下:
一个请求都会经历这几个流程:
查询商户信息对请求报文加签发送http请求出去对返回的报文验签通过HTTP发请求出去时,有的商户可能将是走代理的,有的是走直连。假设当前有A,B商户接入,不少伙伴可能将这么实现,伪标识符如下:
// 商户A处理句柄 CompanyAHandler implements RequestHandler { Resp hander(req){//查询商户信息 queryMerchantInfo(); //加签 signature(); //http请求(A商户假设走的是代理) httpRequestbyProxy() //验签 verify(); } }// 商户B处理句柄 CompanyBHandler implements RequestHandler { Resp hander(Rreq){ //查询商户信息 queryMerchantInfo(); //加签 signature(); // http请求(B商户不走代理,直连) httpRequestbyDirect(); // 验签 verify(); } }假设新加一个C商户接入,你需要再实现一套这样的标识符。显然,这样标识符就重复了。这时候他们能封装一个通用模板!他们就能定义一个抽象类,包涵请求流程的几个方式,伪标识符如下:
abstract class AbstractMerchantService { //模板方式流程 Resp handlerTempPlate(req){ //查询商户信息 queryMerchantInfo(); //加签 signature(); //http 请求 httpRequest(); // 验签 verifySinature(); } // Http是否走代理(提供给子类实现) abstract boolean isRequestByProxy(); }接着所有商户接入,都做这个流程。假如这个通用模板是你抽取的,别的小伙伴接到合作开发任务,都是接入你的模板,是不是会有点自豪呀,哈哈~
封装通用模板,是抽个模板商业模式嘛?其实不仅仅是,而是他们对需求、标识符的思考与总结,一种编程思想的升华。
6. 封装繁杂的方式论判断条件
他们来看下这段标识符:
public void test(UserStatus userStatus){ if(userStatus != UserStatus.BANNED && userStatus != UserStatus.DELETED && userStatus != UserStatus.FROZEN) {//doSomeThing return } }这段标识符有什么问题呢?是的,方式论判断条件太繁杂啦,他们能封装一下它。如下:
public void test(UserStatus userStatus){ if(isUserActive(userStatus)) {//doSomeThing } } private boolean isUserActive(UserStatus userStatus) { returnuserStatus != UserStatus.BANNED && userStatus != UserStatus.DELETED && userStatus != UserStatus.FROZEN; }7. 保持优化性能的嗅觉
杰出的前端合作开发,假如保持优化性能的嗅觉。比如说避免创建比必要性的对象、异步处理、使用缓冲流,减少IO操作之类。
比如说,他们设计一个APP首页的USB,它需要查用户信息、需要查banner信息、需要查弹窗信息之类。假设耗时如下:
查用户信息200ms,查banner信息100ms、查弹窗信息50ms,那一共就耗时350ms了。假如还查其他信息,那耗时就更大了。如何优化它呢?能并行发起,耗时能降为200ms。如下:
8. 可变参数的配置化处理
日常合作开发中,他们经常会遇到一些可变参数,比如说用户多少天没登录注销、运营活动,相同节日红包皮肤切换、订货多久没付款就删除之类。对这些可变的参数,不用该直接写死在标识符。杰出的前端,要做配置化处理,你能把这些可变参数,放到数据库一个配置表里面,也能放到工程项目地配置文件或者apollo上。
比如说产品经理提了个红包需求,圣诞节的时候,红包皮肤为圣诞节相关的,春节的时候,为春节红包皮肤等。假如在标识符写死控制,可有类似以下标识符:
if(duringChristmas){ img = redPacketChristmasSkin; }else if(duringSpringFestival){ img = redSpringFestivalSkin; }假如到了元宵节的时候,运营小姐姐突然又有想法,红包皮肤换成灯笼相关的,这时候,是不是要去修正标识符了,重新发布了?
从一开始USB设计时,能实现一张红包皮肤的配置表,将红包皮肤做成配置化呢?更换红包皮肤,只需修正一下表数据就好了。总之,还有一些场景适合一些配置化的参数:一个分页多少数量控制、某个抢红包多久时间过期这些,都能搞到参数配置化表里面。这也是扩充性思想的一种体现。
9. 会总结并使用工具类。
很多小伙伴,判断一个list是否为空,会这么写:
if (list == null || list.size() ==0) { return null; }这样写呢,方式论是没什么问题的。但是更建议用工具类,比如说:
if (CollectionUtils.isEmpty(list)) { return null; }日常合作开发中,他们既要会用工具类,更要学会他们去总结工具类。比如说去文件处理工具类、日期处理工具类之类。这些都是杰出前端合作开发的一些好习惯。
10. 控制方式函数繁杂度
你的方式不要写得太繁杂,方式论不要混乱,也不要太长。一个函数不能超过80行。写标识符不仅仅是能跑就行,而是为了以后更好的保护。
反例如下:
public class Test { private String name; privateVector<Order> orders =new Vector<Order>(); public void printOwing() { //print banner System.out.println(“****************”); System.out.println(“*****customer Owes *****”); System.out.println(“****************”); //calculate totalAmount Enumeration env = orders.elements(); double totalAmount = 0.0; while(env.hasMoreElements()) { Order order = (Order) env.nextElement(); totalAmount += order.getAmout(); }//print details System.out.println(“name:” + name); System.out.println(“amount:”+ totalAmount); …… } }其实能使用Extract Method,抽取机能单一的标识符段,组成命名明晰的小函数,去解决长函数问题,正例如下:
public class Test { private String name; private Vector<Order> orders = new Vector<Order>(); public void printOwing() { //print banner printBanner(); //calculate totalAmount double totalAmount = getTotalAmount(); //print detailsprintDetail(totalAmount); }void printBanner(){ System.out.println(“****************”); System.out.println(“*****customer Owes *****”); System.out.println(“****************”); } double getTotalAmount(){ Enumeration env = orders.elements(); double totalAmount = 0.0; while(env.hasMoreElements()) { Order order = (Order) env.nextElement(); totalAmount += order.getAmout(); }returntotalAmount; }void printDetail(double totalAmount){ System.out.println(“name:”+ name); System.out.println(“amount:” + totalAmount); } }11. 在finally块中对资源展开释放
假如大家都有过这样的经历,windows系统桌面假如打开太多文件或者系统软件,就会觉得电脑很卡。总之,他们linux服务工程项目器也一样,平时操作文件,或者数据库连接,IO资源流假如没关闭,那么这个IO资源就会被它占着,这样别人就没办法用了,这就造成资源浪费。
他们操作完文件资源,需要在在finally块中对资源展开释放。
FileInputStream fdIn = null; try { fdIn = new FileInputStream(new File(“/test.txt”)); } catch (FileNotFoundException e) { log.error(e); } catch(IOException e) { log.error(e); }finally { try { if (fdIn != null) { fdIn.close(); } } catch(IOException e) { log.error(e); } }12.把日志打印好
日常合作开发中,一定需要把日志打印好。比如说:你实现转账销售业务,转个几百万,接着转失败了,接着客户投诉,接着你还没打印到日志,想想那种水深火热的困境下,你却毫无办法。。。
一般情形,方式入参、出参需要打印日志,极度的时候,也要打印日志之类,如下:
public void transfer(TransferDTO transferDTO){ log.info(“invoke tranfer begin”); //打印入参 log.info(“invoke tranfer,paramters:{}”,transferDTO); try{ res= transferService.transfer(transferDTO); }catch(Exception e){ log.error(“transfer fail,account:{}”, transferDTO.getAccount()) log.error(“transfer fail,exception:{}”,e); } log.info(“invoke tranfer end”); }之前写过一篇打印日志的15个建议,大家能看看哈:工作总结!日志打印的15个建议
13. 考虑极度,处理好极度
杰出的前端合作开发,应当考虑到极度,并做好极度处理。给大家提了10个极度处理的建议:
尽量不要使用e.printStackTrace(),而是使用log打印。因为e.printStackTrace()语句可能将会导致内存占满。catch住极度时,建议打印出具体的exception,利于更好定位问题不要用一个Exception捕捉所有可能将的极度提过使用finally关闭流资源或者直接使用try-with-resource。捕获极度与放出极度必须是完全匹配,或者捕获极度是抛极度的父类捕获到的极度,不能忽略它,至少打点日志吧注意极度对你的标识符层次内部结构的侵染自定义封装极度,不要丢弃原始极度的信息Throwable cause运行时极度RuntimeException ,不假如通过catch的方式来处理,而是先预检查,比如说:NullPointerException处理注意极度匹配的顺序,优先捕获具体的极度14. 考虑系统、USB的兼容性
杰出的前端合作开发,会考虑系统、USB的兼容性。
假如修正了对外旧USB,但是却不做兼容。这个问题可能将比较严重,甚至会直接导致系统发版失败的。新手程序员很容易犯这个错误哦~
因此,假如你的需求是在原来USB上修正,尤其这个USB是对外提供服务不然,一定要考虑USB兼容。举个例子吧,比如说dubboUSB,原本是只接收A,B参数,现在你加了一个参数C,就能考虑这样处理:
//老USB void oldService(A,B){ //兼容新USB,传个null代替C newService(A,B,null); } //新USB,暂时不能删掉老USB,需要做兼容。 void newService(A,B,C){ … }15. 采取措施避免运行时错误
杰出的前端合作开发,假如在编写标识符阶段,就采取措施,避免运行时错误,如数组边界溢出,被零整除,空指针等运行时错误。类似标识符比较常见:
String name = list.get(1).getName();//list可能将越界,因为不一定有2个元素哈所以,假如采取措施,预防一下数组边界溢出,正例如下:
if(CollectionsUtil.isNotEmpty(list)&& list.size()>1){ String name = list.get(1).getName(); }