PHP/JAVA 雜談 一(php 槽點)


【本文為個人意見,不喜就噴吧!】

最近,同事問到我,『那時候為什么從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差,你不知,只因你未接觸!

 

槽點8:php代碼打包功能弱

在寫java前呢,每次遇到要復用的php代碼呢,我都是直接copy,但是寫java 一段時間后,我就覺得java 這方面比較好了,我可以通過maven 對共用的包進行打包,放到另一個項目中去,這樣子既方便管理,又利於版本的迭代,省時省力!

 

 

好了,就到這里吧,接下來還會有一篇吐槽java的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM