规范化程序设计的实例(1)

提出问题
首先要感谢实验室的章老师提出一个有现实应用的背景与问题:
智能手机中,用户十分关心已经使用的流量, 希望可以查看已经使用的网络流量; 本程
序主要实现过去 1 分钟以及过去 1 小时已经使用的网络流总量,并且希望整个设计具备一定
的可扩展性,比如可以很方便地扩展到统计过去一天的网络流总量。
另外,程序在使用时还需要其运行速度和内存的使用情况。
学习目标:
1.  如何撰写可读性强的代码;
2.  基于性能和存储空间的代码优化设计;
3.  基于设计灵活性的代码优化设计;
概要:
1.  要解决的问题是统计过去一分钟以及一小时的网络流量总和;
2.  我们忽略界面等非核心的要素,关注核心数据结构和实现;
3.  在设计过程中,以接口设计为主导,往往是先给出接口设计,然后再考虑具体实现,
当然实际的设计过程中,可能是同时进行;
4.  设计实现的过程包含三个版本,从简单版本开始,迭代改进,直到最终的版本;第
一个版本只关注功能的实现,不考虑其他因素;第二个版本在前者基础上,考虑性
能和内存空间的优化;最后一个版本进一步对内存空间使用进行优化,并且同时考
虑设计的灵活性;


定义类接口

<span style="font-size:14px;">
class MinuteHourCounter{
//add a count
void Count(int num_bytes);
//return the count over this minute
int MinuteCount();
//return the count over this hour
int HourCount();
}
</span>
在实现这个类之前,让我们首先看一看这些名字和注释,看看有哪些地方有改进的地方。

MinuteHourCounter 这个类名很好,很专门、具体,并且容易读出来。
Count()是有问题的,因为有人会认为它的意思是“返回所有时间里的总的计数”。这个名字有点违反直觉。问题是count既是个名词又是个动词,所以既可以是“我想要得到你所见过的所有样本的计数”意思也可以是“我想要你对样本进行计数”的意思。

下面有几个名字可供替代count():

1、Increment()

是会误导人的,因为它意味着一个只会增加的值。

2、Observe()

还可以,但是感觉有点模糊。

3、Record()

既是动词又是名称,不好

4、Add()

它既可以是“以算术方法增加”的意思,也可以是“添加到一个数据列表的意思”,在该情况下,两种情况兼有,所有适合。

所以修改为void Add(int num_bytes)。

但是参数名num_bytes太有针对性了,可以采用更加通用的count,既简单、通用并且暗示“非负数”。


版本 1:
下面是主要的接口设计,其中的 Add()对新到来的流量事件进行记录,而 MinuteCount()和
HourCount()分别用于统计过去一分钟和一小时的网络流量和;

<span style="font-size:14px;">
class MinuteHourCounter{
//add a count;
void Add(int count);
//return the accumalated count over the last 60 seconds;
int MinuteCount();
//return the accumalated count over the last 3600 seconds;
int HourCount();
}
//下面是上述接口的具体实现:
class MinuteHourCount{
struct Event{
Event(int count, time_t time):count(count), time(time){}
int count;
time_t time;
};
list<Event> events;
public:
void Add(int count){
events.push_back(Event(count, time());
}
int MinuteCount(){
int count = 0;
const time_t now_secs = time();
for(list<Event>::reverse_iterator i = events.rbegin(); i!=events.rend()&&i->time >
now_secs-60; ++i){
count += i->count;
}
return count;
}
int HourCount(){
int count = 0;
const time_t now_secs = time();
for(list<Event>::reverse_iterator i = events.rbegin(); i!=events.rend()&&i->time >
now_secs-3600; ++i){
count += i->count;
}
return count;
}
};
</span>
简评:
上述的代码将流量产生作为一个个事件保存起来,MinuteCount()和 HourCount()则根据
时间戳将符合要求的事件进行累加,并且返回累加值。
暂时不考虑设计本身,光考虑代码的可读性而言,上述代码存在如下的问题:
1. int MinuteCount();  这里的循环操作可读性比较差;

2. int MinuteCount()  和 int HourCount()两者之间的代码重复度太大;可以考虑合并抽取;

<span style="font-size:14px;">
//对于上述的问题1的改进:
int MinuteCount(){
int count = 0;
const time_t now_secs = time();
for(list<Event>::reverse_iterator i = events.rbegin(); i!=events.rend(); ++i){
if(i->time > now_secs - 60) //将判断条件独立出来,增加可读性;
count += i->count;
else 
break;
}
return count;
}</span>
观察上述的代码,就可以发现很多的代码都是重复的,因此对于上述问题 2 的改进:

<span style="font-size:14px;">int CountSince(int cutoff){
int count = 0;
const time_t now_secs = time();
for(list<Event>::reverse_iterator i = events.rbegin(); i!=events.rend(); ++i){
if(i->time >  cutoff)
count += i->count;
else
break;
}
return count;
}
int MinuteCount(){
return CountSince(time()-60);
}
int HourCount(){
return CountSince(time()-3600);
}
</span>
从设计的角度讲,上述代码的主要问题:
1.需要的存储量是无限;因为需要保存到现在的所有的event,所以内存量不可小觑;
2.另外,计算的时间也不固定,如果每秒钟到来的event很多的话, 那么要统计一个小时
的话,需要进行的累加操作数量巨大,耗费的时间很多;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#是一种面向对象的编程语言,它是由微软公司开发的一种通用型编程语言。下面是关于面向对象程序设计C#的介绍: 1. 类和对象:C#是一种基于类的编程语言,它支持创建类和对象。类是一种模板,用于定义对象的属性和行为。对象是类的实例,可以通过实例化类来创建。 2. 封装:C#支持封装,即将数据和方法封装在类中,并通过访问修饰符来控制对类成员的访问权限。这样可以保护数据的安全性,并提供统一的接口供外部使用。 3. 继承:C#支持继承,即一个类可以派生出子类,子类可以继承父类的属性和方法,并可以添加自己的特性。继承可以实现代码的重用和扩展。 4. 多态:C#支持多态,即一个对象可以以多种不同的方式工作。多态性通过虚函数和抽象类来实现。虚函数允许子类重写父类的方法,而抽象类定义了一组抽象方法,子类必须实现这些方法。 5. 接口:C#支持接口,接口定义了一组方法和属性的规范,类可以实现接口并提供具体的实现。接口可以实现多继承的效果,增加了代码的灵活性。 6. 构造函数和析构函数:C#中的构造函数用于初始化对象的状态,析构函数用于释放对象占用的资源。构造函数在创建对象时自动调用,而析构函数在对象被销毁时自动调用。 7. 异常处理:C#提供了异常处理机制,可以捕获和处理程序运行过程中的异常。通过使用try-catch语句块,可以捕获异常并采取相应的处理措施,保证程序的稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值