对抽象层次一致性的看法
什么抽象
其实抽象是一个很玄乎的东西。其实我们周围的写的很多代码,都是过程式的书写。
大家都知道面向对象的三大基本原则分别是:封装继承和多态。我们往往一遍一遍被这些教科书式的定义所洗脑。
但是其实在我看来,不是的。我觉得面向对象编程最终的是抽象,就是一个建模的过程。这里的建模不仅仅只是针对普通说法上的建模。
那到底什么是抽象?我的理解是,抽象是在一个业务或者一系列业务中,找出一些我们认为可以单独构成一个类,并且对应提供它的方法的。其实这句话等于没有说,但是如果要解释抽象真的很困难。具体可以移步看下我的这篇文章关于抽象
为什么要抽象
当然,抽象不仅仅像说的那么简单。因为一个业务流程,可能你可以有1000种抽象的方式。
好的抽象,我认为的首先肯定是模块化的。
模块化:就是做一件事,在一个地方尽量给它做好。比如说计算订单的价格,我们尽量在一个地方给它做好。而不是这里算一下,等下在其他地方再算一下。(主要好的好处就是在以后维护的时候方便,并且出问题了容易排查)
当然模块化的一个结果就是很好的封装,把一件事都封装在一个类里面。更加容易应对扩展。
其实抽象很像小组件的形式。把整个业务分成一个个小的组件,然后最后组合他们。
好的抽象还有一点,就是能够对抽象的东西很好的扩展,这就需要经验和感觉了。
什么叫做抽象层次一致性
首先在类的维度来看,一个类的方法必须要有抽象一致性。
抽象一致性:整个格局做的事情应该在同一个维度上的
举个例子:
<code> public class OrderComposeService{ public void composeOrder(){ //TODO } public void composeSku(){ //TODO } } </code>
我们这个OrderComposeService
主要功能是组合订单,但是composeSku()
这个方法和composeOrder()
这个方法的就不在同一个抽象层次上。
其实对于类方法的抽象一致性,我现在还是很模糊。如果谁有准确的说明,希望能够指导下。
然后就是方法维度的抽象一致性
<code> public void composeOrder(B b){ composeSku(); calculateShipping(); createPageage(); } </code>
在composeOrder
这个方法中,三个子方法就是在同一抽象层次上面的。但是如果出现
<code> public void composeOrder(B b){ List<a> list = new ArrayList</a><a>(); Map<long> map = new HashMap<long>(); for(A a : list ){ map.put(a.getId,a); } composeSku(); calculateShipping(); createPageage(); } </long></long></a></code>
像下面的这个方法,中间多出的一段就破坏了这个方法的抽象一致性。抽象一致性的代码读起来,就像在读原生的需求一样。不管在可读性还是在扩展性或者是问题的排查性上抽象一致性的代码都胜过一筹。这也是注释少些的原因了,代码本身就是注释。
问题
当然这样子做,有的问题就是方法里面的私有方法会变的很多。参考我上个问题[关于业务分层]
(http://segmentfault.com/q/1010000002631646 "关于业务分层") 。
当然如果是简单的需求,或者业务部是很重的代码不需要考虑这么多。
请问大家对这个有什么看法?
回复内容:
什么抽象
其实抽象是一个很玄乎的东西。其实我们周围的写的很多代码,都是过程式的书写。
大家都知道面向对象的三大基本原则分别是:封装继承和多态。我们往往一遍一遍被这些教科书式的定义所洗脑。
但是其实在我看来,不是的。我觉得面向对象编程最终的是抽象,就是一个建模的过程。这里的建模不仅仅只是针对普通说法上的建模。
那到底什么是抽象?我的理解是,抽象是在一个业务或者一系列业务中,找出一些我们认为可以单独构成一个类,并且对应提供它的方法的。其实这句话等于没有说,但是如果要解释抽象真的很困难。具体可以移步看下我的这篇文章关于抽象
为什么要抽象
当然,抽象不仅仅像说的那么简单。因为一个业务流程,可能你可以有1000种抽象的方式。
好的抽象,我认为的首先肯定是模块化的。
模块化:就是做一件事,在一个地方尽量给它做好。比如说计算订单的价格,我们尽量在一个地方给它做好。而不是这里算一下,等下在其他地方再算一下。(主要好的好处就是在以后维护的时候方便,并且出问题了容易排查)
当然模块化的一个结果就是很好的封装,把一件事都封装在一个类里面。更加容易应对扩展。
其实抽象很像小组件的形式。把整个业务分成一个个小的组件,然后最后组合他们。
好的抽象还有一点,就是能够对抽象的东西很好的扩展,这就需要经验和感觉了。
什么叫做抽象层次一致性
首先在类的维度来看,一个类的方法必须要有抽象一致性。
抽象一致性:整个格局做的事情应该在同一个维度上的
举个例子:
<code> public class OrderComposeService{ public void composeOrder(){ //TODO } public void composeSku(){ //TODO } } </code>
我们这个OrderComposeService
主要功能是组合订单,但是composeSku()
这个方法和composeOrder()
这个方法的就不在同一个抽象层次上。
其实对于类方法的抽象一致性,我现在还是很模糊。如果谁有准确的说明,希望能够指导下。
然后就是方法维度的抽象一致性
<code> public void composeOrder(B b){ composeSku(); calculateShipping(); createPageage(); } </code>
在composeOrder
这个方法中,三个子方法就是在同一抽象层次上面的。但是如果出现
<code> public void composeOrder(B b){ List<a> list = new ArrayList</a><a>(); Map<long> map = new HashMap<long>(); for(A a : list ){ map.put(a.getId,a); } composeSku(); calculateShipping(); createPageage(); } </long></long></a></code>
像下面的这个方法,中间多出的一段就破坏了这个方法的抽象一致性。抽象一致性的代码读起来,就像在读原生的需求一样。不管在可读性还是在扩展性或者是问题的排查性上抽象一致性的代码都胜过一筹。这也是注释少些的原因了,代码本身就是注释。
问题
当然这样子做,有的问题就是方法里面的私有方法会变的很多。参考我上个问题[关于业务分层]
(http://segmentfault.com/q/1010000002631646 "关于业务分层") 。
当然如果是简单的需求,或者业务部是很重的代码不需要考虑这么多。
请问大家对这个有什么看法?
其实做了这些年的项目,经历和见识了很多种的设计,比如:给你文档要你完全按照文档来写甚至每个service里面的方法名都有规范,只是没有严格到怎么去实现他们,我觉得这就是半填空的coding;有一种是完全填空的coding甚至说调用的方法都有参考文档,让你来做的目的就是把谁调用谁填进去,这种是完全填空coding;需求拿来自己设计自己来实现,我觉得这是全包的coding啊,小公司很多这样;还有一种接手的项目已经存在且有自己的架构了,我们做的目的就是来完美它丰满它;公司有个新的案子要从头来做,你们团队中有架构有pg有qa,各司其职这种应该算是比较正常的了。
上面说的这些例子有没有发现一个问题,除了严格的限制你要做什么和你只能做什么以外,其实在团队开发中你身处的角色决定了这个框架的走向,做ui的只是在乎view,甚至他们只是看js css纯ui哦!做service的只是在乎前台和他交互,他怎么和dao去交互。做dao只在乎怎么把service告诉我的东西再交给db,怎么把db的东西交给service。
说了这些可能会认为我跑题太严重了,其实不然!我上面举的例子不可能包含了全部,还只是很小的一部分,就和设计模式一样,曾经看到有人说“什么设计模式啊,很多的这种所谓的设计模式放到其他的语言都没有意义”(我是搞java的),他说的有些是对的,正如中国从古代就讲究不完美一样,那个怎么说来着?“大道五十,天衍四十九,留一线生机,遁去一道”,别吵!我不是看仙侠小说看多了!
我想说的其实是没有完美的!人不完美,事物也不完美,随着你的学识、见闻、体验总能从以前看似完美的东西里面去找出不完美的一面,所以大家还是不要费劲的去追求完美了,如果完美了就不会有什么多少种的设计模式了,一种足以,还有什么nosql,还有什么mvc框架,mvc只是个主流而已,还有很多叫不上名字的(因为人家可能根本没起个好听的名字)。
好吧,题主的问题我到现在都没有认真的回复这是不对的,上面说的这些就是想说一个道理,做自己在这个时刻认为是对的事情就可以了,以后的事情可以适当的去想,但是你的这个以后其实也是有个长度的,想的总是不会太远。
这里开始说下问题的回答。
public void composeOrder(B b){ List<a> list = new ArrayList</a><a>(); Map<long> map = new HashMap<long>(); for(A a : list ){ map.put(a.getId,a); } composeSku(); calculateShipping(); createPageage(); }</long></long></a>
这段代码,你觉得和上下文不一致性,“关于业务分层”的帖子特意去看了下,后面有人提到用helper,manager,facade来做那段“不和谐”的代码都对,哪怕你准备用XX来做都可以的,不就是个名字吗?咱们要的是种思想!我意识到了这段“不和谐”,我就去让它看上去“和谐”点呗。
其实我们周围的写的很多代码,都是过程式的书写。
这句话我非常认同,还记得学oo之前,老师跟我吹呼说很多的语言都是过程的、函数的、程式的、方法的,java可是面向对象的,听上去高大上,但实际呢?就好像每天在家里看ccav非常美好,但出门怎么样?现实和想象总是有差距的。
真正去使用的时候总是图省事没有写“繁琐”的oo代码,比如下面这段
class 我{
N种牛X的属性。。。
public void 做超人(){
无敌了。。想到什么都写这里
}
}
一个method就是超人了,牛不牛?写的时候为什么就不想想,最少得有个红裤衩传给你才能变身呢?超人会干啥?眼睛冒激光,这不得有个光学的类吗?力大无穷?好么这最少牵扯到了人体学。还能飞呢!我们在这能把人体学重用了!超人不是还有女的吗?但是女超人有件事不能做哦!
class 她{
N种牛X的属性。。。
public void 做超人(){
无敌了(比“我”差一点 ,有件事不能做!)。。想到什么都写这里
}
}
ps:我是男的,所以上面没写男超人,呵呵。
好吧,女超人比较惨咱们让她少做一件事,但他们都是超人啊!怎么能写2个类?就要写一个!但是我就一个做超人的method啊,怎么办?这样吧,咱弄个子类继承男超人的优点吧!不行咱就重载一下做超人的method好了。下面就不写了,多态的孩子快出来了。
上面恶搞了一下,很多概念工作年头多了的人都明白,其实概念不会是记的很清楚,但是都知道是怎么回事,我也记的不是很清楚,但就是随便写了,哪怕看到的可能有问题,但总是从一个角度去看可以说通!
这不就是设计吗?这不就是分层吗?这不就是学以致用吗?学java之初说的那个oo的概念,其实我总觉得和那句“道可道,非常道”很相同,道不是说他们说的事情相同,而是那种描述的感觉很像,有些事情可能说不清楚,但是你明白,这就是只可意会不可言传啊,之前在segmentfault看到过个例子(人类玩扑克开车之类的……)帮忙说怎么写class,还是segmentfault的人不多,或者很多人瞧不上这种问题,我敢说如果有100个人让他们去写,可能会出现101种方式,你不能要求一个人只能写一种。
就说这些吧,写的可能有点杂有点乱了,大家伙看个乐就完了,哈哈。
你所说的都是结构化编程的概念,其基本思想是各层过程类似于一本书的目录,从整本书到章到节。
而面向对象虽然也有一个对象向另一个对象请求服务的情况。但是和结构化编程有微妙的不同。更像是用不同芯片组成逻辑电路。各个对象之间未必有统属关系,更多的是强调知识归属和不同对象的责任问题。
网易公开课里有个编程范式的课程,如果有耐心看完,应该有助于你理解这个问题。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

在PHP8 中,match表達式是一種新的控制結構,用於根據表達式的值返回不同的結果。 1)它類似於switch語句,但返回值而非執行語句塊。 2)match表達式使用嚴格比較(===),提升了安全性。 3)它避免了switch語句中可能的break遺漏問題,增強了代碼的簡潔性和可讀性。
