caxa公司的cad软件产品_工业软件开发

caxa公司的cad软件产品_工业软件开发通过对FreeCAD、SALOME等多款代码的分析研究,发现这些软件在架构设计、模块实现等方面,存在许多相似(同)的技术思想

壹、技术篇

 通过对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:文章内容会不定期更新。

零、形势、对策、原则

一、工程组织

Fielding博士在其博士论文中提到,软件结构不一定要要与软件架构保持一致。

Ref. from Architectural Styles and the Design of Network-based Software Architectures

This raises an important distinction between software architecture and what is typically referred to as software structure: the former is an abstraction of the run-time behavior of a software system, whereas the latter is a property of the static software source code. Although there are advantages to having the modular structure of the source code match the decomposition of behavior within a running system, there are also advantages to having independent software components be implemented using parts of the same code (e.g., shared libraries). We separate the view of software architecture from that of the source code in order to focus on the software’s run-time characteristics independent of a given component’s implementation. Therefore, architectural design and source code structural design, though closely related, are separate design activities. Unfortunately, some descriptions of software architecture fail to make this distinction.

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

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

Ref. from Mastring CMake.

Variables in CMake have a scope that is a little different from most languages. When you set a variable it is visible to the current CMakeLists fileor function, as well as any subdirector’s CMakeLists files, any functions or macros that are invoked, and any files that are included using the INCLUDE command. When a new subdirectory is processed(or a function called) a new variable scope is created and initialized with the current value of all variables in the calling scope. Any new variables created in the child scope, or changed made to existing variables, will no impact the parent scope.

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提出的一种客户端软件设计框架,主要用于实现数据/逻辑/界面的分离

caxa公司的cad软件产品_工业软件开发

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. 

caxa公司的cad软件产品_工业软件开发

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等设计模式。

caxa公司的cad软件产品_工业软件开发
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.

caxa公司的cad软件产品_工业软件开发

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.

Unlike the Model-View-Controller pattern, the model/view design does not include a completely separate component for managing interaction with the user. Generally, the view is responsible for the presentation of model data to the user, and for processing user input. To allow some flexibility in the way this input is obtained, the interaction is performed by delegates. These components provide input capabilities and are also responsible for rendering individual items in some views. 

在文档/视图框架中,将每一条数据抽象成一个数据项(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.

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

caxa公司的cad软件产品_工业软件开发

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

caxa公司的cad软件产品_工业软件开发

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.

caxa公司的cad软件产品_工业软件开发

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完全隔离自动同步

caxa公司的cad软件产品_工业软件开发

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

caxa公司的cad软件产品_工业软件开发

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模块提供了非常完善、强大的对象串行化功能。

七、命令系统

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

caxa公司的cad软件产品_工业软件开发

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

Presentation logic 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 client to 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 source logic 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.

caxa公司的cad软件产品_工业软件开发

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

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

借助于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 extends QAction 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 objects that 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++编写。

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

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

十二、打包与部署

十三、 软件上云:基于Cloud的CAx协同仿真系统

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

随着高性能计算特别是超级计算平台的兴起,CAx软件正逐渐由桌面系统逐渐向基于云平台的网络应用进行转变;另一方面,CAx所求解的问题规模与学科复杂性愈加复杂,传统的桌面CAx系统已经很难胜任。因此,将CAx技术与云技术结合起来形成CAx协同仿真系统必将是下一代CAx软件研发的一个重要方向

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

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

  • 云桌面CAx软件

近几年,以虚拟化、云计算等技术为基础的云桌面逐渐兴起。云桌面实际上就是一种桌面软件上云的解决方案。

  • Web版CAx软件
编程技术 开发框架
前端 HTML, CSS, JavaScript jQuery, Angular, React, Vue
后端 PHP, Java, Ptyhon Django
  • 云原生

CAx应用程序从设计之初就要考虑到云的环境,原生为云而设计。

caxa公司的cad软件产品_工业软件开发

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.

Joseph Ingeno. Handbook of Software Architecture. 

Roy T. Fielding. Architectural Styles and the Design of Network-based Software Architectures. 2000.

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.

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. 

John K. Ousterhout. Scripting: Higher Level Programming for the 21st Century. IEEE Computer magazine, March 1998.

网络资源

FreeCADhttps://www.freecadweb.org/

大型CAx(CAD/CAE/CAM)工业软件开发中的关键组件
SALOMEhttps://www.salome-platform.org/

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

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

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

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

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

QCAD https://qcad.org/en/

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

Qt: Build with CMakehttps://doc.qt.io/qt-5/cmake-manual.html

CMakeQthttps://github.com/bhaisaab/cmakeqt

GUI Architectures https://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

MVVM https://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

QMessageLogger https://doc.qt.io/qt-6/qmessagelogger.html

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

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

Wikipedia: Reflection programming https://en.wikipedia.org/wiki/Reflective_programming

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

typeid operator https://en.cppreference.com/w/cpp/language/typeid

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

Boost UUID https://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 System https://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 Preprocessors https://www.boost.org/doc/libs/1_79_0/libs/preprocessor/doc/index.html

RTTR https://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/

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

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

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

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

Extending and Embedding the Python Interpreterhttps://docs.python.org/3/extending/index.html Boost.Pythonhttps://www.boost.org/doc/libs/1_80_0/libs/python/doc/html/index.htmlSHOGUNhttps://github.com/shogun-toolbox/shogun.git

OpenAPIhttps://www.openapis.org/GitHub:  OpenAPI Generatorhttps://github.com/OpenAPITools/openapi-generator

Qt Scripthttps://doc.qt.io/qt-5/qtscript-index.html

ECMAScript® 2022 language specificationhttps://www.ecma-international.org/publications-and-standards/standards/ecma-262/

Octavehttp://www.octave.org/

Rlabhttp://rlab.sourceforge.net/

SWIG https://www.swig.org/

Service Architecture https://www.service-architecture.com/

curl https://curl.se/

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

 OpenSSHhttps://www.openssh.com/

CORBA https://www.corba.org/

gSOAP https://www.genivia.com/products.html

Slurmhttps://slurm.schedmd.com/

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

Dockerhttps://www.docker.com/

Kuberneteshttps://kubernetes.io/


贰、团队篇


叁、市场篇 

We constantly put ourselves in the shoes of our customer, the developer. We seek their feedback and, by understanding their needs, we build solutions that they love. Every decision we make, big or small, starts with the customer in mind. We drive simplicity. We focus on innovation and great design in order to create a sense of “magic” for everyone of them. — Docker Virtues 

参考文献

罗利民. 从Docker到Kubernetes入门与实战.  清华大学出版社, 2019.

 网络资源

Dockerhttps://www.docker.com/

今天的文章
caxa公司的cad软件产品_工业软件开发分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/80231.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注