java nio的演进_Java接口的防御性API演进
java nio的演進(jìn)
API的發(fā)展絕對(duì)是不平凡的。 只有少數(shù)幾個(gè)需要處理的事情。 我們大多數(shù)人每天都在使用內(nèi)部專有API。 現(xiàn)代IDE附帶了很棒的工具,可以分解,重命名,上拉,下推,間接,委托,推斷,泛化我們的代碼偽像。 這些工具使重構(gòu)我們的內(nèi)部API變得輕而易舉。 但是我們中的一些人在公共API上工作,其中規(guī)則發(fā)生了巨大變化。 如果正確完成,則對(duì)公共API進(jìn)行版本控制。 每次更改(兼容或不兼容)都應(yīng)在新的API版本中發(fā)布。 多數(shù)人會(huì)同意,API演化應(yīng)在主要和次要版本中完成,類??似于語(yǔ)義版本控制中指定的內(nèi)容 。 簡(jiǎn)而言之:不兼容的API更改發(fā)布在主要版本(1.0、2.0、3.0)中,而兼容的API更改/增強(qiáng)發(fā)布在次要版本(1.0、1.1、1.2)中。
如果您正在計(jì)劃,那么您將在很長(zhǎng)時(shí)間內(nèi)預(yù)見到大多數(shù)不兼容的更改,然后才實(shí)際發(fā)布下一個(gè)主要版本。 棄用是Java中提早宣布這樣的變化的一個(gè)好工具。
接口API的演變
現(xiàn)在,棄用是一個(gè)很好的工具,它表明您將要從API中刪除類型或成員。 如果要在接口的類型層次結(jié)構(gòu)中添加方法或類型怎么辦? 這意味著實(shí)現(xiàn)您的接口的所有客戶端代碼都將中斷–至少只要尚未引入Java 8的防御方法即可。 有幾種技術(shù)可以規(guī)避/解決此問題:
1.不在乎
是的,這也是一種選擇。 您的API是公開的,但使用的可能不是很多。 讓我們面對(duì)現(xiàn)實(shí):并不是我們所有人都在JDK / Eclipse / Apache / etc等代碼庫(kù)上工作。 如果您很友好,則至少要等待主要版本引入新方法。 但是,如果確實(shí)需要,您可以打破語(yǔ)義版本控制的規(guī)則-如果您可以處理引起一群憤怒的用戶的后果。
但是請(qǐng)注意,其他平臺(tái)并不像Java Universe那樣向后兼容(通常是根據(jù)語(yǔ)言設(shè)計(jì)或語(yǔ)言復(fù)雜性)。 例如,使用Scala將事物聲明為隱式的各種方法,您的API并不總是完美的。
2.用Java方式完成
“ Java”方式根本不發(fā)展接口。 JDK中的大多數(shù)API類型永遠(yuǎn)都是今天的樣子。 當(dāng)然,這使API感覺很“恐龍化”,并在各種相似類型之間(例如StringBuffer和StringBuilder或Hashtable和HashMap)增加了很多冗余。
請(qǐng)注意,Java的某些部分不遵循“ Java”方式。 最具體地說(shuō),JDBC API就是這種情況,它是根據(jù)第1節(jié)“不關(guān)心它”的規(guī)則演變的。
3.用Eclipse的方式來(lái)做
Eclipse的內(nèi)部包含大量API。 在Eclipse中/進(jìn)行開發(fā)時(shí), 有很多指南如何開發(fā)自己的API(即,插件的公共部分)。 關(guān)于Eclipse家伙如何擴(kuò)展接口的一個(gè)示例是IAnnotationHover類型。 根據(jù)Javadoc合同,它允許實(shí)現(xiàn)還實(shí)現(xiàn)IAnnotationHoverExtension和IAnnotationHoverExtension2 。 顯然,從長(zhǎng)遠(yuǎn)來(lái)看,這種經(jīng)過改進(jìn)的API很難維護(hù),測(cè)試和記錄文檔,最終很難使用! (考慮ICompletionProposal及其6(!)擴(kuò)展類型)
4.等待Java 8
在Java 8中,您將能夠使用防御者方法 。 這意味著您可以為新的接口方法提供明智的默認(rèn)實(shí)現(xiàn) ,如Java 1.8的java.util.Iterator (摘錄)所示:
public interface Iterator<E> {// These methods are kept the same:boolean hasNext();E next();// This method is now made 'optional' (finally!)public default void remove() {throw new UnsupportedOperationException('remove');}// This method has been added compatibly in Java 1.8default void forEach(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);while (hasNext())consumer.accept(next());} }當(dāng)然,您并不總是希望提供默認(rèn)的實(shí)現(xiàn)。 通常,您的接口是必須完全由客戶端代碼實(shí)現(xiàn)的合同。
5.提供公共默認(rèn)實(shí)現(xiàn)
在許多情況下,明智的做法是告訴客戶端代碼,他們可能需要自己承擔(dān)風(fēng)險(xiǎn)(由于API的演變)來(lái)實(shí)現(xiàn)接口,而他們應(yīng)該更好地?cái)U(kuò)展提供的抽象或默認(rèn)實(shí)現(xiàn)。 一個(gè)很好的例子是java.util.List ,可能很難正確實(shí)現(xiàn)。 對(duì)于簡(jiǎn)單的而不是對(duì)性能至關(guān)重要的自定義列表,大多數(shù)用戶可能選擇擴(kuò)展java.util.AbstractList 。 然后剩下剩下要實(shí)現(xiàn)的唯一方法是get(int)和size()。所有其他方法的行為都可以從這兩個(gè)方法中得出:
class EmptyList<E> extends AbstractList<E> {@Overridepublic E get(int index) {throw new IndexOutOfBoundsException('No elements here');}@Overridepublic int size() {return 0;} }遵循的一個(gè)很好的約定是,如果您的默認(rèn)實(shí)現(xiàn)為AbstractXXX,則將其命名為默認(rèn)實(shí)現(xiàn);如果是具體的,則將其命名為DefaultXXX
6.使您的API很難實(shí)現(xiàn)
現(xiàn)在,這并不是真正的好技術(shù),而只是一個(gè)可能的事實(shí)。 如果您的API很難實(shí)現(xiàn)(一個(gè)接口中有100多個(gè)方法),則用戶可能不會(huì)這樣做。 注意: 可能 。 永遠(yuǎn)不要低估瘋狂的用戶。 一個(gè)示例是jOOQ的 org.jooq.Field類型,它表示數(shù)據(jù)庫(kù)字段/列。 實(shí)際上,這種類型是jOOQ的內(nèi)部領(lǐng)域特定語(yǔ)言的一部分 ,提供了可以在數(shù)據(jù)庫(kù)列上執(zhí)行的各種操作和功能。 當(dāng)然,擁有太多方法是一個(gè)例外,并且-如果您不設(shè)計(jì)DSL-可能表明整體設(shè)計(jì)不佳。
7.添加編譯器和IDE技巧
最后但并非最不重要的一點(diǎn)是,您可以將一些巧妙的技巧應(yīng)用于您的API,以幫助人們了解他們應(yīng)該做些什么,以便正確實(shí)現(xiàn)基于接口的API。 這是一個(gè)艱難的例子,它使API設(shè)計(jì)人員的意圖直接撲向您的臉。 考慮一下org.hamcrest.Matcher API的以下摘錄:
public interface Matcher<T> extends SelfDescribing {// This is what a Matcher really does.boolean matches(Object item);void describeMismatch(Object item, Description mismatchDescription);// Now check out this method here:/*** This method simply acts a friendly reminder not to implement * Matcher directly and instead extend BaseMatcher. It's easy to * ignore JavaDoc, but a bit harder to ignore compile errors .** @see Matcher for reasons why.* @see BaseMatcher* @deprecated to make*/@Deprecatedvoid _dont_implement_Matcher___instead_extend_BaseMatcher_(); }“友好的提醒” ,來(lái)吧。
其他方法
我敢肯定,還有許多其他方法可以開發(fā)基于接口的API。 我很好奇您的想法!
參考: JAVA,SQL和JOOQ博客上的JCG合作伙伴 Lukas Eder 提供了Java接口的防御性API演變 。
翻譯自: https://www.javacodegeeks.com/2013/02/defensive-api-evolution-with-java-interfaces.html
java nio的演進(jìn)
總結(jié)
以上是生活随笔為你收集整理的java nio的演进_Java接口的防御性API演进的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 长裙怎么搭配上衣好看(长裙外面配外套的图
- 下一篇: Java 8可选