设计合适的接口

告别接口焦虑:如何为你的MacBook/Windows笔记本挑选和设计最合适的Type-C扩展坞? 本文详细解析了如何为MacBook/Windows笔记本挑选和设计最适合的Type-C扩展坞,从芯片方案如AG9311到实际应用场景,帮助用户避免常见陷阱。文章还对比了五款热门扩展坞的性能表现,并提供了未来升级的考量建议,助你告别接口焦虑。 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> 我们在设计系统接口时,经常会遇到这样的问题: 1、我们的接口应该提供多少方法才合适? 2、我们的接口应该提供"原子方法"还是"复合方法"? 3、我们的接口是否应该封装(或者,能否封装)所有的细节? 接口的设计需要考虑用户的使用习惯、使用的方便程度、使用的安全程度,根据我的编程经验,下面会详细讨论接口设计的2个需要权衡的方面:接口的单一化 & 复合化。 接口 接口提供了不同系统之间或者系统不同组件之间的界定。在软件中,接口提供了一个屏障,从而从实现中分离目标,从具体中分离抽象,从作者中分离用户。 站在用户的角度看,一个接口建立并命名了一个目标对象的使用方法。一些约束(例如:编译时的类型系统、运行时的异常机制及返回值)使得类作者的目的得以体现和加强。供给(affordances)指事物的被感知的真实的属性,这些属性可以决定事物使用的可能方法,供给提供了对事物操作的线索。 类设计者的一个职责便是在接口中减小约束与供给之间的隔阂、匹配目标以及一定程度上的自由度,尽可能减小错误使用目标对象的可能。 封装 对于封装来说,远不止数据私有那么简单。在设计中,封装往往会涉及到自我包含(self-containment)。如果一个类需要你知道如何调用它方法(e.g. 在一个线程的环境中,在一个方法调用后调用另一个方法,你必须明确地同步对象),那么它的封装性就不如将所有这些全部包含并隐藏的类(e.g. 这个类是thread-safe的)好。前一个设计存在着设计的漏洞,它的许多限定条件是模糊的,而且把部分责任推给了用户,而不是让类提供者做这些工作来完成类的设计。 在空间或者时间上分离方法的执行(例如,线程,远程方法调用,消息队列),能够对设计的正确性和效率产生意义深远的影响。这种分离带来的结果是不可忽视的: 并发引入了不确定性和环境(context)选择的开销; 分布引入了回调的开销,这些开销可能不断增加,而且会导致错误。 这些是设计的问题,修改它们可不是象修改bug那样简单。 如果一个接口主要由存取方法(set和get方法)组成,每个方法都相应的直接指向某个私有域,那么它的封装性会很差。接口中的域存取方法通常是不会提供信息的:他们在对象的使用中不能通讯、简单化和抽象化,这通常会导致代码冗长,并且容易出错。 所以,我们首先考虑接口设计的第一个原则: 命令与查询分离(Command-Query Separation) 要求:保证一个方法不是命令(Command)就是查询(Query) 定义: 查询:当一个方法返回一个值来回应一个问题的时候,它就具有查询的性质; 命令:当一个方法要改变对象的状态的时候,它就具有命令的性质; 通常,一个方法可能是纯的Command模式或者是纯的Query模式,或者是两者的混合体。在设计接口时,如果可能,应该尽量使接口单一化,保证方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用(side effects),而会改变对象的状态的方法不可能有返回值。也就是说:如果我们要问一个问题,那么就不应该影响到它的答案。实际应用,要视具体情况而定,语义的清晰性和使用的简单性之间需要权衡。 例如,在java.util.Iterator中,hasNext可以被看作一种查询,remove是一种命令,next合并了命令和查询: public interface Iterator{ boolean hasNext(); Object next(); void remove(); } 这里,如果不将一个Iterator对象的当前值向前到下一个的话,就不能够查询一个Iterator对象。如果没有提供一个复合方法next,我们将需要定义一系列的命令方法,例如:初始化(initialization)、继续(continuation)、访问(access)和前进(advance),它们虽然清晰定义了每个动作,但是,客户代码过于复杂: for(initialization; continuation condition; advance){ ... access for use ... } 将Command和Query功能合并入一个方法,方便了客户的使用,但是,降低了清晰性,而且,可能不便于基于断言的程序设计并且需要一个变量来保存查询结果: Iterator iterator = collection.iterator(); while(iterator.hasNext();){ Object current = iterator.next(); ... use current... } 下面,我们考虑接口设计的第二个原则: 组合方法(Combined Method) 组合方法经常在线程和分布环境中使用,来保证正确性并改善效率。 一些接口提供大量的方法,起初,这些方法看来是最小化的,而且相关性强。然而,在使用的过程中,一些接口显现得过于原始,它们过于简单化,从而迫使类用户用更多的工作来实现普通的任务,并且,方法之间的先后顺序及依赖性比较强(即,暂时耦合)。这导致了代码重复,而且非常麻烦和容易出错。 一些需要同时执行成功的方法,在多线程、异常、和分布的情况下会遇到麻烦。如果两个动作需要同时执行,它们由两个独立的方法进行描述,必须都完全成功的执行,否则会导致所有动作的回滚。 线程的引入使这种不确定性大大增加。一系列方法同时调用一个易变的(mutable)对象,如果这个对象在线程之间共享,即使我们假设单独的方法是线程安全的,也无法确保结果是意料之中的。看下面对Event Source的接口,它允许安置句柄和对事件的查询: interface EventSource{ Handler getHandler(Event event); void installHandler(Event event, Handler newHandler); } 线程之间的交叉调用可能会引起意想不到的结果。假设source域引用一个线程共享的对象,对象很可能在1、2之间被另一个线程安装了一个新的句柄: class EventSourceExample{ public void example(Event event, Handler newHandler){ oldHandler = eventSource.getHandler(event); // 1 //对象很可能在这里被另一个线程安装了一个新的句柄 eventSource.installHandler(event, newHandler); // 2 } private EventSource eventSource; private Handler oldHandler; } 为了解决问题,也需要由类的使用者而不是类的设计者来完成: class EventSourceExample{ public void example(Event event, Handler newHandler){ synchronized(eventSource){ oldHandler = eventSource.getHandler(event); eventSource.installHandler(event, newHandler); } } private EventSource eventSource; private Handler oldHandler; } 我们假设:目标对象eventSource是远程的,执行每一个方法体的时间和通讯的延迟相比是很短的。在这个例子中,eventSource的方法被调用了两次,并可能在其他的实例中重复多次,因而,开销也是至少两倍。 此外还有一个问题是对外部的synchronized同步块的使用需求。对synchronized块的使用之所以会失败,主要因为我们通过代理对象来完成工作,所以,调用者的synchronized块,同步的是代理对象而不是最终的目标对象,调用者不可能对其行为做太多的保证。 Combined Method必须在分布的环境,或者,线程环境中同时执行。它反映了用户直接的应用,恢复策略和一些笨拙的方法被封装到Combined Method中,并简化了接口,减少了接口中不需要的累赘。Combined Method的效果是支持一种更像事务处理风格的设计。 在一个组合的Command-Query中提供一个单独的Query方法通常是合理的。提供分离的Command方法是不太常见的,因为Combined Method可以完成这一工作,只要调用者简单的忽略返回结果。如果返回一个结果招致一个开销的话,才可能会提供一个单独的Command方法。 回到前一个例子中,如果installHandler method返回上一次安装的句柄,则设计变得更加简单和独立: interface EventSource{ Handler installHandler(Event event, Handler newHandler); } 客户代码如下: class EventSourceExample{ public void example(Event event, Handler newHandler){ oldHandler = eventSource.installHandler(event, newHandler); } private EventSource eventSource; private Handler oldHandler; } 这样,我们给调用者提供了一个更加安全的接口,并且不再需要他们解决线程的问题。从而降低了风险和代码量,将类设计的职责全部给了类设计者而不是推给用户,即使有代理对象的出现也不会影响到正确性。 一个Combined Method可以是许多Query的集合,许多Command的集合,或者两者兼有。这样,它可能补充Command、Query方法,也可能与之相抵触。当冲突发生的时候,优先选择Combined Method会产生一个不同的正确性和适用性。 在另一个例子中,我们考虑获得资源的情况。假设,在下面的接口中,方法acquire在资源可用前阻塞: interface Resource{ boolean isAcquired(); void acquire(); void release(); } 类似于下面的代码会在一个线程系统中推荐使用: class ResourceExample{ public void example(){ boolean acquired = false; synchronized(resource){ if(!resource.isAcquired()) resource.acquire(); else acquired = true; } if(!acquired) ... } private Resource resource; } 然而,即使我们放弃可读性和易用性,这样的设计也不是一个Command-Query分离的设计。如果引入了代理,它就会失败: class ActualResource implements Resource {...} class ResourceProxy implements Resource {...} 如果用户既可以通过ActualResource来完成工作,也可以通过ResourceProxy来完成工作,而且,ActualResource和ResourceProxy都没有处理同步,则synchronized块可能会失败。因为,既然我们可以通过代理对象ResourceProxy来完成工作,那么,调用者的synchronized块,同步的就是代理对象ResourceProxy而不是最终的目标对象ActualResource。 一个Combined Method解决了这个问题,它使并发和间接性更加透明。 interface Resource{ boolean tryAcquire(); } 下面的代码清晰、简单并且正确: class ResourceExample{ public void example(){ if(!resource.tryAcquire()) ... } private Resource resource; } Combined Method带来的一个结果是使一些测试和基于断言的程序设计变得十分笨拙,然而,它适合解决线程和分布问题。 实际应用中,接口应该单一化还是复合化,要视具体情况而定。
CUDA编程00 - 配置CUDA开发环境 第一步:在一台装有Nvidia显卡和驱动的机器上,用nvidia-smi命令查看显卡所支持cuda版本。安装时按提示下一步即可,安装完成用 nvcc -V 命令检查是否成功。第二步: 到Nvidia官网下载CUDA Toolkit并安装,第三步:编写HelloWorld。 阅读详情

相关推荐

【windows】【系统还原】亦是美kms执行一键关闭defender 之后,windows defender 被卸载了,无论如何都打不开

还是执行 都没有明显效果 那么,我最后是怎么解决得呢? 一、打开控制面板(任务栏搜索kzmb)

weixin_41899098的博客 6915

基于Java的通用图表接口设计与实现

现如今,互联网上充斥着各式各样的图表产品,有基于Java实现的(如JfreeChart)、有基于Javascript实现的(如highcharts和国内的ichartjs)、还有基于Flash实现的(如fusioncharts)。那么不同公司根据自己的需求,会选择不同类型的图表产品,甚至有的公司感觉当前的图表产品已经不适合公司长远发展,就会考虑选择一套新的图表组件,但是期间最大的问题不是挑选新的...

上善若水任方圆 2436

稳压二极管选型指南:关键参数与电路稳定性优化

本文深入解析了稳压二极管在电路设计中的核心作用与选型要点。文章详细阐述了稳定电压、动态电阻、额定功耗等关键参数对电路稳定性的影响,并结合实战案例,提供了从需求分析到参数验证的系统化选型流程与优化策略,帮助工程师避免常见设计陷阱,实现电路稳定性优化。

weixin_29196891的博客 688

嵌入式矩阵按键多键扫描:从状态矩阵到差分检测的实战指南

在嵌入式系统开发中,按键扫描是人机交互的基础功能,其核心原理是通过扫描矩阵的行列线来检测按键状态。传统的单键扫描方法在面对多键并发操作时,常因“幽灵键”和去抖动问题导致识别错误,影响用户体验。从技术价值看,可靠的多键扫描能显著提升产品的交互质感,是消费电子、工业面板和智能家居等应用场景的刚需。本文聚焦于矩阵按键之多按键扫描,深入探讨了状态矩阵法和差分检测法两种核心算法。状态矩阵法通过为每个按键维护独立的状态机,构建全局视图以实现稳定识别;而差分检测法则关注状态变化,计算量更小。文中还涵盖了硬件层面的二极管隔

459

华为防火墙主备模式工作原理

防火墙主备模式下,备墙的工作状态

weixin_67050107的博客 2141

nRF52832——大量数据传输时导致蓝牙断开连接,且无法被搜索到的解决方案(广播参数的设置、程序设计方法)

有时蓝牙通信单次发送数据量较大,且连续发送多次的时候,你会发现蓝牙就会出现异常,可能运行30min,40min,或者1h后,蓝牙就不能传输数据了,且无法被搜索到,用主机扫描蓝牙时可能会提示类似这样的DEBUG信息:bta_gattc_mark_bg_conn unable to find the bg connection mask for bd_addr=xx:xx:xx:xx:xx:xx。

数字世界 万物互联 2008

JAVA接口设计篇:这些都不知道,别说你懂接口设计

1、接口清晰,调用端看得懂,后面自己人修改也不麻烦; 2、外面的坏人很多,最好的办法是自己保护好自己,也就是说鲁棒性要杠杠的; 3、捡芝麻,也不要丢西瓜。修改接口不是重建,而是糊裱匠,顶级的糊裱匠,那是李合肥那种级别的,劝你就别想了,一般人也做不来。

沛哥儿的专栏 6559

ATS Request中的PASID的作用是什么

摘要: PASID(进程地址空间标识符)是PCIe ATS(地址转换服务)中的关键组件,用于标识不同进程或虚拟机的地址空间。其主要作用包括:1)支持多进程共享设备时隔离地址空间;2)实现共享虚拟地址(SVA),允许用户态程序直接访问设备;3)提升虚拟化性能(如SIOV),通过PASID区分虚拟机请求;4)增强安全性,基于PASID限制设备内存访问权限。PASID通过20位标识符在TLP前缀中传递,与IOMMU协作完成地址转换与缓存,适用于高性能计算、AI及虚拟化场景,但依赖硬件支持和软件适配。

元直的博客 1563

设计一个高质量的API接口

参考网址:http://url.cn/5UaTeyv 前言 在设计接口时,有很多因素要考虑,如接口的业务定位,接口的安全性,接口的可扩展性、接口的稳定性、接口的跨域性、接口的协议规则、接口的路径规则、接口单一原则、接口过滤和接口组合等诸多因素,本篇文章将简要分析这些因素。 一、规范性建议 1、职责原则 在设计接口时,必须明确接口的职责,即接口类型,接口应解决什么业务问题等...

weixin_30478619的博客 1913

Cost-effective Attention Reuse across Multi-turn Conversations in Large Language Model Serving

通过多回合对话与人类互动是大型语言模型(LLM)的一个基本特征。然而,由于需要重复计算历史token的密钥值(KV)缓存,用于执行多回合会话的现有LLM服务引擎效率低下,从而导致高服务成本。为了解决这个问题,本文提出了AttentionStore,这是一种新的注意力机制,可以在多回合对话中重用KV缓存(即注意力重用),显著降低重复计算开销。AttentionStore维护一个分层的KV缓存系统,该系统利用经济高效的内存/存储介质为所有请求保存KV缓存。

c_cpp_csharp的专栏 395

基于 YOLOv26 的 PCB 板缺陷检测:工业级视觉实战

本文提出了一种基于YOLOv26的PCB板缺陷检测系统,通过深度学习技术实现对PCB板缺陷的自动化检测。系统能够识别短路、开路、焊点不良等8种常见缺陷,具有高精度、多类别分类和实时推理等优势。文章详细介绍了系统架构,包括数据采集、预处理、YOLOv26模型检测和后处理模块。在代码实现部分,给出了环境配置、数据预处理与增强的具体方法,使用Albumentations库进行图像增强处理。该系统为电子制造业提供了高效、准确的PCB质量检测解决方案,显著提升了检测效率和准确性。

一键难忘的博客 339

一些软件设计的原则

以前本站向大家介绍过一些软件开发的原则,比如优质代码的十诫和Unix传奇(下篇)中所以说的UNIX的设计原则。相信大家从中能够从中学了解到一些设计原理方面的知识,正如我在《再谈“我是怎么招聘程序”》中所说的,一个好的程序员通常由其操作技能、知识水平,经验层力和能力四个方面组成。在这里想和大家说说设计中的一些原则,我认为这些东西属于长期经验总结出来的知识。这些原则,每一个程序员都应该了解。但是请不要

苍天在上 601

一、【vmware虚拟机使用】安装vmware workstations17

本文介绍了VMware Workstation 17的安装与网络配置方法。主要内容包括:通过下载安装包进行标准安装(含许可协议、路径选择等步骤);重点讲解了NAT模式下的网络配置,包括修改子网IP为192.168.2.0网段、设置网关地址和DHCP范围等操作,以避免与主机网络冲突。文章还简要说明了VMware的Hypervisor核心技术原理,包括CPU、内存和存储虚拟化。最后指出完成这些准备工作后,后续将进行CentOS7系统的安装。整个流程配有详细图文说明,适合初学者跟随操作。

信创运维工程师 · 银河麒麟 & 容器实战 | 金融生产环境迁移·等保加固 | 142篇原创·17万+阅读 2753

怎样设计合适的接口

转自:http://www.zhujiangroad.com/program/JAVA/1878.html 本文转自IBM Developerworks中国网站 摘要:我们在设计系统接口时,经常会遇到这样的问题:   1、我们的接口应该提供多少方法才合适?   2、我们的接口应该提供"原子方法"还是"复合方法"?   3、我们的接口是否应该封装(或者,能否封装)所有的细

blueangle17的专栏 1473

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

怎样设计合适的接口(1)

怎样设计合适的接口(1) [ 作者: 李炜   添加时间: 2001-9-3 8:06:50 ]作者:李炜 北京杰合伟业软件公司产品技术部经理来源: www.cn.ibm.com摘要:我们在设计系统接口时,经常会遇到这样的问题: 我们的接口应该提供多少方法才合适? 我们的接口应该提供"原子方法"还是"复合方法"? 我们的接口是否应该封装(或者,能否封装)所有的细节? 接口的设计需要

zou5655的专栏 1002

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

怎样设计合适的接口(2)

怎样设计合适的接口(2) [ 作者: 李炜   添加时间: 2001-9-3 8:06:50 ]为了解决问题,也需要由类的使用者而不是类的设计者来完成: class EventSourceExample{public void example(Event event, Handler newHandler){synchronized(eventSource){oldHandler

zou5655的专栏 811

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Go语言的接口和抽象:如何设计合适的接口和抽象

1.背景介绍 1. 背景介绍 Go语言是一种现代编程语言,由Google的Robert Griesemer、Rob Pike和Ken Thompson于2009年开发。Go语言旨在简化编程,提高开发效率,同时保持高性能和可扩展性。Go语言的设计倾向于简洁、可读性强、高性能和可维护性。 接口和抽象是Go语言中非常重要的概念,它们有助于编写可重用、可扩展和可维护的代码。接口定义了一组方法的签名,...

AI天才研究院 802

怎样设计合适的接口(1) (转)

怎样设计合适的接口(1) (转)[@more@]怎样设计合适的接口(1) [ 作者: 李炜 添加时间: 2001-9-3 8:06:50 ]作者:李炜 北京杰合伟业软件公司产品技术部经理来源: www.cn.ibm.com摘...

csd3176的博客 104

怎样设计合适的接口(2) (转)

怎样设计合适的接口(2) (转)[@more@]怎样设计合适的接口(2) [ 作者: 李炜 添加时间: 2001-9-3 8:06:50 ]为了解决问题,也需要由类的使用者而不是类的设计者来完成: class Eventso...

csd3176的博客 98

怎样设计合适的接口-Java基础-Java-编程开发

google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//<script type="text/javascript"

java专栏 253

告别笔记本接口焦虑:如何为你的MacBook/轻薄本挑选和设计最合适的Type-C扩展坞?

本文深入解析如何为MacBook/轻薄本挑选和设计最适合的Type-C扩展坞,解决接口不足的痛点。从核心技术矩阵(如USB Type-C协议、AG9311芯片方案)到职业场景配置策略(程序员、设计师需求),再到定制化设计和性能调优,提供全面指南。帮助用户避开常见陷阱,实现高效稳定的多设备连接。

weixin_30915951的博客 378

教你写接口需求文档

作者:果果 转载已取得作者授权一、什么是接口百科上对接口的定义:API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的...

liudada8265的博客 2万+

接口测试用例设计

正常用户是无法操作的,但是兑换其实是调后台的一个接口,如果绕过页面按钮的限制,直接调用后台接口兑换呢?上图为一个典型的接口。针对处理逻辑的设计中,可能使用某一种或某几种方式就可以将用例覆盖前,故实际使用中,可能不会全部使用,只要找到最合适的方式覆盖用例即可。在一些复杂的活动中,一个活动是由一系列动作按照指定顺序进行的,这些动作形成一个动作流,只有按照这个顺序依次执行,才能得到预期结果。在正常的流程里,这些动作是根据程序调用依次进行的,并不会打乱,在接口测试时,需要考虑如果不安装时序执行,是否会出现问题。

2301_81967703的博客 694
上一篇: J2ee应用程序设计――多层框架
下一篇: 轻松架起Java连接COM对象的桥梁
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值