PowerBuilder编程新思维10.5:外传2(PowerPlume下一代开发解决方案)
万里归来年愈少
PB编程新思维10.5:外传2(PowerPlume下一代解决方案)
前言
今天我们就来盘点一下,PB下一代开发的所有技术可能性。所谓下一代开发技术,就是指脱离或半脱离PBVM的应用开发技术,主要指后端。
后端技术汇总
| 前端PB+JSON | 前端PB+BLOB | WEB | |
| 后端PBVM | PbNode/Pbgo | PbniServ,PowerServer | PbNode |
| 后端无代码 | GraphQL | SatRDA/VDN | 无 |
| PB转浏览器 | PbXds | VDN | PbXds |
| PB转C# | PowerServer | PowerServer | PowerServer |
| 其它后端方案 | PbPdd | EXTPB.NET | SatWeb |
SatRDA
SatRDA是远程数据访问组件,使用它无需要改动原来的数据访问代码就可以支持外网访问远程数据库。
评价:商用方案(由「成都Only」提供)。
SatWeb
SatWeb是远程数据访问组件的Web版,使用它可以远程访问DW(纯Web方案H5DW)。
评价:商用方案(由「成都Only」提供)。这是最接近PowerPlume的方案,包括SatReport都非常好。
VDN
通过Web组件实现PB程序的浏览器运行,不用修改主程序代码,瞬间实现类似B/S的效果。
评价:商用方案(由「烟台沃森」提供)。
EXTPB.NET
基于.Net开发,采用PBNI和ActiveX技术实现PB程序的浏览器运行,充分利用了DataWindow控件的功能。
评价:商用方案(由「广州同享」提供)。黄总在群里说会在H5上发力,期待有突破性进展。
PBNIServ
It uses the PBNI to execute functions within a non-visual userobject.
评价:商用方案(由「Topwiz」提供)。
PowerServer
官方的方案。
评价:商用方案(由「appeon」提供)。
GraphQL
利用GraphQL框架搭建后端。
评价:开源方案。不成熟,PB程序转换跨度大,可行性低
PbGo
是一套PB开发Web服务的后端框架(基于golang的PBNI扩展),可以做为静态站点服务器,支持 RESTful 风格API。
评价:开源/商用方案(由「杭州-夕木双」提供)。
PbNode
Node.js环境插件,可以调用PB代码,返回Web或JSON。
最初的尝试,源码放在群里面了。单纯地在服务器运行一些PB代码,已经有相当多的产品支持了。再做一个没有什么质的提升。
评价:开源方案(由「PowerPlume」提供)。性能堪忧,PB程序转换成本高,可行性低
PbPdd
利用多线程访问PBVM,返回JSON,可以做三层服务器,算是前端多线程的后端应用。
评价:商用方案(由「PowerPlume」提供)。PB转换成本较小,性能受限,可行性高
PbXds
PB下一代开发解决方案(neXt-generation Development Solution),分成四个部分
- PbXtc 下一代Trans Compiler编译器(golang/js)
- PbXdw 下一代DataWindow(js)
- PbXrt 下一代虚拟机接口运行时(c/js)
- PbXsf 下一代Service运行框架(golang)
利用PbXtc编译器,将PB程序整体转换为js前端应用。程序也可以在后端(golang)运行,甚至还能在手机上运行。
评价:商用方案(由「PowerPlume」提供)。PB转换成本较小,但功能复杂,可行性中
技术分析
PbXdw 分析
PbXdw是前端的核心代码,成都Only的SatWeb已经有成品发布了,同我的思路还是有区别的
PbXdw的目标是能像素级兼容,在打印时无需调整。要严丝合缝,这个工作量比较多。
PbXsf 分析
PbXsf 是后端的核心代码,就是不调用PBVM的情况下,支持数据的增删改查。静态解析PBL,生成可运行的后端代码。首先它要解析PBL,继而解析DW,再连接数据库,最后启动Web服务。有了PbXsf ,我们就可以把DW变成三层架构,可以在互联网访问。
PbXrt 分析
PbXrt是前后端共用的PBVM功能API接口,分成前端和后端两个部分。前端用JS语言,后端用C语言。
PbXtc 分析
PbXts,将Pb程序编译为Js。
在网上看过关于正阳的传闻,他们可能是第一个做非官方编译器的开发者,可惜还是失败了。说起来,也是生不逢时,在06年搞纯JS前端实在太困难了。现在,在无数前端开源项目的铺垫下,难度降低太多。有了前车之鉴,成功就有可能了。

Q: APB是一个什么产品?
A: APB 是 Appeon for PowerBuilder 的缩写。
Appeon 公司专注于实现 C/S 架构的 PowerBuilder 应用迁移到 B/S 架构的完整解决方案。Appeon for PowerBuilder 是这个解决方案的核心,是一套平台型软件产品。 Q: PB转换后的程序是Java代码或JSP吗?
A: 转换后的文件格式包括: HTML 、 XML 、 JavaScript 、 Image 文件。不是 Java 代码,也不是 JSP 。 Q: 用APB转换后的Web应用和JSP开发的Web应用,技术上有什么区别?
A: APB 在客户端使用的是 ActiveX 技术,服务器端使用的是 J2EE 技术,包括 Servlet 、 EJB 、 JDBC 。 APB 综合使用了 ActiveX 技术和 J2EE 技术。
JSP 则主要是服务器端的技术,给客户端传来的是 HTML 标记的文档,用于表现用户界面。对于一些要求复杂用户交互的应用,用 JSP 实现起来很困难。 Q: 前后台数据是XML传递的吗,可否在其它JSP程序中使用这些XML数据?
A: 前后台之间数据传递是二进制格式。前后台的调用和数据传输都是基于 http 的 RPC 。调用格式和传输的数据都是二进制的。这样做主要是出于安全和性能的考虑。
APB 早期的技术里,曾采用过 XML 来传输数据,但由于 XML 的解析和装配需要一定的时间,会影响运行的速度。 Q: 现有控件是用Javascript实现的吗?
A: PB 中的控件,如 DataWindow 、 Treeview 、 Tab 等都是用 ATL 技术实现的, Javascript 难以实现这么复杂的控件。还有如 Blob 的类型, JavaScript 也难以实现。 Q: 为什么要采用IE插件的技术?不要插件行吗?
A: 使用 ActiveX 插件是为了最大程度上,支持 PowerBuilder 的各种控件、对象和功能特性。例如 Datawindow 控件、 TreeView 控件、 Dragdrop 等。这些功能在一般的 Web 应用中很难实现。
APB 在迁移 Web 应用时,具有两种发布方式,一种是 AX 方式,也就是插件的方式,可以支持 PB 中各种复杂的控件和对象。另一种方式是 JS 方式,也就是纯 JavaScript 方式,这种方式只能支持有限的 PowerBuilder 特性。 Q: ActiveX插件有多大,会不会每次都下载?
A: Appeon 的插件有点类似于我们常见的 IE 的 Flash 插件。大约 1M 左右的 Cab 包。 IE 会自动下载,并且只是在头一次使用的时候去下载。多个 Appeon Web 应用会使用一个插件,不会去下载多个插件,除非其版本不一样。 Q: 为什么需要架构调整和性能优化?
A: 我们用 Powerbuilder 开发的应用一般是两层应用,也就是 C/S 架构应用。绝大部分代码都是在客户端实现的,用户界面和业务逻辑基本上是交织在一起。
APB 目前主要是实现语言的自动翻译工作,也就是 PowerScript 语言到 JavaScript 语言的翻译,还不能自动分离用户界面和业务逻辑相关的代码。 因此,翻译后的应用如果要运行在 Internet 上,或者低带宽网络环境下,一般还需要进行一些手工调整,将数据存取密集代码和业务逻辑代码转移到数据库服务器或者应用服务器上。这就是所谓的对 APB Web 应用的架构调整和性能优化。
需要说明的一点是,如果翻译后的应用运行在带宽很好的网络环境中,例如带宽 10/100M 的企业网里,可以不做或只做少量的架构调整和性能优化工作。
正阳APB问答
相比APB无奈选择的JavaScript/ActiveX/Blob/J2ee技术栈 ,今天选择JavaScript/React/Json/REST技术栈就顺理成章多了。
为了能够清楚地认识PowerBuilder语法,我专门写了一个包含所有语法的过程:数鸭子

1 public function integer of_count_ducks (string as_ducks) throws exception;
2 /* for testing of PowerPlume Ps2Js.exe
3 usage: f_count_ducks("黄鸭子,黑鸭子,白鸭子,黄鸭子,麻鸭子,灰鸭子,小黄鸭,唐老鸭,盐水鸭,南京鸭")
4
5 本过程包括所有PowerScript语法,是编译器开发的the quick brown fox jumps over a lazy dog。
6 */
7
8 call nonvisualobject::constructor
9 if super::classname() <> "n_count_ducks" then messagebox("提示", "final类不能被继承")
10
11 n_count_ducks nvo_test; nvo_test = create n_count_ducks
12
13 string ls_info = "门前大桥下,游过一群鸭,快来快来数一数,"
14
15 string errors_arr[7] = { "warn1:灰鸭子已废弃,请使用麻鸭子","warn2:小黄鸭的规范写法为黄鸭子","err3:唐老鸭已终止授权",&
16 "err4:不得使用死鸭","err5:南京鸭必须死", "err6:鸭子的数量应不小于八只", "err7:远程调用未知错误"}
17
18 string numbers_arr[1 to 8] = {'', '二', '', '四', '', '六', '七', '八'}
19
20 string ducks_arr[16, 2], as_ret
21
22 blob{255} data
23 integer color
24
25 int counter=0, index=0, li_begin=1, li_current=1
26 do
27 try
28 li_begin = li_current
29 data=blob(as_ducks, EncodingUTF8!)
30 //Remote Procedure Call
31 color = nvo_test.static trigger function of_get_instance().of_get_duck(data, li_current);
32 catch(exception e)
33 color = 7
34 finally
35 index ++
36 end try
37
38 choose case color
39 case -1, -2, -3, -4
40 ducks_arr[index, 1]=mid(as_ducks, li_begin, li_current - li_begin -1)
41 ducks_arr[index, 2]=""
42 case 9
43 goto hack ;// 被攻击暗号
44 case 1 to 2
45 ducks_arr[index, 1]=mid(as_ducks, li_begin, li_current - li_begin -1)
46 ducks_arr[index, 2]=errors_arr[color]
47 case 3 to 5
48 ducks_arr[index, 1]=""
49 ducks_arr[index, 2]=errors_arr[color]
50 continue
51 case 6
52 ducks_arr[index, 1]=""
53 ducks_arr[index, 2]=errors_arr[color]
54 exit //数量小于8
55 case is >= 7
56 ducks_arr[index, 1]=""
57 ducks_arr[index, 2]=errors_arr[color]
58 exit
59 case else
60 goto error
61 end choose
62 counter ++
63 loop while (counter < 8 and index < 16)
64
65 int i = 1, j = 1
66 int li_warns=0, li_errors=0
67 string ls_ducks = ""
68 do until (j > counter)
69 if (ducks_arr[i, 1]="") then
70 li_errors ++
71 elseif (ducks_arr[i, 2]="") then
72 ls_info += numbers_arr[j]
73 ls_ducks += ducks_arr[i, 1] + " "
74 j++
75 else
76 ls_info += numbers_arr[j]
77 ls_ducks += ducks_arr[i, 1] + "* "
78 j++
79 li_warns ++
80 end if
81 i ++
82 loop
83
84 ls_info += ":~r~n"+ls_ducks+"~r~n警告:"+ string(li_warns) +"~t错误:" + string(li_errors) + "。~r~n"
85
86 for i = 1 to 16
87 if (ducks_arr[i, 2]<>"") then
88 ls_info += ducks_arr[i, 2]
89 ls_info += ";~r~n"
90 end if
91 next
92
93 date ld_begin, ld_today
94 time lt_begin, lt_now
95
96 ld_begin=date("2021-4-14") //求日期值的写法
97 lt_begin=19:18:01
98 ld_today = today()
99 lt_now = now()
100
101 longlong seconds
102 Seconds= daysafter(ld_begin, ld_today)*86400 + SecondsAfter(lt_begin, lt_now)
103 ls_info += "数鸭子代码已发布:"+string(seconds)+"秒。"
104 messagebox("数鸭子过程包含所有PowerScript语法", ls_info)
105
106 destroy nvo_test
107 return counter
108
109 hack:
110 halt close
111
112 error:
113 destroy nvo_test
114 throw create exception
115
116 end function
PowerBuilder语法大家都熟悉,JavaScript实际上是语法上最接近PB的语言了,毕竟都是90年代的产品,理念也差不多。
至于类与继承,也很像,PB是不支持构造函数的,就是单纯的克隆。JS实际上也是一样,通过原型克隆产生的原型链控制继承。
PbXtc(包括PbXrt)开发计划:
分为六个阶段来开发
V0.1.x 编译函数为JS代码片断
V0.2.x 编译窗口为JSX界面代码片断
V0.3.x 编译数据窗口为DataWeb代码片断
V0.4.x 编译数据库访问为Rest访问
V0.5.x 编译事件驱动的完整应用
V0.6.x 编译其它外部代码
一般问题解答:
1、转换后,界面的一致性
答:转换时会有选项:严格一致,数据窗口一致,有限弹性,完全弹性四种,一致性由大到小。
2、转换后,本地DLL接口,ocx控件如何处理
答:完全可以兼容,会在本地运行一个微型Web服务,以Rest接口的形式供Web应用调用。
3、是否需要开发配套后端
答:转换时会有选项:完全前端,安全性前端,微前端三种,自动生成的后端代码由少到多,无需开发。
技术升级
上面这个版本的PbXds最终被否定了,所有代码都推倒重来。
原因是我在开发过程中,一直对这个方案不太满意,主要问题是前端太过Web化,还需要维护JS/GO两个框架。
最终我找到了一条完全后端化的道路,具体内容详见《PowerBuilder现代编程方法X11:PB程序完全跨平台方案》
<本节完>
PowerBuilder编程新思维10.5:外传2(PowerPlume下一代开发解决方案)的更多相关文章
- PowerBuilder编程新思维5:包装(界面美化与WebUI+React)
PowerBuilder编程新思维5:包装(界面美化与WebUI+React) 前一节,分析了三种界面美化方案,都是控件级的美化.今天再来分析一下窗口级的美化.上一次讲的DirectUI,大家反响一般 ...
- PowerBuilder编程新思维4:钩挂(界面美化与DirectUI)
<第二部分 Outside> PowerBuilder编程新思维4:钩挂(界面美化与DirectUI) PB的界面由于其封闭性,一直以来都是最大的弱项.自PB9.0开放了PBNI接口后,开 ...
- PowerBuilder编程新思维3:适配(三层架构与GraphQL)
PowerBuilder编程新思维3:适配(三层架构与GraphQL) PB在富客户端时代,是一线开发工具.随着网络发展,主流架构演进到三层架构的时代,PB拿不出有力的三层架构,已经明显力不从心,市场 ...
- PowerBuilder编程新思维2:嵌入(Thread多线程)
PowerBuilder编程新思维2:嵌入(Thread多线程) 在PB中使用多线程,在网上有大量的文章介绍.不过深入研究并试着给出更易用的模型的,目前还只有"路人甲cw"的一篇& ...
- PowerBuilder编程新思维1:扩展(Lua)
前言 PowerBuilder作为开发工具退出一线行列已经很久了,在2019年来谈这样一款老旧的编程工具是否有意义?诚然,PB有着太多硬伤,但还是有它的用武之地的.而且今天讲的这个“新思维”大部分内容 ...
- C++编程新思维中的技巧
1.编译器断言 技巧大致跟后面的一样,都是利用偏特化,但是在C++ 0X里面已经有static_assert,所以感觉这东西也没什么用处了,更多的只是开阔眼界 2.偏特化 就是专门对一个类型去进行特殊 ...
- 【响应式编程的思维艺术】 (2)响应式Vs面向对象
目录 一. 划重点 二. 面向对象编程实例 2.1 动画的基本编程范式 2.2 参考代码 2.3 小结 三. 响应式编程实现 四. 差异对比 4.1 编程理念差异 4.2 编程体验差异 4.3 数学思 ...
- 《C++设计新思维》Command设计模式读后感
原文内容提领: 本书第5章标题为泛化仿函数,我认为本章真正讲述的内容可以总结出一句话! 如何利用C++老标准实现C++11新标准类似std::function提供的功能. std::function简 ...
- 《C++设计新思维》勘误,附C++14新解法
勘误: 原书(中文版)3.13节,65-69页中GenScatterHierarchy以及FieldHelper均存在问题,当TypeList中类型有重复时,无法通过编译(原因在于“二义性基类”). ...
- 郑晔谈 Java 开发:新工具、新框架、新思维【转载】【整理】
原文地址 导语:"我很惊讶地发现,现在许多程序员讨论的内容几乎和我十多年前刚开始做 Java 时几乎完全一样.要知道,我们生存的这个行业号称是变化飞快的.其实,这十几年时间,在开发领域已经有 ...
随机推荐
- java学习之旅(day.18)
网络编程 概述 计算机网络:自己百度吧 网络编程的目的:传播交流信息.数据交换.通信 想要达到这个效果需要什么: 如何准确的定位网络上的一台主机 端口 定位到这个计算机上的某个资源 找到了这个主机,如 ...
- 各大插件市场智能助手评分榜出炉!百度Comate稳居第一
近日,在VSCode.Jetbrains等各大插件市场智能助手评分榜中,百度Comate分别以4.5和4.4位列第一,通义灵码位居第二.第三,CodeGeeX.iFlyCode.aiXcoder.Gi ...
- Java RMI遇到的Connection refused to Host: 127.x.x.x/192.x.x.x/10.x.x.x问题解决方法
问题故障解决记录 -- Java RMI Connection refused to host: x.x.x.x .... 在学习JavaRMI时,我遇到了以下情况 问题原因:可能大家的host是10 ...
- cmder右键打开方式
第一步: 新打开一个cmder窗口 第二步: 输入: Cmder.exe /register user 或 Cmder.exe /register all 第三步: 回车执行命令
- 用Vue全家桶纯手工搓了一个开源版「抖音」
前言 2018年刚入行前端时,公司使用的还是Angular.Angular什么都好,就是写代码时的体验老糟心了,改一个地方,按下保存之后,要等好几秒刷新后才能看到效果,Webstorm无比好用的自动保 ...
- mac http&git代理配置
git代理清除git config --global --unset http.proxygit config --global --unset https.proxy 输出代理:$echo $htt ...
- Codes 重新定义 SaaS 模式的研发项目管理平台开源版 4.5.3 发布
一:简介 Codes 重新定义 SaaS 模式 = 云端认证 + 程序及数据本地安装 + 不限功能 + 30 人免费 Codes 是一个 高效.简洁.轻量的一站式研发项目管理平台.包含需求管理,任 ...
- VmWare虚拟机和主机配置为同一网段IP
参考博客:将虚拟机IP与主机IP设置在同一网段的方法 - 天懿 - 博客园 (cnblogs.com) 主机地址 主机通过WiFi连接,地址信息为: 虚拟机配置 选择编辑-->虚拟网络编辑器-- ...
- 判断是不是ie浏览器 加上ie11
var b_version = navigator.appVersion; var version = b_version.split(";"); var trim_Version ...
- kettle从入门到精通 第三十五课 kettle 变量
1.设置变量 a.可以通过转换中的"设置变量"步骤进行设置. b.手动通过kettle.properties文件或通过"编辑"菜单中的"设置环境变量& ...