通过对FreeCADSALOME等多款代码的分析研究,发现这些软件在架构设计模块实现等方面,存在许多相似(同)的技术思想。因此,有必要对这些共性、主流的技术予以总结分析。

Structuring a system into subsystems helps reduce complexity.  ---GoF. Design Patterns.
Layering is one of the most common techniques that software designers use to break apart a complicated software system. ---Martin Fowler. Patterns of Enterprise Application Architecture.

通过不断地分析总结,旨在系统性地分析总结大型CAx(CAD/CAE/CAM)工业软件开发中的关键组件设计方法。希望对从事国产工业软件研发的朋友们在技术选型系统设计等方面有所帮助,也非常欢迎大家予以批评指教。

注1:限于研究水平,分析难免不当,欢迎批评指正。

注2:文章内容会不定期更新。


零、形势、对策、原则


一、工程组织

工程组织着眼于组织管理CAx软件研发过程中相关的代码、文档、工程配置文件等。虽然,很难在软件开发初始阶段就设计出能够兼顾诸多诉求的工程组织形式。但是,有一点却很确定,良好的工程组织对于管理、维护软件文件是大有裨益的

从目前来看,基于Qt的桌面CAx软件开发仍旧是主流,并且在未来有限的时间内仍旧会占据较大份额。

CMakeQt是GitHub上一个开源Qt软件开发的CMake模板,已经被Blender等许多开源项目所采用,非常值得借鉴引用。

二、MVC类框架

在面向对象程序设计语言中,软件框架一般使用虚类(接口)构筑对象间的关系。

Ref form GoF's Design Patterns

A framework is a set of cooperating classes that make up a resuable design clas of software. Frameworks use abstract classes to define and maintain relationships between objects.

MVC(Model-View-Controller,模型-视图-控制器)是上世纪七八十年代由SmallTalk提出的一种客户端软件设计框架,主要用于实现数据/逻辑/界面的分离

Ref. form Matin Fowler's Patterns of Enterprise Application Architecture

Model View Controller (MVC) has been one of the most quoted (and most misquoted) patterns around. It started life as a framework developed by Trygve Reenskaug for the Smalltalk platform in the late 70's. Since then it's played an influential role for most UI frameworks and thinking about UI design.

MVC considers three roles. The model is an object that represents some information about the domain. It is a non-visual object and contains all the data and behavior other than that used for the UI.

The view represents the display of the model in the UI.The controller takes user input and manipulates the model and causes the view to update appropriately. The UI is therefore a combination of the view and the controller.

As I think about MVC I see two principal separations: separating the presentation from the model and separating the controller from the view.Of these the separation of presentation from model is one of the most fundamental heuristics of good software design.

A key point in this separation is the direction of the dependencies: the presentation depends on the model but not the other way around. People programming in the model should be entirely unaware of what presentation is being used. This both simplifies their task and makes it easier to add new presentations later on. It also means that presentation changes can be made freely without altering the model.

The second separation, that of view and controller, is less important.

The fact that most GUI frameworks combine view and controller has led to the many misquotations of MVC that I've run into.

依据GoF(Gang of Four)的Design Patterns一书中所介绍的23种模式,MVC框架并不是单一的设计模式,而是由多种设计模式构成的系统。

实现要点:

  • 使用Observer模式来处理Model-View之间的关系:当模型数据(Model)发生变换时,通知所有关联的视图(View)来更新界面
  • 使用Command模式处理Controller-Model之间的关系:当触发命令时,Controller构造(或返回)一个命令对象(Abstract Factory模式),运行该命令对象以修改模型数据(Model)

Ref. from Wikipedia Model–view–controller

Model–view–controller (MVC) is a software architectural pattern commonly used for developing user interfaces that divide the related program logic into three interconnected elements. This is done to separate internal representations of information from the ways information is presented to and accepted from the user.

Ref form GoF's Design Patterns:

MVC consists of three kinds of objects. The Model is the application object, the View is its screen presentation, and the Controller defines the way the user interface reacts to user input. Before MVC, user interface designs tended to lump these objects together. MVC decouples them to increase flexibility and reuse.

MVC decouples views and models by establishing a subscribe/notify protocol between them. A view must ensure that its appearance reflects the state of the model. Whenever the model's data changes, the model notifies views that depend on it. In response, each view gets an opportunity to update itself. This approach lets you attach multiple views to a model to provide different presentations. You can also create new views for a model without rewriting it.

Ref. from Martin Fowler's GUI Architecture

As I've discussed above, Smalltalk 80's MVC was very influential and had some excellent features, but also some faults. As Smalltalk developed in the 80's and 90's this led to some significant variations on the classic MVC model. Indeed one could almost say that MVC disappeared, if you consider the view/controller separation to be an essential part of MVC - which the name does imply.

The things that clearly worked from MVC were Separated Presentation and Observer Synchronization. So these stayed as Smalltalk developed - indeed for many people they were the key element of MVC.

PureMVC是一套轻量级的MVC开发框架,最初支持ActionScript 3语言,目前已经移植到18种编程语言,PureMVC包括两个版本:标准版和多核版。PureMVC使用到Observer、FacadeProxyMediatorCommandIterator等设计模式。

Conceptual Diagram
Ref. from PureMVC

文档/视图架构源于MVC模式,用于实现数据与显示的分离。

Ref. from Qt Model/View Programming

If the view and the controller objects are combined, the result is the model/view architecture. This still separates the way that data is stored from the way that it is presented to the user, but provides a simpler framework based on the same principles. This separation makes it possible to display the same data in several different views, and to implement new types of views, without changing the underlying data structures. To allow flexible handling of user input, we introduce the concept of the delegate. The advantage of having a delegate in this framework is that it allows the way items of data are rendered and edited to be customized.

The model/view architecture

The model communicates with a source of data, providing an interface for the other components in the architecture. The nature of the communication depends on the type of data source, and the way the model is implemented.

The view obtains model indexes from the model; these are references to items of data. By supplying model indexes to the model, the view can retrieve items of data from the data source.

In standard views, a delegate renders the items of data. When an item is edited, the delegate communicates with the model directly using model indexes.

在文档/视图框架中,将每一条数据抽象成一个数据项(Document Item),文档则将一系列数据项按照一定方式组织起来,实现独立于底层具体存储方式的数据项访问、编辑等功能视图以GUI的形式显示、编辑数据项

Ref form GoF's Design Patterns:
The Application class is responsible for managing Documents and will create them as required—when the user selects Open or New from a menu, for example.

文档\视图架构要点在于处理应用程序、主框架、文档、子框架、视图等(桌面)应用程序组件之间的关系

MVP(Model-View-Presenter,模型-视图-展示器)框架最早是由IBM Taligent公司在上世纪90年代提出的。相对于MVC框架MVP可用于实现ViewModel的完全隔离。

Ref. from Wikipedia Model-view-presenter

Model-view-presenter(MVP) is a derivation of the model-view-controller(MVC) architectural pattern, and is used mostly for building user interfaces.

In MVP, the presenter assumes the functionality of the "middle-man". In MVP, all presentation logic is pushed to the presenter.

MVP is a user interface architectural pattern engineered to facilitate automated unit testing and improve the separation of concerns in presentation logic:

  • The model is an interface defining the data to be displayed or otherwise acted upon in the user interface.
  • The view is a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.
  • The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.

Ref. from Mike Potel's MVP

The role of the presenter within MVP is to interpret the events and gestures initiated by the user and provide the business logic that maps them onto the appropriate commands for manipulating the model in the intended fashion.

Ref. from Martin Fowler's GUI Architecture

One of the variations in thinking about MVP is the degree to which the presenter controls the widgets in the view. On one hand there is the case where all view logic is left in the view and the presenter doesn't get involved in deciding how to render the model. This style is the one implied by Potel. The direction behind Bower and McGlashan was what I'm calling Supervising Controller, where the view handles a good deal of the view logic that can be described declaratively and the presenter then comes in to handle more complex cases.

You can also move all the way to having the presenter do all the manipulation of the widgets. This style, which I call Passive View isn't part of the original descriptions of MVP but got developed as people explored testability issues. I'm going to talk about that style later, but that style is one of the flavors of MVP.

实现要点:

  • View->Presenter->Model:当View触发事件之后,通过signal/slot调用Presenter关联的回调函数,而在Presenter回调函数中通过Command模式完成对Model的更新。(对应于业务逻辑部分
  • Model->Presenter->View:当Model发生更新时,使用Observer模式通知Presenter进行更新,而在Presenter中,调用View的接口来完成对View的更新。(对应于界面逻辑部分在实际实现中,Presenter包含对View的引用,可以直接调用View接口完成界面更新。

由此可以看出,MVC中的ControllerMVP中的Presenter非常相似。但是,在MVC中,视图逻辑代码存在于View中,业务逻辑代码主要存在于Controller中;而在MVP中,View通常只包含部分简单的视图逻辑与业务逻辑代码,比较复杂的视图逻辑与业务逻辑代码则存在于Presenter中。

一言以蔽之:与MVC相比,MVP的Presenter可包含视图逻辑代码,MVP的View可包含业务逻辑代码,这便是MVP与MVC最大的不同之处

为了深化对MVP的理解,拟考虑如下两种极端情况:

  • 第一种情况,视图逻辑代码全部位于View中Presenter仅包含业务逻辑代码(部分较为简单的业务逻辑代码可放在View中)。这样,对于一般的业务处理,由View直接处理即可。而对于较为复杂的业务逻辑,需由Presenter处理,当Presenter完成对Model的修改之后,需要借助于Observer模式,由Model通知View更新界面。
  • 第二种情况,视图逻辑代码全部位于Presenter中,当Presenter完成对Model的修改之后,可以在Presenter中直接调用View接口更新界面,这样可实现ViewModel的完全隔离,这种View通常称为被动视图(Passive View)。

MVVM(Model-View-ViewModel,模型-视图-视图模型)框架是微软架构师John Gossman在2005年提出的一种设计模式。MVVMMVC的进行了改进:通过View和ViewModel之间的双向绑定,实现了ViewModel完全隔离自动同步

Ref. from Wikipedia Model–view–viewmodel

Model–view–viewmodel (MVVM) is a software architectural pattern that facilitates the separation of the development of the graphical user interface (the view) – be it via a markup language or GUI code – from the development of the business logic or back-end logic (the model) so that the view is not dependent on any specific model platform. The viewmodel of MVVM is a value converter, meaning the viewmodel is responsible for exposing (converting) the data objects from the model in such a way that objects are easily managed and presented. In this respect, the viewmodel is more model than view, and handles most if not all of the view's display logic. The viewmodel may implement a mediator pattern, organizing access to the back-end logic around the set of use cases supported by the view.

Ref. from Martin Fowler's GUI Architecture

Keeping screen state and session state synchronized is an important task. A tool that helped make this easier was Data Binding. The idea was that any change to either the control data, or the underlying record set was immediately propagated to the other.

In general data binding gets tricky because if you have to avoid cycles where a change to the control, changes the record set, which updates the control, which updates the record set.... The flow of usage helps avoid these - we load from the session state to the screen when the screen is opened, after that any changes to the screen state propagate back to the session state. It's unusual for the session state to be updated directly once the screen is up. As a result data binding might not be entirely bi-directional - just confined to initial upload and then propagating changes from the controls to the session state.

Ref. from Martin Fowler's Data Bingding

A mechanism that ensures that any change made to the data in a UI control is automatically carried over to the underlying session state (and vice versa).

实现要点:

  • View/ViewModel:使用Observer模式实现Data Bingding,当View触发事件时,通过Observer模式通知ViewModel;当ViewModel触发事件时,通过Observer模式通知View
  • ViewModel/Model:ViewModel可以直击调用Model接口修改模型数据;当Model发生变化时,使用Observer模式通知ViewModel

在GitHub上,C++实现的MVVM软件框架并不多,可以参照qt-mvvm、QtMvvm等代码来研究MVVM的具体实现方法。


三、日志系统

日志系统用于输出运行过程中的信息,方便跟踪软件运行状态及其异常排错。

Qt 提供了QMessageLogger用于将日志输出到文件;而Boos Log v2则提供了更加强大的日志输出功能。

QMessageLogger is used to generate messages for the Qt logging framework.

四、类型系统

从面向对象编程的角度来看,每一个对象包含的数据实际上由两部分组成:一部分是对象数据(object data),这需要借助文档对象模型属性系统来处理;另一部分则是类型信息(type info),这就需要类型系统来实现

类型系统基于运行时类型信息(RTTI, RunTime Type Information)与反射机制(Reflection),提供了类型比较对象动态生成与管理等功能。

Ref. from Wikipedia: Run-time type information

In computer programming, run-time type information or run-time type identification (RTTI) is a feature of some programming languages (such as C++, Object Pascal, and Ada) that exposes information about an object's data type at runtime. Run-time type information may be available for all types or only to types that explicitly have it (as is the case with Ada). Run-time type information is a specialization of a more general concept called type introspection.

Ref. from Wikipedia: Reflective programming

In computer science, reflective programming or reflection is the ability of a process to examine, introspect, and modify its own structure and behavior.

C++11引入了typeid关键字来获取类型/对象的类型信息std::type_info,同时提供了std::type_index以支持在关系型容器内索引std::type_info元素。

Ref. from cppreference: typeid operator

Queries information of a type.

Used where the dynamic type of a polymorphic object must be known and for static type identification.

Boost中,boost::typeindex::type_infoboost::typeindex::type_index等用于存储类型信息,在类型名称可读性、跨平台等方面做了不少改进。

Qt Meta-Object System借助于Qt RTTI,实现了对象动态生成、基于信号/槽的通信等功能。

Qt's meta-object system provides the signals and slots mechanism for inter-object communication, run-time type information, and the dynamic property system.

FreeCAD中,Base::Type实际上将类型信息(Type Info)与类型索引(Type Index)两部分功能合二为一,但是需要用户手动注册类型信息。

通过上述的分析,可以总结出类型系统实现的技术要点。

实现要点:

  • type_info用于存储类型名称、对象构造器等相关信息;
  • type_index实现关系型容器内类型信息的索引功能;
  • 将所有已注册的类型信息存储到关系型容器中(键是type_index,值是type_info);
  • 客户端根据type_index获取type_info,进而调用type_info内的对象构造器来完成类型实例化。

五、属性系统

在面向对象程序设计中,对象由属性方法组成,属性所有者称为属性容器。属性用于表述对象的状态,属性一般由属性类型属性名称属性值等要素构成;对属性的操作包括:添加删除编辑等。

对于C++等静态编程语言,对象所包含的属性由对象所属类型决定,无法动态地添加属性、删除属性,只能编辑属性。因此,需要实现动态地添加/删除属性的功能。

在OSG,osg::Object包含一个osg::userDataContainer对象,osg::ValueObject、osg::UserDataContainer两个类分别表示对象属性、属性容器,派生于osg::ValueObject的osg::TemplateValueObject模板用于特化bool、char、int、float、double等属性。

在Qt中,QObject可以关联任意属性数据,QVaraint、QMetaObject用于表示属性、属性容器。

在FreeCAD中,App::DocumentObject间接继承于App::PropertyContainer(App::DocumentObject继承自App::TransactionalObject,而App::TransactionalObject继承自App::PropertyContainer),App::Property、App::PropertyContainer分别表示属性、属性容器。

六、文档对象模型

文档对象模型(Document Object Model)主要用于管理软件中数据,将数据抽象成对象,进而将对象按照一定方式(Directed Acyclic Graph,DAG)组装成文档。从这个角度来看,文档对象模型实际上就是数据模型(Data Model),也就是研究如何抽象并组织数据的问题

Qt将对象组织成树状结构,这的确可以满足大部分的场景应用,但却难以处理对象的多引用与数据一致性问题。

QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is

Ref form GoF's Design Patterns

The  Application class also keeps track of Document objects that a user has  opened.

OSG则将对象组织成了DAG以优化OpenGL渲染性能,但所提供的DAG节点主要是面向OpenGL渲染管线。

FreeCAD实现了以App::DocumentObject为节点的对象树,由于App::DocumentObject间接派生于App::PropertyContainer,因此App::DocumentObject可以包含任意的属性元素App::Property。

SALOME kernel模块延续了OpenCACADE的数据管理方法,实现了以DF_Label为索引、以DF_LabelNode为节点的对象树,每个DF_LabelNode可以关联任意个属性元素DF_Attribute;SALOME gui模块实现了基于SUIT_DataObject的树状对象模型。

数据模型还需要支持对象串行化功能。Boost Archive/Serialization模块提供了非常完善、强大的对象串行化功能。

七、命令系统

分层架构是最为广泛的架构模式,通过分层可以实现关注点分离,达到“高内聚低耦合”的效果。一般可以将系统分成表示层领域层数据层。表示层用于显示数据、获取用户输入等;领域层完成特定领域内的逻辑处理;数据层关联数据源,为领域层提供数据。

Ref. from Martin Fowller's Patterns of Enterprise Application Architecture

Layering is one of the most common techniques that software designers use to break apart a complicated software system.

So for this book I'm centering my discussion around a layered architecture of three primary layers: presentation, domain, and data source

Presentationlogic is about how to handle the interaction between the user and the software. This can be as simple as a command line or a text based menu system. These days it's more likely to be a rich client graphics UI or an HTML based browser UI. (In this book I use rich clientto mean a windows / swing / fat client style UI, as opposed to an HTML browser.) The primary responsibilities of the presentation is to display information to the user and to interpret commands from the user into actions upon the domain and data source.

Data sourcelogic is about communicating with other systems that carry out tasks on behalf of the application. These can be transaction monitors, other applications, messaging systems and so forth. For most enterprise applications the biggest piece of data source logic is a database which is primarily responsible for storing persistent data.

The remaining piece is the domain logic, also referred to as business logic. This is the work that this application needs to do for the domain you're working with. It involves calculations based on inputs and stored data, validation of any data that comes in from the presentation, and figuring out exactly what data source logic to dispatch depending on commands received from the presentation.

用户大部分请求最终用于编辑文档、数据对象等可以将用户的请求(参数、操作等)封装成命令

注:命令对象不一定会修改底层数据对象,可能仅与界面显示相关,本文仅讨论会修改底层数据对象的命令对象。

Ref. from Mike Potel. MVP: Model-View-Presenter

A command then defines an operation on a selection in my model.

Ref. from GoF's Design Patterns

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

命令对象可以分为无状态与有状态等两种。无状态命令每次执行仅根据用户输入调用领域逻辑接口以完成对底层文档、数据对象的编辑,不会在命令对象内部保存相关数据对象的历史快照,这样便可以复用同一个命令对象来执行用户的多次请求,因此需要在其他模块设计数据结构来完成相关数据对象的快照存储以实现命令撤销功能;而有状态命令会保存相关数据对象的历史快照,每次用户发起请求,需要重新生成一个命令对象,相对来说比较容易实现命令撤销功能。

Ref. from Overview of Qt's Undo Framework

Qt's Undo Framework is an implementation of the Command pattern, for implementing undo/redo functionality in applications.

The Command pattern is based on the idea that all editing in an application is done by creating instances of command objects. Command objects apply changes to the document and are stored on a command stack. Furthermore, each command knows how to undo its changes to bring the document back to its previous state. As long as the application only uses command objects to change the state of the document, it is possible to undo a sequence of commands by traversing the stack downwards and calling undo on each command in turn. It is also possible to redo a sequence of commands by traversing the stack upwards and calling redo on each command.

在桌面应用程序中,命令对象至少包含两面的职责:

  • 命令对象对应的菜单、工具按钮等界面表示

借助于QAction等构造一个Action类来完成命令对象的界面外观等方面的职责;

Ref. from QAction

The QAction class provides an abstraction for user commands that can be added to different user interface components.

In applications many common commands can be invoked via menus, toolbar buttons, and keyboard shortcuts. Since the user expects each command to be performed in the same way, regardless of the user interface used, it is useful to represent each command as an action.

Actions can be added to menus and toolbars, and will automatically keep them in sync. For example, in a word processor, if the user presses a Bold toolbar button, the Bold menu item will automatically be checked.

Ref. from QWidgetAction

The QWidgetAction class extendsQAction by an interface for inserting custom widgets into action based containers, such as toolbars.

  • 根据用户输入调用领域逻辑完成用户请求的执行

可以使用GoF 的Command模型来完成。对于Command模式,为了解决参数传递问题,可以将用户输入参数封装成一个Request对象。

Ref. from GoF's Design Patterns

Encapsulate a request as an object, thereby letting you parameterize clients

with different requests, queue or log requests, and support undoable operations.

Ref. from GoF's Design Patterns

To address the parameter-passing problem, we can use separate request objectsthat bundle request parameters. A Request class can represent requests explicitly, and new kinds of requests can be defined by subclassing. Subclasses can define different parameters. Handlers must know the kind of request (that is, which Request subclass they're using) to access these parameters.

在FreeCAD中,每个Workbench加载时注册了若干派生于Gui::Command的命令对象,Gui::Command定义了menu texticontooltip等相关的界面显示信息;每次用户触发事件,通过其关联的Gui::Action将用户事件转发到Gui::Command::activated()事件处理函数,因此FreeCAD中的命令对象是无状态的。关于FreeCAD中Undo/Redo的实现原理,可以参见笔者的博文:FreeCAD源码分析:Undo/Redo实现原理。

八、资源系统

九、窗口系统


十、插件系统

插件(Plugin)可以看作是满足一定接口标准的动态链接库允许第三方开发商在不修改软件主体的前提下扩展软件功能

Ref. from Plugins in C++

In this paper, a plugin is code that can become part of a program under that program's control. For C and C++ programs plugins are typically implemented as shared libraries that are dynamically loaded (and sometimes unloaded) by the main program.

Ref. from Boost.Dll

Adding a specific features to an existing software applications at runtime could be useful in many cases. Such extensions, or plugins, are usually implemented using Dynamic Library Modules (DLL,SO/DSO) loaded at runtime.

Ref. from Who Needs Plugins?

Plugins are the way to go if you want to develop a successful and dynamic system. Plugin-based extensibility is the current best practice to extend and evolve systems in a safe manner. Plugins let third-party developers add value to systems and let in-house developers add functionality without risk of destabilizing the core functionality. Plugins promote separation of concerns, guaranty implementation details hiding, isolated testing, and many other best practices.

Ref. from Plugin-Based System Architecture

A plugin-based system can be divided into three parts:

  • The domain-specific system.
  • A plugin manager.
  • The plugins.

The domain-specific system loads the plugins and creates plugin objects via the plugin manager. Once a plugin object is created and the main system has some pointer/reference to it, it can be used just like any other object. Usually, there are some special destruction/cleanup requirements as we shall see.

The plugin manager is a pretty generic piece of code. It manages the life-cycle of the plugins and exposes them to the main system. It can find and load plugins, initialize them, register factory functions and be able to unload plugins. It should also let the main system iterate over loaded plugins or registered plugin objects.

The plugins themselves should conform to the plugin manager protocol and provide objects that conform to the main system expectations.

在不同软件中,虽然插件系统的具体实现不尽相同,但是它们的原理却是相似的,主要包括插件接口定义插件查找插件加载插件版本管理插件接口访问插件卸载等基本功能。

Ref. from Plugin Programming Interface

Plugins are all about interfaces. The basic notion of plugin-based system is that there is some central system that loads plugins it knows nothing about and communicates with them through well-defined interfaces and protocols.

Ref. from How to Create Qt Plugins

Making an application extensible through plugins involves the following steps:

  1. Define a set of interfaces (classes with only pure virtual functions) used to talk to the plugins.
  2. Use the Q_DECLARE_INTERFACE() macro to tell Qt's meta-object system about the interface.
  3. Use QPluginLoader in the application to load the plugins.
  4. Use qobject_cast() to test whether a plugin implements a given interface.

Writing a plugin involves these steps:

  1. Declare a plugin class that inherits from QObject and from the interfaces that the plugin wants to provide.
  2. Use the Q_INTERFACES() macro to tell Qt's meta-object system about the interfaces.
  3. Export the plugin using the Q_PLUGIN_METADATA() macro.
  4. Build the plugin using a suitable .pro file.

Ref. from Boost.Dll

The first thing to do when creating your own plugins is define the plugin interface.

Ref. from Boost.DLL

Be careful: creator variable holds a reference to the loaded shared library. If this variable goes out of scope or will be reset, then the DLL/DSO will be unloaded and any attempt to dereference the plugin variable will lead to undefined behavior.

Boost.Dll可以在在不同平台上动态加载的插件库文件;而Qt提供了QPluginLoader用于加载插件。

在SALOME中,启动器suitexe调用不同应用对应的动态链接库内的createApplication()来生成不同的SUIT_Application对象;

SUIT_Application* createApplication();

而CAM_Application(间接派生于SUIT_Application)则会通过调用不同Module对应的动态连接库内的createModule函数来创建不同CAM_Module对象。

CAM_Module* createModule();

关于SALOME此部分内容的讲解,可参见笔者博文:SALOME源码分析:GUI模块 。

在FreeCAD中,Moduel加载是通过运行InitGui.py实现的,InitGui.py会创建一个Workbench对象,该Workbench的GetClassName()成员函数则指定了对应的C++ Workbench的名称,进而通过FreeCAD类型系统来创建对应的C++ Workbench对象。

关于FreeCAD此部分内容讲解,可参见笔者博文: FreeCAD源码分析:FreeCADGui模块 。

注:相对于SALOME,FreeCAD采用了Layered Architecture,大部分模块都分成了App(业务逻辑)与Gui(显示逻辑)两层,但是FreeCAD仅对Gui层(也就是InitGui.py)做了接口约束,对于App层(也就是Init.py)并没有接口约束。

class PartWorkbench ( Workbench )   def GetClassName(self):return "PartGui::Workbench"Gui.addWorkbench(PartWorkbench())

CTK (The Common Toolkit)是一款生物医疗成像开源代码,基于OSGi规范实现了一套插件框架,非常值得研究。

 结合前述分析,可以总结出插件系统开发的技术实现要点。

实现要点:

  • Plugin类定义接口,每个动态链接库定义一个单独的Plugin子类;
  • PluginManager依据指定的动态链接库路径加载插件;
  • PluginManager创建插件对象,并调用Plugin::initialize()完成类型注册等初始化工作;
  • 软件主体通过插件对象(类型系统/反射机制)来创建业务对象,完成具体的业务逻辑处理;
  • 插件使用完毕,调用Plugin::cleanup(),PluginManager负责销毁插件对象,并卸载插件。

十一、接口扩展

CAx核心代码大多采用C/C++编写。

接口扩展需要结合行业习惯应用场景软件技术栈等因素,选择合适的脚本语言。这样不仅可以降低用户使用软件的门槛与成本,而且可以通过复用现有软件技术栈来提升软件开发的效率与应用范围。目前比较流行的脚本编程语言有:PythonJavaScriptMatlab等。

脚本语言 开发引擎 应用
Python CPython, Boost.Python, PyCXX FreeCAD, SALOME, QGIS
JavaScript QCAD
Matlab Octave, Rlab 光学, 电磁

十二、 基于Web的CAx协同仿真系统

分布式计算(Distributed Computing,又称分散计算)是利用网络大量计算资源连接起来以解决大型计算问题的一种计算科学。分布式计算研究主要集中在分布式操作系统分布式计算环境等两个方面。主流的分布式计算技术包括中间件技术网格技术移动Agent技术P2P技术Web Service技术等。

近十年来,国家也建立了天津、济南、郑州、无锡、昆山、广州、深圳、长沙、成都等八大超算中心。随着高性能计算特别是超级计算平台的兴起,CAx软件正逐渐由桌面系统逐渐向基于云计算平台的网络应用进行转变;另一方面,CAx所求解的问题规模与学科复杂性愈加复杂,传统的桌面CAx系统已经很难胜任。因此,将CAx技术与云计算技术结合起来形成CAx协同仿真系统必将是下一代CAx软件研发的一个重要方向

鉴于目前的形势,CAx软件在设计之初就应当考虑云计算赋能的问题,因此,需要对目前云计算平台的软硬件情况做深入的研究,为前期软件系统设计技术选型等提供依据。

关于HPC集群架设相关的技术,笔者在前面的博文中,已经以此进行了论述。

参见:部署HPC集群的实施方案

超算中心大都基于Linux操作系统或者其衍生版本,其中又以CentOS系统居多,大都提供Web登录、VPN SSH登录等访问方式。济南超算中心山河计算平台提供了Web Services、SDK、CLI等三种开发接口。

单从CAx软件研发来看,基于云计算的CAx软件开发至少会涉及到远程登录、文件/数据传输、命令执行、作业管理等功能模块。

基于B/S架构的CAx软件研发,在实时性等方面还存在一些技术难点;基于C/S架构方案中,缺少专门的CAx软件通信协议。

近几年,以虚拟化、云计算等技术为基础的云桌面逐渐兴起,这或许为发展基于云计算的CAx软件提供了可行性。

编程技术 开发框架
前端 HTML, CSS, JavaScript jQuery, Angular, React, Vue
后端 PHP, Java, Ptyhon Django

考虑到目前的Web前后端开发技术栈的情况,可将CAx C/C++代码进行Python封装,然后借助于Python Web应用开发框架完成Web版CAx软件的开发


Verification:QGIS


Prototype:CAx软件开发框架Acise


附录:FAQ


参考文献

Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides. Design Patterns:elements of reusable object-oriented software. Addison Wesley, 1994.

Martin Fowler. Patterns of Enterprise Application Architecture.  Addison Wesley, 2002.

Robert C. Martin. Clean Architecture: A Craftsman's Guide to Software Structure and Design. Prentice Hall, 2017.

Joseph Ingeno. Handbook of Software Architecture.

EURIWARE. SALOME GUI Architecture. 2010.

Mike Potel. MVP: Model-View-Presenter  The Taligent Programming Model for C++ and Java. 1996.

Bower A ,  Mcglashan B . TWISTING THE TRIAD.

Daveed Vandevoorde. Plugins in C++. 2006.

游俊慧.MVC、MVP、MVVM三种架构模式的对比[J].办公自动化,2020,25(22):11-12+27.

网络资源

FreeCADhttps://www.freecadweb.org/

FreeCAD源码分析:FreeCADGui模块https://blog.csdn.net/qq_26221775/article/details/113898970?spm=1001.2014.3001.5502
SALOMEhttps://www.salome-platform.org/

SALOME GUI Architecturehttps://docs.salome-platform.org/latest/extra/SALOME_GUI_Architecture.pdf

SALOME - CMake build procedurehttps://docs.salome-platform.org/latest/dev/cmake/html/index.html

Salome JobManagerhttps://github.com/FedoraScientific/salome-jobmanager

SALOME源码分析:GUI模块https://blog.csdn.net/qq_26221775/article/details/127759145?spm=1001.2014.3001.5502

QGIShttps://qgis.org/en/site/

QCADhttps://qcad.org/en/

Mayohttps://github.com/fougue/mayo/tree/v0.5.2

CMakeQthttps://github.com/bhaisaab/cmakeqt

GUI Architectureshttps://martinfowler.com/eaaDev/uiArchs.html

MVChttps://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

The PureMVC Frameworkhttp://puremvc.org/

Qt Model/View Programminghttps://doc.qt.io/qt-6/model-view-programming.html

Cliff Hall. PureMVC Implementation Idioms and Best Practices.http://puremvc.org/docs/PureMVC_IIBP_English.pdf

MVPhttps://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter

MVVMhttps://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel

QtMvvmhttps://skycoder42.github.io/QtMvvm/

GitHub Googlehttps://github.com/google

GItHub Apachehttps://github.com/apache

QMessageLoggerhttps://doc.qt.io/qt-6/qmessagelogger.html

Boost.Log v2https://www.boost.org/doc/libs/1_79_0/libs/log/doc/html/index.html

Wikipedia: Run-time type informationhttps://en.wikipedia.org/wiki/Run-time_type_information

Wikipedia: Reflection programminghttps://en.wikipedia.org/wiki/Reflective_programming

OpenC++https://opencxx.sourceforge.net/

typeid operatorhttps://en.cppreference.com/w/cpp/language/typeid

Boost.TypeIndexhttps://www.boost.org/doc/libs/master/doc/html/boost_typeindex.html

Boost UUIDhttps://www.boost.org/doc/libs/1_79_0/libs/uuid/doc/uuid.html

The Meta-Object Systemhttps://doc.qt.io/qt-6/metaobjects.html

Property Systemhttps://doc.qt.io/qt-5/properties.html

Object Modelhttps://doc.qt.io/qt-6/object.html

Boost Serializationhttps://www.boost.org/doc/libs/1_79_0/libs/serialization/doc/index.html

Boost Preprocessorshttps://www.boost.org/doc/libs/1_79_0/libs/preprocessor/doc/index.html

RTTRhttps://www.rttr.org

Mick West. Evolve Your Hierarchyhttps://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

Building Your Own Plugin Framework: Part 1https://drdobbs.com/cpp/building-your-own-plugin-framework-part/204202899

Building Your Own Plugin Framework: Part 1https://drdobbs.com/cpp/building-your-own-plugin-framework-part/204702751?pgno=1

CTK- The Common Toolkithttp://www.commontk.org/index.php/Main_Pag

Boost.Dllhttps://www.boost.org/doc/libs/master/doc/html/boost_dll.html

How to Create Qt Pluginshttps://doc.qt.io/qt-5/plugins-howto.html

Extending and Embedding the Python Interpreterhttps://docs.python.org/3/extending/index.htmlBoost.Pythonhttps://www.boost.org/doc/libs/1_80_0/libs/python/doc/html/index.html
PyCXXhttp://cxx.sourceforge.net/

Octavehttp://www.octave.org/

Rlabhttp://rlab.sourceforge.net/

SWIGhttps://www.swig.org/

Service Architecturehttps://www.service-architecture.com/

curlhttps://curl.se/

国家超级计算济南中心https://www.nsccjn.cn/
libsshhttps://www.libssh.org/libssh2https://www.libssh2.org/

OpenSSHhttps://www.openssh.com/

CORBAhttps://www.corba.org/

gSOAPhttps://www.genivia.com/products.html

Slurmhttps://slurm.schedmd.com/

B/S 架构软件:Web APP开发的技术框架和一体化解决方案https://zhuanlan.zhihu.com/p/466965226?utm_id=0&utm_source=wechat_session&utm_medium=social&s_r=0

大型CAx(CAD/CAE/CAM)工业软件开发中的关键组件相关推荐

  1. 关于 C3P (CAD/CAE/CAM PIM) 的简单介绍

    C3P 是福特汽车开发的一套用于整车研发的系统,通过推广到零配件供应商,将会优化供应链的产品设计.制造能力. 随着全球化竞争的日益加剧,世界发达国家的汽车产业发生了新的变化,汽车零部件产业也呈现出一些 ...

  2. 大型软件开发中的流程与规范

    对于长生命周期的大型软件,流程和规范十分必要.IT行业作为一个快节奏的行业,不光技术革新快,人员的更替也是很快的,没有严格的规范和流程,几个大版本迭代下来,可能产品的代码就维护不下去了. 估计很多大厂 ...

  3. 计算机技术在塑料模具中的应用,浅谈CAD/CAE技术在塑料模具中的应用

    裴焕龙 [摘 要]近些年来,随着计算机科学技术的发展,在许多领域都发挥了巨大的作用,计算机辅助设计(CAD)以及计算机辅助分析(CAE)是我们在工业模具制造的过程中常用的计算机技术,能够有效的保证模具 ...

  4. STL文件在医学软件开发中的应用

    本文由Markdown语法编辑器编辑完成. 1. 什么是STL文件? STL(Stereolithography,光固化立体造型术的缩写)文件格式,是由3D SYSTEMS公司于1998年制定的一个接 ...

  5. 软件开发重要性_在软件开发中考虑时间的重要性

    软件开发重要性 by Crunch Tech 通过Crunch Tech 在软件开发中考虑时间的重要性 (The importance of time to think in Software Dev ...

  6. 论软件开发中的可信赖的工作

    中大型软件开发,免不了团队开发,团队开发就少不了分工合作.在团队开发中,当然每个人的能力都很重要,但是我认为可信赖的工作是团队开发的首要条件,也是团队开发存在的基本保证.没有可信赖的工作,就没有团队分 ...

  7. 建模语言UML在软件开发中的应用

      建模语言 UML 在软件开发中的应用 摘要:UML( Unified Modeling Language)是建立系统模型和分析业务处理流程强有力的工具,它能够帮助软件开发人员从不同角度描述系统,使 ...

  8. 【软件测试】稳定性和可靠性测试在软件开发中的重要性

    软件测试的某些方面经常会在那些刚接触流程的人中造成混淆--例如在稳定性和可靠性测试之间划清界限.两者通常可以互换使用,并且有一个共同的目标,即确保系统可以在选定的时间范围内稳定运行. 在这篇文章中,我 ...

  9. 软件开发中会使用到的图

    文章目录 软件开发中会用到的图 一.背景 二.图为了解决什么问题 三.不同流程中适合运用的图 四.实际的运用 五.结语 软件工程中的各种图 软件工程用的15种图 数据关系流图怎么画?这款软件教你轻松绘 ...

最新文章

  1. 食堂就餐刷卡系统源码_智慧食堂重新定义你的食堂管理系统
  2. py3提取json指定内容_python3 取页面指定数据(json)
  3. linux 路由器去广告,linux – 如何正确发送路由器广告?
  4. onmouseover和onmouseout在GridView中应用
  5. 多波次导弹发射中的规划问题(一) 网络图绘制及数据整理
  6. 黑马程序员-面向对象-06天-3(static-静态代码块)
  7. 查询时注意 查询字段传值参数类型,尽量和数据库字段类型一致
  8. 使用libsvm实现归一化
  9. 【theano-windows】学习笔记九——softmax手写数字分类
  10. 给数据库表字段设置默认值
  11. python 跳过计算错误_在python中计算分数时如何跳过被0除的错误?
  12. 商用工程开发中的一些习惯
  13. Java自学之路(新手一定要看)
  14. IT基础架构变革,Hitachi Vantara如何解决超融合(HCI)的真正痛点?
  15. es 创建索引 指定id_简单操作elasticsearch(es版本7.6)
  16. 小小的天地 大大的梦想
  17. 实现sqlite datediff日期时间相减(日期差)的方法
  18. 《别用面包钓鲔鱼》--读书流水账no3
  19. c++动态规划解决一系列数中互不相邻数字之和的最大值
  20. 线性代数-向量,矩阵,线性变换

热门文章

  1. comsenzexp php5.3,ComsenzEXP Discuz集成PHP环境
  2. Flume Sink
  3. Ubuntu 使用play命令播放音乐 mp3 wav 等文件
  4. Runtime 隐藏Status Bar背景
  5. 字体、图标字体、行高、文本样式(css)
  6. LaTex插入图片的几种常用的详细方法
  7. num(num-1)的用途
  8. android反编译工具jadx卡死解决方案。
  9. sklearn中常见的线性模型参数释义
  10. istio功能介绍(二.Istio使用说明)