软件体系结构-KWIC索引系统

引言

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)
在这里插入图片描述
这道题旨在深入理解模块和组件之间的划分,解法有多种,通过不同的解决方案来体会软件设计的体系结构。

解决方案1:使用共享数据的主程序/子程序

解法:分解为四个组件:输入、移位、排列和输出,主程序依次对他们进行调用,数据通过共享存储在组件间共享,组件与数据之间读写不受约束,由主程序协调保证读写顺序。

优劣

  • 直观、算法隔离
  • 应对数据变化能力弱
  • 可复用性差
    共享数据
    在这里插入图片描述
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
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;
}

解决方案2:抽象数据类型/面向对象风格

解法:对比方案一,分为五个模块,数据不再共享,而是相反做了接口隔离,将各个功能模块分开设计,并且利用权限控制保证了封装的特性,系统的扩展性和封装性增强,是个基本的面向对象方案。
优劣

  • 数据的变化可以在各子模块内更改
  • 支持复用
  • 不适合增加功能
    在这里插入图片描述
// C++参考代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
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 <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
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索引系统是软件体系结构研究领域的一个经典案例,它为我们提供了一个理解软件架构设计原则和实践的框架。它的价值在于,可以帮助我们在设计大型软件系统时,更好地平衡复杂性、灵活性和性能,帮助我们更好地理解和应用软件体系结构设计原则。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/26563.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL(三)SQL优化、Buffer pool、Change buffer

MySQL系列文章 MySQL&#xff08;一&#xff09;基本架构、SQL语句操作、试图 MySQL&#xff08;二&#xff09;索引原理以及优化 MySQL&#xff08;三&#xff09;SQL优化、Buffer pool、Change buffer MySQL&#xff08;四&#xff09;事务原理及分析 MySQL&#xff08;五&a…

自学数据结构和算法(5)

二叉树的遍历 分为先序、中序、和后序遍历。 这三种遍历都可以由递归序来得到&#xff1a; &#xff08;1&#xff09;先序遍历&#xff08;也是二叉树的深度优先遍历&#xff09;是第一次到某个结点才打印&#xff1b; &#xff08;2&#xff09;中序遍历是第二次到某个结…

谋合作、创新境 | 百度参观图为科技生产全链路

当代科技的发展不断催生出新的变革和机遇&#xff0c;百度作为全球顶尖的高科技公司&#xff0c;凭借其强大的创新基因&#xff0c;一直处于人工智能领域的最前沿。   近日&#xff0c;百度公司派出了一支专业团队来到了图为科技&#xff0c;对图为的研发技术及生产线进行了全…

《Maven实战》读后感

目录 一、一些思考1、为什么平时编写的Java项目也叫做Maven项目&#xff1f;2、平常的Java项目目录为什么长这样&#xff0c;可以改变目录结构吗&#xff1f;3、对于Maven项目来说&#xff0c;Maven能帮我们做什么&#xff1f;4、为什么一定需要Maven私服&#xff0c;不要行不行…

每天一道C语言编程:排队买票

题目描述 有M个小孩到公园玩&#xff0c;门票是1元。其中N个小孩带的钱为1元&#xff0c;K个小孩带的钱为2元。售票员没有零钱&#xff0c;问这些小孩共有多少种排队方法&#xff0c;使得售票员总能找得开零钱。注意&#xff1a;两个拿一元零钱的小孩&#xff0c;他们的位置互…

GoFrame v2.5 版本发布,企业级 Golang 开发框架

大家好啊&#xff0c;GoFrame 框架今天发布了 v2.5.0 正式版本啦&#xff01;&#x1f44f;&#x1f44f;&#x1f44f;&#x1f44f; 本次版本主要是对已有功能组件以及开发工具上的改进工作。其中&#xff0c;开发工具新增了 gf gen ctrl 命令&#xff0c;以规范化定义、开发…

orcle报错:TNS 监听程序无法为请求的服务器类型找到可用的处理程序

orcle报错&#xff1a;TNS 监听程序无法为请求的服务器类型找到可用的处理程序 方法一&#xff1a;配置文件修改 服务端的数据库是专用服务器,但是在客户端的tnsname.ora里配置中设置了连接方式为shared,这种情况下打开tnsnames.ora, 找到安装orcle的安装目录&#xff0c;点…

Java常用类(一)

⭐ 基本数据类型的包装类⭐ 包装类基本知识⭐ 包装类的用途⭐ 自动装箱和拆箱⭐ 自定义一个简单的包装类 ⭐ 字符串相关类 ⭐ 基本数据类型的包装类 我们之前写过八种基本数据类型并不是对象&#xff0c;为了将基本类型数据和对象之间实现互相转化&#xff0c;Java 为每一个基…

【EXCEL】数据录入的快捷键和正确格式

目录 0.环境 1.内容概述 2.具体内容 2.1数据录入换行换列的快捷键&#xff08;标准的数据输入方式&#xff09; 2.2日期的正确格式和使用&#xff08;标准日期格式与长日期&#xff09; 2.2.1 标准日期 2.2.2 长日期 2.2.3 显示当前日期和时间的快捷键 2.3百分比的正确…

stm32(串口知识点)

HAL串口发送/接收函数&#xff1a; HAL_UART_Transmit(); 串口发送数据&#xff0c;使用超时管理机制HAL_UART_Receive(); 串口接收数据&#xff0c;使用超时管理机制HAL_UART_Transmit_IT(); 串口中断模式发送 HAL_UART_Receive_IT(); 串口中断模式接收 HAL_UART_Transmit(…

人工智能LLM模型:奖励模型的训练、PPO 强化学习的训练、RLHF

人工智能LLM模型&#xff1a;奖励模型的训练、PPO 强化学习的训练 1.奖励模型的训练 1.1大语言模型中奖励模型的概念 在大语言模型完成 SFT 监督微调后&#xff0c;下一阶段是构建一个奖励模型来对问答对作出得分评价。奖励模型源于强化学习中的奖励函数&#xff0c;能对当前…

数据库三范式

MySQL系列文章 MySQL&#xff08;一&#xff09;基本架构、SQL语句操作、试图 MySQL&#xff08;二&#xff09;索引原理以及优化 MySQL&#xff08;三&#xff09;SQL优化、Buffer pool、Change buffer MySQL&#xff08;四&#xff09;事务原理及分析 MySQL&#xff08;五&a…