万里归来年愈少

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. Python基础篇(安装)

    Python简介 Python是Guido van Rossum发布于1991年的一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,是一种解释型的,弱类型的高级计算机语言.需要注意的是pyth ...

  2. java学习之旅(day.18)

    网络编程 概述 计算机网络:自己百度吧 网络编程的目的:传播交流信息.数据交换.通信 想要达到这个效果需要什么: 如何准确的定位网络上的一台主机 端口 定位到这个计算机上的某个资源 找到了这个主机,如 ...

  3. 将python文件转换成exe可执行文件

    一.安装Pyinstaller pip install pyinstaller(Pyinstaller) 二.找到 .py文件的路径并执行如下命令 pyinstaller -F 要转换的文件.py 三 ...

  4. .NET6之MiniAPI(九):基于角色的身份验证和授权

    身份验证是这样一个过程:由用户提供凭据,然后将其与存储在操作系统.数据库.应用或资源中的凭据进行比较. 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作. 授权指判断允许用户执行 ...

  5. DevOps全面综述:从概念到实践

    这篇文章详尽介绍了DevOps的背景.核心实践.工具和技术,探讨了团队协作.文化建设及组织变革,旨在帮助企业高效实现持续交付和创新. 关注作者,分享互联网架构.云服务技术的全维度知识.作者拥有10+年 ...

  6. Java异常中throw 与throws的区别

    throw 与 throws区别 在Java中,throws和throw是两个不同的关键字,它们在异常处理中起着不同的作用. throws关键字: throws用于声明一个方法可能会抛出的异常.当一个 ...

  7. 为何Mysql数据库上读和代码读取的数据不一致

    上周,做了一个同步删除的功能,具体流程是,数据库删除-->调用第三方运行删除接口,同步删除. 具体流程 数据库删除数据后,这里使用标志删除,再调用第三方数据. 在调用第三方数据之前需要通过id查 ...

  8. 使用WinSW把nginx做成windows服务

    1.下载nginx:http://nginx.org/en/download.html 2.下载win sw:https://github.com/winsw/winsw/releases/tag/v ...

  9. 发现XWPFDocument写入Word文档时的小BUG:两天的探索与解决之旅

    引言 最近在使用XWPFDocument生成Word文档时,遇到一个错误:"未将对象引用设置到对象的实例".这个平常很容易找到原因的问题却困扰了我两天,最终发现问题出在设置段落时赋 ...

  10. zabbix如何监控服务器

    1.zabbix架构图 zabbix核心概念 先记住如下zabbix中的核心几个概念 主机 ( HOST ) : 就是具体的一个监控对象,某一个被监控的实例,可以是一个数据库,也可以是一个操作系统. ...