C++学习笔记----5、重用之设计(三)---- 设计可用的接口(1)

        除了正确地抽象化和结构化你的代码之外,为重用之设计要求你把重点放在程序员与之交互的接口上。即使你有最美和最有效的实现,如果接口令人讨厌,库也好不到哪儿去。人靠衣裳马靠鞍,不要输在第一印象上。

        记住在程序中的每一个部件都应该有良好的接口,即使你不打算在其他的程序中使用它们。首先,你永远不知道什么时候什么东西会被重用。其次,良好的接口即使第一次使用也很重要,特别是你在团队中编程,其他程序员必须使用你设计和编写的代码。

        在C++中,类的属性与成员函数可以是public,protected,或者private。属性与成员函数为public意味着所有代码都可以访问到;protected意味着只有类自身及其派生类可以访问;private控制比较严格,意味着不光是属性与成员函数将其他代码拒之门外,即使是派生类也无法访问。注意访问关键字是在类层次,不是在对象层次。这就意味着类的成员函数可以访问,例如,同类的其他对象的private属性或者private成员函数。

        设计暴露的接口就是关于选择什么是public的问题。应该将暴露接口设计看作是一个过程。接口的主要目的是使代码易用,但是有些接口技巧也可以帮助你遵从总的原则。

1、考虑一下听众

        设计暴露的接口的第一步就是考虑你在为谁而设计。你的听众是团队中的其他成员吗?还是说只是你个人用的一个接口?还是说你公司外的程序员要用的接口?也许是客户或者离岸的合同商?考虑谁为了这个接口会向你寻求帮助,这可以帮你弄清楚设计目的。

        如果接口只是为了你自己使用,你可能会在设计上有更多迭代的自由。你在使用接口的时候,依自己所需对其进行修改。然而,一定要记住在工程团队中的角色变化,事实上就是这样,也许某一天,其他人就也会用到这个接口。

        设计其他内部程序员使用的接口有所不同。某种程度上,你的接口就变成了与他们的一种契约。例如,如果你在实现程序的数据存储部件,其他人依赖这个接口支持特定的操作。你需要找到其他成员想让你的类去做的所有事情。它们需要未来吗?要存储什么类型的数据?

        当为外部客户设计接口时,理想情况下是外部客户应该指定什么析的功能与接口需要暴露,就像为内部客户设计接口时一样。需要考虑当下与未来客户想要的特定特性。接口所用术语也要用客户熟悉的,写文档时也要考虑到听众是谁。自己才懂的笑话,代号,以及程序员黑话都不应该出现在你的设计中。

        不管是为内部程序员还是外部客户设计的接口,接口就是一个合同。如果在编码之前接口达成一致,在代码完成之后如果决定修改,你一定会受到使用你接口的用户的抱怨。

        你为之设计接口的听众也影响了你在设计上花费的时间。例如,如果只是设计一个只有少数用户在少数场合使用的几个成员函数的接口,以后对其进行修改是可以接受的。然而,如果你是在设计一个复杂的接口被许多用户所用,你就要好好花点精力在设计上了,尽量避免必须修改已经被用户开始使用的接口。这就是通常所说的希鲁姆定律(不用管它,有兴趣的话,单独研究吧,也可以到www.hyrumlaw.com上去看看)。

2、考虑目的

        写接口是有许多原因的。在纸上写代码之前或者甚至决定暴露什么样的功能之前,需要理解接口的目的。

2.1、应用程序接口(API)

        一个应用程序接口就是一个外部可见的技术,在其他上下文中扩展产品或者使用其功能。如果一个内部接口是一个合同,那么,一个API就接近于一个板上钉钉的法律了。一旦不是为你公司工作的人使用了你的API,除非你增加了能够帮助他们的新特性,否则他们是不想其被修改的。所以啊,一定要好好规划API,在提供给他们之前要与客户进行细致的讨论。

        设计API的平衡点在于易用与灵活的双重考虑。因为接口的目标听众不熟悉产品的内部工作机制,使用API的学习曲线应该是渐进的。毕竟,你的公司把API暴露给客户因为公司想让其被使用。如果很难用,那这个API就失败了。而灵活性却与之相反,你的产品可能有许多不同的用途,你想让你的客户能够利用你提供的所有功能。然而,让你的客户做任何你的产品能做的事儿也许就太复杂了。

        就像一句通用的编程格言所说,“好的API使得通常情况更容易,高级/不可能的情况变为可能。”,也就是说,API应该有一个简单的学习曲线。大部分程序员想做的事情都可以接触到。然而,API应该有高级用法,应该在不常见的情况下的复杂性与通常情况的简单性之间做一个平衡。这个好像很深奥,我们适时再讨论吧。

2.2、工具类或库

        通常情况下,你的任务就是开发应用中的通用的特定功能,例如,日志类。在这种情况下,接口相对来说比较容易决定,因为你想要将大部分或者所有功能对外暴露,理想情况下,其实现是不会放弃太多。通用性是珍上需要考虑的重要问题。因为类或者库是为通用目的的,在设计中要考虑尽可多的使用情况。

2.3、系统接口

        你可能设计一个应用两个主要子系统之间的接口,例如数据库访问。在这种情况下,将接口与实现分隔开就是至关重要的了,原因如下:

        重要原因之一就是模拟能力。在测试情形下,你会想要将同样的接口用一种实现来替换另一种实现。例如,当编写数据库接口的测试代码时,你可能不会想访问真实的数据库。接口实现访问真实数据库可以被模拟所有数据库访问来替代。

        另一原因就是灵活性。即使是除了测试场景外,你依然想对于可以交互使用的特定接口提供几种不同的实现。例如,你可能会候将使用MySQL的数据库的接口实现替换成使用SQL Server数据库。你甚至可能会想在运行时在不同的实现之间进行切换。

        还有一个原因:首先完成接口,其他程序员在你的实现完成之前,针对你的接口可以早早开始编程。

        当对一个子系统进行编程时,首先要考虑其主要目的是什么。一旦你搞懂了子系统的主要任务是什么,思考一下特定用途以及怎么展现给其他代码部分。要设身处地地去替别人着想,不要陷入实现细节的泥淖。

2.4、部件接口

        大部分定义的接口很可能与子系统接口或API小,这些就是你写的在其他代码中使用的类。在这种情况下,当你的接口逐渐演化,陷阱就会出现,变得毫无章法。即使这些接口只是你自己在用,也要把它们想象成还有其他人在用。在子系统接口中,考虑每个类的主要目的,小心那些不是为这个目的面存在的暴露的接口。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王俊山IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值