消息耦合还是接口耦合

嵌入式开发中的耦合度:从紧耦合到松耦合的设计权衡与实践 在软件工程和嵌入式系统设计中,耦合度是衡量模块间依赖关系紧密程度的核心概念。其原理在于模块间交互的机制,紧耦合表现为直接、即时的调用与共享,而松耦合则通过接口、消息等间接方式进行通信。理解耦合度的技术价值在于构建高内聚、低耦合的系统,这能显著提升代码的可维护性、可测试性与可复用性,是应对需求变化和长期演化的关键。其应用场景广泛,从嵌入式实时系统到大型软件架构,都需要根据性能、资源与维护需求进行权衡。本文通过**嵌入式开发**和**模块化设计**的具体案例,深入探讨了如何在工程实践中平衡紧耦合的效率与松耦合的 阅读详情


最近公司准备开发一个新产品,需要重新设计一套新的框架,但是就这框架中各模块的通信方式,大家产生了争论,主要集中在各模块的交互方式是消息耦合还是接口耦合。

需求大概这样,我们需要封装一套客户端SDK, 暴露一系列API给外部用,而这套SDK内部会有很多模块组成,这些模块之间相互会有交互。

第一种设计是基于接口耦合,框架如下:


这种接口方式的设计要点是:
a. 各模块以类似COM组件的方式封装和暴露接口,也就是说模块会以接口的形式暴露接口,并且以Sink的方式通知外部事件。比如模块A的接口如下
class  IA
{
public :
     virtual  void  fun1() = 0;
     virtual  void  fun2() = 0;
     .
     virtual  void  int  AdviseSink(IASink* pSink) = 0;
     virtual  void  bool  UnAdviseSink( int  nCooki) = 0;
}

class  IASink
{
public :
     virtual  void  Event1() = 0;
     virtual  void  Event2() = 0;
     .
}
b. 有一个统一的模块管理平台来管理所有模块,可以通过该平台查询和加载需要的模块,然后后得到相应的接口指针进行操作。
c. 各模块间的交互全都通过直接调用其他模块的接口或是订阅该模块的Sink来实现。

第二种设计是基于消息耦合,框架如下:

这种消息方式的设计要点是:
a. 各个模块只有一个消息处理接口。 
     class  IMessageHandler
    {
     public :
         virtual  void  ProcessMessage(Message& msg) = 0;
    };
b. 中间的消息总线提供消息的订阅和分发,各个模块会向消息总线注册自己感兴趣的消息。
c. 需要调用某个模块接口 或是 触发某个事件时,都是通过向消息总线发送消息的方式, 然后由订阅消息的模块执行。

上面2种架构的设计方式各有优劣,下面我们来简单比较一下:
(1)耦合性: 尽管基于接口的耦合已经降低了耦合性,但是相比消息来说,显然是消息方式耦合性更弱。
(2)可扩展性: 某个模块新增加一个接口, 接口方式需要新加接口函数,而消息方式只需要新加一个消息类型。即使新增加一个模块,消息方式只是新增加几个消息处理类型,非常方便。所以可扩展性来说,显然也是消息方式占优。
(3)性能: 接口方式是直接调用,可是消息方式需要经过消息总线过滤分发, 显然性能上接口方式更高。 
(4)编码安全性,接口方式是强类型,接口一修改,编译时就能很快发现问题;消息方式却是弱类型,消息修改后,有可能要到运行时才能发现问题, 另外很多消息内容要做强制了类型转换才能使用。
(5)文档要求: 显然接口方式相对比较清晰,消息的话每个消息都要详细定义,并且严格按照该定义执行。
(6)可调试性: 显然接口方式要方便些,消息很可能不小心就会引起混乱。
(7)监控过滤方便性:消息方式走同一总线,可以很方便的增加过滤和监控功能, 接口方式则因为各个模块interface和Sink各不相同,增加这些功能没那么方便。
(8)跨线程或是跨进程,甚至跨机器调用:显然接口方式基本做不到,消息方式的话只要修改总线就可以做到。
(9)异步支持: 消息方式可以很方便的支持异步,接口方式则做不到。

 

经过上面的比较, 我们可以得出一些结论:

消息方式的强项是耦合性和扩展性,以及监控的方便性,个人感觉比较适合于Server端的大规模应用。
接口方式的强项是性能高效以及开发的方便性, 比较适用于同一进程内客户端的小规模应用。

但是大部分时候, 对于架构师或是公司领导,他们会更关注可耦合性和可扩展性,所以他们会倾向于选择消息方式,尽管有时可能不是那么适用。

另外,个人觉得编译时静态类型检测是C++的优势,能让我们高效而可靠的开发程序,我们不应该放弃这些优势而去把C++当作弱类型的动态语言来使用,我在 软命令接口的适用场合 一文也有相关描述。

最后,对于该框架的设计,其实我个人倾向于上面2种方式的结合, 即各个模块的入接口(调用接口)走接口方式,而各模块内部触发的事件走消息总线的方式,虽然没人采用这种方式,还是在这里记录一下。

一个多月了,消息还是接口,领导们老大们关于走何种架构还在争论中, 我等小兵就默默等待吧 ...

呵呵,不知道各位看客会作何选择?

最近公司准备开发一个新产品,需要重新设计一套新的框架,但是就这框架中各模块的通信方式,大家产生了争论,主要集中在各模块的交互方式是消息耦合还是接口耦合。

需求大概这样,我们需要封装一套客户端SDK, 暴露一系列API给外部用,而这套SDK内部会有很多模块组成,这些模块之间相互会有交互。

第一种设计是基于接口耦合,框架如下:


这种接口方式的设计要点是:
a. 各模块以类似COM组件的方式封装和暴露接口,也就是说模块会以接口的形式暴露接口,并且以Sink的方式通知外部事件。比如模块A的接口如下
class  IA
{
public :
     virtual  void  fun1() = 0;
     virtual  void  fun2() = 0;
     .
     virtual  void  int  AdviseSink(IASink* pSink) = 0;
     virtual  void  bool  UnAdviseSink( int  nCooki) = 0;
}

class  IASink
{
public :
     virtual  void  Event1() = 0;
     virtual  void  Event2() = 0;
     .
}
b. 有一个统一的模块管理平台来管理所有模块,可以通过该平台查询和加载需要的模块,然后后得到相应的接口指针进行操作。
c. 各模块间的交互全都通过直接调用其他模块的接口或是订阅该模块的Sink来实现。

第二种设计是基于消息耦合,框架如下:

这种消息方式的设计要点是:
a. 各个模块只有一个消息处理接口。 
     class  IMessageHandler
    {
     public :
         virtual  void  ProcessMessage(Message& msg) = 0;
    };
b. 中间的消息总线提供消息的订阅和分发,各个模块会向消息总线注册自己感兴趣的消息。
c. 需要调用某个模块接口 或是 触发某个事件时,都是通过向消息总线发送消息的方式, 然后由订阅消息的模块执行。

上面2种架构的设计方式各有优劣,下面我们来简单比较一下:
(1)耦合性: 尽管基于接口的耦合已经降低了耦合性,但是相比消息来说,显然是消息方式耦合性更弱。
(2)可扩展性: 某个模块新增加一个接口, 接口方式需要新加接口函数,而消息方式只需要新加一个消息类型。即使新增加一个模块,消息方式只是新增加几个消息处理类型,非常方便。所以可扩展性来说,显然也是消息方式占优。
(3)性能: 接口方式是直接调用,可是消息方式需要经过消息总线过滤分发, 显然性能上接口方式更高。 
(4)编码安全性,接口方式是强类型,接口一修改,编译时就能很快发现问题;消息方式却是弱类型,消息修改后,有可能要到运行时才能发现问题, 另外很多消息内容要做强制了类型转换才能使用。
(5)文档要求: 显然接口方式相对比较清晰,消息的话每个消息都要详细定义,并且严格按照该定义执行。
(6)可调试性: 显然接口方式要方便些,消息很可能不小心就会引起混乱。
(7)监控过滤方便性:消息方式走同一总线,可以很方便的增加过滤和监控功能, 接口方式则因为各个模块interface和Sink各不相同,增加这些功能没那么方便。
(8)跨线程或是跨进程,甚至跨机器调用:显然接口方式基本做不到,消息方式的话只要修改总线就可以做到。
(9)异步支持: 消息方式可以很方便的支持异步,接口方式则做不到。

 

经过上面的比较, 我们可以得出一些结论:

消息方式的强项是耦合性和扩展性,以及监控的方便性,个人感觉比较适合于Server端的大规模应用。
接口方式的强项是性能高效以及开发的方便性, 比较适用于同一进程内客户端的小规模应用。

但是大部分时候, 对于架构师或是公司领导,他们会更关注可耦合性和可扩展性,所以他们会倾向于选择消息方式,尽管有时可能不是那么适用。

另外,个人觉得编译时静态类型检测是C++的优势,能让我们高效而可靠的开发程序,我们不应该放弃这些优势而去把C++当作弱类型的动态语言来使用,我在 软命令接口的适用场合 一文也有相关描述。

最后,对于该框架的设计,其实我个人倾向于上面2种方式的结合, 即各个模块的入接口(调用接口)走接口方式,而各模块内部触发的事件走消息总线的方式,虽然没人采用这种方式,还是在这里记录一下。


编程中的耦合问题及其解决方法 在软件开发中,耦合(coupling)是指不同模块或组件之间的依赖关系和相互影响程度。耦合度高意味着模块之间的关联性强,一处的改动可能会引起其他地方的变化,从而增加了代码的脆弱性和维护成本。综上所述,耦合是软件开发中常见的问题,它会导致代码的脆弱性和维护成本的增加。通过采用合适的编程技巧,如依赖注入、接口抽象、接口适配器、封装数据和消息传递等,可以有效降低耦合度,提高代码的可维护性和灵活性。在设计和编写代码时,我们应该注重降低耦合度,以实现高质量的软件开发。的构造函数,实现了依赖的注入。 阅读详情

相关推荐

docker配置国内镜像源

【代码】docker配置国内镜像源。

愿听风成曲 9616

关于软件设计耦合的思考

耦合是一种软件度量标准,它描述两个例程或模块之间的紧密程度。 这是质量的度量。 该概念由拉里·康斯坦丁(Larry Constantine)在1960年代提出,并在1974年的《 IBM系统期刊,结构化设计》和1979年的同名书中得到了体现。 拥有模块A和B,需要更多有关B的知识才能理解A,A与B之间的联系也就越紧密。需要检查一个模块以了解另一个模块的操作这一事实表明:互连程度,即使互连...

danpu0978的博客 564

SAP FICO 资产会计AA后台配置 (上)

输入折旧表“CZ11”如有外币计价的资产,则需指定外币计价的资产折旧范围,以及规则。因为在设置资产类型时,需指定一个对应的 资产编号范围、资产账户确定类型(便于分配自动会计科目)、屏幕格式规则(便于设置资产字段必填与否)。因为在设置资产类型时,需指定一个对应的 资产编号范围、资产账户确定类型(便于分配自动会计科目)、屏幕格式规则(便于设置资产字段必填与否)。新增资产类型:Z101 固定资产-房屋及建筑物新增资产类型:Z301 固定资产-房屋及建筑物。

ghgxm520的博客 1762

三、耦合

1.耦合的定义 模块之间互相依赖的程度。 耦合和内聚的区别:耦合关注的是模块间的依赖程度;内聚关注的是模块内部元素的结合程度。 2.耦合的分类 无耦合:模块间完全没有关系和交互。无耦合的模块意味着所有的功能都是自给自足,什么都得自己做。如果是非常底层的模块,还可以接受,但是非底层模块如果完全无耦合,那么意味着它什么都得自己造轮子,既不利于重用,效率也很低下。 消息...

weixin_30519071的博客 307

用友BIP培训资料-设计采购订单新增API接口开发

14.在子实体的String pkMeas = order_hhrSlave0VOJson.getString("pk_meas");Openapi路径:nccloud/api/pu/order_hhrmanage/order_hhrMaster/addAggOrder_hhrMasterVO。实现接口的开发部署,通过openAPI的test类,实现一条数据的插入。16.进入自己的Idea打开老师发的TestOpenApi并且编译完成后如下。12.编写检测是否字段中是否含有中文的方法。

m0_68497879的博客 1548

Nano Banana 2哪里使用?Nano Banana 2提示词合集和使用教程

收集最强的Nano Banana 2提示词合集,以及Nano Banana 2哪里使用的教程,并且有10个免费使用渠道。

qq_42927225的博客 1996

面试 什么情况用接口,什么情况用消息

接口的特点是同步调用,接口实时响应,阻塞等待 消息的特点是异步处理,非实时响应,消息发送后则返回,消息队列可以削峰   一般对实时性要求比较高的功能采用接口 对实时性要求不高的功能可以采用消息,削峰时可以采用消息...

renxing521的专栏 1592

STM32中断实战:用ITR9606红外传感器DIY转速计数器(附完整代码)

本文详细介绍了如何使用STM32中断机制和ITR9606红外传感器DIY高精度转速计数器。从传感器选型、中断配置到抗干扰设计,提供完整的实战指南和优化代码,特别适合嵌入式开发者和硬件工程师快速实现工业级转速检测系统。

weixin_29159613的博客 290

耦合关系从强到弱顺序_接口消息导致的组件耦合问题

背景思考这个问题的时候我翻出了Uncle Bob的clean architecture,我记得这本书里有专门的章节讲组件间依赖程度的度量和管理,希望能有所帮助。结果发现没什么用,这本书里讲的依赖,有点像库和调用库的客户端的依赖,这些不同的块之间可以调用或者引用。这与我想得到的答案不一样。本文这里的组件,指的是部署的独立单元,组件间通过通道进行通信,组件间没有显式的依赖关系,从物理视图方面你可以理解...

weixin_35706067的博客 306

如何在Vitis 2023.1上快速搭建LWIP Echo Server(附YT8521S PHY调试心得)

本文详细介绍了在Vitis 2023.1开发环境下,基于Xilinx MPSoC平台快速搭建LWIP Echo Server的完整实战流程。内容涵盖从Vivado硬件工程配置、Vitis软件工程创建,到关键代码剖析与定制化修改,并重点分享了调试非标准PHY芯片(如YT8521S)的宝贵心得与常见问题排查方法,旨在帮助开发者高效实现FPGA与上位机间的可靠网络通信验证。

weixin_29250403的博客 137

【人工智能】全面盘点国内AI九大模型:各擅胜场的智能先锋(豆包、文心一言、讯飞星火、通义千问、Kimi、智谱清言、腾讯元宝、秘塔、天工AI)

追求性价比与全能:选豆包,适合个人与中小企业日常使用;侧重中文创作与理解:选文心一言,文学与商业文案创作首选;需要专业语音交互:选讯飞星火,智能客服、车载场景必备;看重生态与多场景:选通义千问,适配电商、办公等企业需求;处理超长文本任务:选Kimi,文档分析、学术研究的利器;专注深度推理创作:选智谱清言,学术与创意写作的伙伴;依赖腾讯生态协同:选腾讯元宝,日常轻量需求的便捷之选;深耕法律学术领域:选秘塔,专业文本处理的权威工具;布局前沿技术体验:选天工AI,享受接近国际顶尖的智能服务。

奶爸的编程之路,也就一周冷个三天 1124

面向接口编程在消息中间件中的实战:从强耦合到灵活解耦的设计演进

在我之前开发的高并发商城项目中,遇到了一个典型的微服务通信问题:用户支付完成后需要更新订单状态,但支付服务和订单服务分属不同的微服务模块。在实际项目中,这种设计思路不仅适用于消息中间件,还可以扩展到数据库访问、缓存、RPC调用等各个层面,真正实现"面向接口编程,而非面向实现编程"的软件设计理念。技术选型会变,业务需求会变,但良好的架构设计能让系统在变化中保持稳定和可维护。最近在开发实时货币交易系统时,同样使用了消息中间件。通过面向接口编程的思想,我们将消息中间件的使用从技术实现细节提升到业务架构设计层面。

hubery_hubery的博客 734

Flink实战案例(十三):Flink DataStream 八大分区策略与自定义分区器

声明:本系列博客是根据SGG的视频整理而成,非常适合大家入门学习。 《2021年最新版大数据面试题全面开启更新》 分区策略决定了一条数据如何发送给下游。Flink中默认提供了八大分区策略(也叫分区器)。 本文基于Flink 1.9.0总结Flink DataStream中的八大分区策略以及手动实现一个自定义分区器。 八大分区策略继承关系图 ChannelSelector: 接口,决定将记录写入哪个Channel。有3个方法: void setup(int numberOfChannels):

微信搜:import_bigdata,大数据领域硬核原创作者 1125

告别MQ强耦合!一文了解如何实现消息队列无缝切换

在复杂的分布式系统中,消息队列(如 RocketMQ、Kafka、RabbitMQ)常用于优化系统性能。然而,直接在代码中引入这些消息队列的 API 会导致系统与特定消息队列的强耦合,后续难以切换其他消息队列组件。虽然 Spring Cloud Stream 提供了一种抽象层,但其引入了复杂的概念(如绑定器、通道、处理器等),且与低版本的 Spring Boot 不兼容。

梦想歌的技术博客 1326

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java中耦合的理解

java讲究高内聚,低耦合。今天我们就先来说一下什么是耦合,如何才能低耦合。 1.耦合定义:耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。也就是两者存在着强关联。 ...

weixin_39788777的博客 2311

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

什么是耦合,解耦?

打个比方;两兄弟的工资都共同存在一个银行卡里面,假如有一天,弟弟需要用钱,那么需要找哥哥商量一下,然后再取钱,这就是耦合;后来某天弟弟发现他自己的工资可以单独开一张银行卡存起来,这样等到急需用钱的时候就可以直接取,这就是解耦。     在软件工程中,模块之间是存在依赖关系就必然存在耦合,理论上说绝对的零耦合是做不到的,但可以通过一些现有的方法将耦合降至最低,降低耦合度即可理解为解耦。     在工...

weixin_44151065的博客 5万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

设计模式学习之消息驱动机制

消息驱动机制,也叫观察者模式、事件驱动模式。不论是在应用还是游戏中,都是一种常见的设计模式,该设计模式非常利于模块的解耦。 我们这里以老师和学生为例,有一个老师和多个学生,老师发的每一个消息,学生都要能够收到。如:老师说,明天我们放假,然后确保所有学生都能收到该消息。 首先,建立一个消息分发中心,负责收集和移除消息接收个体(这里就是学生),同时负责通知到收集的每一个个体。该类命名为Human_

继续沉淀! 4354

Java开发中解决紧耦合的方法有哪些?

通常最佳实践是在项目开始阶段就考虑到软件的结构和模块划分,这样可以在后期节约大量的重构成本。在多层架构中,服务层充当业务逻辑和其他层(比如数据访问层和表示层)之间的。面向切面编程将**公共功能(比如日志或事务管理)**模块化为切面,使用上述方法时,我们应该根据具体的应用场景选择合适的策略,,这通常通过使用依赖注入框架(比如 Spring)来实现。例如,使用工厂模式创建对象,可以。应用接口可以降低类之间的依赖性,这样你可以很容易地引入新的。接口,而不是其具体实现。模块化是将系统分解为。组件通过消息队列进行。

訾博(ZiBo)的博客 926

博客摘录「 事件驱动和消息驱动的对比」2024年12月3日

如果你在设计一个东西举棋不定,那么你可以参考win32的GetMessage,本身就是一个藕合度极低的接口,又足够自由,接口任何语言都很方便,具体应用场景再在其基础上封装成事件并不是难事,接口耦合较低,即便哪天事件框架调整,修改外层即可,不会伤经动骨。而如果直接实现成事件,那就完全反过来了。消息是非侵入式设计,将主循环该怎样设计的自由留给用户。事件是侵入式设计,霸占你的主循环;事件模式耦合高,同模块内好用;事件模式集成其它语言比较繁琐,消息模式集成其他语言比较轻松。消息模式耦合低,跨模块好用。

weixin_46009432的博客 252
上一篇: 理解 Windows API 调用过程
下一篇: 软命令接口的适用场合
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值