gMIS吉密斯更新Workflow工作流、FileMgr文件柜及GTAjax等模块

gMIS吉密斯 近期更新了Workflow工作流、FileMgr文件柜及GTAjax等模块,记录于此,备忘备查。北京雾霾持续严重级别,雾霾指数持续300多。翻阅两年前的2016Nov26, 雾霾情况居然相同的严重。

  1. WorkFlow工作流改进更新
    因工作需要,很早的时候就在 gMIS 中增加了一个简易的工作流功能。这次在考虑了多用户协作方面对该功能进行了拓展。
    扩增 Act Options功能,进一步释放操作潜能,在被管理的任意一条数据上,除了常规的“编辑/打印/删除”等,可以允许开发者有针对性的增加任意多的操作动作,这些动作可以通过 xml 绑定到指定的数据表上。
    <actoption>actHrefOne | actHrefTwo | …</actoption>

    Workflow 在 gMIS吉密斯中简称为“todolist/任务管理”, 之前是类似与便签的工作笔记,现在通过 ActOption 增加了 回复 / 转发 等功能,可以为工作流转提供更多便利性。如:

    <actoption>jdo.php::tbl=THIS_TBL,pnskpid=THIS_ID,id=THIS_ID,pnsktriggerbyparent=THIS_triggerbyparent,pnsktriggerbyparentid=THIS_triggerbyparentid,act=’addbycopy’::回复::confirm=0,blank=0 |jdo.php::tbl=THIS_TABLE,pnskpid=THIS_ID,id=THIS_ID,act=’addbycopy’::转交::confirm=0,blank=0</actoption>

    actoption 配置功能标签的增加,将为被管理对象带来更多操作便利,为增加个性化操作提供了一条通道。

  2. 新增文件管理功能FileMgr

    最近在 gMIS 实现了一个简易的Web网盘,可以考虑下载试用。如下是一些操作参考内容。网盘逐渐成为刚需,而且目前市面上有各种各样的网盘服务,限于各种原由,其通用性均差强人意,比如“随时随地跨设备”这样的要求。

    我作为技术“顾问”也多次被寻求类似的简易的网盘解决方案,在 gMIS的过往部署中,也屡次被提及此功能,都是由于“懒”,没有上手弄。这次“出手”成下面这样的gMIS版本的网盘。
    数据表设计为冗余字段 parentid, parentname, pparentname, 其中parentid用于记录上一级目录的名称,适合机器读取操作,parentname用于记录上一级目录的名称,pparentname用于记录当前目录的祖父目录。
    其中, parentname和pparentname都采用了fullpath/全目录的结构设计,适合人读取、理解、使用和接收。

    1)访问路径: Π 首页 → 桌面 & 系统配置 → 文件柜 | 文件柜
    2)上传文件或新建目录
    3)子目录导航、浏览
    4)文件下载/更新,子目录的修改
    当目录名称被修改时,按逻辑同步修改其下所有资源和子目录的目录名称;
    当目录被删除时,按逻辑检查目录下是否非空,当目录下还有内容时,删除目录动作将被拒绝;
    5)其上叠加了很多 gMIS 的各种增强的辅助功能。

    FileMgr 文件柜可以为用户提供了全功能的在线文件管理,轻松实现文件的集中管理、分享、分发、备份等目的。

  3. 升级 GTAjax至最新 5.6 版本
    gMIS 依赖 GTAjax 实现页面局部刷新或者后台通信。这次更新gMIS要解决目标数据表的字段名称为“name”的表单的新增、修改异常问题。

    例如当某个数据表包含有某个字段名称为“name”时,在生成新增HTML表单时,会自动创建如下HTML表单,
    <form name=”gmisForm” id=”gmisForm”>
        <input name=”name” id=”name”/>
        ….
    </form>

    针对上述表单,gMIS 会依照一贯的方法呼叫 GTAjax 进行表单数据递交。

    此时,如果通过 <button name=”submitbtn” type=”submit” onclick=”javascript:doAction(this.form.name);”></button> 对表单的递交进行处理的话, this.form.name 预期返回的是 “gmisForm”, 而如果有一个input元素的名称是“name”时,HMTL form的 this.form.name 会返回一个 input对象。

    GTAjax 是一个单独项目,主要用来处理在页面无刷新的情况下,对页面元素进行局部更新,从而实现更高效地HTTP通信。
    GTAjax 项目开源地址在 -GTAjax

  4. 其他更新与修正
    1)修正了导出数据到MS Office Excel时的UTF BOM指定,增加打开目标数据文件的模式为“wb”;
    2) 更新了文件上传模块,增加更多的上传错误明细显示;
    3) 更新了核心类 MySQLix.class, 增加异常日志打印;
    4)更新了登录模块验证码功能,增加实时校验验证码功能;
    5)改进act/trigger参数传递;
    6)改进 pickup 区域同步刷新机制;
    7)改进 class/pagenavi ,增加 notcontainslist等操作符;
    8)多实例对象共享多数据库配置。在最早的设计中,gMIS 只依赖  gtbl.class 一个全局对象完成对数据的操作,因此在实现对多个数据库进行操作时,只需在 gtbl.class 中进行多数据库的连接配置即可。
    随着 gMIS 的功能的增强,我们增加了越来越多的实例对象,如 IntSiteSearch, Pivot, PickUp 等,如何在这些对象里共享 gtbl.class 的多数据库信息成为需要解决的问题。
    本次引入了全局配置参数 args_to_parent 将 gtbl.class 的共享配置信息传递给 InSiteSearch, Pivot 和 PickUp 等。

-gMIS (general Management Information System) 是一种基于 -GWA2 (General Web Application Architecture) 的通用管理信息系统应用软件,具有可配置的输入和输出接口、开箱即用等特征。
可以在其上构建各种信息管理应用软件系统,如
内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等, 以及各种行业应用管理系统软件,如
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统(BOSS)等等。
实现零代码开发、快速搭建各种管理信息系统(MIS, Management Information System).

-gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems (BOSS), etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

Lower Costs, 
Better Productivity.
降低成本,
提高效率.

Posted in -gMIS, -GTAjax, 编程技术, 计算机技术 | Tagged , , , , , , | Leave a comment

GWA2Perl研发:try-catch无法退出循环、方法传参引用传值及多数据库链接

在使用 GWA2Perl 开发时遇到一些破费周折才发现的 Bug或改进的功能,分析记录如下,备忘。 GWA2 是一套跨语言的网络应用软件开发框架,目前有PHP、Java和Perl版本可供下载选用,也即 GWA2PHP, GWA2Java 和 GWA2Perl。

1. 应用 Tiny::Try 的Catch模块无法执行退出循环的问题


use Tiny::Try
….
foreach my $i(keys %alist){
try{
    # something
}
catch{
    if(aCondition==1){
        next; # cannot?
    }
}
}

此处的 next 无法按预期执行. 改进的措施是,预先顶一个 $tryresult = 0; 然后在成功的时候,将 $tryresult =1; 在 try::catch 执行完毕之后再对 $tryresult 进行判断,以决定是否退出循环. 修改后的代码大致如下。


use Tiny::Try
….
foreach my $i(keys %alist){
my $tryresult = 1;
try{
    # something
}
catch{
    if(aCondition==1){
        next; # cannot?
    }
    $tryresult = 0;
}
if($tryresult == 0){
    next;
}
}

2. Perl方法传递参数应用传值的问题

my %alist = (‘a’=>1, ‘b’=>2);
&functionA(\%alist);
&functionA(%alist); # wrong!
&functionA($alist) # wrong!

my $blist = \%alist;
&functionA($blist);
&functionA(\%blist); # wrong!

Perl的方法参数传递问题,在此前的贴文中进行过相应的讨论,如 -R/H2SP 和 -R/32SJ , 这次重新再三的提及,主要还是由于在Perl的参数传递过程中,极易发生误解,对Perl依靠形式来获取数据类型的做法认识的不够深刻。如给定同一个变量名称,可能表述不同的意思。

$varA = undef; –> 一个普通的未知类型的变量 varA;
$varA[0] –>  一个数组变量 varA ;
$varA{‘a’} –> 一个哈希变量 varA ;
$varA = []; –> 一个hashref变量 varA;

正是这种随意性使得Perl语言的变量掌握起来让人容易出错,再结合传值或者传引用,迷惑性更大。

3. Perloop/Perlobj 面向对象的Perl进行多数据库同时连接的问题

3.1.问题描述
在 GWA2Perl的实现中,对象连接数据库通过 WebApp –> Dba –> Conn –> Driver 的过程( -R/12SL  )。 设若有对象ObjectA,需要连接数据库DatabaseA; 有对象ObjectB,需要连接数据库DatabaseB。
在此设置下,若单独运行实例化的 ObjectA,或者ObjectB均没有问题,或者同时运行ObjectA/ObjectB,同时连接到数据库DatabaseA,也没有问题。 当我们希望同时运行实例化的ObjectA/ObjectB,并分别连接数据库DatabaseA/DatabaseB时,问题就发生了,Perl的运行时环境中,总是留存最后一个活跃的数据库连接信息。
类似的问题并不会在非PerlOOP的环境中产生,如果在通过的函数式编程中,可以通过声明不同的 $dbi 实例来映射到不同的数据库连接上,并保持到一个session执行结束或者手工关闭。比如 $dbiDatabaseA 连接到DatabaseA上,$dbiDatabaseB连接到DatabaseB上。

3.2. 通过对象实例的UniqueId来区别实例
根据对问题的描述,在 PerlOOP中,实例化后的对象共享数据库连接,如果其中以参数的方式带入不同的数据库连接信息,实例化后对象的无法保持数据库信息与具体实例的对应关系。
解决的思路是在 WebApp一层增加如下设施:
1) + getUniqueId
2) + _checkDbConn
其中 1) 是在对象实例化后根据对象 Scalar::Util 的方法 refaddr 来获取对象的唯一 Id号,然后在 WebApp 中,实现对象与数据库信息做绑定;
2) 在 WebApp 中每当进行数据库读写操作时,获取当前实例化对象的 唯一Id,然后从环境变量 %hmf 中获得其绑定的 数据库信息,从数据库对象 $dba 中获得当前活跃的数据库信息,然后对两者做比较,当两者相符时,继续前行;当两者不一致时,重置/切换数据库连接至实例化对象所绑定的数据库上。
也许这是临时解决方案,在后续的PerlOOP中能得到解决,或者在 Perl 6中能够将对象封装的更严密些。

3.3 实例化后的对象根据唯一Id扩展
实现了可以同时操作多个数据库的PerlOOP,GWA2Perl的能力将进一步扩增,其他类似的资源读取均可以实现多源读取,如Session,Cache,File等其他网络资源。
这一问题是第二次碰到,起初遇到时,想到的是在程序中临时切换数据库连接,当其时并没有更好的解决方案,今次深入分析,获得一个可以自动化的持续解决方法,可以实现:
1) 同一个对象在一个时期内,总是持续一致地维持对资源的连接;
2) 不同的对象,拥有不同的资源连接,且可以同时并行。

-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.

Posted in -GWA2, 编程技术, 计算机技术 | Tagged , , , , | Leave a comment

[转]我所经历的三次工业革命

真正的经济增长,主要不是表现在GDP(国内生产总值)统计数字上,而是表现在新产品、新技术、新产业的不断出现,表现在人们的生产方式和消费方式的不断改善。

(原作者 张维迎,北京大学国家发展研究院教授,联合创始人)

S1.
纪念改革开放40周年

人类的历史有250万年,但人类的经济增长只有250年的历史。经济增长在今天被当作常态,但250年前,经济不增长是常态。

真正的经济增长,主要不是表现在GDP(国内生产总值)统计数字上,而是表现在新产品、新技术、新产业的不断出现,表现在人们的生产方式和消费方式的不断改善。250年前,人类生产和消费的产品种类大概只有100种到1000种,今天则是10亿到100亿种。根据2017年10月的统计,亚马逊网站销售的商品就有5.98亿种。

人类过去250年的经济增长,是三次工业革命的结果。第一次工业革命大约从1760年代开始持续到1840年,其标志是蒸汽动力的发明、纺织业的机械化和冶金工业的变革;第二次工业革命大约从1860年代开始持续至第二次世界大战之前,其标志是电力和内燃机的发明和应用,还有石油化学工业、家用电器等新产业的出现;第三次工业革命大约从上世纪50年代开始直到现在,其标志是计算机的发明、信息化和通信产业的变革。

但三次工业革命并不是在所有国家同时发生的。英国引领了第一次工业革命,美国和德国引领了第二次工业革命,美国接着又引领了第三次工业革命。有些国家虽然不是引领者,但在每次工业革命发生后,能很快追赶上,而另一些国家则被远远甩在后面,其中有些国家至今还没有完成第一次工业革命。这就是富国与穷国差距的原因。

西方发达国家像我这样年龄的人,当他们出生的时候,前两次工业革命早已完成,只能经历第三次工业革命,但作为中国人,我有缘享受“后发优势”,用短短的40年经历了三次工业革命,走过了西方世界十代人走过的路!

S2.
我的第一次工业革命

1959年秋,我出生在陕北黄土高原一个偏远的小山村。在我出生的时候,除了共产党的领导和人民公社是第一次工业革命的产物,当地人的生活方式和生产方式几乎没有受到第一次和第二次工业革命的影响。我出生的窑洞是什么时候修建的,我父亲不知道,他的父亲也不知道。

在人类漫长的历史中,生活就是衣食住行、柴米油盐,生产就是春种秋收、男耕女织。在我年幼的时候,我穿的衣服和鞋都是母亲手工纺线、手工织布、手工缝制完成的。我至今仍然能回想起,我睡梦中听到的纺车发出的嗡嗡声和织布机发出的吱咔声。

纺织业是人类最早的工业。手摇纺车在汉代就普遍使用,母亲使用的纺车看上去与汉画像石上的纺车没有什么区别。母亲用的木制脚踏织布机是印度人在公元500年至1000年间发明的,大约在公元11世纪传入中国(也有专家认为是中国人发明的)。英国人约翰·凯伊于1733年发明了飞梭,在接近1760年的时候,飞梭在英国已经普及开来,但200年之后,母亲仍然不知道有飞梭,所以不仅织布速度慢,而且只能织出窄幅匹的布,一条被子需要好几块布料拼接而成。

根据英国科技史学家李约瑟的考证,中国在公元1313年就有了三锭甚至五锭纺车,但不知为什么直到我小时候,母亲用的仍然是单锭纺车。英国工业革命期间,詹姆斯·哈尔格里夫斯于1765年发明了多轴纺纱机(珍妮机),使得一个人同时能纺出几根线。哈尔格里夫斯最初的模型仅有八个锭子,但在他还活着的时候,人们已经能制造80个甚至更多锭子的多轴纺纱机了。如果母亲当年能用上多轴纺纱机,她就不会那么辛苦了。理查德·阿克赖特于1768年发明了水力纺纱机,埃德蒙德·卡特赖特于1785年发明了机械织布机了,这些都没有影响母亲的生活。

母亲缝制的衣服都是老式的,所以我小时候穿的裤子前面没有开口拉链。偶然会发生尴尬的事情,就是尿急时裤带打成了死结解不开,就只能尿在裤子里了。每每想起此事,总会让我觉得美国人威特康·L·朱迪森和瑞典人吉迪昂·森贝克在100多年前发明的拉链,真是了不起。

美国人艾萨克·辛格早在1851年就发明了缝纫机并很快投入商业化生产,但我小的时候,缝纫机在我们那里仍然非常罕见。在我10来岁时,村里的一位复员军人带回一位山东媳妇,按母亲一方的亲戚关系,我叫她嫂子。这位嫂子心灵手巧,会用缝纫机做衣服,我穿的第一件“制服”就是她做的。

上大学之后,我就不再穿母亲用土布缝制的衣服了。后来,家里的纺车和脚踏织布机也被当作柴火烧了。

纺和织是棉纺织业的两道主要工序,但在原棉变成能纺纱的原料之前,还需要一些其他工序,其中一项是梳棉。梳棉就是通过疏松、清理和混合,将棉花纤维变得连续可纺的工艺。母亲纺纱用的棉卷是父亲用梳棉弓梳理的。根据李约瑟的考证,梳棉弓(carding bow)是印度人在公元2世纪发明的。梳棉弓在我们当地被称为“弹花弓”,弹花算是一门小小的手艺,能赚点小钱,父亲是从他的四舅那里学到这门手艺的。

“文革”初期,父亲和他四舅及另一个人合伙买了一台梳棉机,存放在离我们村25华里的镇上,逢集的时候就提前一天去镇上弹棉花。梳棉机比梳棉弓的效率要高好多,每次干两天活,每人可以赚到三四块钱,这在当时算一笔不小的收入。可惜好景不长,后来政府搞“割资本主义尾巴”运动,他们的生意就做不成了。

1979年,村里搞起了“包产到户”。父亲把那台梳棉机从镇上搬回家,以为又可以弹棉花赚钱了。但父亲的预测完全错了。没过多久,村里人都开始买机织布了,连棉花也没有人种了,他的那点小手艺也就废了。根据我脑子里的印象,父亲他们的那台梳棉机,就是1748年刘易斯·保尔发明、1775年理查德·阿克赖特改进过的那种梳棉机!

改革开放后,父亲的另一项手艺也废了。我小时候冬天穿的袜子,都是父亲自己捻毛线、自己编织而成。父亲捻毛线用的捻锤,是新石器时代的发明。我上大学后,就不再穿父亲织的袜子了,他也就不再编织了。其实早在1598年,英国剑桥大学的毕业生威廉·李就发明了织袜子机。

第一次工业革命的另一项重要进步发生在冶金工业。冶金工业也是一个非常古老的产业,人类掌握冶炼技术已有5000年,炼铁业也有3000多年的历史。但即使进入“铁器时代”,铁仍然是一种稀有的贵金属,中国宋代曾用铁做过货币。

但铁的稀缺性被第一次工业革命改变了。1710年,英国企业家亚伯拉罕·达比发明了焦炭炼铁工艺,使得大规模廉价铁的生产成为可能。1870年代,英国海军采购代理人亨利·科特发明了搅拌炼铁法。不久,搅拌炼铁法便在全大不列颠境内成为生产熟铁的通用方法,千百万吨铁就这样制造出来,人类真正进入铁的时代。1856年和1861年又相继出现了贝塞麦转炉炼钢法和西门子平炉炼钢法,钢的生产成本大幅度下降,从此,钢逐渐替代铁和木材,成为机器设备和车船的主要制造材料。钢不仅架起了跨江大桥,而且托起了摩天大楼。1889年巴黎埃菲尔铁塔的建成,标志着铁时代的结束和钢时代的开始。

进入钢铁时代,也是新中国领导人的梦想。在我出生的前一年,中国搞起了全民大炼钢铁运动。但遍地土高炉圆不了举国钢铁梦。我在农村时,钢还只能用在刀刃上,全村没有一把全钢制的斧头、镰刀、菜刀。不要说钢,铁也很稀缺,最值钱的就是做饭用的锅,所以“砸锅卖铁”就成为人们陷入绝境的隐喻。锅是生铁铸造的,空锅烧热时一沾凉水,就会裂缝,我们家的锅不知补过多少次了。当时农用工具基本都是木制的,门窗上唯一的金属是锁环。由于这个原因,尽管几乎每个村都有一两个木匠,周围数十里才有一个铁匠。

但改革开放后,随着现代化冶炼技术的引进,中国终于进入钢的时代。1996年,中国取代日本成为世界第一大钢铁生产国。现在再回到农村,发现犁、耙子、扇车都已经变成钢制的了,木制工具已成为古董。

煤炭在工业革命中发挥了重要作用,不仅炼铁需要大量的煤,蒸汽机也要烧大量的煤。中国和英国都是煤炭资源丰富的国家,但英国的煤炭助燃了工业革命,中国的煤炭则长期躲藏在人们看不见的地方。经济史学家彭慕兰用煤炭资源的丰富性解释英国工业革命的起源,看来说服力不是很大。我的老家榆林市现在已成为中国的煤都,其产量占到全国的十分之一。但在我小的时候,村民做饭、取暖用的燃料主要是柴草、树梢和秸秆,大部分庄户人家用不起煤,尽管那时候每百斤煤的价格只有4毛钱(现在的价格是20元左右)。今天政府已经开始禁止老百姓烧煤取暖了,但那个时候是烧不起煤。

在漫长的历史中,人类生产和生活需要的动力主要是人自身和大型动物的肌肉,这一点直到蒸汽机出现之后才得到根本性改变。但蒸汽机发明200年之后,我在农村的时候,动力仍然是人力和畜力。农村人看一个人是不是好劳力,主要看他肩能扛多重,背上能揹多少斤。我们村没有马,因为马太贵,饲养起来也麻烦,仅有的几头驴,是生产队最珍贵的生产工具,耕地、驮碳、拉磨、娶亲,都靠它们。如果一头驴死了,就是生产队最大的损失。

我小的时候不爱干家务活。当时农村磨面用的是石磨,碾米和脱壳用的是石碾。据说,石磨在公元前二世纪的汉代中国就有了,而古罗马在公元前160年也已广泛使用;石碾也是从汉代开始就被人们用来碾米和脱粒了。逢年过节或有红白喜事的时候,由于需要碾磨的量大,通常使用畜力驱动石碾和石磨,但平时小量的碾磨,只能使用人力。母亲要我帮她碾米推磨时,我总有些不情愿,围着碾盘或磨盘转圈圈让人觉得枯燥无味。

蒸汽机最初只用于矿井排水。在瓦特把蒸汽机转变为旋转动力之后,蒸汽机就逐步替代人力和马力,成为石磨旋转的动力。1786年,瓦特和博尔顿在伦敦建立了大不列颠面粉厂,两台蒸汽机推动50对磨石,每周生产435吨的面粉。这个面粉厂的开设轰动了整个伦敦,来这里参观成为一种风气,搞得瓦特很不耐烦。

我老家的石磨和石碾从来没有被蒸汽机推动过,但在我离开家乡三十年后,石磨和石碾基本上都被废弃了。村民们跨越了蒸汽机,直接进入内燃机和电动机时代,这或许就是人们说的“弯道超车”吧!

S3.
我的第二次工业革命

第一次工业革命主要发生在纺织和冶金这两个传统部门,第二次工业革命则创造了许多新的产业。第一次工业革命用蒸汽机动力代替了人力和畜力,第二次工业革命则用内燃机和电动机代替了蒸汽机。内燃机是德国人奥古斯塔·奥托(August Otto)于1879年发明的,电动机是移民美国的塞尔维亚人尼古拉·特斯拉(Nikola Tesla)于1888年发明的。但直到我上初中之前,我们村里还没有内燃机,更没有电动机。

在黄土高原,能种庄稼的地都是些沟沟峁峁的山地,祖祖辈辈都是靠天吃饭。但不知从什么时候起,村民们还是用石头在沟里垒起了一些水地。

水地在当地被称为“园子”,只有少数园子可以引水灌溉,大部分只能靠人工浇灌。零散的小块园子靠挑水浇灌,稍大块的园子则使用一种叫“橘槔”的装置提水浇灌。橘槔是这样一个装置:在一个架空的横木中间垂直钩一个长木杠,长木杠的一端固定一块很重的石头,另一端用一个活动连杆挂着一个柳编水桶。提水的时候,操作者站在石墙半空突出来的台阶上,用力将连杠向下拉,等水桶到达下面的水池灌满水后,再将手松开,靠着长木杠另一端石头的重力,水桶被提到适当的高度时,操作者将桶里的水倒入引水沟。如此往复不断,就可以灌溉大片的园子。

橘槔工作的时候,从远处看起来,酷似托马斯·纽科门于1712年发明的蒸汽机水泵,只是它的原动力来自人力,而非蒸汽。橘槔的英文名字叫shaduf,早在公元前1500年前,埃及人就用它提水了。至于橘槔何时引入中国,不得而知。但从古埃及人最初发明到我们村的人弃之不用,有3500年之久,真是不可思议!

橘槔之所以被弃用,是因为柴油机的引进。

柴油机是内燃机的一种,它是由德国人鲁道夫·狄塞尔(Rudolf Diesel)于1893年发明的,被认为是自瓦特分离式冷凝器之后动力生产方面最重要的发明。狄塞尔死后,柴油机经过一系列改进,在许多应用领域(包括火车、轮船、农业机械等)代替了蒸汽机,至今仍然是移动机械的重要动力。

大约在我上初中的时候,村里有了一台6马力的柴油机。柴油机配上一个水泵,就可以把沟里的水扬程到园子地里,轰动了全村人。只是这台柴油机老出问题,并没有立马替代橘槔。

后来公社又给我们村奖励了一台12马力的手扶拖拉机。这个英国人赫伯特·阿克伊德·斯图尔特于1896年发明的东西,八十年后,终于出现在我们这个偏僻小村。手扶拖拉机马力不大,但又好像无所不能,农忙时耕地、脱粒、抽水,农闲时带动磨面机磨面,或者跑运输。

包产到户后,拖拉机被拆成部件分了,我以为农业机械化没希望了。但没过多久,村里好几户人家自己买了拖拉机,其中还有人买了面粉机和脱粒机,开始商业化运营。慢慢地,到上世纪90年代后期,石磨和石碾被淘汰了,橘槔也被弃之不用,牛驴也没有人养了。

内燃机的最大影响发生在交通运输业。1886年,德国人卡尔·本茨和戈特利布·戴姆勒同时发明了内燃机驱动的汽车;22年后,美国人亨利·福特用自动组装线生产出了廉价的T型车,使得普通工薪阶层也能够买得起。到1930年,汽车已进入60%的美国家庭,美国由此成为“骑在轮子上的国家”。

但我小的时候,方圆几十里内见过汽车的人还屈指可数,全村没有一辆自行车,人们出行的方式仍然是步行。我既兴奋、又恐惧的是每年正月初二跟随父亲去探望改嫁远村的奶奶,虽然路程不过五十华里,但好像有翻不完的山峁、走不完的沟壑,早晨出发傍晚才能到达。

1973年公路修到我们村,起因是五里外的邻村变成了全国农业学大寨的先进大队,省委第一书记要去视察,必须从我们村路过。当26辆吉普车队尘土飞扬经过时,全村男女老少都站在硷畔上观看,真是大开眼界!

我到北京工作之后,每次回家探亲,县政府总会派车把我送到村里,走时又派车把我接到县城。据说这是对在外地工作的县团级官员的待遇,我虽然不是县团级干部,但他们觉得我有点名气,又在中央机关工作,所以就视同县团级对待。我自己也欣然接受这种安排,因为,从县城到我们村八十华里路程,没有班车,找顺风车也不方便。

在牛津读博士期间,我花了一千英镑买了一辆福特二手车,从此有了自己的小轿车。回国后,我又用免税指标买了一辆大众捷达车。记得直到1999年,光华管理学院大楼前平时还只孤零零停着我的一辆车,没想到几年之后,大楼前已是车满为患了。

更让我们没有想到的是,现在每次回老家,村里总停着几辆车,汽车在农村也已不再是稀罕物了,一个远房的堂弟还买了辆中巴跑班车,仍然住在村里的年轻人大多有摩托车。

据统计数据,中国城市人口中每百户拥有的家用汽车在1999年只有0.34辆,2015年则达到30辆。虽然普及率还不及美国1930年全国水平的一半,但在汽车发明130年后,大部分中国城市居民总算享受到了这个第二次工业革命的重要创新!

电力,是第二次工业革命的另一项重要创新。1882年,美国人托马斯·爱迪生在纽约曼哈顿建成了人类历史上第一个集中供电的照明系统,为电气化时代打开了大门。到1930年,美国近70%的人口都用上了电,1960年这一比例已达100%。列宁曾说过,共产主义就是苏维埃+电气化,但在我的家乡,虽然苏维埃很早就捷足先登,电气化却是姗姗来迟。

从出生到去县城上高中之前,我没有见过电灯,村里人照明用的都是煤油灯或麻油灯,有些家道贫困的人家连煤油灯也用不起,一到晚上就黑灯瞎火。有个流传的笑话说,一位客人在主人家吃晚饭,主人舍不得点灯,客人不高兴,就在主人家小孩的屁股上狠狠拧了一下,小孩顿时嚎啕大哭,客人说,快把灯点着,孩子看不见,把饭吃到鼻子里了。

父母鼓励我读书,说愿意为我多费二斤油钱。确实,村里好多人家就是因为怕花油钱,不让孩子晚上看书。为了省油,煤油灯的灯芯都很小,晚上在灯下看书的时候,头必须尽量靠近灯光,有时候打瞌睡,第二天上学的时候,头上就顶着一缕烧焦的头发,被同学们取笑。当时全村最亮的灯在生产大队的公用窑,是带玻璃罩的罩子灯,比小煤油灯费油好几倍。

到县城上高中时,我第一次见到了电灯,不仅宿舍里有白炽灯,教室里还有日光灯。但电压总是不稳,时明时暗,还经常断电,罩子灯仍然是宿舍的必备。

1993年我在牛津读书期间,暑期回老家看望父母,听说两公里外的村子已经拉上电了,我们村因为县上没人说话就没有拉上。知道我认识县委书记,村民们专门到我家,希望我给县委书记说说,给我们村也拉电。我说了,但没有管用。想到村里人对我的期待,这事成了我的一块心病。几个朋友愿意帮忙,一共筹集了四万多块钱,1995年,我们村终于通电了!

通了电,村民的生活就完全不一样了。电不仅能照明,而且能带动家用电器和其他机械。从本世纪第一个十年开始,不少人家相继买了电视机。电冰箱、洗衣机、电风扇、电熨斗、空调等家用电器,这些第二次工业革命时期的重要发明,虽然在那里的农村没有很大的实用价值,但还是有个别人家买了。村里也有了由电动机驱动的磨面机、碾米机、脱粒机、电锯。更重要的是,有了电动机,家家户户都可以用上自制的自来水系统,就是在比窑洞高的地方修一个封闭的蓄水池,把井水抽到蓄水池,水管连接到屋里,水龙头一打开,水就自动流出来了。我在农村的时候,每天早晚去井里挑水是一件很愁人的事,现在再没有人为挑水发愁了。

S4.
我的第三次工业革命

1978年4月,我离开老家去西安上大学。我从县城搭长途汽车到山西介休,再乘火车到西安。这是我第一次坐火车,也是第一次见到火车。火车是英国企业家斯蒂文森父子1825年发明的。至1910年,美国已修建了近40万公里的铁路,而到1978年,国土面积相当的中国只有5万公里铁路。

此时距离第一台大型数字计算机的发明已有33年,微型计算机产业正处于顶峰,比尔·盖茨和保罗·艾伦的微软公司已经成立4年,斯蒂芬·乔布斯和斯蒂芬·沃茨尼亚克的苹果II个人计算机也已经上市两年了,但直到进入大学后,我才第一次听说计算机这个名词。一开始,我以为计算机就是用于加减乘除运算的,可以替代我当生产队会计时使用的算盘。算盘是中国人和埃及人在公元前400年前就使用的东西。但后来我就知道自己错了,计算机将替代的远不止算盘。

经济系一年级的课程有一门“计算机原理”,记得第一次上课的时候,看到硕大无比的计算机感到很新奇。后来知道,1945年宾州大学研发的第一台计算机ENIAC重量接近30吨,长100英尺,高8英尺,占地面积相当于一间大教室。我们还学过二进位制、打孔卡原理和BASIC语言。但除了拿到考试成绩,整个本科四年和研究生三年期间,计算机对我的学习和生活没有发生任何影响。

1985年,我开始在北京国家机关工作。我所在的研究所买了两台电脑,但放在机房,神神秘秘,由专人看管,只有搞经济预测的人可以使用。单位还有一台四通电子打字机,由打字员操作。与手写复写纸、蜡纸刻字印刷以及传统打字机相比,电子打字机最大的好处是可以储存文本,反复修改。复写纸是在19世纪初英国人雷夫·韦奇伍德发明的,蜡纸刻字印刷是爱迪生于1886年发明的,我在高中时和高中毕业返乡务农时都用过。英文打字机是克里斯托弗·肖尔斯等几个美国人于1868年发明的,中文打字机是山东留美学生祁暄于1915年发明的,我上高中时我们学校有一台。

我第一次使用计算机是1988年在牛津读书的时候。我把自己手写的两篇英文文章拿到学院计算机房输入计算机,然后用激光打印机在A4纸上打印出来。激光打印出来的字体真是漂亮,像印刷出版的书一样,让人无比兴奋。

激光真是一个神奇的东西。据说1960年刚发明时,贝尔实验室的专利律师甚至不主张申请专利,因为它“没有什么实用价值”,但自与康宁公司1970年发明的光纤玻璃结合后,它就彻底改变了通讯产业,并且变得无处不在。我第一次享受激光技术是1981年,医生用激光切除了我脸上的一个痣。现在讲课时,我手里拿的是激光笔,不是粉笔。

1990年9月,我回到牛津攻读博士学位时,买了一台286个人电脑,从此就告别了手写论文的时代。1994年回国时,我还把这台电脑托运回北京。但个人电脑技术的发展是如此之快,很快出现了486电脑,这台旧电脑的托运费也白交了。后来又有了桌面激光打印机,这样我就有了自己的桌面出版系统。之后还换过多少台电脑(包括笔记本电脑),自己也记不清楚了。

计算机从公共教室那么大,变得办公桌上放得下(个人电脑)、书包里装得下(笔记本电脑)、甚至口袋里揣得下(智能手机),从而使得像我这样的普通人也能买得起,全仰仗于因特尔公司于1971年发明的微处理器。有了微处理器,个人电脑才成为可能。而微处理器建立在诺伊斯和基尔比于1969年发明的微芯片(集成电路)的基础上,微芯片又以晶体管为基础。所以有人说,晶体管对数字时代的意义,相当于第一次工业革命时期的蒸汽机。

晶体管是贝尔实验室的三位科学家于1947年发明的,不仅比真空管体积小、成本低、能耗少,而且不易损坏,其在消费设备上的第一个应用是德州仪器公司于1954年生产的袖珍收音机。在牛津读书期间,一位台湾来的同学送了我一个台湾产的袖珍收音机,像香烟盒大小,但音质非常好,让我爱不释手。回想起我在农村时滋滋啦啦的有线广播,真是天壤之别。

对大部分人而言,一台孤立的电脑不过是一个文字处理机,我当初买个人电脑的目的就是为了写论文方便。但多台计算机连接成一个网络,用处就大了。1969年,第一代互联网——阿帕网诞生了。1972年,阿帕网的第一个热门应用——电子邮件诞生了。1992年后,我自己也开始用电子邮件了,但当时国内的人还无法使用电子邮件。1993年在筹办中国经济研究中心时,我们向北京大学校领导提的一个要求就是,给我们通电子邮箱。这个愿望被满足了。但没过多久,北大所有的教员都可以使用电子邮箱了。几年之后,中国就进入互联网时代了。

记得1993年12月我儿子在牛津出生的消息,我还是先通过国际长途电话告诉国内亲戚,然后再由这位亲戚发电报告诉老家的父母。电报是美国人戈登·摩斯于1844年发明的,最初一条电报线只能发送一个频率,亚历山大·贝尔想让一条线路同时发送多个频率,结果于1876年发明了电话。到1930年,美国家庭电话的普及率已达到40%,但至1978年的时候,除了少数政府高级官员家里装有公费电话外,中国普通老百姓家庭的电话普及率几乎为0。我在农村的时候,生产大队的公窑里有一部手摇电话,一根电话线串着好几个村,通话时必须大喊大叫才行;往不同线路的电话需要人工交换机转接,全公社只有一个交换机,接线员是很让人羡慕的工作。

转盘拨号电话是西门子公司于1908年发明的,按键拨号电话是贝尔公司于1963年发明的(必须有晶体管电子元件)。上大学之前,我没有见过转盘拨号电话,更没有见过按键拨号电话,因为连县长办公室的电话都是手摇的。我第一次使用转盘拨号电话是1982年上研究生期间,在校门口的一个公用电话上,还是过路的一位老师教我怎么拨号的。在牛津读书期间,偶尔给国内家人打一次长途电话,心跳的比电话上显示的英镑数字蹦得还快。当时国际长途电话很贵,从牛津到北京,每分钟的费用在3英镑以上。

我第一次安装家用电话是留学回国的1994年,也就是贝尔发明电话118年后。当时安装电话要先申请,缴纳5000元的初装费后,再排队等候。后来初装费取消了,但我早已缴过了。1999年,我开始使用移动电话,家里的固定电话就很少用了。

但很长时间,我还是没有办法和老家的父母通电话,直到老家农村也可以安装电话为止。我最后一次收到姐姐写的家信是2000年。

2006年之后,老家农村也有移动电话信号了。我给父母买了一部手机,母亲高兴得不得了, 可惜她的信息时代来得太迟了。2008年母亲下葬的时候,我把她心爱的手机放在她身边,希望她在九泉之下也能听到儿子的声音。

自从用上iPhone智能手机,短期出差我不再带笔记本电脑,也不带相机了。有了智能手机,我与父亲不仅可以通话,还可以用微信视频。父亲现在住在榆林城里,春节时能与村里的乡亲们手机拜年,他很开心。

2017年8月,我带几位朋友去了一趟我们村。朋友们有心,给村里每户人家带了一条烟、一瓶酒。我正发愁如何通知大家来领,村长告诉我,他可以在微信群里通知一下。傍晚时分,乡亲们果真都来了,烟和酒一件不剩领走了。回想起我在农村时,村支书需要用铁皮卷成的喇叭筒大喊大叫很久,才能把全村人召集在一起,真是今非昔比。

S5.
结束语 

我祖父于1943年去世,当时只有三十岁,父亲刚刚12岁。祖父出生的时候(1913年),第二次工业革命的绝大部分新技术和新产品都已发明出来并投入商业化使用,他去世的时候,西方发达国家已经进入第二次工业革命的尾声,但他连第一次工业革命也没有经历。他短暂的一生中吃的、穿的、用的与他的祖父时代没有什么区别。

父亲比祖父幸运,他和我一起经历了三次工业革命。他下半辈子吃的、穿的、用的与祖父在世时大不相同,也与他自己的前半辈子有很大不同。他坐过火车、飞机、汽车,在我写这篇文章时,也许正在看着电视、用着手机。

我比父亲更幸运,因为每次工业革命我都比他早几年经历。我坐火车比他早,坐飞机比他早,坐汽车比他早,看电视比他早,用手机比他早。我还会上网购物,他不会。

我的幸运是托中国市场化改革开放的福。正是改革开放,使得像我这样的普通中国人有机会享受到人类过去三百年的发明和创造,即便我自己并没有对这些发明和创造做出任何贡献。这或许就是经济学家讲的创新的“外溢效应”吧!生活在世界经济共同体,真是一件好事。

据说第四次工业革命已经在美国的引领下开始了。如果中国晚四十年改革开放,我就得从后半生开始,和我儿子一起同时经历四次工业革命。如果那样,我敢肯定,未来40年中国经济增长率会比过去40年的实际增长率还要高,更让世界瞩目。但我还是庆幸,历史没有这样进行。

作为经济学家,在享受三次工业革命成果的同时,我还是期待着我们的国家,能在未来第四次工业革命中做出原创性的技术贡献,而不再只是一个搭便车者。我知道,九泉之下的杨小凯先生会立马警告说,这要看中国能否走出“后发劣势”陷阱。

-R/l2SR

 

Posted in 社会生活 | Tagged , , , | Leave a comment

mysqld运行时参数配置文件与命令行有何异同?

1. 在 my.cnf 中配置:
interactive_timeout=300 
wait_timeout=300
重启 mysqld, 通过 show vairables
mysql> show variables like ‘%timeout%’;
+—————————–+———-+ | Variable_name | Value | +—————————–+———-+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| have_statement_timeout | YES |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 300 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 60 |
| wait_timeout | 300 |
+—————————–+———-+
13 rows in set (0.00 sec)
能看到已经生效,但 mysqld 并不会在 300时杀掉 sleep 超过 300的连接。

2. 在 mysqld 的其中脚本 mysql.server 中增加:
other_args=”$other_args –explicit_defaults_for_timestamp –wait_timeout=300 –interactive_timeout=300″;
重启 mysqld 后, 通过 show variables 看, 参数无变化, 但当某个查询连接超过 300 时会被强行关闭。

为何? 配置文件中的指令不生效而命令行参数的指令则生效?

 

Posted in 服务器运维 | Leave a comment

超越前端Beyond Frontend — 吉密斯/gMIS 增加点选/PickUp概览功能

“….总是拿着微不足道的成就来骗自己….,
总是靠一点酒精的麻醉才能够睡去….”
— 台湾歌手郑智化《水手》歌词.

超越前端Beyond Frontend — 吉密斯/gMIS 增加点击勾选(点选)概览等功能侧记。
一直以来,gMIS吉密斯定位于管理操作后台、生产支撑、运营管控系统,主要面向于生产运营、管理操作人员,鲜有面向终端用户的机会,所以,设计考虑和实现权衡时,多是可用性,少有易用性。虽然多有追求美的勇气,终是在这方面难有建树。

直到写下这些文字,完成了gMIS具有标志意义的模块:点选/点击勾选/Pick Up/Click2Select. 从这一功能其,gMIS吉密斯已经具有超越一些前端设计交互能力的模块,强大且便捷。

S1.
基于数据库的管理系统主要功能是增删改查,其中的“查”字用的是最多的,可能1:9或者2:8于其他功能模块,也即1分量的增删改,对应着8~9分量的查,所以 gMIS吉密斯在“查”字上也下足功夫,目前主要的查询功能包括:

1. List页面试图顶部的快捷检索输入框;
(见下图)
2. “深度搜索查询”模块;

(gmis-deepsearch-with-quicksearch)
3. 站内搜索模块;
参考“-gMIS持续优化更新, +InSiteSearch站内搜索”,-R/52SN 。

这些模块应对的功能需求各部相同,前两个是基于单表查询,后一个是站内所有数据表“合适”字段的扫描。“点击勾选”已是“查”字上的第四个“搜索/查询”模块。

S2.
“点击勾选概览”在打开某一数据表的主体数据的同时,快速扫描主要字段,并对每一项字段按一定的规则进行汇聚,如统计去重数,计算区间等,然后生成一个针对该数据表的概览数据,并分别置为可供进一步筛选的“选项”,当用户点击某个“选项”时,下发列表数据自动做相应的更新,当有多个不同维度的“选项”被选择时,维度之间按“并且”求“交集”;当同一维度的多个选项被选中时,维度内选项按“或者”求“并集”——也即,当用户点击同一维度的两个选项时,我们理解为用户想要“A”或者“B”。

这里是对目前点击勾选实现的一次升级和超越——合并了多选和单选,集成到一个视图、同步完成,此其一;其二,在可供统计的维度,提供了聚类统计数据,对要浏览的数据能够一目了然,所谓“概览/概要浏览”。

(gmis-pickup-full-mode)

当我们被驱动要实现点击勾选时,我们对目前已经存在的实现做了一番考察。
1. 最先想到的是,几年前,我们用 GWA2 实现一个周边度假村数据检索的站点,其终端/前端页面对度假村的一些维度,实现了点选。用起来顺手,得意。@Shujuan
2. 点击勾选进入大众视野,并被广泛接受应该是电商平台的筛选功能,比如 -京东 , -天猫 等在商品列表页,均设计了点击勾选,按不同商品的不同维度,提供了各种筛选组合,其中将多选和单选分开进行。

(pickup-jingdong, 京东商品页面点选)

(pickup-tianmao, 天猫商品页面点选)

本质上,点击勾选/点选是为了减少用户输入的麻烦。这种繁琐来自两个方面:1)需要使用键盘操作,需要录入相应的关键词;2)有些情况下不知道目标关键词或者拼写错误等。

这次新增的“点击勾选概览”解决了这个麻烦,用户无需再手工录入相应的文字,依据“概览”提供的相应的线索,可以实现“按图索骥”一般,逐步筛选出预期的结果集。

S3.
与此前惯常见到的点选不同,gMIS 吉密斯的点选实现,还融合了多选与单选,不再显示地要求用户进行多选还是单选,当用户在同一筛选条件上选择一个“选项”时,我们理解为是单选,当用户选择两个以上的“选项”时,我们理解为用户是多选。如此简单、直白、有力,gMIS 吉密斯这一次超越了前端繁琐的多选、单选切换,融合单选、多选模式为一种操作模式。

(gmis-pickup-multiple-select)

单独做某一个/某一类的数据的拣选条件相对容易,正如电商平台里所列勾选条件一下,gMIS吉密斯需要一定的通用性,如何面对一个未知的数据集,能够在没有配置,第一次遇到时,就能够自动获得各种相应的具有统计意义的“概览”数据?

为实现这一点,我们将“数据”抽象为两大类——数值型和字符型。对于数值型的字段数据,我们设计了取值区段,并将可能的区段列出来供点选使用;对于字符型字段数据,我们使用枚举,并将尽可能多的记录的选项列在前排。有了这样的算法,对于任何给定的数据集,我们能够快速的排列出可供勾选的筛选条件列表。

这种做法,大多时是可靠的,尤其是对于数值型字段数据,在获得最小值Min和最大值Max之后,再辅以求值一个步长,很容易能够实现列出可供勾选的区段列表。对于字符型,也能够求得各个字段值的相应记录条数,尤其是一些枚举类型的字段,比如表现在管理后台的 select/选择项,或者 enum类型。

S4.
然而,我们不得不在工程实现时考虑异常,由于gMIS吉密斯的实现是通过页面 组装通信地址,然后通过GTAjax 递交给处理程序到服务器,然后将返回数据写入到指定区域,这种依赖JavaScript的功能实现,要考虑如何规避 “+”和空格,如何规避“'”, ‘”‘ 等敏感符号等,由于不能预先获知被管理数据类型(通用性要求),这些需要预先做兼容处理并Cover这样的场景。

于是,应对计算机符号问题的专家—— -Base62x 再次被排上用场。在生成候选选项列表时,对字符型的值进行 Base62x 编码(Server端PHP版本),前端点击触发相应 JavaScript 操作时,也使用同样的 Base62x编码(Client端JavaScript版本),当数据被递交回服务器端进行查询或显现时,又需要做解码操作,这一部分在 comm/header.inc 中完成. 有了这样的闭环操作,在管理页面上显示为明文的候选项,在通信和JavaScript代码层,则是Base62x编码后的无符号字符串,很好的规避了符号问题,类似的解决方案可参考:“-gMIS 吉密斯优化更新+分组项区段AddGroupBySeg/+复制AddByCopy等(-R/G2SW )” 提到的“注册动作registerAct: 改进增加 Base62x.class.js”。

S5.
额外地,点选与现有查询等功能的交互:1)在List顶部的导航快速搜索模块,当有选项被点选时,需要将对应的选项列入相应的输入框中,当List页面的右上角的“并搜”,“或搜”时,查询能够继续下去。2)当所点选的条件组合没有查询到相应结果时,gMIS吉密斯默认会给出当前查询条件组合并在每一个筛选条件上提供进一步地操作——去掉相应的条件做再一次的搜索尝试。这里就设计到快捷搜索和点选的交互。在此前的设计中,快捷搜索,当去掉一个搜索条件时,刷新List列表即可,而如果与点选结合,则需要进一步地更新点选的相关选项——选中或者未选中。

关于“选中/Selected”与“未选中/Unselected”,我们在设计时参考了在实现 -UFQI-News 的做法——当某个选项未被选中时,我们以常规的超级链接显示,并冠以加法符号“+”, 表述为:点击当前以“+”开头的链接表示在此前的语境上进一步的加上即将选择的内容;当某个选项已经被选中时,我们以背景色、前景色互换的方式将当前已经被选中的选项标识出来,并冠以“-”减法符号,表述为:点击当前以“-”开头的链接表示在当前语境中进一步地减去即将点选的内容。

(-UFQI-News)

-UFQI-News 的点选设计正符合这样的场景,于是就借用得来。当某个待点选的条件尚未被选择时,冠以加法符号,“+”,意为点击该选项,将在当前语境增加此条件;当某个已被选中的条件呈现时,冠以减法符号,“-”,意为点击该选项,将在当前语境减去此条件。大约符号语言或者“言简意赅”即是如此。

(gmis-selected-and-unselected)

S6.
通常情况下,可供使用的筛选条件维度,往往会有多个,默认为List页面所有显示的字段均提供了点击概览,通常这会慢慢地显示为一整屏幕,从而遮盖了List内容主体。为此,我们参考电商平台页面的筛选条件折叠功能,默认提供减缩模式,只列每个List页面的关键字段,也既List页面左侧的3-5个字段作为候选项列出来。
当遇有不适合作为候选字段的,则沿着List列表头部的字段往后顺延,凑齐了3-5个为算。

(gmis-pickup-full-mode)
当用户在默认减缩模式下无法满足检索需求时,可以点击右上角的“+更多”来显示全部可供使用的筛选条件。对应的,当用户在full-mode下点击右上角的“-更多”这可以收起富于的候选项,进入减缩模式。

S7.
gMIS吉密斯 点选PickUp功能带来变更模块摘要: 
1)comm/header.inc : + $base62xTag 及相应解码;
2)comm/ido.js : + fillPickUpReqt; 
3) + act/pickup.php 
4) + class/pickup.class.php 
5) ido.php: + doActionEx with act=pickup 
6) jdo.php: +doActionEx with act=pickup 
7) class/pagenavi: +containslist, inrangelist

一些继续的思考和改进:
1)针对一些字符型数值,如果按其值进行聚类统计,字符串截取太长则可能无意义,太短则又太笼统,根据小范围测试,目前默认值被设置为截取字符型数值的 240 字节;
2)针对数值型字段,其区间的划分,默认被划分为 12个区间;
3)字符型或选择型字段,如果候选项太多时,默认只显示前 12个选项。
这些默认值都有待进一步商榷。

 

gmis-logo-201606

-gMIS 是一种基于 -GWA2 的通用管理信息系统(Management Information System)应用软件,具有可配置的输入和输出接口、开箱即用等特征。
可以在其上构建各种管理应用软件系统,如
内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等, 以及各种行业应用管理系统软件,如
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统(BOSS)等等。
实现零代码开发、快速搭建各种管理信息系统(MIS).

-gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems (BOSS), etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

Lower Costs, 
Better Productivity.
降低成本,
提高效率.

“…看看可爱的天,摸摸真实的脸,
…想想长长的路,擦擦脚下的鞋…”
——电视剧《外来妹》主题曲

 

Posted in -gMIS, Base62x, 计算机技术 | Tagged , , , , , , | Leave a comment

-Base62x 新增 -Perl 版本技术实现 Base62x.pm

在此前的一篇Blog(-R/G2SW )中,“-gMIS 吉密斯优化更新+分组项区段AddGroupBySeg/+复制AddByCopy等”, 我们提到“注册动作registerAct: 改进增加 Base62x.class.js”, 初尝跨编程语言、运行时环境进行数据交换的便利,这次也因着部署一个新的 -GWA2 的项目,需要在 -PHP 和 -Perl 中进行多字节非ASCII字符数据的传递,于是就推荐了 -Base62x , 这样 Base62x in Perl 的工作就排上日程,在两个周末的实验下,完成了 Base62x in Perl 的初个版本. 如下是一些使用细节,同时也可以在 -GitHub-Wadelau 上寻找获得, 或者直接访问 -Base62x .

  1. 面向对象编程OOP的 Base62x.pm
    use Base62x;

    my $base62x = Base62x->new();
    my $str = “Hello World!\n”;
    my $encoded = $base62x->encode($str);
    $str = $base62x->decode($encoded);

    在 Perl 程序的开始,引入 Base62x.pm , 然后生成相应的对象实例,通过调用 该实例的 encode/decode 方法实现相应的编码与解码。
    同 Base62x 的其他版本相通,实现了跨编程语言、运行时环境的数据安全交换。
    同 Base62x的其他版本一样,Perl版本也实现了针对数字进制转换和ASCII快捷处理的相关方法。如,

    my $i = 100;
        # treas $i as base 10 and transform it into Base62x
    my $numInBase62x = $base62x->encode($i, 10);
        # try to decode a Base62x num into base 10
    $i = $base62x->decode($numInBase62x, 10);

    OOP的调用方式,适合进行循环内反复调用的使用场景,由于在实例化时,进行了环境变量的初始化而节省了后续重复动作。
    .

  2. 函数式编程的Base62x.pm
    除了 OOP式的写法,Base62x.pm 还提供了函数式编程的调用方式,列如下。
    use Base62x qw (base62x_encode base62x_decode);

    my $str = “Hello World!\n”;
    my $encoded = base62x_encode($str);
    $str = base62x_decode($encoded);

    函数式编程适合单一次启动并运行的使用场景。
    详细实现可以参考 Base62x.pm 的代码。
    .

截止目前,Base62x 已经可以提供的编程语言版本包括 C, Java, PHP, JavaScript, Perl. 其中JavaScript 还有两个实现, Base62x.class.js 和 npm base62x.


Base62x: An alternative approach to Base64 for only-alphanumeric characters in output.
Base62x is an non-symbolic Base64 encoding scheme. It can be used safely in computer file systems, programming languages for data exchange, internet communication systems, and is an ideal substitute and successor of many variants of Base64 encoding scheme.
Base62x 是一种无符号的Base64编码方案。在计算机文件系统、编程语言数据交换、互联网络通信系统中可以安全地使用,同时是各种变种Base64编码方案的理想替代品、继任者。

Posted in Base62x, 编程技术, 计算机技术 | Tagged , | Leave a comment

-gMIS 吉密斯优化更新+分组项区段AddGroupBySeg/+复制AddByCopy等

-gMIS 吉密斯持续更新优化升级,最近一段时间的功能改进包括如下几项,备忘如下。

  1. 数据透视Pivot模块: +分组项区段AddGroupBySeg
    这个功能面临的场景是,当我们在使用数据”透视“功能时,分组group by统计时,总是将整个字段的值参与计算,此前已经提供了 addGroupByDateYmd —— Ymd的功能是格式化时间相关的字段,以Ymd的形式参与计算。
    addGroupBySeg 则在此基础上更进一步,可以提供了截取字段值的给定区间部分参与计算。例如 iname字段的值是 abc123efg456, 如果需求希望截取iname的前三个字符参与计算,则可以调用 addGroupBySeg功能,同样地,也可以截取中间的 “efg” 出来。
    “数据透视Pivot“模块功能源自 Microsoft Excel,这一刻起,差不多要超乎 Excel的数据透视功能了。

  2. 数据操作: +复制AddByCopy
    在管理信息系统(MIS)中,录入数据是一件繁琐的事,有先后相邻两条记录差别不多时,可以通过复制前一条并做少量修改来满足实现快速录入数据的需求。AddByCopy 即是在此背景下创建的,当我们要输入相似、相邻的记录时,可以使用复制功能,快速使用此前刚刚录入的数据,极大地加快数据录入,提升工作效率。

  3. 页面Tititle修改为三级递进改进
    改进后:模块名称 – 目录名称 – 吉密斯(默认)。

  4. List模式: +字段在title hint时最长限制
    此前有字段限制在列表中显示的字段值最大长度,
    list_disp_limit = 38
    新增加在title hint时的字段长度限制,
    list_disp_title_max_length = 300
    如果不加 title hint时的长度限制,当遇到有字段类型为 text 的超长文本时,会憋坏整个浏览器进程/线程。

  5. 注册动作registerAct: 改进增加 Base62x.class.js
    计划了很久的事情,registerAct 本身由于 JavaScript的 escape有bug,当 Base62x.class.js 创制完成之后就想着替换,现在终于找到合适的时机,在服务器端使用PHP版本的 Base62x.class.php 对待注册的动作进行编码,然后在浏览器终端,使用JavaScript版本的 Base62x.class.js 对待注册的动作进行解码,进而进行动作注册,一气呵成。
    注册动作registerAct 是 -gMIS 发现的一个JavaScript进行透传待执行动作的方法。通常使用 Ajax 或者 iFrame 等方式进行服务器端/浏览器端进行数据交互时,无法将制定的 JavaScript方法释放到指定的执行域进行执行,registerAct 就是为解决这个问题而设计的。 

    同时得益于 Base62x.class.js 的引入, switchEdit 等函数也将获得更好的兼容性,inline模式的双击即编辑也将得到改善。

  6. 核心模块:db连接增加长连接
    得益于 -GWA2 的升级改进,-gMIS 在读取数据库数据时,如果探测或者根据设置,当PHP运行时环境支持数据库长连接时,则启动数据库长连接。
    至此在这方面的速度优化,又提升一点点。
    PHP + MySQL的数据库长连接是基于进程的,也即长连接在进程范围内共享,其MySQL并发的连接数大致相当于:
    Nginx/Apache所触发的PHP进程数 * Request并发数 * 每个Request实例化的数据库连接数.

  7. 安全模块Sid:+&db=
    改进 comm/ido.js , 针对 appendSid,增加了 &db= 为进一步的多数据库的支持提供保证.
  8. 安全模块移除 eval
    改进 comm/header.inc.php 中对 eval 的应用,降低外部输入带来恶意代码执行的风险。 PHP eval 类似 JavaScript eval 一样,具有不严谨的反射(Reflection), 对待执行的脚本如果检测不够严格,可能会有预留后门的隐患,已消除。
    eval 函数在 -PHP 官网( -R/P2ST  )上也被明显提示是“危险”的。
    Caution

    The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

  9.  更新getUrlByTime
    增加针对字段名称中含有 ”time“的,启用”00:00:00″ — “23:59:59” 的支持。

  10. 改进站内搜索InSiteSearch 初始化的逻辑
    使之能够兼容不同的数据库的情况.
    改进判定是否可检索字段的判断系数。

  11. 改进错误输出Error Print
    当有数据库数据读取异常时,显示更为友善的提示信息,并提供“反馈给管理员”的邮件链接,使异常处理更人性化一些。
    对于写重复等信息,提供了更直白的显示和解释。

    gmis-logo-201606

    -gMIS 是一种基于 -GWA2 的通用管理信息系统(Management Information System)应用软件,具有可配置的输入和输出接口、开箱即用等特征。
    可以在其上构建各种管理应用软件系统,如
    内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
    办公自动化系统(OA)等, 以及各种行业应用管理系统软件,如
    人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
    商品管理及业务运营支撑系统(BOSS)等等。
    实现零代码开发、快速搭建各种管理信息系统(MIS).

    -gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
    Various management application software systems can be built on it, such as
    Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
    Office automation systems (OA), as well as different industry application management system softwares, such as
    Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
    Commodity management and business operations support systems (BOSS), etc.
    With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

    Lower Costs,
    Better Productivity.
    降低成本,
    提高效率.

Posted in -gMIS, -GWA2, Base62x, 计算机技术 | Tagged , , , , | Leave a comment

GWA2-Java built-in cache with connection pool design/带连接池的缓存流程设计

最近花很大力气在 -GWA2-Java 中实现了带连接池的缓存设计流程(GWA2-Java built-in cache with connection pool design)并部署成功。之所以花很大力气,是由于这些功能在 -GWA2-PHP 中均没有碰到,兹整理记录如下。

按此前在 -GWA2-PHP 中实现的 built-in cache( -GWA2 更新缓存调用built-in cache方法,  -R/r2SH ),其大致思路是:
1) 应用对象 myObject 调取父类 WebApp的方法,
2) WebApp进一步地前转读取 Cache 的请求给CacheAdmin (Cachea);
3) CacheA 被调用后,首先查询配置及运行时参数,决定连接哪个在线服务,
4) 在获得服务器相关信息后,进一步地的查询配置及运行时参数,决定使用哪种驱动程序;
5)获得服务信息及驱动信息后,比如最终连接 CacheMaster主机,使用 Memcached 驱动,然后Memcached的实例被创建,Memcached完成初始化后,进行读写操作;
6) Memcached获得相应结果后,前转查询结果给Cachea,Cachea进一步地前转查询结果给WebApp及myObject调用对象。

这一流程可以用上图表示,其中一个完整的查询涉及到五个对象,五个流程分叉判断。五个对象为:myObject, WebApp, CacheAdmin, CacheMaster, Memcached;
五个分叉流程判断为:
1)是否读取Db还是Object对象数据?
2)是否读取Cache?
3)连接哪个Cache主机?
4) 使用哪种驱动程序读取Cache?
5) 是否有连接池到指定的Cache主机?

相比 -GWA2-PHP 的实现,-GWA2-Java 中需要额外地创建了 CacheDriver 接口 以此来约束和规范各个驱动程序模块,额外地创建和维护连接池程序,额外地创建Memcached Java Client。

这三种新的创造,单独拿其中一块都可以大书特书一篇。CacheDriver 接口相对容易,由于在 Cachea 需要预设一种对象类型,使之能够被赋值为某种驱动模块的实例,自然这就非 Java Interface 莫属,Interface CacheDriver 同时定义和约束了各个不同的驱动模块来实现相应的方法,从而保证数据流的正常流转。

Socket Connect Pool(SocketPool)相对复杂,但思路很简单,依赖Java Servlet Container可以维护运行状态的特性,创建一个可以寄宿其上的数据对象,并约定一定的状态管理机制即可实现。与Servlet Container本身提供的连接池(如JDBC的连接池)相比,这个需要自我手工实现。幸运的是,基于Java的连接池管理,早于2005年,我们在 -ChinaM 最早的解决方案中就有相应的实践及成功应用,这次是优化升级,并增加了根据先进的 SocketStream 和 SocketString 来应对不同的IO读写。

连接池能够极大地提升服务器性能表现,所以在最常见的场景,连接数据库时,Resin,Tomcat等均提供了针对数据库的连接池。而 Session, Cache 或者其他网络服务的连接池,则需要自行手工提供。这也是 -Java 在某些地方性能优胜的关键之一。在 201807年的一次针对 -PHP 应用环境的优化分析中,由于一个改进数据库连接的修改,直接优化节省一台数据库服务器。这个数据库连接由于在开发初期被置于某个循环体内的Bug,每次运行时,都会初始化向数据库的连接,导致开销大增。

比较难的模块是Memcached Java Client (Memcached, -R/r2ST ). 这个模块在 -GWA2-PHP 中是跟随PHP源码提供的,编译进去即可。而在 -GWA2-Java 中,则需要手工实现。好在有前人探索,也不需要重新造轮子,我们经过对比,选择了 -GitHub 上的 gwhalin 的 Memcached Java Client . 由于需要融合到 -GWA2 中,而且也觉得可以在优化一些该版本,主要修改如下:
1)  expiry 参数由 Date 修改为 int ;
2) 摘除自带的 SocketIOPool,融合上文提到的 GWA2 实现的 Socket Pool;
3) 改进对传入连接主机服务的支持;
4) 改进 if(a==1) b=2; 等不规范的为 if(a==1){ b=2; } ;
5) 改进key的 sanitize操作,用 -Base62x 替代 UrlEncoder,Base62x 比 UrlEncoder提供了跟“干净、短小”的字符编码; 判断当key 长度大于 32时,启用 MD5 操作等等。
从根本上来说,Memcached也不算复杂,就是操作Socket读写,类似Java Mail等类库一样。

至此,-GWA2-Java 基本完善,一段时间针对Java版本的集中优化基本完成,可以考虑将其应用到具体生产环境了。她的各种性能表现及更高级的优化,需要在实践中不断加深、加强。

-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.

 

Posted in -GWA2, 服务器运维, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

-Java forEach中 Lambda Expr中的 final变量要求

本文是关于 -Java Lambda Expression在forEach方法的应用讨论。对比其他编程语言的foreach 操作(文末附带7种主要编程语言的Loop HashMap by forEach的程序片段),Java 8引入的运用 Lambda Expression方式的 forEach操作方法是最接近语言所要表达的本意,且简洁、直接。
在持续优化 -GWA2 in -Java 过程中,由于 -GWA2 多层结构设计,层间数据传递很多依赖Map/HashMap完成,经常用到这个 forEach 并碰到一些问题(引入外部变量,有条件筛选及终止等),兹记录相关探索过程如下。

通常在 -Java 中遍历一个数据集合是常见的操作场景,比如遍历数组 (-R/G2ST ):

int[] numbers = 
             {1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
    System.out.println("Count is: " + item);
}

再比如常规的借助 keySet遍历一个key-value结构的 Map / Hash, 哈希 (-R/k2SP ):

for (KeyType key : m.keySet()){
    System.out.println(key+", "+m.get(key));
}

-R/k2SP 列举了三种方法进行遍历key-value 的Map, 实际上根据 -R/92SS  页面上第二个回答所进行的测试,大概有十多种方法可以实现遍历一个 key-value 的Map. 这么多方法中,又以 forEach 的表达最为直接、高效,所以推荐使用 Map.forEach .

forEach 本质上是建造一个 Lambda Expression 并进行运算,其中 Map.forEach 等同的表达式也是针对  keySet的调用( -R/V2SQ )。

//- Map.forEach is equivalent to:
for (Map.Entry<K, V> entry : map.entrySet()) action.accept(entry.getKey(), entry.getValue());

//- an example
HashMap<String, Integer> hm = new HashMap<String, Integer>();
hm.forEach((key, val)->{
    System.out.println(key+”, “+val);
    });

由于 Lambda Expression 是一个 enclosing scope,它与代码区块外的沟通成为问题,外部变量无法在 Lambda 内部调用,内部变量也无法在外部访问到。在这近乎隔离的运行时环境里,还留了final变量可以穿行的缝隙,如果要实现将Lambda Expr与外部变量进行数据交换,就需要在代码区块外部定义final类型变量作为数据信息载体。常见的应用有如下两个场景.

  1. 将Map/HashMap的数据遍历并加工
    例子程序:
    HashMap<String, Integer> hm = new HashMap<String, Integer>();
    final HashMap<String, Integer> hm2 = new HashMap<String, Integer>();
    hm.forEach((key, val)->{
        System.out.println(key+”, “+val);
        hm2.put(key, val + 1);
        });

    借助 Lambda Expression 对 final变量的支持,可以容易地将遍历并加工后的数据中转取出做进一步的操作.
    final 变量由于无法再次出现在赋值语句的左边,也即无法对对象做再次赋值操作。但这不影响我们后续将 hm2的值进行遍历或者将其复制到另外一个非final的对象中去,如上例中的 hm.
    同样地,作为final的 hm2 无法整体被赋值,但可以对其本身进行操作,如上例中的,通过 hm2.put 将某个元素放入这个容器中。类似的还有,比如 StringBuffer 的操作。

    StringBuffer pageIdsb = new StringBuffer(“0”);
    pageList.forEach((k, v)->{
        HashMap tmphm = (HashMap)v;
        pageIdsb.append(“,”).append(tmphm.get(“id”));
        });

    public final class StringBuffer
    extends Object
    implements Serializable, CharSequence

    由 StringBuffer 类的定义(-R/V2SQ ),我们知道其是 final 类,于是在初始化后,可以在 Lambda Expr中通过 pageIdsb.append 的方式进行其值的操作与变化。

  2. 有条件过滤或推出、终止遍历
    在遍历Map/HashMap等对象集合时,有时候需要有条件的过滤或者终止,如果将外部约束条件带入?
    又如何定义内部自循环变量?
    一种可行的方式,依然是使用 final变量,然后基本变量类型,如果定义为final之后则不能被直接修改,无法满足循环体内计数的需求.
    于是就需要设计一个复合final类的变量,其成员一个负责约束条件,另外一个负责循环计数。
    HashMap<String, Integer> hm = new HashMap<String, Integer>();
    final HashMap<String, Integer> hm2 = new HashMap<String, Integer>(){{
        put(“iCount”, 0);
        put(“maxCount”, 4);
        }};
    hm.forEach((key, val)->{
        int iCount = Wht.parseInt(hm2.get(“iCount”));
        int maxCount = Wht.parseInt(hm2.get(“maxCount”));
        if(iCount < maxCount){
            System.out.println(key+”, “+val);
        }
        hm2.put(“iCount”, iCount + 1);
        });

    在上面的例子程序中,我们定义了循环体内计数变量 iCount 和 满足退出条件 maxCount 每次循环时取出并做对比,每次循环时, iCount++ 。
    上面例子程序中的 Wht.parseInt 是 -GWA2 的基础设施类,可以在 -GWA2@Github (-R/h2SO )下载到.
    上面例子程序中的hm2 的声明实例中,通过构造方法并以一个匿名类完成了两个 put操作。关于匿名类 Anonymous Class,参考 -Java 文档(-R/i2SP ), 在 -GWA2 in -Java 里也有不少应用。
     

-Java 中引入的 forEach 操作,尽管是以 Lambda Expression为载体的一个 Consumer / BiConsumer对象,运行在一个 enclosing scope,依靠可以外部 final 变量这个渠道,可以提供媲美其他编程语言一样的 foreach 效果,对增加程序可读性、可维护性有一定的帮助,已有的评测 forEach也表现出不错的性能,值得更多地应用。

 

-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.


(1) Loop HashMap in PHP ****

$hm = array(“a”=>1, “b”=>2, “c”=>3);
foreach($hm as $key=>$val){
    print “key:$key , val:$val\n”;
}

(2) Loop HashMap in Perl ***

my %hm = (“a”=>1, “b”=>2, “c”=>3);
foreach my $key (keys %hm){
    my $val = $hm{$key};
    print “key:$key , val:$val\n”;
}

(3) Loop HashMap in Swift *****

let hm = [“a”:1, “b”:2, “c”:3];
for (key, val) in hm {
    print(“key:\(key) , val:\(val)\n”);
}

(4) Loop HashMap in Python ***

hm = {“a”:1, “b”:2, “c”:3};
for key in hm:
    print(“key:{} , val:{}”.format(key, hm[key]));

(5) Loop HashMap in C++ *

std::map<std::string, std::int> hm {
    {“a”, 1},
    {“b”, 1},
    {“c”, 3}
};
for(const auto& key : hm){
    std::cout << “key:” << key.first
        << ” , val:” << key.second
        << “\n”;
}

(6) Loop HashMap in JavaScript ***

var hm = {“a”:1, “b”:2, “c”:3};
for (var key in hm){
    console.log(“key:”+key+” , val:”+hm[key]);
};

(7) Loop HashMap in Java ***

HashMap<String, Integer> hm = new HashMap<String, Integer>(){{
    put(“a”, 1″);
    put(“b”, 2);
    put(“c”, 3);
}};
hm.forEach((key, val)->{
    System.out.println(key+”, “+val);
    });

 

Posted in -GWA2, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

参观“纪念马克思诞辰200周年主题展览”有感, Karl max, 200 Ani Exhi

2018年6月28日下午,在北京位于天安门广场东侧的国家博物馆参观了正在展出的“真理的力量——纪念马克思诞辰200周年主题展览”。

国家博物馆门口人潮涌动,工农商学兵各界,东西南北中各地的人群络绎不绝前来参观学习。主题展览位于国家博物馆的南区1、2和3号馆。入口处即是巨幅卡尔马克思的幕墙,然后映入眼帘的是卡尔马克思和弗恩格斯的合影铜像。各厅内展出了大量图像、史料、实物和相关人物,真实再现了卡尔马克思波澜壮阔的精彩人生,全面生动展示了马克思的生平、革命实践、理论贡献和精神境界,展现了马克思主义在中国传播运用和丰富发展的光辉历程。

或许是由于时序的关系,在领略其出生、成长、成才、奋斗、贡献等各个精彩的人生篇章后,当我驻足在卡尔马克思辞世的那副巨型油画前时,思绪感慨万千,久久未曾移开。

这副油画作者是当代著名艺术家艾中信先生。为纪念马克思诞辰200周年,艾中信创作了这幅油画《三月十四日》(1883年3月14日),再现了马克思在躺椅中溘然长逝的凝固瞬间。艾中信师从和追随徐悲鸿、吴作人等第一代油画大师,是我国的杰出画家、艺术家。

触动我的情感和思绪并引发我共鸣和思考的是这副油画的几个细节:老人、沙发、毛毯和掉落在地上的书籍。这无疑给人一种安详的感觉,作为全人类最为著名的无神论领袖之一,卡尔马克思辞世的瞬间却生动而自然地呈现了无疾而终天人合一至善至美的景象。

根据弗恩格斯后来在《在马克思墓前的讲话》中的细节描述,“3月14日下午两点三刻,当代最伟大的思想家停止思想了。让他一个人留在房里还不到两分钟,当我们进去的时候,便发现他在安乐椅上安静地睡着了——但已经永远地睡着了。”

卡尔马克思及其创建的共产主义是坚定的无神论者。如果不是因为这个,他的离世确切地符合佛教中的得道高僧的“圆寂”,这通常是一个人的大福报,是灵魂的得道升仙,成就不死的永恒。也许正是因为他的奋斗的一生、奉献的一世而得到上帝的垂怜或者眷顾,能够做到自然而然地油尽灯枯、溘然长逝,仿佛睡着了一般,永远地。

作为无神论者,显然不能这样推演。然而从唯物主义历史观出发,似乎有两个结论可以推测出来。一是,卡尔马克思对自身的内省认识,对个体生命的整体观念;二是弗恩格斯及其他卡尔马克思的亲密团队对生命的认识,对人生的思考。

与我们现在经常在新闻传播中听到、读到或者看到的领导人逝世,离得最近的词语就是“因病医治无效,于某某医院离世”。卡尔马克思的辞世时,为何是在家里,躺在沙发上,盖着毛毯,捧着书本? 这是多么享受的一幕,多么安详的画面,仿佛我们每个人都曾经历或者经常体验的那样——某个慵懒的午后,躺在自家的沙发上,看了一会书,然后就倦意袭来,昏昏睡去……

也许可以推测,卡尔马克思本人已经对生死有某种超然脱然的认识,所以当生命的终点或者尽头来临时,他选择的是待在自己熟悉的、温暖的家里,以自己舒服的姿势、读着自己喜欢的书,以此沉沉永远地睡去。

正是基于这一对生命的超脱认识,他选择了以家作为终点,而不是“于某某医院离世”。

其二,弗恩格斯及其他亲密团队成员,充分尊重卡尔马克思的选择,没有强行在卡尔马克思有生命危险时进行重度医疗。可以设想,以当时卡尔马克思的社会声望及地位,如果他需要医疗,可以召来全世界当时最好的医生团队,进行各种极其高精尖的治疗。

显然,卡尔马克思没有要求,甚至可以说是拒绝了进一步的治疗,信奉进化论的他懂得生死更替的大自然的规律。同时,他身边的人,也理解到这一点,并给予充分的尊重。我们无法还原每一个细节,甚至还没有充分的史料来表述与支持这些推测的想法,只能说这些或更贴近已经看到的这副油画。又或许这副油画是艺术的加工,当其时情景并不是那么和谐,这些都不重要了。

如果可以再多一些佐证的话,可以考虑近几年前离世的美国苹果公司的创始人之一史提夫乔布斯先生,当时他被诊断出某种疾病,但他淡然的接受并放弃过度医疗,自然地离去。史提夫乔布斯当时位列全球富人榜前列,以他的社会声望与财富,以近两百年后的不断进步的医学技术,他本应可以续命好多年,然而他却选择了放弃。

个体生命或许是相同的,思想的高度应是差异巨大的,尤其是在庸俗、平凡与卓越、领袖之间。这种巨大的差异不单体现在辉煌的事业上,亦表征在挥别这个美好世界的一刻。

Posted in 社会生活 | Tagged , , , , | Leave a comment

SQL查询优化: 既有Unique Index为何还要另加Index?

在使用 -GWA2 进行WebApp开发时,我们创建基于MySQL的相关数据表时,都会有意识地在数据表的关键字段上增加索引,以期待查询时能够较快地返回结果集。

在我们现有的生产线上的数据观测中,同样一张数据表,通常当数据达到10M+时,如果某个待检索字段(用在Where里作为查询字段)没有使用索引,一次查询大约需要耗时50s+,如果增加了相应的索引,则单次查询大约耗时5s左右,性能提升10倍以上。

所以,理论联系实际,我们都应该在相关待检索的字段上增加索引,这次要提及和澄清的是增加Unique Index还是Index? 只增加Unique Index,还是Index即可?或者两种Index都需要? 在检索方面,Unique Index保持了数据的唯一性,实际兼有Index的功能,在被检索时提供同样的优化性能。

情况稍微复杂一些的例子是这样,当一个Unique Index增加到多个字段的组合上时,其Index的作用并不能想当然地将Index效果追加到每一个组合中的字段上。如下是 -MySQL 官方文档对于组合字段的Unique Index的描述。

-R/u2SN  ) “If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1)(col1, col2), and (col1, col2, col3).
MySQL cannot use the index to perform lookups if the columns do not form a leftmost prefix of the index. ”

用简略地话来说,Unique Index的Index作用:1)当只有一个字段时,其Index作用也同样地施加到该字段上;2)当为多个字段的组合时,其Index的作用,只施加到组合的第一个字段上。

所谓差之毫厘,谬之千里。当待检索的字段是某个Unique Index的组合字段之一,且不是第一个时,被用做Where的查询条件,查询性能将急剧下降,每次皆是全表扫描,逐行对比。

这种性能隐患,在开发初期并不容易发现,只有当数据量级增长到10M+时,查询耗时才会逐步显现出来。

 

gwa2-logo-201606.v2

-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序, 
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等, 
也包括各种企事业单位网上门户,在线交互及服务作业系统等. 
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .
-GWA2 is a “General Web Application Architecture”, and based on -GWA2 developers can easily build a variety of network applications,
Including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various enterprises and institutions online portals, online interaction and service operations systems.
And it also includes server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出. 

Posted in -GWA2, 服务器运维, 计算机技术 | Tagged , , , , , | Leave a comment

Apache-Tomcat: 虚拟主机VirtualHosts

接续此前的 “嘗試 Apache + Apache Tomcat (簡稱 Tomcat)融合” , -R/H2SL ,和 第二篇,“apache tomcat: mod_jk missing uri map”, -R/n2SK ,  这次叙述一下在 Apache 和 Tomcat 下融合搭配虚拟主机 Virtual Hosts的事, 顺带回应前述,为何技术选型是 Apache + Tomcat ,而不是 Nginx + Resin ?

1. 为何选用“Apache + Tomcat”?
单一就性能而言, Ningx 在服务静态页面胜过 Apache , Resin 在服务动态页面上胜过 Tomcat,那么强强联手,Ningx + Resin 的搭配应该会胜过 Apache + Resin. 至少理论上是这样,然而理性的技术选型中,技术性能是一方面,也会考虑经济性,这也是一些互联网公司曾经有过的关于去 IOE (IBM, ORACLE和EMC,分别代表大规模计算, 数据处理和存储)的浪潮的一个依据。

在从计算机&IT业早期,我所接触的就是 Resin 作为Java的Application Server,多年过去之后,当我再次思考这个问题的时候,我的认识发生了改变,这次我选择了 Tomcat,而不是 Resin,经济是一方面,其开源和社区属性应该是另外一面,相应地性能优势已经不是那么明显。
由于硬件性能几十年来一直以摩尔定律(单位面积上的集成电路晶体管数量每18-24个月翻一倍,性能提升而价格-成本下降)的速度在发展,如果纯粹的开源软件无需考虑这些,而如果是以一定的成本购买来的性能提升,是否该软件带来的性能提升速度能够跟得上硬件摩尔定律的发展?
设若以1000$的硬件运行A软件(1000$)获得性能为1000个并发,B软件(0$)为500个并发;一两年后,1000$的硬件自然地能够运行B软件(0$)获得1000个并发。此时如果A软件(1000$)相应地预期应该能够获得2000个并发,如果不能,我们认为这笔开支是不理性的。实际运营需求,可能对性能的要求并没有快过硬件的摩尔定律式的发展。这一问题回归,就是花成本在购置软件上的获得性能提升是否值得或者经济,尤其是在分布式,云计算大行其道的情况下? 可能的场景是,如果现在花1000$购置某闭源软件带来+500个并发性能,而1-2年后,同样的硬件成本可以0$的获得+500个并发性能,此时额外的1000$到底该不该花?

决策时的另一个考虑是,无论是 Ningx 还是 Resin 其开源版本总是给人一种“阉割版”的印象,要想要更高级的功能,都需要花钱才能实现,这多少令人不爽。开源和闭源都可能打造较好的软件,但免费推出“阉割版”,然后根据高级功能收费,这种做法,在我看来是不合适的,只好对 Ningx 和 Resin 说再见,尽管他们在性能上有优秀的表现,我更相信对 Apache 和 Tomcat 的站队投资,能促使其不断成长、优化和改进,形成良性循环。

多年来,随着 -gMIS-GWA2 的成长、成熟,从软件开发者的角度,我越来越能理解到,一款所谓好的软件,就是有人不断地使用,不断地应对新的scenarios,不断地修正bugs,从而不断地健壮、丰富和强大。Apache, Tomcat 应该也是这样,软件发展注定会是马太效应,强者更强,弱者更弱,某个细分领域,某个独特场景下,最终可能只会存在1-2款软件。

几年前,在 -人民网 进行某个互联网项目前期调研时,其中对互联网应用的发展趋势,有个小结是,互联网因的越来越具有服务方式的排他性和内容格式的统一性——大白话就是某种应用(服务)只存在其本身就够了,天下无二;在其上,各种内容兼容并包,既有文字、图片、动画,也有音频和视频,基于这些小众内容分类创新也基本不用想了。

这是今次我这么选择 Apache + Tomcat 的原因。接下来继续回复关于在 Apache 和 Tomcat 下设置虚拟主机VirtualHost的细节。

2. Tomcat 的虚拟主机配置
虚拟主机的配置,在以前的blog里提到过,”apache, resin, ssl对虚拟主机的支持”,  -R/12SY , 这次就不再重复在 Apache 里设置虚拟主机的情况,转而重点在 Tomcat 对虚拟主机的支持及设置情况.

Tomcat对虚拟主机的支持,官方文档和网上教程也有一些,下面是一个小结。

在 Tomcat 的 conf/server.xml 中,在
<Server>
    –> <Service>
        –> <Engine>
            –> <Host> 
中并列地新增一个 <Host> 标记即可。例如,默认的 <Host> 形式为

<Host name=”localhost” autoDeploy=”true” appBase=”webapps” …

在此之后,并列的新增一个针对虚拟主机的 <Host>设置,一般情况的形式为

<Host name=”srvXXX.ufqi.com” autoDeploy=”true” appBase=”/www/webroot/srvXXX”>
    <Context path=”” docBase=”/www/webroot/srvXXX”></Context>
    <!– something else –>
</Host>

其中 “<Context>” 需求强调的是,如果不通过其设置 docBase, 按 Tomcat的默认,则请求 http://srvXXX.ufqi.com/abc.jsp 时会将解析指向默认 <Host> 的默认 docBase ,通常是 默认 <Host> 的 appBase , 也即 webapps/ROOT .
通过 <Context> 设置新的 docBase之后,这可以解决这一解析寻址路径,再次请求 http://srvXXX.ufqi.com/abc.jsp 路径时,会按图索骥地在 /www/webroot/srvXXX 目录下进行寻找,从而能够获得预期的请求资源。

进一步地,由于 Tomcat 的部署默认对象单位是 application,所以即便不指定 docBase ,在 /www/webroot/srcXXX 子目录(application)下的相应资源是能够被准确定位的。上述情况,如果不指定 docBase , 通过访问路径 http://srvXXX.ufqi.com/pathX/abc.jsp 则是能够获得相应地资源的。

3. 对SSL 的支持
在设置相应的虚拟主机时,如果在 Apache 上启用了 SSL支持,可能一般情况下都会启用,而且以后会成为默认选项。
按 “apache, resin, ssl对虚拟主机的支持”,  -R/12SY  的描述需要在 Apache 的 conf/extra/http-ssl.conf 中做相应的设置,才能使得 Apache + Tomcat 对 SSL 的预期的支持。

Posted in 服务器运维, 编程技术, 计算机技术 | Tagged , , , | Leave a comment

-gMIS持续优化更新, +InSiteSearch站内搜索

-gMIS 部署和应用的场景越来越多,最近在考虑为所有gMIS承载管理的数据库系统增加一个站内搜索功能, +InSiteSearch 。前因是在 2017年11月份的更新中,我们设想“层级目录导航是“传统”的,属于 Yahoo 时代的产物,未来的导航应该是 Google 式的智能导航。
未来拟开发一个 gMIS 域内全文搜索引擎,这样用户就无需使用或者记录层级目录。” (-R/p2SM)。 约半年后,我们实现了这方面的一个探索。

主要动机可以类比为Yahoo时代的目录搜索与Google时代的全文检索,当 -gMIS 所管理的对象超过一定数量级后,管理人员面临的问题就自然而然地迷失在多层复杂的目录式的导航中,如何有效地定位到目标功能模块成为迫切需要解决的问题。(在Google出现之前,用户想找某个主题/关键词的内容,需要去Yahoo的站点目录里去逐层逐级的查找相应的站点,Yahoo提供的网站目录满足了当时的需求)

站内搜索也被称之为局域网搜索Intranet search /Onsite search有别于互联网搜索Internet search. 其目的是搜索网址内部通常不公开的,格式化或者非格式化的内容。-gMIS 针对此项的规划远景是集成一个智能助理。

  1. 站内搜索InSiteSearch主要思路

    格式化数据的搜索是一个老课题。相对于非格式化数据,比如常见的网页数据,格式化数据有得天独厚的优势,我们能确切的预先知道,数据的格式、类型与规模。
    在获得这些之后又该怎样实现站内搜索呢?
    大致有两个思路,列如下。

    一是将待搜索的数据,读取到某个index service上实现对数据的indexing,当有某种关键词进行搜索时,按indexing的数据进行相应数据的返回。
    这种方式,是事先、同步地将所有格式化数据同步到indexing 服务,并实现相应的增删改的操作同步。
    也即,在格式化数据库/表之外,需要独立的建立一套应对全文搜索的数据结构存储系统,通常为 keyword–>pagelist 结构,也即某个待搜索关键词会对应一个包含该关键词的文档列表,其中列表的排序规则为某个权重值,其主要指标是为了表名当前关键词与当前文档的依存关系。
    若无意外,该indexing的数据存储结果将同等尺寸于原始格式化数据。
    另外一种思路,也即,是否可以为待搜索的数据提供某种roadmap(路书、地图),当有某种关键词进行搜索时,知道在什么地方以什么方式进行搜索。而实际数据的增删改人保留在原数据库/表中,当下的站内搜索InSiteSearch只是提供某种ShortCut服务,该服务能够实现以较为经济的、智能的方式,帮助调用者以较合理地方式返回预期的搜索内容。
    可以设想,在这种思路下,系统不需要创建一套indexing服务,也不需要额外地复制全部格式化数据副本作为待检索的对象。
    也即,当触发在全域进行某个关键词进行搜索时,InSiteSearch知道该关键词最可能出现在某些数据表的数据字段项上,而不太可能出现在其他字段项或者其他数据表相应的字段项上。
    这种路书(地图)导引式的搜索辅助设施,将极大地提升搜索范围和搜索精度,在格式化数据的搜索上,很好的契合了搜索需求的应用场景。

    两相比较,在 -gMIS 中,我们选用了,基于路书的指引式站内搜索方式。

  2. 站内搜索InSiteSearch的实现方式

    依据前述讨论,我们在 -gMIS 中实现了基于导引式地站内搜索实现。其主要操作内容如下。
    A. 创建 insitesearch 表
    用于存储当有基于某个关键词进行搜索时,所依赖的数据表路径。
    insitesearch表的生成主要依赖 /act/insitesearchsort.php 程序。
    该程序读取当前数据库连接下的所有数据表,并分析每个数据表的每个字段,如果发现当前字段数据可被检索字符串类型,通常为char(4-255),则将该数据库、数据表的数据字段记为待检索字段。
    以此循环所有数据表的所有数据字段,生成待检索数据字段列表。
    当有待搜索关键词递交到系统程序时, /extra/insitesearch.php , 站内搜索引擎程序按图索骥地逐个待搜索数据库、数据表、数据字段的进行检索。
    根据当前页的size设置,搜索到N个结果时,自动返回给调用者,以此形成翻页功能。

    B. 增加站内搜索入口
    对应地,我们在 进入系统主页和list view识图页面,在顶部导航栏增加了对 站内搜索 的接入功能,若用户需要进行站全域站内搜索,只需将待搜索关键词递交给搜索模块即可实现该功能。

    C. 动态更新搜索源
    辅助地,我们在 

    Π 首页  桌面 & 系统配置 → 搜索源配置 | 搜索源配置 

    增加了对 搜索源的配置与管理,在该模块可以实现对待搜索列表的手工更新与配置。当有新的数据模块被手工添加到当前数据库时,可以通过 “更新搜索源列表” 来实现对待搜索资源列表的更新与维护。

    D. 精细化操作的黑白名单设置
    同样地,我们在

    Π 首页  桌面 & 系统配置 → 搜索源黑白名单 | 搜索源黑白名单

    额外地增加了对待搜索源的黑白名单设置,以满足特性的运营需求,比如当某个数据库的数据表的数据字段被程序规则判定为“黑名单”时,可以在此将相应的条件设置为允许“白名单”;同样地,当某个数据库的数据表的字段被程序判断为“白名单”而通过系统检测,可以在此将相应条件设置为“黑名单”,以阻止其进入待搜索队列。

  3. UI批量更新与优化
    单条记录更新模块,增加了行间距,当字段之间跟容易识别;
    字段名称加粗显示,区别与字段值、字段备注等信息;
    列表显示时,增加了 break-all 属性,数据表默认不再撑破窗口,在纵向滚动和横向滚动中选择其一,仍不能排除某些情况下,纵横项同时滚动的可能;
    更新GTAjax,修正增加对 Array.sort 的支持;
    增加对List View下的活跃记录的所有字段值加粗显示,响应鼠标事件;
    增加对JavaScript更多的异步调用,页面提速更快;
    bugfix for getSelectOption;
    +checkSQLKeyword
    +allow multiple order fields

  4. 增删改查搜算
    截至 InSiteSearch 功能发布以后, -gMIS 的核心功能已经由 增删改查 升级为 增删改查搜算 (Create, Retrieve, Update, Delete, +Search, +Statistics)。
    其中”搜” 指的是增加了站内搜索功能,而算 则是指 -gMIS 中的数据透视功能,可以轻易地实现对目标数据表的各种维度的数据统计计算功能。
    可以预见 -gMIS 将从普通的通用信息管理功能逐渐升级改进,增加更多的商业智能功能模块,为业务运营支撑提供更多的信息数据与决策支持。

  5. GitHub 被 Microsoft 收购
    会影响到 -gMIS 在 -Github 的托管与开源吗?

 

gmis-logo-201606

-gMIS 是一种基于 -GWA2 的通用管理信息系统(Management Information System)软件,具有可配置的输入和输出接口。
可以在其上构建各种管理应用软件系统,如
内容管理系统(CMS),客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等, 以及各种行业应用管理系统软件,如
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统等等。
实现零代码开发、快速搭建各种管理信息系统(MIS).

-gMIS is a -GWA2 based Management Information System (MIS) software with configurable input and output interfaces.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems, etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a minute.

Lower Costs, Better Productivity.
降低成本, 提高效率.

Posted in -gMIS, 服务器运维, 编程技术, 计算机技术 | Tagged , , , | 2 Comments

商业组织忠诚与职业道德

最近在读《Investments》(投资学, -R/G2SS )第十版,在其中“Excerpts from CFA Institute Standards of Professional Conduct”章节提到CFA对客户第一条要“Loyalty(忠诚)”,对雇主的要求中第一条也是要“Loyalty(忠诚)”。尤其是对客户的忠诚里,要求必须把客户利益的优先级放在自己的利益前面。这听起来与某些党派的对组织忠诚、先人后己的要求很相似,如果是这样,是不是觉得“党性”要求不那么苛刻?

顺着这个忠诚的话题,我捡了几个反例叙述,商业不忠诚及职业不道德的例子示以警示。

  1. 中介员工自己跳单
    做中介的最怕跳单,大意是在居间服务市场,买家和买家通过中介取得联系后自行交易,绕过了中介一方。这在中介市场是严重不允许的,中介居间费用也是中介赖以生存的源泉。所以如果买家、卖家任一方试图绕过中介进行跳单,必遭中介追诉。
    据闻眼下,有某中介组织员工可以自己设定跳单并私吞中介服务费用。当某员工履行职责引荐买家、卖家之后,撮合达成交易收取居间费用,但上报给中介组织的内容却是交易未达成,并以服务费打折、优惠为条件劝诱买、卖双方与自己保持一致的说辞。然后再通过某种方式取消此次买卖标的物的邀约。一切像没发生过一样。
    买家、卖家、中介员工三方均受益,而唯一受损的一方是中介组织。

    类似例子,似乎并不止于中介服务,其他组织中应该也存在,员工利用其组织平台谋取私利,并对组织谎报内容。

    以损害组织利益谋取私利实在罪有应得,却屡禁不绝,大致是人的本性使然,组织如何在一定程度上使之不能、不敢、不想这样?

    也据闻眼下有在不损害组织利益的情况下谋取私利,比如统计数据修改。

  2. 程序“魔法值”修改账单
    统计数据是组织进行商务活动所依赖的根本。实施统计数据修改,一般是内外勾结在一起进行。员工A与外部合作伙伴甲达成利益输送,员工A在其数据底层,通过修改日志、统计数据输出,将原本属于合作伙伴乙的收益算入到合作伙伴甲账上。进而,合作伙伴甲收到额外的空账后再分赃给员工A。
    表面上看,似乎天衣无缝一般。组织总账平衡,不多不少,员工A和合作伙伴甲都受益,唯一受损的是合作伙伴乙,但其并不知情。

    这一犯罪的实施,需要修改生产系统或者统计程序的源代码,而且要通过某种“魔法值”(未经定义的常量,语见《码出高效——阿里巴巴Java开发手册》,-R/92SP )来进行,也即所说的“后门”的一种。

    计算机程序代码通用规范中明确要求不能使用这种“魔法值”,而一些不遵守这样约定的软件通常以“高效”等要求直接在代码中使用这些魔法值,通过使用这样的“魔法值”来满足日益复杂多变的运营需求。久而久之陷入混乱的恶性循环,也为通过这样的“魔法值”修改来实施利益输送提供了温床。

    大型的软件及互联网企业,严格要求这一项,既有技术层面的代码规范、可读性要求,还有言下之意不允许额外的特例出现在代码层,从根本上杜绝了通过“魔法值”来实施犯罪。

    如果某些作业系统程序复杂、多变,且充满了“魔法值”,则这样的犯罪实施起来将得心应手,且死无对证。除了员工A和合作伙伴甲,无人知晓,而利益受损方合作伙伴乙并无感知,也不会发起追诉。

本质上,个体是趋利的,理性的思维又要求个体要遵守商业文明。个体选择扭曲价值观的不忠诚、犯罪,一定是群体的体制机制存在一定问题。列以上反例,大致也能从侧面显示商业环境的恶劣、人性的扭曲和制度的崩溃。

法国经济学家Thomas Piketty在其著作《Capital in the Twenty-First Century 》(21世纪资本)(-R/M2SM )中表示,社会财富正由拥有资产(土地、工厂、设备)等的“地主”向拥有知识与创新的“精英”转移,职业经理人将在财富分配中扮演越来越重要的角色,其对组织的忠诚度似乎也显得格外重要。

这种白手起家或靠发明创造而快速巨额致富成为可能的社会,被现任英国首相Theresa May在其演讲中称之为“MeritCracy”(-R/F2SO ),这似乎是对经济学家的发现的印证。 

经理人或员工是人,人本性是自私的,如果一个组织不能抑私扬善,职务犯罪则防不胜防,组织最终将溃于一个个自私的蚁穴。就像一个社会,如果不能弘扬正义、彰显公平,各种犯罪则愈演愈烈,社会最终将泯灭于一件件自私的犯罪下。

Posted in 社会生活 | Tagged , , , , | Leave a comment

[转]母亲的舍得

【编按】微信朋友圈传的文章,题目是自拟的,有人说可比语文课的《父亲的背影》,微言大义,是为推荐。

父亲去世10年后,在我的“软硬兼施”下,母亲终于同意来郑州跟着我——她最小的女儿一起生活。这一年,母亲70岁,我40岁。70岁的母亲瘦瘦的,原本只有一米五的身高,被岁月又缩减了几厘米,看起来更加瘦小,面容却仍然光洁,不见太多沧桑的痕迹,头发亦未全白,些许黑发倔强地生长着。 

我们借了一辆车回去接她,她早把居住了几十年的老屋收拾妥当,整理好了自己的行李。那些行李中有两袋面,是她用家里的麦子专门为我们磨的,这种面有麦香。但那天,那两袋面我决定不带了,因为车的后备箱太小,我们要带的东西太多。母亲却坚持把面带着,一定要带,她说。 

她这样说的时候,我忽然愣了一下,看着她,便想明白了什么,示意先生把面搬到里屋,我伸手在外面试探着去摸。果然,在底部,软软的面里有一小团硬硬的东西。如果我没猜错,里面是母亲要给我们的钱。 

把钱放在粮食里,是母亲很多年的秘密。十几年前,我刚刚结婚,在郑州租了很小的房子住,正是生活最拮据的时候。那时,我最想要的不是房子,不是一份更有前途的工作,只是一个像样的衣柜。就是那年冬天,母亲托人捎来半袋小米。后来先生将小米倒入米桶时,发现里面藏着500块钱,还有一张小字条,是父亲的笔迹:给梅买个衣柜。出嫁时,母亲给我的嫁妆中已有买衣柜的钱。后来她知道我将这笔钱挪做他用,便又补了过来。那天晚上,我拿着10元一张厚厚的一沓钱,哭了。那些年,母亲就是一次次把她节省下来的钱放在粮食里,让人带给我,带给大姐二姐,在我们都出嫁多年后,仍贴补着我们的生活。但那些钱,她是如何从那几亩田里攒出来的,我们都不得而知。这一次,即使她随我们同行,也还是将钱放到了面袋里,在她看来,那是最安全的。

面被带回来后,我把钱取出来交还母亲,母亲说,这是我给童童买车用的。童童是她的外孙,这段时间他一直想要辆赛车,因为贵,我没有给他买,上次回老家,他许是说给母亲听了,母亲便记下这件事。2000块,是她几亩地里一年的收成吧,我们都不舍得,但她舍得。记忆中,母亲一直是个舍得的人,对我们,对亲戚,对左邻右舍,爱舍得付出, 东西舍得给,钱舍得借,力气也舍得花。有时不知道她一个瘦小的农村妇人,为什么会这样舍得。母亲住下来,每天清晨,她早早起来做饭,小米粥、小包子、鸡蛋饼……变着花样儿。中午下班我们再也不用急赶着去买菜,所有家务母亲全部包揽。阳台上还新添了两盆绿莹莹的蒜苗,有了母亲的家,多了种说不出的安逸。 

母亲带来的两袋面,一袋倒入桶里,另外一袋被先生放到了阳台上。过了几天,我却发现阳台地板上的那袋面被移到了高处的平台上晾晒。先生是个粗心的人,应该不会是他放的,我疑惑地问母亲,她说,啊,我放上去的,晒晒,别坏了。我一听就跟她急了,那平台, 一米多高 ,那袋面,六七十斤,身高不足 一米五,体重不足90斤的母亲,竟然自己把它搬了上去。我冲她大喊,你怎么弄上去的?那么沉,闪着腰怎么办?砸着你怎么办?出点儿什么事怎么办……一连串地凶她。她却只是笑,围着围裙站在那里,等我发完脾气,小声说,这不没事吗?有事就晚了!我还是后怕,但更多的是心疼。直到母亲向我保证,以后不再干任何重活,我才慢慢消了气。 

母亲来后不久,有天对先生说,星期天你喊你那些同学回家来吃饭吧,我都来了大半个月了,没见他们来过呢。先生是在郑州读的大学,本市同学的确很多,关系也都不错,起初还会在各家之间串门,但现在,大家都已习惯了在饭店里聚会。城市生活就是这样繁华而淡漠,不是非常亲近的,一般不会在家里待客了。我便替先生解释,妈,他们经常在外面聚呢。母亲摇头,外面哪儿有家里好,外面饭菜贵不说,也不卫生。再说了,哪儿能不来家呢?来家才显得亲。然后,母亲态度坚决地让先生在周末把同学们带回家来聚一聚。我们拗不过她,答应了。 

先生分别给同学中几个关系最亲近的老乡打了电话,邀请他们周末来我们家。周末一整天,母亲都在厨房忙碌。下午,先生的同学陆续过来了,象征性地提了些礼品。我将母亲做好的饭菜一一端出,那几个事业有成、几乎天天在饭店应酬的男人,立刻被几盘小菜和几样面食小点吸引过去。其中一个忍不住伸手捏起一个菜饺,喃喃说,小时候最爱吃母亲做的菜饺,很多年没吃过了。母亲便把整盘菜饺端到他面前,说,喜欢就多吃,以后常来家里吃,我给你们做。那个男人点着头,眼圈忽然就红了,他的母亲已经去世多年,他也已经很久没回过家乡了。 

那天晚上,大家酒喝得少,饭却吃得足,话也说得多。那话的内容,也不是平日在饭店里说的生意场或单位里、社会上的事。很少提及的家事,被慢慢聊起来,说到家乡,说到父母……竟是久违的亲近。那以后,家里空前热闹起来。母亲说,这样才好,人活在世上,总要相互亲近的。 

母亲来后的第三个月,一个周末的下午,有人敲门,是住在对面的女人,端着一盆洗干净的大樱桃。女人有点儿不好意思地说,送给大娘尝尝。我诧异不已,当初搬过来时,因为装修走线的问题,我们和她家闹了点儿矛盾。原本就不熟络,这样一来,关系更冷了下来,住了3年多,没有任何往来。连门前的楼道,都是各扫各的那一小块儿地方。她冷不丁送来刚刚上市的新鲜樱桃,我因摸不着头脑,一时竟不知该说什么好。她的脸就那样红着,有点儿语无伦次,大娘做的点心,孩子可爱吃呢……我才恍然明白过来,是母亲。母亲并不知道我们有点儿过节儿,其实即使知道了,她还是会那么做,在母亲看来,”远亲不如近邻”是句最有道理的话。所以她先敲了人家的门,给人家送小点心,送自己包的粽子,还送自己种的新鲜小蒜苗……诚恳地帮我们打开了邻居家的门。后来,我和那女人成了朋友,她的孩子也经常来我们家,奶奶长奶奶短地跟在母亲身后,亲好得犹如一家人。 

邻居们,不仅仅是对门,前后左右,同一个社区住着的许多人,母亲都照应着。她常在社区的花园和先生同事的父母聊天,帮他们照顾孙子。不仅如此,还有物质上的往来,母亲常常会自制一些风味小点,热情地送给街坊四邻,这也是母亲在农村生活时养成的习惯。小点心虽然并不贵重,却因有着外面买不到的醇香味道,充满了浓浓的人情味。 

有一次,得知先生一个同事的孩子患了白血病,母亲要我们送些钱过去。因为是来往并不亲密的同事,我们只想象征性地表示一下,母亲却坚决不答应,说,人这辈子,谁都可能会碰到难事,你舍得帮人家,等你有事了,人家才会舍得帮你。孩子生病对人家是天大的难事,咱们碰上了,能帮的就得帮。我们听了母亲的。 

在母亲过来半年后,先生竟然意外升职,在单位的推荐选举上,他的票数明显占了优势。先生回来笑着说,这次是妈的功劳呢,我这票是妈给拉来的。我们才发现,最近我们的人际关系竟然空前好起来,那种好,明显地少了客套多了真诚。一个字都不识的母亲,只是因为舍得,竟不动声色地为我们赢得了那么多,是我们曾经一直想要赢来却一直得不到的。再想她说过的话,你舍得对人家好,人家才会舍得对你好。于她,这是一个农村妇人最朴实本真的话;于我们,无疑是一个太过深刻的道理。 

温煦的日子里,我很想带母亲到处走走。可母亲因为天生晕车,坐次车如生场大病,于是常拒绝出门。那个周末,我决定带她去动物园。母亲说,没有见过大象呢。动物园离家不远,几站路的样子。母亲说,走着去吧。我不同意,几站路,对一个70岁的老人,还是太远了。可她又坚决不坐车,我灵机一动,妈,我骑车带你去。母亲笑着同意了。我推出车子,小心地将她抱到前面的横梁上,一只胳膊刚好揽住她。抱的时候,心里一疼,她竟然那么轻,蜷在我身前,像个孩子。 

途中要经过两个路口,其中一个正好在闹市区。小心地骑到路口,是红灯,我轻轻下车,还未站稳,却有警察从人流中穿过来,走到我面前说,不许带人你不知道吗?还在前面带。说完,低头便开罚单。母亲愣了一下,攥着我的胳膊要下来,我赶忙扶稳她,跟那个年轻的警察说了声对不起,解释说,我母亲晕车,年纪大了,不能坐车,我想带她去动物园看看…… 

警察也愣了一下,这才看清我带的是一位老人,还不等他说什么,母亲责备我,你怎么不告诉我城里骑车不让带人呢?然后坚持要下来。我正不知所措,那个警察伸手一把搀住了母亲,大娘,对不起,是我没有看清楚, 城里只是不让骑车带孩子,您坐好。然后他忽然抬起手,向我认认真真地敬了个礼。接着,他转身让前面的人给我腾出一个空间,打着手势,阻止了四面车辆的前行,招手示意我通过。我带着母亲,缓缓地穿过那个宽阔的路口,四面的车辆静止行人停步,只有我带着母亲在众人的目光里骄傲前行。 

那是我有生以来第一次受到如此厚重的礼遇。因为母亲,因为舍得给予她一次小小的爱,一个萍水相逢的年轻警察,便舍得为我破例,舍得给我这样高的尊敬。这礼遇,是母亲送给我的。 

母亲是在跟着我第三年时查出肺癌的。 结果出来以后,有个做医生的朋友诚恳地对我说,如果为老太太好,不要做手术了,听天命尽人事吧。这是一个医生不该对患者家属说的话,却是真心话。和先生商议过后,决定听从医生的安排,把母亲带回了家。又决定不向母亲隐瞒,于是对她讲了实情。母亲很平静地听我们说完,点头,说,这就对了。然后,母亲提出要回老家。 
母亲在世的最后一段时间,我陪在她身边。药物只是用来止疼,抵挡不了癌症的肆虐。她的身体飞快地憔悴下去,已经不能站立,天好的时候,我会抱她出来,小心地放在躺椅上,陪着她晒晒太阳。她渐渐吃不下饭去,喝口水都会吐出来,却从来没有流露过任何痛苦的神情,那些许黑发依旧倔强地蓬勃着,面容消瘦却光洁,只要醒着,脸上便漾着微微的笑容。那天,母亲对我说,你爸他想我了。妈,可是我舍不得。我握着她的手,握在掌心里,想握牢,又不敢用力,只能轻轻地。梅,这次,你得舍得。她笑起来,轻轻将手抽回,拍着我的手。但是这一次,母亲,我舍不得。我说不出来,心就那么疼啊疼得碎掉了。母亲走的那天,送葬的队伍浩浩荡荡,从村头排到村尾,除了亲戚,还有我和先生的同学、朋友、同事,我们社区前后左右的邻居们……很多很多人,里面不仅有大人,还有孩子,是农村罕见的大场面。 
队伍缓缓穿行,出了村,依稀听见围观的路人中有人议论,是个当官的吧?或者是孩子在外面当大官的……母亲这一生,育有一子三女,都是最普通的老百姓,不官不商。母亲本人,更是平凡如草芥,未见过大的世面,亦没有读过书,没有受过任何正规教育,她只是有一颗舍得爱人的心。而她人生最后的盛大场面,便是用她一生的舍得之心,无意间为自己赢得的。 

Posted in 社会生活 | Tagged | Leave a comment