今天的问题让我又一次意识到不注重用户体验,以及忽视产品细节是传统PC端业务系统的通病。

这些系统的产品经理很可能抱着那种能用就行的态度,你可以鄙视他傲慢,也可以笑话他无知。

说他傲慢是因为这类软件的使用者鲜有那些持有话语权的高级管理者,往往是那些最基层用户在用,好不好用都得用,不得不用,你可以提改进意见、花钱实现需求,但实现永远跟你想象差一大截,他不会真正花心思了解用户的诉求;说他无知是因为他根本不懂产品,他用他的无知不断降低产品质量、降低用户对好产品的期望,这一点也是他傲慢的缘由。

市场上的这类产品能做到实现业务功能的同时,又兼顾操作友好的,少之又少,大部分是那种平平无奇的,企业只能在其中做选择。再加上这类产品实施周期长投入费用高,跟业务深度绑定,在没有客观因素存在的情况下,企业很难有决心花大的代价找替代,这又造成了让他觉得自己系统很棒的错觉。

假如把产品当作的自己孩子,他不是合格的父母。

到6月底,也就是下周,我就从上家公司离职满一年了,今天突然接到一个贵州的前客户电话,向我咨询问题。

我对这个客户很是熟悉,去过他家,至今仍记得几年前到贵州,在他的家乡,第一次见面认识,他不但工作上很配合,还非常热情地接待我这个毛头小伙,带我认识当地的风土人情,相谈甚欢,因为这也是我感兴趣的,真没想到虽初次见面竟也如此自然。后续的多次会议上也有见面,偶尔也有过电话交流。他都一如既往的热情而又待人以诚,起码跟我这种技术人员是这样。

所以,我的意识里他是一位真诚、热情、值得信赖的老大哥。今天的电话我当然接了,听到对方声音很是亲切,只是问题我确实记不大清楚,简单给了排错建议,未能解决问题,再者,囿于上班时间办公室人多不便多说,简单聊了几句个人发展问题,只能引导老大哥联系原公司其他同事了。

工作这些年来接触到了一些人,特别是这些因工作相识的人,有的人即使在你离开公司彼此不再有交集了,他还是那种能找到你,让你乐意帮助他、愿意跟他交流的人,这大概也是这些人能成功的原因之一吧。

今天是端午节,午饭媳妇要吃饺子,孩子要吃龙虾,这两个都是费时费力的活。最后午饭包饺子,晚饭烧龙虾。

烧龙虾的技能是多年前跟我的老同学学的,作为农村人深知近年龙虾生活环境的恶化,一般我是不主动吃龙虾的,特别是外面饭馆那种整烧的做法,他们不会花太多功夫在清理龙虾上。

好在老同学传授的那套烧龙虾流程重点就在清理龙虾上:清水洗,刷子挨个刷,剪掉步足,去头抽尾,特别是去头这一步尤为重要,龙虾头部实在太脏了。清理过后整个龙虾只剩螯足和腹部了。这种清理方式的好处自然是清理的更干净、烧起来更易入味了,坏处是整个清理过程比较费功夫。

略过烧制过程,起锅装盘即成,孩子吃的可香了。

昨天是六一儿童节,这天早晨我在睡梦中被孩子叫醒,此时尚未到起床时间,往常是我到点起床烧好饭再叫醒孩子,今天孩子提前醒来,叫醒并提醒我不要耽误了到校时间,原来孩子学校今天组织夏游。

等到送到学校门口,孩子是蹦蹦跳跳冲进学校大门的;然而今天早上孩子是迈着稍显迟缓的步子走进校园的,可能是昨天夏游一天太累了吧。😄😄😄

最近几天办公室几乎每天都在讨论今天谁谁家的孩子学校组织旅游了,给人的感觉是最近全市的学校都在有序地组织孩子去本地的几家头牌收费景点旅游。从幼儿园至今在学校的组织下光动物园就去好几次了。记得去年在本地的乐园春游孩子带了100元,买了两根冰棍,自己一根请同学吃一根,又买了一个大概是义乌产的小钥匙扣,最后只剩下5块钱。疫情重创下的本地旅游业,只能靠学校的孩子们来救急了。

学校组织的旅游本是好事,但是,在当下大量人员从上海流散出来的节骨眼,如此大规模组织孩子到社会人员流动频繁的景点真的合适么!但是,真的只能选那几家收费的头牌景点来回轮流去么!

最近用到了正则表达式,总结下常用的正则表达式。

所有单词

'pear orange apple abc123 oracle'.match(/\b[a-z]+\b/gi);
//pear orange apple oracle

以指定字符串开头的单词

一个条件

以 app 开头的单词

'pear orange apple abc123 oracle'.match(/\bapp[a-z]*\b/gi);
//apple

也可以写成这样:

'pear orange apple abc123 oracle'.match(/(\bapp)(?<=\1)[a-z]*\b/gi);
//apple

总体来讲,这个模式不如上一个模式直接,好在可以通过这个模式来了解断言和引用两种语法:
这里使用了后行断言语法 (?<=y)x,仅当 x 前是 y 时匹配 x:(?<=\1)中的\1 引用的是模式 (\bapp)所匹配的文本(即开头是 app 三个字母,\b 是词边界),(?<=\1)表达的意思是只在开头是 app 时匹配后续的字母。 (\bapp)(?<=\1)[a-z]*合到一起就是开头的 app 加上后续的字母 le,得到 apple 。

多个条件

以 app 或 ora 开头的单词

'pear orange apple abc123 oracle'.match(/\b(app|ora)[a-z]*\b/gi);
//orange apple oracle

这里通过 (x|y)语法实现多个条件任选

以指定字符串结尾的单词

le 结尾的单词

'pear orange apple abc123 oracle'.match(/\b[a-z]*\Ble\b/gi);
//apple oracle

不以指定字符串开头的单词

比较拗口,也可以说以非指定字符串开头的单词。这里以非 app 开头的单词为例

'pear orange apple oracle'.match(/\b(?!app)[a-z]*/gi);
//pear orange oracle

不以指定字符串结尾的单词

le 结尾的单词

'pear orange apple abc123 oracle'.match(/[a-z]*(?<!le)\b/gi);
//pear orange

以下为本次任务用到的模式:

匹配 sql 语句中的注释

匹配 sql 语句中的注释部分,sql 注释有两种形式:--/**/

/(\/\*(.|\r\n)\*\/|\-{2,}[^(\r\n)].*(\r\n)*)/gi

其中\/\*(.|\r\n)\*\/匹配/**/形式的注释,之所以将它方前面,是因为这里使用了任选模式 (x|y),在找到匹配项之前,它会从左到右依次匹配任选模式,一旦匹配到左边的就不会继续匹配右边的任选模式了。现实中/**/注释中可能会存在--形式的字符,这就要求匹配/**/形式注释的模式优先(靠左),否则将会出现匹配不到的情况。

匹配 sql 语句中用到的表和函数

/\b((call|join)[\s\r\n\t]+(?!(\"?\w+\"?\.?\"?)?(t[e]?mp_|ds_|unnest|query_str|json_|splittable|\())\1+\"?\w+\"?\.?\"?\w*)|\b(((from)[\s\r\n\t\b\(]+)(?!(\"?\w+\"?\.?\"?)?(t[e]?mp_|ds_|unnest|query_str|json_|splittable|(\bselect)))\1+\"?\w+\"?\.?\"?\w*)|[\s\r\n\t\b]*crm_\w+\b/gi

这是迄今我写的最复杂的正则表达式了,这个模式可以满足以下要求:

  • 匹配关键字 callfromjoin 和表名;
  • 支持开头关键字排除,如排除 tmp_开头的;
  • 支持开头指定关键字,如匹配所有 crm_开头的;
  • 支持以下 sql 写法:
select a.c1,d.c4
from (((t1 a left outer join t2 b on (a.c1 = b.c1))
left outer join t3 c on ( b.c2 = c.c2))
left outer join t4 d on ( c.c3 = d.c3))

参考:MDN 正则表达式