2012-05-18 89 views
8

以下是該場景。作爲公開許可的開放源代碼API的創建者,我的團隊創建了一個基於Java的Web用戶界面框架(所以還有什麼新功能?)。爲了使事情保持良好,並像Java一樣組織起來,我們使用了命名約定 org.mygroup.myframework.x的包,其中x是組件,驗證器,轉換器,實用程序等等的東西(同樣,還有什麼是新的?)。現在缺少「框架級」訪問修飾符

,地方類org.mygroup.myframework.foo.Bar是一種方法void doStuff(),我需要執行特定的邏輯,以我的框架,我需要能夠從其他一些地方在我的框架叫它例如org.mygroup.myframework.far.Boo。鑑於Boo既不是Bar的子類,也不是完全相同的包,doStuff()方法必須聲明爲公開才能被Boo調用。

但是,我的框架作爲一種工具存在,可以讓其他開發人員爲他們的客戶創建更簡單更優雅的R.I.A.s。但是,如果com.yourcompany.yourapplication.YourComponent調用doStuff(),它可能會帶來意想不到的後果。我會 寧願這絕不允許發生。請注意,Bar包含真正公開的其他方法。在一個象牙塔世界中,我們將重新編寫Java語言,並將默認訪問插入一個標記化模擬,這將允許我們選擇的包結構中的任何類訪問我的方法,可能類似於:

[org.mygroup.myframework.*] void doStuff() { .... } 

其中通配符將意味着其封裝org.mygroup.myframework開始可以調用任何類,但沒有其他人。

鑑於這個世界不存在,我們還有什麼其他的好選擇?


請注意,這是由真實生活場景驅動的;名稱已被改變以保護有罪。存在一個真正的框架,其中遍佈Javadoc的人會發現公共方法評論爲「這種方法是內部的,而不是它的公共API的一部分,不要打電話!!!!!!」一些研究表明這些方法是從框架內的其他地方調用的。

事實上,我是一個開發人員使用有問題的框架。雖然我們的應用程序已經部署並取得了成功,但我的團隊遇到了很多挑戰,我們希望說服我們的老闆永遠不要再使用此框架。我們希望通過深入瞭解框架開發人員做出的糟糕設計決定來做到這一點,而不僅僅是咆哮。這個問題將是我們的觀點之一,但我們不能指責我們可能做得有什麼不同。我的工作場所已經有一些熱烈的討論,所以我想知道世界其他地方會怎麼想。


更新:沒有冒犯到兩個應答者,到目前爲止,但我想你已經錯過了標記,或者是我沒有表達得很好。無論哪種方式讓我嘗試照亮事物。盡我所能,框架的開發人員應該如何重構以下內容。請注意,這是一個非常粗略的例子。

package org.mygroup.myframework.foo; 
public class Bar { 
    /** Adds a Bar component to application UI */ 
    public boolean addComponentHTML() { 
     // Code that adds the HTML for a Bar component to a UI screen 
     // returns true if successful 
     // I need users of my framework to be able to call this method, so 
     // they can actually add a Bar component to their application's UI 
    } 

    /** Not really public, do not call */ 
    public void doStuff() { 
     // Code that performs internal logic to my framework 
     // If other users call it, Really Bad Things could happen! 
     // But I need it to be public so org.mygroup.myframework.far.Boo can call 
    } 
} 

另一個更新:所以我剛剛得知,C#有 「內部」 的訪問修飾符。所以也許更好的方法來解釋這個問題可能是「如何模擬/模擬Java中的內部訪問?」不過,我不是在尋找新的答案。我們的老闆最終同意上面提到的問題

+0

聽起來像是你的分裂公共API和實現成單獨的項目,由大量的接口的公共API有很大的情況下。 – Perception

+0

@Perception:我相信這就是JSF所做的,並帶有單獨的jsf-api.jar和jsf-impl.jar。 – cobaltduck

+1

'存在一個真正的框架,其中遍佈其Javadoc的人會發現公共方法評論爲......'嗯,我想知道哪個框架可能:)) – biziclop

回答

0

你得到最接近的答案時,你提到的文檔問題。真正的問題不是你無法「保護」你的內部方法;相反,內部方法會污染您的文檔並引入客戶模塊可能錯誤地調用內部方法的風險。

當然,即使您確實擁有細粒度的權限,您仍然無法阻止客戶端模塊調用內部方法--- jvm無法防止基於對私有方法的基於反射的調用無論如何。

我使用的方法是爲每個有問題的類定義一個接口,並讓類實現它。這個接口可以單獨記錄在客戶端模塊中,而實現類可以提供你想要的內部文檔。如果你不想要,你甚至不需要在你的發佈包中包含實現javadoc,但是無論哪種方式,邊界都是明確劃分的。

只要確保在運行時每個文檔界面只加載一個實現,現代jvm將保證您不會因使用它而遭受任何性能損失;並且,您可以在測試期間加載線束/存根版本以獲得額外的獎勵。

0

爲了提供這個缺少的「框架級訪問修飾符」,我能想到的唯一想法是CDI和更好的設計。 如果您必須在各種(但很少)的情況下使用非常不同的類和包中的方法,那麼肯定會有一種重新設計這些類的方法,以便使這些方法「私密」且無法訪問。

+0

請定義「CDI」 – cobaltduck

+0

我對CDI一無所知,但我猜shuuchan引用了上下文和依賴注入:http://jcp.org/en/jsr/detail?id = 299 – Curtis

0

對於這種類型的訪問級別,您不需要Java語言的支持(您希望像名稱空間中的「internal」那樣)。您只能限制訪問包級別(或已知的繼承public-protected-private模型)。

根據我的經驗,您可以使用Eclipse約定: 創建一個名爲「internal」的包,此包的所有類層次結構(包括子包)將被視爲非API代碼,並且可以隨時更改保證您的用戶。在那個非API代碼中,只要你喜歡就使用公共方法。由於它只是一個約定,並不是由JVM或Java編譯器強制執行的,所以不能阻止用戶使用代碼,但至少要讓他們知道這些類不應該被第三方使用。

順便說一下,在Eclipse平臺源代碼中,有一個複雜的插件模型,通過爲每個插件實現自定義類加載器來防止加載類應該是「內部」的類,從而強制您不要使用其他插件的內部代碼這些插件。

+0

我的問題在於,我稱爲org.mygroup.myframework.foo.Bar的類包含一個公共方法,我希望其他應用程序能夠調用,而另一個我不需要。 – cobaltduck

0

接口和動態代理有時用於確保您只暴露您想要公開的方法。

但是附帶在一個相當沉重的性能開銷,如果被稱爲非常頻繁的方法。

使用@Deprecated註釋也可能是一個選項,雖然它不會阻止外部用戶調用您的「框架專用」方法,但他們不能說他們沒有被警告過。

一般來說,我認爲你不應該擔心你的用戶故意在腳上自己拍攝自己,只要你向他們明確表示他們不應該使用某些東西。