如何設計合理的service?

來源:互聯網
上載者:User
今天碰到一個bug,最後發現原因應該就是service的設計不當(另一個提問)
那麼我們應該如何設計合理的service?有哪些要注意的?什麼才是好的service?有哪些的例子可以參考?

回複內容:

今天碰到一個bug,最後發現原因應該就是service的設計不當(另一個提問)
那麼我們應該如何設計合理的service?有哪些要注意的?什麼才是好的service?有哪些的例子可以參考?

我的解決辦法如下,有什麼缺點請指教:

Service應該分為2種:1,名詞Service; 2, 行為Service
如:UserService 與 RegisterService

對於【名詞Service】其裡面每個method都必須返回相應的對象,如UserService下的upgrade(uid)就必須返回被升級後的user對象。

對於【行為Service】只對外暴露出一個execute(data),excute(data)必須返回行為成功與否的狀態以及被施加這個行為的對象,如RegisterService下的excute(data)就必須返回註冊成功與否,以及如果成功了它影響的對象。

通常我們約定對外只調用【行為Service】,再在【行為Service】裡調用多個【名詞Service】和其他【行為Service】,如在RegisterService::execute(data)裡調用UserService::create(), UserService::markNewbee(uid),SendEmailService::execut()等;

【名詞Service】中允許調用別的【名詞Service】,但不允許調用【行為Service】,如UserService::upgrade不單單可以修改user也可以調用LogService::create來建立log,但不能調用LogoutService::execute()來登出使用者。

可以簡單的理解為一個Model處理它那張資料庫表,一個【名詞Service】處理多個Model,一個【行為Service】處理多個【名詞Service】,這裡【行為Service】也就是設計模式裡的facade,可以配合command模式使用。

所有Service的每個method的入參都可以是id或者對象執行個體,如upgrade()可以接受uid也可以接受user作為入參。

回到我的另一個提問,可以這麼寫

class AService{    function get(aid_or_object)    {        if (aid_or_object instanceOf A) {            return aid_or_object;        }        return A.getById(aid);    }}class PService{    function get(pid_or_object)    {        if (pid_or_object instanceOf P) {            return pid_or_object;        }        return P.getById(pid);    }}class Do2Service{    function execute(aid_or_object, pid_or_object = null)    {        a = AService.get(aid_or_object);        if (pid_or_object instanceOf P) {            p = pid_or_object        } else {            p = PService.get(a.pid);        }        p.s = 'zz';        p.save();        a.save();        return [:success, a, p];    }}class Do3Service{    function execute(pid_or_object)    {        p = PService.get(pid_or_object);        p.s = 'cc';        p.save();        return [:success, p];    }}class Do1Service{    function execute(pid_or_object)    {        p = PService.get(pid_or_object);        p.s = 'yy' if condition1                result, a, p = Do2Servce.execute(p.aid, p) if condition2        result, p = Do3Servce.execute(p) if condition3        p.a = 'a';        p.b = 'b';        p.save()        return [:success, p, a];    }}

你的問題的本質,是兩個“主語”(只是在你的案例中恰好都是service而已)的各自一個“行為”(do1 和 do2)含有了完全相同的一個“行動效果”(修改p.s的值)。
衝突不在於service,而在於行動效果冗餘。
試想一下,換一個案例,其中只有一個主語,兩個行為(do1 和 do2)都是它的,那麼問題也是等價的。
兩個行為有重疊的行動效果,實在太常見的了。
關鍵在於,你怎樣界定,哪種重疊是滿足需求的?哪種是錯誤、不合理的?

舉一個滿足需求的例子:
需求是:p是一個滑鼠移至上方的tips(介面組件)。先根據滑鼠座標,賦值p.top為一個值。隨後,計算tips是否超出了視窗邊緣。如果是,則計算tips的top的最大值(因為視窗大小可能會被改變,所以需要計算),然後賦值p.top為該最大值。p.left同理。
這是我做網頁前端開發時遇到過的需求。

你的解決辦法,大概可以解決你的那一個具體案例,但換成別的情況可能就又不對症了。
在我看來,關鍵在於,一個行為的源頭(往往是事件)所導致一連串列動效果,其中要避免出現重疊;除非需求要求必要的重疊。
這“一連串”的“串法”,是設計上要想清楚的。你已經在朝這個方向努力了,只是關注點稍有偏離。
至於串的過程中的對象(主語/賓語)是不是service、是何種service,倒是沒有關係。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.