(未学完后面会继续)
消化知识
提取一个隐藏的概念
交流与语言的使用
解释性模型
模式:MODEL-DRIVEN DESIGN
如果整个程序设计或者其核心部分没有与领域模型相对应,那么这个模型就是没有价值的,软件的正确性也值得怀疑。同时,模型和设计功能之间过于复杂的对应关系也是难于理解的,在实际项目中,当设计改变时也无法维护这种关系。若分析与和设计之间产生严重分歧,那么在分析和设计活动中所获得的知识就无法彼此共享。
软件系统各个部分的设计应该忠实地反映领域模型,以便体现出这二者之间的明确对应关系。我们应该反复检查并修改模型,以便软件可以更加自然地实现模型,即使想让模型反映出更深层次的领域概念时也应如此。我们需要的模型不但应该满足这两种需求,还应该能够支持健壮
的UBIQUITOUS LANGUAGE(通用语言)。
从模型中获取用于程序设计和基本职责分配的术语。让程序代码成为模型的表达,代码的改变可能会是模型的改变。而其影响势必要波及接下来相应的项目活动。 完全依赖模型的实现通常需要支持建模范式的软件开发工具和语言,比如面向对象的编程。
从过程设计到MODEL-DRIVEN DESIGN
下面代码还没调试过
#include <cassert>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
class LayoutRule {
public:
int type;
int value;
LayoutRule() {}
LayoutRule(int type, int value) : type(type), value(value) {}
bool operator<(const LayoutRule& other) const { return type < other.type; }
bool operator==(const LayoutRule& other) const {
return type == other.type && value == other.value;
}
};
class Net;
class Bus {
private:
std::string name; // 总线的名称
std::set<LayoutRule> rules; // 假设 Bus 内部也有规则集合
std::set<std::shared_ptr<Net>> nets;
public:
Bus() {}
Bus(const std::string& name) : name(name) {}
void addNet(const std::shared_ptr<Net>& net) {
nets.insert(net);
// net->setBus(std::make_shared<Bus>(*this));
}
std::set<LayoutRule> assignedRules() const {
// 返回分配给 Bus 的规则集合
return rules;
}
void assignRule(const LayoutRule& rule) {
// 为 Bus 分配规则
rules.insert(rule);
}
const std::string& getName() const { return name; }
};
class AbstractNet {
protected:
std::string name; // Net 的名称
std::set<LayoutRule> rules;
public:
AbstractNet(const std::string& name) : name(name) {}
void assignRule(const LayoutRule& rule) { rules.insert(rule); }
std::set<LayoutRule> assignedRules() const { return rules; }
const std::string& getName() const { return name; }
};
class Net : public AbstractNet {
public:
Net(const std::string& name) : AbstractNet(name) {}
std::set<LayoutRule> assignedRules() const {
std::set<LayoutRule> result = AbstractNet::assignedRules();
return result;
}
// void assignRuleToBus(const LayoutRule& rule) { bus.assignRule(rule); }
const std::string& getName() const { return name; }
};
// 假设 Collection 是一个容器类,如 std::vector
using CollectionNet = std::vector<std::shared_ptr<Net>>;
using CollectionBus = std::vector<std::shared_ptr<Bus>>;
class NetListImportService {
public:
static CollectionNet read(const std::string& aFile) {
CollectionNet nets;
std::ifstream file(aFile);
if (!file.is_open()) {
std::cerr << "无法打开文件: " << aFile << std::endl;
return nets;
}
std::string line;
std::map<std::string, Bus> busMap; // 存储已创建的 Bus 对象
while (std::getline(file, line)) {
std::istringstream iss(line);
std::string netName;
std::string componentPin;
// 解析行,假设格式为 "NetName Component.Pin"
if (!(iss >> netName >> componentPin)) {
continue; // 跳过格式不正确的行
}
// 推断总线名称
std::string busName = inferBusName(netName);
Bus& bus = busMap[busName]; // 如果不存在则创建新的 Bus
if (bus.getName().empty()) {
bus = Bus(busName);
}
// 创建 Net 对象并分配给 Bus
auto net = std::make_shared<Net>(netName);
LayoutRule rule;
net->assignRule(rule);
// net->assignRuleToBus(rule);
nets.push_back(net);
}
file.close();
return nets;
}
private:
static std::string inferBusName(const std::string& netName) {
// 根据名称推断总线名称,这里假设总线名称为 netName 的前缀
auto pos = netName.find('_');
if (pos != std::string::npos) {
return netName.substr(0, pos);
}
return netName;
}
};
class NetRepository {
std::map<std::string, std::shared_ptr<Net>> nets;
// 通过名称访问 Net 的接口
public:
void addAll(const CollectionNet& netsCollection) {
for (const auto& net : netsCollection) {
nets[net->getName()] = net;
}
}
std::shared_ptr<Net> getByName(const std::string& name) const {
return nets.at(name);
}
};
class InferredBusFactory {
public:
static CollectionBus groupIntoBuses(const CollectionNet& nets) {
std::map<std::string, std::shared_ptr<Bus>> busMap;
// 遍历所有 Net,基于命名约定推断 Bus
for (const auto& net : nets) {
std::string busName = inferBusName(net->getName());
if (busMap.find(busName) == busMap.end()) {
busMap[busName] = std::make_shared<Bus>(busName);
}
busMap[busName]->assignRule(*net->assignedRules().begin());
}
CollectionBus buses;
for (const auto& pair : busMap) {
buses.push_back(pair.second);
}
return buses;
}
private:
static std::string inferBusName(const std::string& netName) {
// 根据名称推断总线名称,这里假设总线名称为 netName 的前缀
auto pos = netName.find('_');
if (pos != std::string::npos) {
return netName.substr(0, pos);
}
return netName;
}
};
class BusRepository {
std::map<std::string, std::shared_ptr<Bus>>
buses; // 通过名称访问 Bus 的接口
public:
void addAll(const CollectionBus& busesCollection) {
for (const auto& bus : busesCollection) {
buses[bus->getName()] = bus;
}
}
void addBus(const std::shared_ptr<Bus>& bus) {
buses[bus->getName()] = bus;
}
std::shared_ptr<Bus> getByName(const std::string& name) const {
return buses.at(name);
}
};
void testBusRuleAssignment() {
auto a0 = std::make_shared<Net>("a0");
auto a1 = std::make_shared<Net>("a1");
auto a = std::make_shared<Bus>("a");
a->addNet(a0);
a->addNet(a1);
LayoutRule minWidth4(1, 4);
// Using 1 as the type for MIN_WIDTH
a->assignRule(minWidth4);
assert(a0->assignedRules().count(minWidth4) > 0);
assert(a1->assignedRules().count(minWidth4) > 0);
std::cout << "Test passed!" << std::endl;
}
class BusFacade {
private:
BusRepository& busRepository;
public:
BusFacade(BusRepository& busRepo) : busRepository(busRepo) {}
void assignBusRule(const std::string& busName, int ruleType,
double parameter) {
auto bus = busRepository.getByName(busName);
if (bus) {
LayoutRule rule(ruleType, parameter);
bus->assignRule(rule);
}
}
};
void test() {
// Example usage
BusRepository busRepository;
BusFacade busFacade(busRepository);
auto bus1 = std::make_shared<Bus>("Bus1");
busRepository.addBus(bus1);
// Assign a rule to Bus1
busFacade.assignBusRule("Bus1", 1, 10.5);
}
int main() {
NetListImportService NetListImportService;
InferredBusFactory InferredBusFactory;
NetRepository NetRepository;
BusRepository BusRepository;
std::string aFile = "nets.txt";
CollectionNet nets = NetListImportService.read(aFile);
NetRepository.addAll(nets);
CollectionBus buses = InferredBusFactory.groupIntoBuses(nets);
BusRepository.addAll(buses);
return 0;
}
第二部分 模型驱动设计的构造块