通过这段时间的思考,经过实际编码的验证,总结了一下几条设计技巧,记录备忘。
1 模块要提供让外部调用者可以获取模块内部运行信息的手段
在模块设计中,模块内部的运行信息通过回调的形式,给模块外部调用者提供查询模块运行状态的手段。最常见用途的可能就是运行日志了。回调函数是个好东西,在C/C++里叫做函数指针,在.net里叫做事件。
这种模块内部的暴露只是暴露运行信息,而不要把内部成员暴露出来,否则就与模块的低耦合(类的封装)相违背了。
以C#为例:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
a.log += a_log;
a.Test();
}
static void a_log(object sender, string e)
{
Console.WriteLine(DateTime.Now.ToString("u") + " " + e);
}
}
class A
{
public event EventHandler<String> log;
private void OnLog(String msg)
{
if (log != null)
{
log(this, msg);
}
}
public void Test()
{
OnLog("begin do something...");
//do something
OnLog("done.");
}
}
}
2 配置文件、UI、程序运行状态的关系
为了让界面和功能分离,UI不要直接控制程序的运行状态,而是要在UI和程序状态之间加入一个配置文件层。即
UI-----配置文件------程序初始状态
配置文件一般都采用xml格式。这样就需要制定xml配置文件的规范,有了这个规范,UI和程序设计就可以独立进行了。当然一开始,往往不太容易很明确的确定配置文件规范,需要一个迭代的过程。
这样做带来的好处是显而易见的,最明显的就是程序的可移植性。因为移植最难的地方也就是UI了,既然UI与程序本身没有直接联系了,所以移植非常简单。
要做到这种分离方式,必须保证配置文件的规范性。一旦这个规范修改了,UI和程序都需要相应的修改。
伪代码如下:
// 功能类
class A
{
private String filePath; //配置文件路径
public static A FromXml(); //从xml配置文件初始化功能模块
}
//界面类
class UI
{
private String filePath; //配置文件路径
public void FromXml(); //从xml配置文件初始化UI
public void ToXml(); //保存当前UI配置为配置文件
}