230 likes | 430 Views
API 设计实例分析. 通用 IO API. 目录. IO API 设计实例分析 IO 要解决 的功能 典型场景,划分 功能 接口 整理 标准使用方式(客户) 拦截 [ 传输 ] 过程 IO API 实现说明 成本收益分析. IO API 设计实例 分析. IO 要 解决的 功能. 多数据类型 String 、 Byte[] 、领域对象 多数据来源 文件、 SPI Provider 异常处理、善后虚处理(如资源释放) IO 类型转换 附加分析: IO 计数等等. 典型场景,划分功能.
E N D
API设计实例分析 通用IO API
目录 • IO API设计实例分析 • IO要解决的功能 • 典型场景,划分功能 • 接口整理 • 标准使用方式(客户) • 拦截[传输]过程 • IO API实现说明 • 成本收益分析
IO要解决的功能 • 多数据类型String、Byte[]、领域对象 • 多数据来源文件、SPI Provider • 异常处理、善后虚处理(如资源释放) • IO类型转换 • 附加分析:IO计数等等
典型场景,划分功能 1: File source = new File( getClass().getResource( "/iotest.txt" ).getFile() ); 1: File destination = File.createTempFile( "test", ".txt" ); 1: destination.deleteOnExit(); 2: BufferedReader reader = new BufferedReader(new FileReader(source)); 3: long count = 0; 2: try { 4: BufferedWriter writer = new BufferedWriter(new FileWriter(destination)); 4: try { 2: String line = null; 2: while ((line = reader.readLine()) != null) { 3: count++; 4: writer.append( line ).append( '\n' ); 2: } 4: writer.close(); 4: } catch (IOException e) { 4: writer.close(); 4: destination.delete(); 4: } 2: } finally { 2: reader.close(); 2: } 3: System.out.println(count)
接口整理(1)——输入 public interface Input<T, SenderThrowableType extends Throwable> { <ReceiverThrowableType extends Throwable> void transferTo( Output<T,ReceiverThrowableType> output) throws SenderThrowableType, ReceiverThrowableType; }
接口整理(2)——输出 public interface Output<T, ReceiverThrowableType extends Throwable> { <SenderThrowableType extends Throwable> void receiveFrom( Sender<T, SenderThrowableType> sender) throws ReceiverThrowableType, SenderThrowableType; }
接口整理(3)——发送者 public interface Sender<T, SenderThrowableType extends Throwable> { <ReceiverThrowableType extends Throwable> void sendTo( Receiver<T, ReceiverThrowableType> receiver) throws ReceiverThrowableType, SenderThrowableType; }
接口整理(4)——接受者 public interface Receiver<T, ReceiverThrowableType extends Throwable> { void receive(T item) throws ReceiverThrowableType; }
标准使用方式(客户) • 根据契约,然后可以制定几个输入输出(I/O)的标准。比如:从文本文件中读取文本行后再写成文本文件。 • 这个操作可以静态方法中,方便的重用。 • 最后,拷贝文本文件可以写成: File source = ... File destination = ... Inputs.text( source ) .transferTo( Outputs.text(destination) );
拦截[传输]过程——过滤的API public static <T, ReceiverThrowableType extends Throwable> Output<T, ReceiverThrowableType> filter( final Specification<T> specification, final Output<T, ReceiverThrowableType> output) { // create an Output that filters items // based on the Specification<T> ... } interface Specification<T> { booleantest(T item); }
拦截[传输]过程——过滤的使用代码 下面的例子删除文件中的空行: File source = ... File destination = ... Inputs.text( source ).transferTo( Transforms.filter(new Specification<String>() { public boolean test(String string) { return string.length() != 0; } }, Outputs.text(destination) );
拦截[传输]过程——传输类型转换的API public static <From,To,ReceiverThrowableType extends Throwable> Output<From, ReceiverThrowableType> map( final Function<From,To> function, final Output<To, ReceiverThrowableType> output) {...} interface Function<From, To> { To map(From from); }
拦截[传输]过程——传输类型转换的使用代码 Input<String,IOException> input = ...; Output<JSONObject,RuntimeException> output = ...; input.transferTo( Transforms.map(new String2JSON(), output); File source = ... File destination = ... Counter<String> counter = new Counter<String>(); Inputs.text( source ).transferTo( Transforms.map(counter, Outputs.text(destination) )); System.out.println("Nr of lines:"+counter.getCount())
实现说明 & Demo • http://oldratlee.com/493/tech/java/java-api-design-exercise.html • https://bitbucket.org/oldrat/io-api
成本 • 分析好领域 • 需要让实现者理解保持一致 • 适当的文档让其它人了解你的设计 • 术语约定 • 分解方式
收效 • DRY • KISS(客户API简单,实现涉及较多内容) • 分离的功能 • 资源维护 和 操作分离(IO资源维护和IO操作分离) • 核心功能 和 修饰性功能 • 分离功能之间功能方法参数关联起来,即外围功能持有依赖功能,组合方式(非继承)。 • 各个功能有明确的接口,且是组合的,所以可以方便Wrap,方便拦截加入修饰性功能。 • 同时整理出了API(外围接口)和SPI(内部接口)
引申 • 客户类不需要继承框架内的类 • 从框架继承来的代码属于框架 • 框架应该从客户类提取需要的逻辑拼装运行 • 客户类不需要从框架继承额外的逻辑 • 客户 观察不到的 不要 出现在 API中 • API使用方式 是 客户直觉期望使用方式
参考资料 • How to Design a Good API and Why it Matters(by Joshua Bloch) http://lcsd05.cs.tamu.edu/slides/keynote.pdf • The Little Manual of API Design http://chaos.troll.no/~shausman/api-design/api-design.pdf • Practical API Design: Confessions of a Java Framework Architect http://www.amazon.com/Practical-API-Design-Confessions-Framework/dp/1430243171 • Google Search http://www.google.com.hk/search?&q=api+design
The Design Process • 《The Little Manual of API Design》第三章“The Design Process”,可以实际操作: • Know the requirements • Write use cases before you write any other code • Look for similar APIs in the same library • Define the API before you implement it • Have your peers review your API • Write several examples against the API • Prepare for extensions • Don’t publish internal APIs without review • When in doubt, leave it out