万里归来年愈少

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下一代开发解决方案)的更多相关文章

  1. PowerBuilder编程新思维5:包装(界面美化与WebUI+React)

    PowerBuilder编程新思维5:包装(界面美化与WebUI+React) 前一节,分析了三种界面美化方案,都是控件级的美化.今天再来分析一下窗口级的美化.上一次讲的DirectUI,大家反响一般 ...

  2. PowerBuilder编程新思维4:钩挂(界面美化与DirectUI)

    <第二部分 Outside> PowerBuilder编程新思维4:钩挂(界面美化与DirectUI) PB的界面由于其封闭性,一直以来都是最大的弱项.自PB9.0开放了PBNI接口后,开 ...

  3. PowerBuilder编程新思维3:适配(三层架构与GraphQL)

    PowerBuilder编程新思维3:适配(三层架构与GraphQL) PB在富客户端时代,是一线开发工具.随着网络发展,主流架构演进到三层架构的时代,PB拿不出有力的三层架构,已经明显力不从心,市场 ...

  4. PowerBuilder编程新思维2:嵌入(Thread多线程)

    PowerBuilder编程新思维2:嵌入(Thread多线程) 在PB中使用多线程,在网上有大量的文章介绍.不过深入研究并试着给出更易用的模型的,目前还只有"路人甲cw"的一篇& ...

  5. PowerBuilder编程新思维1:扩展(Lua)

    前言 PowerBuilder作为开发工具退出一线行列已经很久了,在2019年来谈这样一款老旧的编程工具是否有意义?诚然,PB有着太多硬伤,但还是有它的用武之地的.而且今天讲的这个“新思维”大部分内容 ...

  6. C++编程新思维中的技巧

    1.编译器断言 技巧大致跟后面的一样,都是利用偏特化,但是在C++ 0X里面已经有static_assert,所以感觉这东西也没什么用处了,更多的只是开阔眼界 2.偏特化 就是专门对一个类型去进行特殊 ...

  7. 【响应式编程的思维艺术】 (2)响应式Vs面向对象

    目录 一. 划重点 二. 面向对象编程实例 2.1 动画的基本编程范式 2.2 参考代码 2.3 小结 三. 响应式编程实现 四. 差异对比 4.1 编程理念差异 4.2 编程体验差异 4.3 数学思 ...

  8. 《C++设计新思维》Command设计模式读后感

    原文内容提领: 本书第5章标题为泛化仿函数,我认为本章真正讲述的内容可以总结出一句话! 如何利用C++老标准实现C++11新标准类似std::function提供的功能. std::function简 ...

  9. 《C++设计新思维》勘误,附C++14新解法

    勘误: 原书(中文版)3.13节,65-69页中GenScatterHierarchy以及FieldHelper均存在问题,当TypeList中类型有重复时,无法通过编译(原因在于“二义性基类”). ...

  10. 郑晔谈 Java 开发:新工具、新框架、新思维【转载】【整理】

    原文地址 导语:"我很惊讶地发现,现在许多程序员讨论的内容几乎和我十多年前刚开始做 Java 时几乎完全一样.要知道,我们生存的这个行业号称是变化飞快的.其实,这十几年时间,在开发领域已经有 ...

随机推荐

  1. 因为我的一次疏忽而带来的golang1.23新特性

    距离golang 1.23发布还有两个月不到,按照惯例很快要进入1.23的功能冻结期了.在冻结期间不会再添加新功能,已经添加的功能不出大的意外一般也不会被移除.这正好可以让我们提前尝鲜这些即将到来的新 ...

  2. Asp-Net-Core开发笔记:使用ActionFilterAttribute实现非侵入式的参数校验

    前言 在现代应用开发中,确保API的安全性和可靠性至关重要. 面向切面编程(AOP)通过将横切关注点(如验证.日志记录.异常处理)与核心业务逻辑分离,极大地提升了代码的模块化和可维护性. 在ASP.N ...

  3. 【漏洞复现】蓝凌OA sysUiComponent 任意文件上传漏洞

    阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站.服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作.利用此文所提供的信息而造成的直接 ...

  4. vue3.4中KeepAlive的一个bug

    KeepAlive可以缓存组件,在不使用include时没有任何问题,可以正常缓存. 但是一旦使用了include,如果动态组件中没有导入ref函数,缓存功能就消失了 比如 editcom.vue & ...

  5. JS监听DOM创建和销毁

    源码 web开发指南 <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&quo ...

  6. Chart.js (v2.9.4)概要介绍

    chart.js是一个非常优秀的开源图表插件,扩展非常灵活,同时也提供了大量的钩子函数,给与用户添加自定义插件,实现个性化的需求. 具体的优势特点,这里不详述,网上大把资料,现开始正式深入了解这个插件 ...

  7. 用python字典统计CSV数据

    1.用python字典统计CSV数据的步骤和代码示例 为了使用Python字典来统计CSV数据,我们可以使用内置的csv模块来读取CSV文件,并使用字典来存储统计信息.以下是一个详细的步骤和完整的代码 ...

  8. 算法金 | 一文读懂K均值(K-Means)聚类算法

    ​大侠幸会,在下全网同名[算法金] 0 基础转 AI 上岸,多个算法赛 Top [日更万日,让更多人享受智能乐趣] 1. 引言 数据分析中聚类算法的作用 在数据分析中,聚类算法用于发现数据集中的固有分 ...

  9. windows server 2016 远程桌面连接,发生身份验证错误。 要求的函数不受支持

    远程桌面连接,发生身份验证错误. 要求的函数不受支持 客户端:WIN7 服务端:windows server 2016 在被远程的机器上-远程设置中-取消"仅允许运行使用网络级别身份验证的远 ...

  10. C# ML.NET 使用GPU遇到 Failed to get convolution algorithm.This is probably because cuDNN failed to initialize

    C# ML.NET 使用GPU遇到 Failed to get convolution algorithm.This is probably because cuDNN failed to initi ...