万里归来年愈少

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. 80x86汇编—分支循环程序设计

    文章目录 查表法: 实现16进制数转ASCII码显示 计算AX的绝对值 判断有无实根 地址表形成多分支 从100,99,...,2,1倒序累加 输入一个字符,然后输出它的二进制数 大小写转换 大写转小 ...

  2. kubernetes之Secret和Configmap

    创建和查询Secret literal 播报 编辑 讨论 上传视频literal是一个英语单词,形容词,意思是文字的:逐字的:无夸张的. [1] 通过--from-literal创建以及查看 [mac ...

  3. Python:Python字符串中的r、u和转义字符

    Python中字符串前面我们经常看到加r(R)或u/(U)的前缀,而这两个符号是什么意思呢? 1.r(R) r意为raw,表示不包含转义字符的原生字符串.常见的转义字符包括下列几种: 转义字符 描述 ...

  4. 使用jsbarcode生成条形码

    安装 yarn add jsbarcode 使用 // HTMLElement 承载条形码的元素 svg/canvas // text 显示在条形码下方的文字 // option 条形码的配置项 具体 ...

  5. 配置Ingress支持HTTPS访问(二):使用cert-manager申请证书

    目录 一.系统环境 二.前言 三.Let's Encrypt和cert-manager简介 四.部署cert-manager 4.1 安装cert-manager 4.2 创建clusterissue ...

  6. Java21 GA新特性-虚拟线程详解

    本文转载至:虚拟线程 - VirtualThread源码透视 - throwable - 博客园 (cnblogs.com) 一. 前提 JDK19于2022-09-20发布GA版本,该版本提供了虚拟 ...

  7. jsonp原理详解——终于弄明白了JSONP

    什么是JSONP? 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自己的方式来阐释一下这个问题,看看是否有帮助. 1.一个众所周知的问题, ...

  8. Nginx 修饰符 Location 详解

    概述 location 指令可以用在虚拟服务器 server 部分,并且意味着提供来自客户端的 URI 或者内部重定向访问. location 的定义如下: location [modifier] u ...

  9. Ubuntu20.04安装MySQL5.7

    ubuntu 20.04系统自带源直接安装的是MySQL 8.0,要安装MySQL 5.7的话,需要先换源. 1.换源 sudo cp /etc/apt/sources.list /etc/apt/s ...

  10. 【论文笔记】SegNet

    [深度学习]总目录 SegNet是Cambridge提出旨在解决自动驾驶或者智能机器人的图像语义分割深度网络,开放源码,基于caffe框架.SegNet运用编码-解码结构和最大池化索引进行上采样,最主 ...