C和C++语言是流行和常用的依赖于顺序的语言。C++略为有点改进,在类范围内部不依赖于顺序。依赖于顺序是一种惩罚,是一种不重视程序员感受的表现,并且在深层次要求采用采用声明和实现分开,因而也就不能维持DRY原则。违背DRY会导致维护复杂。
我详细说明一下为什么依赖顺序是罪恶的。
大家都知道抽象是一种强大的能力,但是,依赖于顺序强迫我们只能从低层次的细节开始,这跟现如今流行的IDE的智能完成一样。我们不得不把所有的细节描述完备,才能构造更大的构件。
我还是用一个实例来说明吧。
我为了练习的目的,试图写一个HTTP Client,自然,我是从阅读RFC规范开始的。通过扫描RFC的目录和快速掠过其内容,我们发现HTTP是一个请求响应模式的简单协议,其请求和响应都是所谓的Message,显然,只要我们能解析和构造这个Message,我们就大致完成任务。
于是就有了:
namespace Http
{
class Message
{
public:
MessageHeader headers;
CRLF crlf;
MessageBody body;
std::string toString(void)
{
return headers.toString() + crlf.toString() + body.toString();
}
};
class MessageHeader
{
public:
std::vector<Field> fields;
std::string toString(void)
{
std::string result;
for (int i = 0; i < fields.size(); ++i)
{
result += fields[i].toString();
}
return result;
}
};
class Field
{
public:
FieldName name;
Colon colon;
FieldValue value;
CRLF crlf;
std::string toString(void)
{
return name.toString() + colon.toString() + value.toString() + crlf.toString();
}
};
class FieldName
{
public:
FieldNameValue name;
std::string toString(void)
{
std::string result;
switch (name)
{
case CacheControl:
result = "Cache-Control";
break;
......
}
return result;
}
FieldNameValue fromString(std::string fieldName)
{
FieldNameValue result;
if (fieldName == "Cache-Control")
result = CacheControl;
else if (...)
...
return result;
}
};
enum FieldNameValue
{
//generic headers
CacheControl,
Connection,
Date,
Pragma,
......
}
我想,上面的代码非常的直接了当。几乎不需要解释,类似于递归下降法制作解析器,而事实上,确实是下降的,但是递归没有,因为HTTP的Message格式还没有那么强大和灵活。稍微有点奇特的是FieldName和FieldNameValue这一对,它们合作构成了我设想的枚举,这也说明了C/C++语言的枚举并不强大到可以作为一个抽象机制使用,当然,这不是我们焦点。暂且不论。
由于其中的toString都是很简单的,所以我准备把它们做成内联函数,这个无可厚非,我们看看就是这个要求是怎么导致我们需要扭曲我们的代码的。
首先需要说明的是:上面的代码不能通过C++编译器的编译。原因很简单:编译器看到MessageHeader被使用的时候还没有发现其定义,会给出一大堆抱怨。怎么办?我们给出一个前向声明吧。也很简单,在使用之前声明一下就行了:class MessageHeader。把它加在使用之前的任意地方,编译器就应该不说话了吧。
哦,还是不行,原因是:对了,它要求必须有完整的类定义才能定义该类的对象,别忘了,C++是值语义的语言。好吧,我们改造成指针……,类型后面加上*,一连串的.变成->,应该没有问题了吧(如果你做过实际的项目,你就知道:这个修改的代价是非常高的,不过区分指针和原始对象不是我们批判的焦点,这里不再深入)。啊……还是不行,原因仍然很简单,就算可以定义指针而不是真正的对象,我们仍然不不能够调用该指针对象的方法,原因是:我(编译器)没有看到类型的定义,怎么知道有没有该方法可以调用呢?
现在我们的选择有三个,但是都不够优雅。
一、我们调整类型定义的顺序,把低层次的构件往前挪。
二、我们把成员函数的实现挪到最后,这时候它已经看到所有的定义了。
三、这是二的彻底化,干脆移动其实现到另一个文件。
方法一的缺陷就是,我们不再能够自然的从上而下看出我们设计的脉络。这跟我看HTTP的RFC一个缺陷是一样的,HTTP的RFC就不是采用自上而下描述的,而是先描述了一些基础的构件,在描述了整体结构,看得人晕头转向,另外,协议中有大量的用途和功能分析,我不是说这不好,但是作为协议这让人分神。可以把功能或者需求放在开始诱导大家构思HTTP应该怎样设计。而不是放在HTTP协议都描述了以后才描述功能。
方法二和方法三本质上是一样的,但是方法三的可维护性就更差一些了,因为所有的修改都得涉及到两个文件,而且,方法三不再能够是inline的,这个代价让我觉得非常不快。而方法二确实仍保持inline,但是,一旦修改我还是得从头到尾的查找。让我写两遍相同的函数头也让我不爽。
而最本质的原因就是:我没有办法让一个决策(函数签名)在一个地方说明,必须出现在两个地方,这是对DRY或者叫做SPOT原则的公然违反,它们会导致大量的微妙的问题和产生难以维护的代码。
C++在很大程度上鼓励我们采用第三种方案,这也是C++中的正统方案,只要我们坚持顺序依赖,我们就不得不倾向于这种方案。顺序依赖把维持依赖关系的责任推给了程序员而不是编译器自己去解决,这当然简化了编译器,但是却使得程序员的日子更艰难。那么,顺序依赖究竟应该是谁的责任呢?是该由程序员处理的呢,还是该由编译器处理的?
我们先大而化之描述一下依赖。依赖表示一个构件(这儿的构件包括函数,类,全局变量,源文件等等任意可以用来搭建整个系统的部分)对别的构件的使用。我们很自然很直观的能感受到,只要我们使用了别的构件,编译器显然知道我们的构件依赖于那些使用的构件,所以,让程序员维持依赖是不必要的。
但是还有一个问题:构件A依赖于构件B,这个编译器知道,但是构件B在哪儿?这个编译器不知道。显然,我们需要而且也只需要在某个地方描述一下这个构件跟位置的映射,我们的编译器就可以工作了。如果我们把这种映射放在任何构件里面,这样势必会导致这种映射关系描述上的重复,导致大量的维护问题。显然,最适合描述构件跟位置的映射关系的地方是工程的配置文件。它是整个工程级别的属性。
那么顺序依赖是什么呢?顺序依赖本质上是希望把构件和位置的映射关系消除。它要求所有依赖的东西必须在它之前出现,这样,被依赖方也就自然不需要指定位置了,它就在前面。这个有利于分块编译(不知道大家注意没有,分块编译的用处似乎并不是很大,无论是大工程还是小工程,因为:毕竟编译只是一个阶段,而且维持构件是否是最新编译版本似乎也一点都不难),但是实现分块编译导致需要大量的重复编译,毕竟任何被多次依赖的组件都必须多次被编译。并且分块编译要求类似于Makefile之类的支持环境,现代的语言及其开发环境都完全不支持分块编译了,它们都采用运行时动态装载这个更灵活的模式。
分享到:
相关推荐
1. 人体各器官功能的生长发育一般遵循由低级到高级、由简单到复杂、由粗到细、由近到远的顺序,这些规律对于护理实践中理解病人的生理变化至关重要。 2. 社会评估内容涉及情绪状态、人格类型、认知能力、应对能力和...
顺序:一系列按特定顺序排列的事物。 14. **shallow** - 浅的:形容水或其他物体深度不大。 15. **shiver** - 发抖:因寒冷、恐惧或疾病引起的颤抖。 16. **shrug** - 耸肩:一种表达不确定或不在乎的动作。 17. **...
基于Python的天气预测与可视化(完整源码+说明文档+数据),个人经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为毕业设计、课程设计、期末大作业,代码资料完整,下载可用。 基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基于Python的天气预测与可视化(完整源码+说明文档+数据)基
内容概要:本文详细介绍了利用MIM(金属-介质-金属)结构进行梯度相位超表面的设计与仿真的全过程。首先,通过Au-MgF2-Au三明治结构,利用磁偶极子共振实现高效的相位控制。接着,通过FDTD仿真工具,编写参数扫描脚本来优化纳米柱尺寸,从而实现广泛的相位覆盖。然后,通过近远场变换计算异常反射效率,验证了高达85%以上的反射效率。此外,还探讨了宽带性能验证的方法以及梯度相位阵列的设计思路。最后,提供了实用的代码片段和注意事项,帮助读者理解和复现实验结果。 适合人群:从事超表面研究、光束控制、电磁仿真领域的科研人员和技术开发者。 使用场景及目标:适用于希望深入了解MIM结构在超表面设计中的应用,掌握FDTD仿真技巧,以及探索高效光束偏折机制的研究人员。目标是通过详细的步骤指导,使读者能够成功复现并优化类似实验。 其他说明:文章不仅提供了理论背景,还包括大量具体的代码实现和实践经验分享,有助于读者更好地理解和应用所学知识。
内容概要:本文探讨了利用主从博弈理论解决共享储能与综合能源微网之间的利益冲突。通过MATLAB和YALMIP+Cplex工具,构建了微网运营商、用户聚合商和共享储能服务商三者之间的博弈模型。主要内容包括系统架构介绍、核心代码解析、求解策略以及仿真结果分析。文中详细展示了如何通过Stackelberg模型实现三方利益的最大化,并提供了完整的代码实现和详细的注释。 适合人群:从事能源互联网项目的研发人员、对博弈论及其应用感兴趣的学者和技术爱好者。 使用场景及目标:适用于希望深入了解能源系统优化、主从博弈理论及其MATLAB实现的研究人员和工程师。目标是掌握如何通过编程手段解决复杂系统中的多主体利益协调问题。 其他说明:文章不仅介绍了理论背景,还提供了具体的代码实现细节,如参数初始化、目标函数构建、约束条件处理等。此外,还包括了仿真结果的可视化展示,帮助读者更好地理解模型的实际效果。
内容概要:本文深入探讨了基于FPGA平台实现直方图统计与均衡化的全过程,涵盖直方图统计、累积直方图计算和均衡化处理三大核心步骤。文中不仅提供了详细的Verilog代码实现,还介绍了关键的设计思路和技术难点,如双端口BRAM的应用、流水线控制、除法器资源优化等。此外,通过Matlab代码进行了结果验证,确保FPGA实现的准确性。 适合人群:从事FPGA开发、图像处理、计算机视觉等相关领域的工程师和技术爱好者。 使用场景及目标:适用于需要高性能、低延迟图像处理的应用场景,如实时视频处理、医学图像处理、卫星图像增强等。目标是掌握FPGA实现直方图均衡化的技术细节,提高图像对比度和清晰度。 其他说明:文章强调了FPGA相较于CPU和GPU在并行处理和硬件加速方面的优势,并提供了丰富的代码实例和测试结果,帮助读者更好地理解和应用这一技术。
内容概要:本文详细介绍了利用LSTM模型进行高速公路车辆换道轨迹预测的研究过程。首先,作者使用来自I-80和US-101高速公路的实际换道轨迹数据,这些数据包括横向和纵向的速度、加速度以及轨迹坐标等特征。通过对数据进行预处理,如标准化、划分训练集和测试集等步骤,确保了数据的质量。然后,设计并实现了包含两层LSTM和一层全连接层的神经网络模型,采用Adam优化器进行训练,并通过交叉熵损失函数评估模型性能。实验结果显示,模型在测试集上的准确率达到85%,表明LSTM模型能够有效捕捉车辆换道的行为模式。 适合人群:从事自动驾驶技术研发的专业人士,尤其是对深度学习应用于交通预测感兴趣的工程师和技术研究人员。 使用场景及目标:本研究旨在提高自动驾驶系统的安全性与效率,具体应用场景包括但不限于城市快速路、高速公路等复杂路况下车辆换道行为的提前预测,从而辅助驾驶员或自动驾驶系统做出更好的决策。 其他说明:尽管目前模型已经取得了较好的成绩,但仍存在改进空间,例如可以通过引入更多类型的传感器数据(如摄像头图像)、优化现有模型结构等方式进一步提升预测精度。此外,考虑到实际应用中的实时性和鲁棒性要求,后续还需针对硬件平台进行针对性优化。
个人资料-111相关内容
内容概要:本文详细介绍了使用HyperWorks和LS-DYNA进行汽车碰撞仿真的方法和技术要点。从网格划分、材料属性设置、连接装配到最后的分析计算和结果处理,每个环节都配有具体的代码示例和注意事项。文中不仅涵盖了正碰、侧碰、偏置碰等多种类型的碰撞分析,还包括了座椅安全带约束等特殊部件的建模技巧。此外,作者分享了许多实践经验,如网格尺寸的选择、材料参数的设定以及求解器设置的最佳实践,帮助读者避免常见的陷阱并提高仿真效率。 适合人群:从事汽车工程领域的工程师、研究人员以及对汽车碰撞仿真感兴趣的初学者。 使用场景及目标:适用于需要掌握汽车碰撞仿真完整流程的专业人士,旨在提升其在实际项目中的应用能力,确保仿真结果的准确性和可靠性。 其他说明:附赠的源代码进一步增强了学习效果,使读者能够快速上手并在实践中不断优化自己的技能。
内容概要:本文详细介绍了如何在MATLAB/Simulink环境中搭建四分之一车被动悬架双质量(二自由度)模型。该模型主要用于研究车辆悬架系统在垂直方向上的动态特性,特别是面对路面不平度时的表现。文中不仅提供了具体的建模步骤,包括输入模块、模型主体搭建和输出模块的设计,还给出了详细的参数配置方法和仿真分析技巧。此外,文章还探讨了如何通过调整悬架系统的参数(如阻尼系数)来优化车辆的乘坐舒适性和行驶安全性。 适合人群:从事汽车动力学研究的专业人士、高校相关专业的学生以及对车辆悬架系统感兴趣的工程师。 使用场景及目标:①用于教学目的,帮助学生理解车辆悬架系统的理论知识;②用于科研实验,验证不同的悬架设计方案;③为企业产品研发提供技术支持,改进现有产品的性能。 其他说明:文中提供的代码片段和建模思路有助于读者快速上手并掌握Simulink建模技能。同时,强调了实际应用中的注意事项,如选择合适的求解器、处理代数环等问题。
内容概要:本文详细介绍了使用MATLAB进行语音数据处理的完整流程,涵盖从音频文件读取、特征提取(特别是梅尔倒谱系数MFCC)、分类器构建(支持向量机SVM)到最后的性能评估(混淆矩阵)。作者分享了许多实用技巧,如避免常见错误、优化特征提取参数以及提高分类准确性的方法。文中提供了大量具体代码示例,帮助读者快速理解和应用相关技术。 适合人群:对语音信号处理感兴趣的初学者或有一定经验的研究人员和技术爱好者。 使用场景及目标:适用于希望深入了解语音识别系统内部机制的人群,尤其是希望通过MATLAB平台实现简单而有效的语音分类任务的学习者。主要目的是掌握如何利用MATLAB工具箱完成从原始音频到分类结果可视化的全过程。 其他说明:除了介绍基本概念外,还强调了一些实践经验,例如预处理步骤的重要性、选择合适的滤波器数目、尝试不同的分类器配置等。此外,作者鼓励读者根据实际情况调整参数设置,以获得更好的实验效果。
基于python+yolov5和deepsort实现的行人或车辆跟踪计数系统+源码+项目文档+演示视频,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 项目运行环境:win10,pycharm,python3.6+ 主要需要的包:pytorch >= 1.7.0,opencv 运行main.py即可开始追踪检测,可以在控制台运行 基于python+yolov5和deepsort实现的行人或车辆跟踪计数系统+源码+项目文档+演示视频,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 项目运行环境:win10,pycharm,python3.6+ 主要需要的包:pytorch >= 1.7.0,opencv 运行main.py即可开始追踪检测,可以在控制台运行~
内容概要:本文详细介绍了金-氟化镁-金(MIM)结构在超表面全息领域的应用及其高效性能。首先探讨了MIM结构中磁偶极子模式的优势,特别是其低辐射损耗的特点。接着讨论了几何相位的应用,展示了纳米柱旋转角度与相位延迟之间的线性关系,并解决了相位误差的问题。随后介绍了改进的GS算法,提高了迭代收敛速度。最后,通过FDTD仿真验证了MIM结构的高效率,提供了详细的仿真参数设置和优化技巧。 适合人群:从事超表面研究、光学工程、纳米技术和FDTD仿真的研究人员和技术人员。 使用场景及目标:适用于希望深入了解MIM结构在超表面全息中的应用,以及希望通过FDTD仿真进行相关研究的专业人士。目标是提高超表面全息的转换效率,探索新的应用场景如涡旋光生成和偏振加密全息。 其他说明:文中提供了大量具体的代码片段和参数设置,帮助读者更好地理解和复现实验结果。此外,还提到了一些常见的仿真陷阱和解决方案,有助于避免常见错误并提升仿真准确性。
内容概要:文章介绍了金融科技公司信用飞如何通过关注用户信用成长,利用先进技术和专业服务为用户量身定制金融解决方案,从而实现用户资产的稳健增值。首先,信用飞通过多维度数据分析,全面了解用户的信用状况和需求,为不同信用水平的用户提供个性化服务。其次,建立了动态信用评估体系,实时监测并调整用户信用服务策略,帮助用户持续提升信用。再者,根据不同用户的需求,提供包括信用消费、理财投资、融资借贷等在内的多样化金融服务。最后,借助大数据、人工智能、区块链等技术手段,确保金融服务的安全可靠和高效便捷,持续陪伴用户实现信用与财富的双重增长。 适合人群:对个人信用管理有一定需求,希望通过科学金融规划实现资产稳健增值的个人及小微企业主。 使用场景及目标:①希望提升个人或企业信用评级的用户;②寻求合适金融产品和服务以优化财务管理的人群;③需要安全可靠的融资渠道支持业务发展的创业者和中小企业。 阅读建议:本文详细阐述了信用飞如何通过技术创新和个性化服务助力用户信用成长及资产增值,建议读者重点关注文中提到的技术应用和服务特色,结合自身情况思考如何更好地利用此类金融科技服务来优化个人或企业的财务状况。
少儿编程scratch项目源代码文件案例素材-AI战争.zip
内容概要:本文详细介绍了出口设备1200线体程序的配置与优化方法,涵盖PLC通讯控制、V90模块配置以及工艺对象与FB284的协同控制。文章强调了开源特性的优势,使得用户可以自由扩展和优化控制系统。主要内容包括:1) 出口设备1200线体程序的核心地位及其复杂控制逻辑;2) 多个PLC设备的通讯协作,确保数据可靠传输;3) V90模块的具体配置步骤,确保各模块稳定运行;4) 工艺对象与FB284的协同控制,避免逻辑冲突;5) 开源带来的便利性,便于用户进行功能扩展和学习;6) 实际应用中的优化措施,提高系统的运行效率。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些希望深入了解PLC通讯控制和V90伺服配置的人。 使用场景及目标:适用于需要配置和优化出口设备1200线体程序的实际工程项目,帮助用户掌握PLC通讯、V90配置及工艺对象与FB284协同控制的方法,从而提升生产线的效率和稳定性。 其他说明:文章提供了大量实用的代码片段和调试技巧,有助于读者更好地理解和实施相关配置。同时,文中提到的一些具体案例和经验分享也为实际操作提供了宝贵的参考。
前端面试与vue源码讲解
少儿编程scratch项目源代码文件案例素材-green vs blue.zip
内容概要:本文详细介绍了博世汽车电驱仿真模型中同步电机和异步电机的FOC(磁场定向控制)技术及其优化方法。主要内容涵盖相电流波形生成、弱磁控制、正反转切换、滑差补偿以及铁损计算等方面的技术细节。通过MATLAB、Python和C等多种编程语言实现了对电机控制的精确模拟,展示了如何通过数学方法和智能算法提高电机性能,减少电流畸变和转矩脉动。文中特别强调了弱磁控制在高速区的应用,通过动态查表法自动调整d轴电流分量,有效解决了电压极限椭圆的问题。此外,还提到了一些创新性的技术应用,如相位预判机制、动态滑差补偿和自适应耦合系数计算等。 适合人群:从事电机控制、电动汽车研究及相关领域的工程师和技术人员。 使用场景及目标:适用于希望深入了解同步电机和异步电机FOC控制原理及其实现方法的研究人员和工程师。目标是掌握先进的电机控制技术和优化方法,应用于实际项目中,提高系统性能和可靠性。 其他说明:文章不仅提供了详细的理论解释,还附有具体的代码实现,便于读者理解和实践。同时,文中提到的一些创新性技术可以为相关领域的研究提供新的思路和方法。
少儿编程scratch项目源代码文件案例素材-RPG游戏引擎5.5c.zip