A rule of thumb about Interface vs Abstract Class

本文探讨了Hadoop创始人Doug Cutting关于在API设计中选择抽象类而非接口的观点。Cutting强调,除非需要多重继承,否则应优先使用抽象类,因为它能提供默认实现,有利于API的演化同时保持向后兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在翻阅Hadoop早期的jira list,对于一些重要的jira,会有很多贡献者的详细讨论,包括Doug Cutting, Tom White, Arun Murthy, Owen O'Malley等一批Hadoop领军人物的思想、观点,具有极强的学习价值。

今天在阅读Hadoop-3412和HADOOP-1230,当中Doug Cutting阐述了如何选择Interface和Abstract Class的观点。虽然这是个老生常谈的问题,但是Cutting作为极有经验的工程师,多个开源项目的创始者,从平台API evolution这个角度来讨论,很有参考性。

Cutting在HADOOP-1230中的原话如下:

The strategy here is to remove stuff that is likely to evolve from interfaces that users implement, so that we canchange it without breaking user implementations

Note that, in general, interfaces are much more difficult to evolve than abstract base classes, and should thus only be used when "mixin" behavior is required, e.g., when one needs to be able to add an interface to an existing class. For example, interfaces like Serializeable and Writable are great, since folks might need to have a class that implements both, which wouldn't be possible if they were abstract base classes. 

Some folks seem to believe that interfaces are somehow 'cleaner' and should be used for all public facing APIs. But that's not true: interfaces are limited to a subset of what abstract base classes can do, andan abstract class's ability to provide default implementations of methods greatly facilitates API evolution. Again (at the risk of sounding repetitive), the only advantage of interfaces is that a class can implement more than one of them

So, as we revisit our core APIs that users implement for the purpose of making them more easily backward compatible,we should use abstract base classes in place of interfaces whenever it is clear that multi-inheritance is not a requirement.


可以看到,Cutting的观点很明确,除非你要有mixing behaviour,也就是说要多继承,否则总是选择abstract class。本质的原因是abstract class可以提供default implementation,当你想要对某个API做修改时,它提供了更大的灵活性,使得你不需要改API interface,从而保持向后兼容性。

举个例子,假如你有一个API class如下:

abstract class JobInProgressListener {
	  public void jobAdded(JobInProgress job) throws IOException{
	  	//do nothing
	  }
}

如果未来你想要做修改,比如增加一个参数,你可以不用动原来的interface,而是增加一个overloaded方法,并且让原来的方法用默认参数调用新方法:

abstract class JobInProgressListener {
	  public void jobAdded(JobInProgress job) throws IOException{
		  jobAdded(job, new Configuration());
	  }
	  
	  public void jobAdded(JobInProgress job, Configuration conf) throws IOException{
		  //do something
	  }
}
如果JobInProgressListener是interface,你只能改变原来contract,从而break原来的客户代码。



### 带宽的规则法则及其在网络规划中的应用 在IT网络规划中,带宽的选择至关重要。通常情况下,为了确保良好的用户体验并支持预期的应用程序性能,工程师们依赖一些经验性的指导原则来进行估算。 #### 经验公式一:平均每位用户所需带宽 对于一般办公环境而言,可以假设每名员工大约需要1 Mbps到5 Mbps之间的上行和下行带宽[^1]。这取决于具体应用场景;例如视频会议可能需要更高的速率而电子邮件处理则较低。 #### 经验公式二:考虑并发率 并不是所有设备都会同时占用全部分配给它们的数据传输速度。因此,在设计大型企业级无线局域网(WLAN)时, 应该考虑到实际使用的最大并发连接数不超过总接入点容量的一半左右。 #### 经验公式三:冗余与峰值需求预留空间 即使已经基于历史流量模式进行了精确预测,仍然建议保留至少20%至30%额外未被利用的带宽作为缓冲区以应对突发高峰时段的需求增加情况。 ```python def calculate_required_bandwidth(users_count, avg_user_bw=3, concurrency_factor=0.7, buffer_percentage=0.2): """ 计算所需的最小带宽量 参数: users_count (int): 用户数量 avg_user_bw (float): 平均每个用户的带宽数,默认为3Mbps concurrency_factor (float): 同时在线比例因子,默认为0.7 buffer_percentage (float): 预留缓冲百分比,默认为0.2 返回: float: 所需最低带宽总量(Mbps) """ base_req = users_count * avg_user_bw * concurrency_factor buffered_req = base_req / (1 - buffer_percentage) return round(buffered_req, 2) print(f"Required Bandwidth: {calculate_required_bandwidth(100)} Mbps") ``` 此函数`calculate_required_bandwidth()`可以根据输入参数自动计算出满足上述三个经验值所推荐条件下的最小必要带宽值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值