最近, 同事问到我, 那时候为什么从 PHP 转成 Java?, 我想了很久, 且撇开主观上的原因, 当初业务重构使用 java 确实有很多可以说道的地方
槽点 1: 哪有最好的语言, 只有最合适的语言
2017 年的 3 月份, 我所维护的业务, 跑的是 php, 使用的是 thinkphp3.2 框架刚接手的时候, 这个业务还是单机, 还记得有同事笑道: 这台机厉害哈, 单机一年能跑出 200 多万的流水来! 我当然是一笑置之可是随着业务组扩展外部渠道, 开始发展这个业务, 我慢慢发现这样子的系统很难搞: 难维护, 难扩展, 难自定义, 不稳定这样子的系统, 每次改到支付功能, 上线都是心虚的, 就怕突然出现问题, 影响用户体验于是在一段煎熬的思索和过渡后, 老大开始带着我进行重构最开始的一套方案, 是准备放弃原有的 tp 框架, 转而使用 yii2, 但由于人手不够, 老大亲自操刀, 架起了一套 play1.4.3(业务端) + spring-mvc(后台管理) 的一套系统, 所以, 我也转到了 java
我这里想说的是, 一个项目选择啥语言, 需要考虑团队的配置, 不能上来就搞一套不切实际的东西, 从实际出发, 找到适合自己的语言曾几何时, 我也觉得 php 是世界上最好的语言, 还没有之一, 现在只觉得哪有最好的语言, 只有最合适的语言
......
槽点 2: 面向对象编程, 而不是面向数组编程
也许你一定很想知道, 如何才能完成从 php 到 java 的转身呢?
说实话, 一开始的时候, 确实很痛苦, 基础薄弱就不说了, 精神上还有压力, 因为全世界都知道你是写 java 的 php 程序员举个特别糗的例子, 刚刚写 spring-mvc 的时候, 不知道如何接收 10 多个参数, 于是我很活该的使用了 map, 我当时想啊, 这不就是我们 php 的 $_GET 和 $_POST 么想当然害死人呀! 可是写着写着我就发现不妥了, 首先, 别人并不知道你的 map 里面有啥子参数; 然后, 从 map 取出来的值不一定有值, 如果是 null, 还要做逻辑判断, 这样子代码又麻烦了所以呀, 虽然这个代码顺利上线了, 也没发生过大的故障, 但是我一直把这份代码当成我的眼中钉, 肉中刺后面我是知道了, 其实用一个对象来接收这些参数, 既优雅, 有便于维护, 可读性也好
下面, 我把自己最恨的一段代码贴出来, 告诫小伙伴们, 别这样子干啊
- // 控制器
- @RequestMapping(value = "/list", method = RequestMethod.GET)
- @ResponseBody
- public AjaxResponse getOrderList(@RequestParam Map<String, String> searchMap) {
- return orderService.getListsData(searchMap);
- }
- // 恶心的逻辑
- /**
- * 解析搜索关键词, 组装 matches
- *
- * @param matches
- * @param searchKey
- * @param searchVal
- * @return
- */
- public Matches getMatchesBySearchMapEntry(Matches matches, String searchKey, String searchVal) {
- switch (searchKey) {
- case Properties.tradeType:
- if (Integer.parseInt(searchVal)> 0) {
- matches.eq(Columns.tradeType, searchVal);
- }
- break;
- case Properties.state:
- int state = Integer.parseInt(searchVal);
- if (state == 4) {
- matches.match("complete_status", 1); // 表示已完成
- } else if (state == 3) {
- matches.match("order_status", 0); // 0 表示已下单
- } else if (state == 1) {
- matches.match("order_status", 1); // 1 表示已支付
- } else if (state == 2) {
- matches.match("order_status", 2); // 2 表示已退款
- }
- break;
- case Properties.channelId:
- List <Long> belongIds = accountService.getChannelIdBelongThisUser(HttpSessionUtils.getUseAccountId());
- if (belongIds == null) {
- if (GeneralUtil.isObjNotZero(searchVal)) {
- matches.match("channel_id", searchVal);
- }
- } else if (belongIds.size()> 0) {
- Long id = Long.parseLong(searchVal);
- if (belongIds.contains(id)) {
- matches.match("channel_id", id);
- } else {
- matches.match("channel_id", belongIds);
- }
- }
- break;
- case Properties.cepingId:
- if (GeneralUtil.isObjNotZero(searchVal)) {
- List <Long> cepingIds = scalePoolDao.findIdsByParentId(Long.parseLong(searchVal));
- matches.match("ceping_id", cepingIds);
- }
- break;
- case Properties.orderNo:
- matches.match("order_no", searchVal);
- break;
- case Properties.openId:
- String userKey = userDao.getUserKeyByOpenidAndUserType(searchVal, 1);
- matches.match("user_key", userKey);
- break;
- case Properties.userKey:
- matches.match("user_key", searchVal);
- break;
- case Properties.createStartTime:
- // 下单时间
- Date createStartTime = DateTimeHelper.timeFormatStringToDate(searchVal);
- matches.gte("create_time", createStartTime);
- break;
- case Properties.createEndTime:
- Date createEndTime = DateTimeHelper.timeFormatStringToDate(searchVal);
- matches.lte("create_time", createEndTime);
- break;
- case Properties.payStartTime:
- // 支付时间
- Date payStartTime = DateTimeHelper.timeFormatStringToDate(searchVal);
- matches.gte("pay_time", payStartTime);
- break;
- case Properties.payEndTime:
- Date payEndTime = DateTimeHelper.timeFormatStringToDate(searchVal);
- matches.lte("pay_time", payEndTime);
- break;
- case Properties.userType:
- int userType = Integer.parseInt(searchVal);
- if (userType> 0) {
- matches.eq(Columns.userType, searchVal);
- }
- break;
- case Properties.buyType:
- int buyType = Integer.valueOf(searchVal);
- if (buyType> 0) {
- if (buyType == BuyType.DEFAULT_COPY_ORDER.getCode()) {
- buyType = 0;
- }
- matches.eq(Columns.buyType, buyType);
- }
- break;
- }
- return matches;
- }
我现在用又臭又长来形容, 这样子的 code 既不方便阅读, 出问题了也不好排查而且这个代码, 我还是放在个循环中来拼接的, 可读性之烂可想而知唉, 要是我如果有时间了, 就把这段代码改了
其实呢, 说了这么多, 我就想说, 包括我在内的部分 phper 额, 太过分依赖数组了是啊, 在 php 里面, 没有啥是一个数组搞不定的, 如果有, 那就俩个我走心看了下其它业务线的 php 代码, 哎哟喂, 好家伙推送服务配置用数组, 微信公众号配置用数组, 接受请求用数组, 传参用数组 (个人最不喜欢的方式), 好像数组少些, 项目就不能正常运行了
我并不是说不该用数组, 但是数组确实不好维护当我们思绪乱的时候, 你根本记不清这个数组中有哪些参数, 你也可能想不起这个 return 的对象有哪些对象, 特别是 return json 的时候, 如果一个数组不存在, 这时候返回了 null, 这样子返回的接口数据, 对客户端的同学来说就是一种灾难
槽点 3: 一包不扫, 何以扫天下
除此之外, 也是我最想吐槽的一点, 就是 php 的命名空间和包管理虽然 php 现在也有了 composer, 但是部分包载入时, 还是需要做一下手动处理的, 如果是一些小白的话, 那久很尴尬了相对于 php 呢, java 就很成熟了, maven 一出, 问题基本就解决了而 php 的命名空间呢, 我最不爽的一点是, 明明一个包没关联上, 项目居然还若无其事的走着, 之前没觉得咋样, 写 java 后就觉得, 这样子特别不严谨, 对于我这样的强迫症者来说, 不能接受!
还有就是, 需要手动载入 扩展, 关于这点, php 做的不够好
槽点 4: 定时任务
此外呢, php 有一点做的不够好的, 定时任务!(且不说用 swoole 做定时任务哈, 毕竟 swoole 还是需要点学习成本的呢!)
之前我很少用 php 做定时任务, 如果要做的话, 就要依赖 linux 系统 crontab, 或者用 swoole 了
但是在 java 里面, 完全不是这样子的体验, 在 play 或者 spring-mvc , 完全就是一个 job 就搞定了, 哪里要这般麻烦!
槽点 5: 必不可少的单元测试
然后呢, php 在单元测试方面比 java 差挺多的这里我不否认有 idea 的功能, 但是想要用 phpunit 测试一个方法, 我感觉千难万难, 但是在 java 里, 很容易就实现了! 除此之外, 包括我在内的部分 phper, 很少写单元测试, 甚至有些压根就不知道这是咋回事! 我觉得这是个可怕的现象, 这样子的代码, 连自己这关都没过, 如何敢上线, 如何能稳呢! 基本上走过单元测试的代码, 基本不存在啥语法错误, 这就是妥妥的保障啊!
槽点 6: 你 debug 都不用, 就不要假装在搬砖了
接下来, 包括我在内的部分 phper 呢, 很少去 debug, 有些甚至从来没这么搞过在那段维护 thinkphp 的时间了, 我开始使用 phpstrom 的 debug, 说实话, 代码质量, 开发效率都有很大的提升! 我实在不能再接受自己用 echo, var_dump 这样子去调试代码, 这样子会让人觉得, 这是个门外汉呢!
槽点 7:php 是世界上最好的语言
请放下这个想法, 你会发现, 无论是 python,golang,java 都不比咱 php 差, 你不知, 只因你未接触!
好了, 就到这里吧, 接下来还会有一篇吐槽 java 的
来源: https://www.cnblogs.com/zeopean/p/8585633.html