利用接口构建系统架构的一次实践和反思:
namespace MyApplication.Library
{
/*架构设计版本*/
public abstract class AdapterFramework
{
public abstract IScheme[] LoadScheme();
public abstract void FireScheme(IScheme scheme, ILog log);
}
/*最终交付版本*/
public class AdapterFramework
{
public static IScheme[] LoadScheme(); //基本没有修改,除了取消abstract修饰以外,因为没有必要采用重载实现,同时采用了一个static限制
public static void FireScheme(IScheme scheme, ILog log);//基本没有修改,除了取消abstract修饰以外,因为没有必要采用重载实现,同时采用了一个static限制
}
/*架构设计版本*/
public interface IDataAdapter
{
DataTable LoadTable(string table);
}
/*最终交付版本*/
public interface IDataAdapter:IComponent
{
DataTable LoadTable(IFunctionComponent function,string table);//增加了IFunctionComponent参数,设计未实现,需求已定义,在调用遗留系统中的ExcelHelper相关方法时,需要IProcess,IStateHandle作为调用时必须扮演的参数,而在设计时就已知由IFunctionComponent包装IProcess功能,因此设计时应考虑本因素
DataTable LoadTable(IFunctionComponent function);//增加了重载的LoadTable方法,当外部没有显式提供一个string参数时,提供一个默认的实现(由string File和string FileDetail支持)
string File{get;set;}//由于在ExcelAdapter的实现中,需要获取文件名称
string FileDetail{get;set;}//由于在ExcelAdapter的实现中,需要获取Excel中的目标Sheet名称进行加载,需求已定义,设计未实现
SucceedStrategy SucceedStrategy{get;set;}//由于在ExcelAdapter的实现中,需要制定操作完成后是否删除原始文件的策略,需求已定义,设计未实现
}
/*架构设计版本*/
public interface IDataObjective
{
void ExecuteUpdateTransaction(string[] sqlScripts);
OracleConnection PopActiveOracleConnection();
void PushActiveOracleConnection(OracleConnection activeConnection);
}
/*最终交付版本*/
public interface IDataObjective:IComponent
{
void ExecuteUpdateTransaction(string[] sqlScripts);
OracleConnection PopActiveOracleConnection();
void PushActiveOracleConnection(OracleConnection activeConnection);
string ConnectionString{get;set;}//对于一个目标数据对象来说,如果目标对象是关系数据库,那么没有什么比链接字串更重要的属性了
}
/*架构设计版本*/
public interface IDataSource
{
DataTable ExecuteReadTransaction(string[] sqlScripts);
void SetDataAdapter(IDataAdapter dataAdapter);//本方法在最终交付版本中被移除是因为实现中发现不能将IDataAdapter和IDataSource混合在一起,无形中增加了复杂度,IDataAdapter和IDataSource同样能够提供数据源,但是在同一个解决方案定义中又是互斥的
IDataAdapter GetDataAdapter();//同上
}
/*最终交付版本*/
public interface IDataSource:IComponent
{
DataTable ExecuteReadTransaction(string sqlScripts);//修改了string[]声明,在一个执行脚本的环境中,因为string[]元素间没有关联,或者ExecuteReadTransaction方法无法获知关联,因此采用string更加实际
string ConnectionString{get;set;}//对于一个信宿数据对象来说,如果信宿对象是关系数据库,那么没有什么比链接字串更重要的属性了
}
/*架构设计版本*/
public interface IFunctionComponent
{
void SetStrategy(IStrategy[] strategy);
IStrategy[] GetStrategy();
void Execute(ILog log);
void SetDataSource(IDataSource dataSource);
void SetDataObjective(IDataObjective dataObjective);
IDataSource GetDataSource();
IDataObjective GetDataObjective();
}
/*最终交付版本*/
public interface IFunctionComponent:IComponent,IEditor,IParameterHandle,IStateHandle
{
//IEditor,IParameterHandle,IStateHandle是遗留系统中对IProcess进行调用时必须扮演的参数,作为两个系统间的假面舞会,没有什么能够比当初的接口设计架构更能够支持灵活的功能交互了
void SetStrategy(IStrategy[] strategies);
IStrategy[] GetStrategy();
void Execute();//去掉了ILog参数是因为,IFunctionComponent其它的方法被执行环境调用时,ILog由于是null而无法执行日志记录工作,造成无法跟踪IFunctionComponent其它方法的内部情况,进而采用void SetLog(ILog log);进行替代解决
void SetDataSource(IDataSource dataSource);
void SetDataObjective(IDataObjective dataObjective);
IProcess WrappedProcess{get;}//需求已定义,需要复用遗留系统中的IProcess,但设计未实现,本方法作为IProcess的一个包装
IDataSource GetDataSource();
IDataObjective GetDataObjective();
void SetDataAdapter(IDataAdapter dataAdapter);//作为IFunctionComponent的数据源的替代实现,IDataAdapter必须突破IDataSource的掩盖独立出来
IDataAdapter GetDataAdapter();//同上
DataSourceType GetDataSourceType();//由于IDataAdapter和IDataSource的互斥关系,IFunctionComponent必须表明自己的立场
void SetDataSourceType(DataSourceType dataSourceType);//同上
void SetSchemeId(int schemeId);//IFunctionComponent与IScheme是多对一的关系,所以必须显式声明以表明这种层次关系
int GetSchemeId();//同上
void SetLog(ILog log);//剔除了void Execute(ILog log);中的ILog参数,目的是在整个内部共享ILog
}
/*架构设计版本*/
public interface ILog
{
void WriteLog(ILog[] log);
void DeleteLog(ILog[] log);
void SetID(int id);
int GetID();
void SetEvent(String events);
string GetEvent();
void SetSender(String sender);
string GetSender();
void SetTime(DateTime time);
DateTime GetTime();
}
/*最终交付版本*/
public interface ILog
{
void WriteLog(string sEvent,object sender,string sTrace,LogType logType);//本次设计最大的败笔,在架构设计时,考虑ILog的存储结构是合理的,但是将属性和基于这些属性的操作声明在同一个接口中被证明是失败的,实现过程中无论怎么去观察,都有如鲠在喉
}
/*架构设计版本*/
public interface IScheme
{
IFunctionComponent SetFunction(IFunctionComponent function);
void FireFunction(IFunctionComponent function, ILog log);
IStrategy[] GetStrategy();
void SetStrategy(IStrategy[] strategy);
IFunctionComponent GetFunction();
void SetDataSource(IDataSource dataSource);//需求已定义,设计未考虑,其实IDataSource和IDataAdapter仅对IFunctionComponent才有意义,作为IFunctionComponent的一个一对多的包装,既然不知道如何去分派,又何必多次一举?
IDataSource GetDataSource();//同上
IDataObjective GetDataObjective();//同上
void SetDataObjective(IDataObjective dataObjective);//同上
}
/*最终交付版本*/
public interface IScheme:IComponent
{
IFunctionComponent[] SetFunction(IFunctionComponent[] functions);
void FireFunction(IFunctionComponent function, ILog log);
IStrategy[] GetStrategy();
void SetStrategy(IStrategy[] strategies);
IFunctionComponent[] GetFunction();
FireType GetFireType();//需求已定义,方案的激活策略,按月,按周,按天,因此接口定义时必须将这些约束定义进来
void SetFireType(FireType fireType);//同上
DateTime GetFireTime();//如果执行环境需要激活IScheme,而IScheme没有提供自己的FireTime,目的如何达成?
void SetFireTime(DateTime fireTime);//作为操作接口和存储实体之间的转换,关键的属性必须从存储注入到操作接口中
string[] GetFireDays();//当采用按月,按周策略时,多个日期以逗号分割的一个字串列表体现了需要激活的日期
void SetFireDays(string[] fireDays);//同上
}
/*架构设计版本*/
public interface IStrategy
{
void SetContext(object context);
bool Apply();
}
/*最终交付版本*/
public interface IStrategy:IComponent
{
void SetContext(object context);
bool Apply(ILog log);//策略执行的时候,也需要进行日志记录,不是吗?
}
/*架构设计版本*/
public class VirtualEntityModel
{
private int Id;
private string Name;
private string Code;
private string Summary;
}
/*最终交付版本*/
public class VirtualEntityModel
{
protected int _id;//采用protected为继承开放了绿灯
protected string _name;//同上
protected string _code;//同上
protected string _summary;//同上
}
/*最终交付版本中增加接口定义*/
public interface IComponent
{
//本接口基本上为在关系数据存储对象和动态链接库文件反射对象之间提供了一个联系的纽带,使它们能够在多持久机制的架构系统之中自由转换
void SetID(int id);//无论将对象持久化到关系数据库中,还是一个动态链接库文件里,它都需要标识,如果它的痕迹还需要出现在关系数据库中,那么这些标示就更为重要
int GetID();//同上
string GetName();//同上
void SetName(string name);//同上
}
}
namespace MyApplication.Library
{
/*架构设计版本*/
public abstract class AdapterFramework
{
public abstract IScheme[] LoadScheme();
public abstract void FireScheme(IScheme scheme, ILog log);
}
/*最终交付版本*/
public class AdapterFramework
{
public static IScheme[] LoadScheme(); //基本没有修改,除了取消abstract修饰以外,因为没有必要采用重载实现,同时采用了一个static限制
public static void FireScheme(IScheme scheme, ILog log);//基本没有修改,除了取消abstract修饰以外,因为没有必要采用重载实现,同时采用了一个static限制
}
/*架构设计版本*/
public interface IDataAdapter
{
DataTable LoadTable(string table);
}
/*最终交付版本*/
public interface IDataAdapter:IComponent
{
DataTable LoadTable(IFunctionComponent function,string table);//增加了IFunctionComponent参数,设计未实现,需求已定义,在调用遗留系统中的ExcelHelper相关方法时,需要IProcess,IStateHandle作为调用时必须扮演的参数,而在设计时就已知由IFunctionComponent包装IProcess功能,因此设计时应考虑本因素
DataTable LoadTable(IFunctionComponent function);//增加了重载的LoadTable方法,当外部没有显式提供一个string参数时,提供一个默认的实现(由string File和string FileDetail支持)
string File{get;set;}//由于在ExcelAdapter的实现中,需要获取文件名称
string FileDetail{get;set;}//由于在ExcelAdapter的实现中,需要获取Excel中的目标Sheet名称进行加载,需求已定义,设计未实现
SucceedStrategy SucceedStrategy{get;set;}//由于在ExcelAdapter的实现中,需要制定操作完成后是否删除原始文件的策略,需求已定义,设计未实现
}
/*架构设计版本*/
public interface IDataObjective
{
void ExecuteUpdateTransaction(string[] sqlScripts);
OracleConnection PopActiveOracleConnection();
void PushActiveOracleConnection(OracleConnection activeConnection);
}
/*最终交付版本*/
public interface IDataObjective:IComponent
{
void ExecuteUpdateTransaction(string[] sqlScripts);
OracleConnection PopActiveOracleConnection();
void PushActiveOracleConnection(OracleConnection activeConnection);
string ConnectionString{get;set;}//对于一个目标数据对象来说,如果目标对象是关系数据库,那么没有什么比链接字串更重要的属性了
}
/*架构设计版本*/
public interface IDataSource
{
DataTable ExecuteReadTransaction(string[] sqlScripts);
void SetDataAdapter(IDataAdapter dataAdapter);//本方法在最终交付版本中被移除是因为实现中发现不能将IDataAdapter和IDataSource混合在一起,无形中增加了复杂度,IDataAdapter和IDataSource同样能够提供数据源,但是在同一个解决方案定义中又是互斥的
IDataAdapter GetDataAdapter();//同上
}
/*最终交付版本*/
public interface IDataSource:IComponent
{
DataTable ExecuteReadTransaction(string sqlScripts);//修改了string[]声明,在一个执行脚本的环境中,因为string[]元素间没有关联,或者ExecuteReadTransaction方法无法获知关联,因此采用string更加实际
string ConnectionString{get;set;}//对于一个信宿数据对象来说,如果信宿对象是关系数据库,那么没有什么比链接字串更重要的属性了
}
/*架构设计版本*/
public interface IFunctionComponent
{
void SetStrategy(IStrategy[] strategy);
IStrategy[] GetStrategy();
void Execute(ILog log);
void SetDataSource(IDataSource dataSource);
void SetDataObjective(IDataObjective dataObjective);
IDataSource GetDataSource();
IDataObjective GetDataObjective();
}
/*最终交付版本*/
public interface IFunctionComponent:IComponent,IEditor,IParameterHandle,IStateHandle
{
//IEditor,IParameterHandle,IStateHandle是遗留系统中对IProcess进行调用时必须扮演的参数,作为两个系统间的假面舞会,没有什么能够比当初的接口设计架构更能够支持灵活的功能交互了
void SetStrategy(IStrategy[] strategies);
IStrategy[] GetStrategy();
void Execute();//去掉了ILog参数是因为,IFunctionComponent其它的方法被执行环境调用时,ILog由于是null而无法执行日志记录工作,造成无法跟踪IFunctionComponent其它方法的内部情况,进而采用void SetLog(ILog log);进行替代解决
void SetDataSource(IDataSource dataSource);
void SetDataObjective(IDataObjective dataObjective);
IProcess WrappedProcess{get;}//需求已定义,需要复用遗留系统中的IProcess,但设计未实现,本方法作为IProcess的一个包装
IDataSource GetDataSource();
IDataObjective GetDataObjective();
void SetDataAdapter(IDataAdapter dataAdapter);//作为IFunctionComponent的数据源的替代实现,IDataAdapter必须突破IDataSource的掩盖独立出来
IDataAdapter GetDataAdapter();//同上
DataSourceType GetDataSourceType();//由于IDataAdapter和IDataSource的互斥关系,IFunctionComponent必须表明自己的立场
void SetDataSourceType(DataSourceType dataSourceType);//同上
void SetSchemeId(int schemeId);//IFunctionComponent与IScheme是多对一的关系,所以必须显式声明以表明这种层次关系
int GetSchemeId();//同上
void SetLog(ILog log);//剔除了void Execute(ILog log);中的ILog参数,目的是在整个内部共享ILog
}
/*架构设计版本*/
public interface ILog
{
void WriteLog(ILog[] log);
void DeleteLog(ILog[] log);
void SetID(int id);
int GetID();
void SetEvent(String events);
string GetEvent();
void SetSender(String sender);
string GetSender();
void SetTime(DateTime time);
DateTime GetTime();
}
/*最终交付版本*/
public interface ILog
{
void WriteLog(string sEvent,object sender,string sTrace,LogType logType);//本次设计最大的败笔,在架构设计时,考虑ILog的存储结构是合理的,但是将属性和基于这些属性的操作声明在同一个接口中被证明是失败的,实现过程中无论怎么去观察,都有如鲠在喉
}
/*架构设计版本*/
public interface IScheme
{
IFunctionComponent SetFunction(IFunctionComponent function);
void FireFunction(IFunctionComponent function, ILog log);
IStrategy[] GetStrategy();
void SetStrategy(IStrategy[] strategy);
IFunctionComponent GetFunction();
void SetDataSource(IDataSource dataSource);//需求已定义,设计未考虑,其实IDataSource和IDataAdapter仅对IFunctionComponent才有意义,作为IFunctionComponent的一个一对多的包装,既然不知道如何去分派,又何必多次一举?
IDataSource GetDataSource();//同上
IDataObjective GetDataObjective();//同上
void SetDataObjective(IDataObjective dataObjective);//同上
}
/*最终交付版本*/
public interface IScheme:IComponent
{
IFunctionComponent[] SetFunction(IFunctionComponent[] functions);
void FireFunction(IFunctionComponent function, ILog log);
IStrategy[] GetStrategy();
void SetStrategy(IStrategy[] strategies);
IFunctionComponent[] GetFunction();
FireType GetFireType();//需求已定义,方案的激活策略,按月,按周,按天,因此接口定义时必须将这些约束定义进来
void SetFireType(FireType fireType);//同上
DateTime GetFireTime();//如果执行环境需要激活IScheme,而IScheme没有提供自己的FireTime,目的如何达成?
void SetFireTime(DateTime fireTime);//作为操作接口和存储实体之间的转换,关键的属性必须从存储注入到操作接口中
string[] GetFireDays();//当采用按月,按周策略时,多个日期以逗号分割的一个字串列表体现了需要激活的日期
void SetFireDays(string[] fireDays);//同上
}
/*架构设计版本*/
public interface IStrategy
{
void SetContext(object context);
bool Apply();
}
/*最终交付版本*/
public interface IStrategy:IComponent
{
void SetContext(object context);
bool Apply(ILog log);//策略执行的时候,也需要进行日志记录,不是吗?
}
/*架构设计版本*/
public class VirtualEntityModel
{
private int Id;
private string Name;
private string Code;
private string Summary;
}
/*最终交付版本*/
public class VirtualEntityModel
{
protected int _id;//采用protected为继承开放了绿灯
protected string _name;//同上
protected string _code;//同上
protected string _summary;//同上
}
/*最终交付版本中增加接口定义*/
public interface IComponent
{
//本接口基本上为在关系数据存储对象和动态链接库文件反射对象之间提供了一个联系的纽带,使它们能够在多持久机制的架构系统之中自由转换
void SetID(int id);//无论将对象持久化到关系数据库中,还是一个动态链接库文件里,它都需要标识,如果它的痕迹还需要出现在关系数据库中,那么这些标示就更为重要
int GetID();//同上
string GetName();//同上
void SetName(string name);//同上
}
}