KWIC作为一个早年间在ACM的Paper提出的一个问题,被全世界各个大学的软件设计课程奉为课堂讲义或者作业的经典。(From Wiki,FYI,D. L. Parnas uses a KWIC Index as an example on how to perform modular design in his paper “On the Criteria To Be Used in Decomposing Systems into Modules” - Available as ACM Classic Paper)
这道题旨在深入理解模块和组件之间的划分,解法有多种,通过不同的解决方案来体会软件设计的体系结构。
解法:分解为四个组件:输入、移位、排列和输出,主程序依次对他们进行调用,数据通过共享存储在组件间共享,组件与数据之间读写不受约束,由主程序协调保证读写顺序。
优劣:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<string> lineList;
void inputStr()
{
ifstream inFile("D:/km.txt", ios::in);
if (!inFile)
{
cerr << "File could not be open file" << endl;
exit(1);
}
string str;
while (getline(inFile, str, '\n'))
{
lineList.push_back(str);
}
}
void circshift()
{
int i;
vector<string> list = lineList;
for (i = 0; i < list.size(); i++)
{
string line = list[i];
vector<string> st;
istringstream ss(line);
while (!ss.eof())
{
string x;
getline(ss, x, ' ');
st.push_back(x);
}
int j = 0;
while (j < st.size() - 1)
{
string tmp = st[0] + " ";
st.erase(st.begin());
st.push_back(tmp);
string t = "";
for (int k = 0; k < st.size(); k++)
t += st[k] + " ";
lineList.push_back(t);
j++;
}
}
}
void sort()
{
sort(lineList.begin(), lineList.end());
}
void output()
{
vector<string>::iterator it;
for (it = lineList.begin(); it != lineList.end();it++)
cout << *it << endl;
}
int main()
{
inputStr();
circshift();
sort();
cout << endl
<< endl;
output();
return 0;
}
解法:对比方案一,分为五个模块,数据不再共享,而是相反做了接口隔离,将各个功能模块分开设计,并且利用权限控制保证了封装的特性,系统的扩展性和封装性增强,是个基本的面向对象方案。
优劣:
// C++参考代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Input
{
private:
vector<string> lineList;
public:
vector<string> getLineTxt()
{
return lineList;
}
void inputLine(string fileName)
{
ifstream inFile(fileName, ios::in);
if (!inFile)
{
cerr << "File could not be open file" << endl;
exit(1);
}
string str;
while (getline(inFile, str, '\n'))
{
lineList.push_back(str);
}
}
};
class circshift
{
private:
vector<string> kwList;
vector<string> lineList;
public:
circshift(vector<string> lineList)
{
this->lineList = lineList;
}
vector<string> getLineList()
{
return lineList;
}
vector<string> getKwList()
{
return kwList;
}
void cirShift()
{
int i;
for (i = 0; i < lineList.size(); i++)
{
string line = lineList[i];
vector<string> st;
istringstream ss(line);
while (!ss.eof())
{
string x;
getline(ss, x, ' ');
st.push_back(x);
}
int j = 0;
while (j < st.size())
{
string tmp = st[0] + " ";
st.erase(st.begin());
st.push_back(tmp);
string t = "";
for (int k = 0; k < st.size(); k++)
t += st[k] + " ";
kwList.push_back(t);
j++;
}
}
}
};
class lineSort
{
private:
vector<string> kwList;
public:
lineSort(vector<string> kwList)
{
this->kwList = kwList;
}
vector<string> getKwList()
{
return kwList;
}
void linsort()
{
sort(kwList.begin(), kwList.end());
}
};
class output
{
private:
vector<string> kwList;
public:
output(vector<string> kwList)
{
this->kwList = kwList;
}
void show()
{
vector<string>::iterator it;
for (it = kwList.begin(); it != kwList.end(); it++)
{
cout << *it << endl;
}
}
};
int main(void)
{
Input in;
in.inputLine("D:/km.txt");
circshift cshift(in.getLineTxt());
cshift.cirShift();
lineSort linesort(cshift.getKwList());
linesort.linsort();
output out(linesort.getKwList());
out.show();
return 0;
}
解法:类似方案一,但数据更抽象,而不是暴露数据格式,数据被修改时,隐式调用计算。
基于事件通知的系统中的各个功能并不是直接被调用的,而是通过组建通知或广播事件信息而触发的。其他组件可以通过注册一个与某个事件通知相关联的过程而与其发生联系。
优劣:
解法:在基于管道的方案中,每个组件都会有一组输入流和一组输出流,一个组件读入,然后处理后送出到下一个组件上。这个组件一般称为filter。连接器则称为pipes。filter之间不能有数据共享,并且彼此相互独立。
管道由一系列过滤器组成,通过数据流连接
分布式,每个过滤器只要有要计算的数据就可以运行
过滤器之间的数据共享严格限于在管道上传输的数据
优劣:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<string> inputStr(string address)
{
vector<string> lineList;
ifstream inFile(address, ios::in); // ifstream inFile("D:/km.txt", ios::in);
if (!inFile)
{
cerr << "File could not be open file" << endl;
exit(1);
}
string str;
while (getline(inFile, str, '\n'))
{
lineList.push_back(str);
}
return lineList;
}
vector<string> circshift(vector<string> &lineList)
{
int i;
vector<string> list = lineList;
for (i = 0; i < list.size(); i++)
{
string line = list[i];
vector<string> st;
istringstream ss(line);
while (!ss.eof())
{
string x;
getline(ss, x, ' ');
st.push_back(x);
}
int j = 0;
while (j < st.size() - 1)
{
string tmp = st[0] + " ";
st.erase(st.begin());
st.push_back(tmp);
string t = "";
for (int k = 0; k < st.size(); k++)
t += st[k] + " ";
lineList.push_back(t);
j++;
}
}
return lineList;
}
vector<string> sort(vector<string> &lineList)
{
sort(lineList.begin(), lineList.end());
return lineList;
}
void output(vector<string> &lineList)
{
vector<string>::iterator it;
for (it = lineList.begin(); it != lineList.end(); it++)
cout << *it << endl;
}
int main()
{
string address = "D:/km.txt";
vector<string> stringList;
stringList = inputStr(address);
stringList = circshift(stringList);
stringList = sort(stringList);
cout << endl
<< endl;
output(stringList);
return 0;
}
KWIC索引系统是软件体系结构研究领域的一个经典案例,它为我们提供了一个理解软件架构设计原则和实践的框架。它的价值在于,可以帮助我们在设计大型软件系统时,更好地平衡复杂性、灵活性和性能,帮助我们更好地理解和应用软件体系结构设计原则。