<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                *** _我發現,我越是努力,就越發幸運。 -- Thomas Jefferson_ ##2.17.1 微服務 ![a pic](http://7qnay5.com1.z0.glb.clouddn.com/qq_20150607110405.jpg) Martin Fowler(我喜歡和敬仰的大師)曾發表了上面這一段話。這段話也出現在了2015年QCon分享會上,并加了一張PPT“什么是微服務”加以說明。 ![a pic](http://7qnay5.com1.z0.glb.clouddn.com/qcon_20150607.png) 里面提到了 **微服務** 這個概念,在PhalApi框架中即對應我們的Api接口服務層,只是我們不是稱之為微服務,而是接口服務。 不管何種說法,我們都應該關注里面提及到的這幾點重要特質: + 小,且專注于做一件事情 + 獨立的進程中 + 輕量級的通信機制 + 松耦合、獨立部署 這里不過多地討論微服務相關的分享,而是重溫接口服務層Api與領域驅動和單元測試之間的關系,以及如何開發一個優雅、穩定又簡單的接口。 ##2.17.2 層級調用的順序 整體上講根據從Api接口層、Domain領域層再到Model數據源層的順序進行開發。 在開發過程中,需要注意不能 **越層調用** 也不能 **逆向調用** ,即不能Api調用Model。而應該是 **上層調用下層,或者同層級調用** ,也就是說,我們應該: + Api層調用Domain層 + Domain層調用Domain層 + Domain層調用Model層 + Model層調用Model層 如果用一張圖來表示,則是: ![a pic](http://7qnay5.com1.z0.glb.clouddn.com/201506071124.png) 為了更明確調用的關系,以下調用是 **錯誤** 的: + 錯誤的做法1:Api層直接調用Model層 + 錯誤的做法2: Domain層調用Api層,也不應用將Api層對象傳遞給Domain層 + 錯誤的做法3: Model層調用Domain層 這樣的約定,便于我們形成統一的開發規范,降低學習維護成本。 比如需要添加緩存,我們知道應該定位到Model層數據源進行擴展;若發現業務規則處理不當,則應該進入Domain層探其究竟;如果需要對接口的參數進行調整,即使是新手也知道應該找到對應的Api文件進行改動。 ##2.17.3 接口服務的定義 現實項目開發過程中,絕大部分我們編寫的接口是給別人使用的,或許給Android客戶端同學使用,或者給iOS客戶端同學使用,抑或提供給其他后臺系統的同學使用。 為了提高并行開發的速度,我們不能等待接口完全開發完成后才提供接口文檔,而且他們也不能忍受這么漫長的等待。 所以,客戶端同學時常會問我們:什么時候可以提供接口文檔? 我們提倡“接口先行”,如果有時不能很好地做到這一點(畢竟多變的需求促發多變的情境),我們可以快速提供接口的定義。 這有點像規約層對接口的定義一樣,在PhalApi中定義一個接口,再具體一點即: + 1、創建一個接口服務類和聲明函數 + 2、配置接口參數規則 + 3、提供接口返回格式的注釋 簡單來說,就是創建一個類,寫個函數,定義參數和返回結果。 下面以 [開發實戰3:一個簡單的小型項目開發(奔跑吧兄弟投票活動)](http://git.oschina.net/dogstar/PhalApi-Demo-Vote) 中的團隊參賽接口為例,說明這三步操作的過程。 ###(1)創建一個接口服務類和聲明函數 ```javascript //$ vim ./Vote/Api/Act.php <?php class Api_Act extends PhalApi_Api { public function joinIn() { } } ``` ###(2)配置接口參數規則 ```javascript <?php class Api_Act extends PhalApi_Api { public function getRules() { return array( 'joinIn' => array( 'teamName' => array('name' => 'team_name', 'require' => true, 'min' => 1, 'max' => 100), ), ); } public function joinIn() { } } ``` ###(3)提供接口返回格式的注釋 ```javascript <?php class Api_Act extends PhalApi_Api { public function getRules() { return array( 'joinIn' => array( 'teamName' => array('name' => 'team_name', 'require' => true, 'min' => 1, 'max' => 100), ), ); } /** * 團隊參賽接口 * * @return int code 0,參賽成功;1,隊名已存在 * @return int team_id 新建的團隊ID */ public function joinIn() { } } ``` ###(4)在線查看一下效果 在完成上面的動作后,我們可以通過在線工具來看下實時的效果,在瀏覽打開后訪問: ``` http://api.vote.phalapi.com/vote/checkApiParams.php?service=Act.JoinIn ``` 可以看到: ![a pic](http://7qnay5.com1.z0.glb.clouddn.com/201506071302.jpg) 到了這里,即使我們未完成接口的開發,也未提供更完善的接口文檔,但接口客戶端同學也可以根據這個在線的接口參數進行開發了。 ##2.17.4 在ATDD下講述故事 我們一直推崇測試驅動開發,但在對于Api接口開發,更準確來說是ATDD,即:驗收測試驅動開發(Acceptance Test Driven Development)。 在前面Domain層文檔中,我們提到了Api層是講述故事的場景。因此,為了驗證我們的業務場景是否正確,我們應該事先編寫好單元測試,以不斷引導我們前往正確的目的地。 我們可以使用腳本來快速生成測試骨架: ```javascript $ pwd $ /path/to/api.vote.phalapi.com/Vote/Tests/Api $ phalapi-buildtest ../../Api/Act.php Api_Act ../test_env.php > Api_Act_Test.php ``` 然后,稍微修改完善測試場景: ```javascript /** * @group testJoinIn */ public function testJoinIn() { //Step 1. 構建請求URL $url = 'service=Act.JoinIn'; $params = array( 'sign' => 'phalapi', 'team_name' => 'test team name', 'user_id' => '1', 'token' => '193CE82D1F4588A9A168BDE6E6B83868B1464F523D16C05206F308E51EB91731', ); DI()->notorm->team->where('team_name', $params['team_name'])->delete(); //Step 2. 執行請求 $rs = PhalApiTestRunner::go($url, $params); //var_dump($rs); //Step 3. 驗證 $this->assertNotEmpty($rs); $this->assertArrayHasKey('code', $rs); $this->assertArrayHasKey('team_id', $rs); $this->assertEquals(0, $rs['code']); $this->assertGreaterThan(0, $rs['team_id']); //create again $rs = PhalApiTestRunner::go($url, $params); $this->assertEquals(1, $rs['code']); } ``` 從上面測試的代碼可以看出,我們先后進行了兩次報名。明顯地,第一次報名應該是成功的,第二次則應該提示不能重復報名。 單元測試的好處,不但在于可以引導我們做正確的事情,還可以提高我們的關注點,不致于在開發過程中被各種事務(如臨時性的會議)打斷后回來卻不知剛才開發到哪了。 然而,更多的是為后期的維護、擴展提供可驗證的業務場景。這點是很重要的。因為每一個測試場景,都保存了對應場景的模擬信息,這樣不僅僅在后面的擴展,還是突如其來的BUGFIXED,我們都可以快速證明我們的修改是正確的,至少不會影響到原來的業務流程。 試想一下,如果原來可以下單支付的接口,突然被影響到而導致支付不成功,這是何等的損失! 我現在慢慢地,每當需要修改別人的代碼時,我都會看下有沒有對應的單元測試。如果沒有,我會先補回,這樣能增強我修改別人代碼的信心。 ##2.17.5 精益接口開發 傳統的接口開發,由于沒有很好的分層結構,而且熱衷于在一個文件里面完成絕大部分事情,最終導致了臃腫漫長的代碼,也就是通常所說的意大利面條式的代碼。 在PhalApi中,我們針對接口領域開發,提供了新的分層思想:ADM(Api - Domain - Model)。 即便這樣,如果項目在實際開發中,仍然使用原來的做法,縱使使用再好的接口開發框架,也還是會退化到原來的局面。 為了能讓大家更為明確Api接口層的職責所在,我們建議: ###(1)Api接口層應該做: + 應該:對用戶登錄態進行必要的檢測 + 應該:控制業務場景的主流程,創建領域業務實例,并進行調用 + 應該:進行必要的日志紀錄 + 應該:返回接口結果 ###(2)Api接口層不應該做: + 不應該:進行業務規則的處理或者計算 + 不應該:關心數據是否使用緩存,或進行緩存相關的直接操作 + 不應該:直接操作數據庫 + 不應該:將多個接口合并在一起 在明確了上面應該做的和不應該做的,并且也完成了接口的定義,還有驗收測序驅動開發的場景準備后,相信這時,即使是新手也可以編寫出高質量的接口代碼。 因為他會受到約束,他知道他需要做什么,主要他按照限定的開發流程和約定稍加努力即可。 如果真的這樣,相信我們也就慢慢能體會到 **精益開發** 的樂趣。 最后,讓我們一起來看下上述團隊參賽接口開發的代碼實現: ```javascript /** * 團隊參賽接口 * * @return int code 0,參賽成功;1,隊名已存在 * @return int team_id 新建的團隊ID */ public function joinIn() { $rs = array('code' => 0, 'team_id' => 0); DI()->userLite->check(true); $domain = new Domain_Team(); if ($domain->isExists($this->teamName)) { $rs['code'] = 1; return $rs; } $teamId = $domain->joinIn($this->teamName); $rs['team_id'] = $teamId; return $rs; } ``` 可以看出,上面的代碼短小達意,簡單清晰。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看