分类 未分类 下的文章

先创造两个概念.
实时服务: 为极短时间内需要得到满足的需求提供的服务. 极短时间通常为几分钟. 如打车/批改作业/外卖等.
居中平台: 联系供需两端生意的平台.即: 自身既不提供需求,也不提供产品或服务, 而是由个体或组织提供. 例子是: 天猫/淘宝/滴滴/美团外卖等. 而京东/亚马逊有自营店, 则不算.高德地图/微信等直接提供服务, 也不算.
互联网实时服务的居中平台似乎都不约而同推出过抢单机制. 滴滴司机抢单/美团外卖小哥抢单/作业帮批改方也抢单. 似乎最后抢单都沦落为机器人抢单.
抢单的出发点开始都是公平公正公开吧, 另外还有点竞争投标的意味, 最后看谁手速快. 但需求似乎永远稀缺, 人永远比不过机器, 所谓供方抢单最后都变成机器人大战. 保证公平似乎还都要回到派单机制.

技能树展示倒是很好的主意

flowchart RL 我---能力 & 简历 能力---数字化 & 软件开发 & 管理 & 产品 & 供应链 数字化---办公 & 数字化管理 & RPA 数字化管理---ERP & 网店管家 & 钉钉 & 企业微信 & Git ERP---EcountERP Git---Gitlab & Github & Gitee & TortoiseGit 办公---文字 & 数据 & 视觉 RPA---UiBot初级证书 & UiBot中级证书 & UiBot高级证书 文字---Word & Markdown & Typecho 数据---Excel & Pandas & numpy 视觉---PPT & Inkscape & Yed & Matplotlib 软件开发---编程 & 测试 & 软件开发管理 软件开发管理---瀑布 & 敏捷 敏捷---TAPD & 站会 & 快速迭代 & UT & TDD & Jenkins 瀑布---需求分析 & 概要设计 & 详细设计 & 编码阶段 & UT阶段 & ST阶段 & IT阶段 测试---Appium & ADT & Selenium & Devtools & Fiddler & Wireshark & Postman 编程---JavaScript/H5/CSS & Python & 嵌入式编程 JavaScript/H5/CSS---Node & Vue & Electron 嵌入式编程---C & MicroPython & FreeRTOS & VxWorks & DOPRA & ESP8266 & W601 产品---ID设计构思 & 结构设计构思/设计 & 模具设计构思 & 量产前阶段控制 结构设计构思/设计---SolidWorks & FreeCAD & OpenSCAD & AutoCAD 量产前阶段控制---打ID样品 & 打结构样品 & 打研发样品 & 打生产样品 & 小批量 & 批量 & 中试 供应链---采购 & 计划 & 生产 & 仓储 & 物流 简历---UESTC & 安国 & 华为 & 大康 & 中兴 & 锐取 & 爱讯 & 康康 UESTC---电子信息工程 安国---MCU开发攻城狮 华为---嵌入式开发攻城狮 & 欧洲售后攻城狮 & 欧洲服务售前经理 大康---三级心理咨询师 锐取---售前攻城狮 & 产品经理 爱讯---产品经理 康康---产品经理 & 产品总监 & 供应链总监 & 副总经理

  • .task作为公共函数库, 似乎只能被当前流程调用,不能跨父子调用
  • 在一个task中的全局变量i似乎是有些奇怪的, 在其所在的task X中的funtion A调用i没有问题, 然而在另一个task Y中调用task X的funtion A时, i就会变成未定义状态. 似乎跨task调用function 并不会将task整体运行一遍,而只是截取其中需要运行的function来运行.
  • .flow是一个json
  • .flow级别的全局变量是所有本flow下的task公用的, 但不能给其他子flow或父flow用.
  • flow之间传递值, 就需要将.flow的变量定义为输入或者输出. 输入变量即相当于flow的形参, 输出变量即相当于flow的返回值.但是,要想使flow中的变量生效, 必须运行flow而不是task.如要父flow的参数能传递到子flow,必须从父flow开始运行.
  • flow里面的操作是不是ctrl-z的

对默认企业级框架的说明

概述

  • 虚线异常导到异常流程快这个功能似乎只有在企业级框架里面才有, 自己编写框架的话是弄不出来虚线的
  • 在配置配置初始化/目标程序初始化/获取新数据三个阶段发生异常就会直接退出
  • 在主业务流程运行时发生异常就会进行按次数重试, 重试从目标程序初始化开始

配置初始化

  • 企业版需要修改 config.xlsx的读取方式为从commander中读取.
  • 流程是读取config.xlsx->读取并设置logLevel->读取并设置g_iRetryNumber->config.xlsx的内容赋值给全局变量g_dicConfigData
  • res\data\config.xlsx中读取配置. 这个文件已有的默认参数不要修改, sheet名不要修改, 其他流程块会有用的. 不过可以在已有sheet里增加新的参数, 也可以增加新的sheet名. 增加新参数不需要改代码, 增加sheet名需要修改sheetsName数组
  • logLevel和g_iRetryNumber后面直接用, 不要用g_dicConfigData里存的副本了, 因为这儿进行了一些健壮性的处理,比如有没有值啊, 值对不对啊之类
  • 截图存储位置还是用g_dicConfigData["常量设置"]["ExScreenshotsFolderPath"]吧, 似乎这儿又没有专门给一个短一点儿的变量用了.
  • 从这个流程快的描述来看, 复杂业务数据不推荐也存储在config.xlsx中, 最好另建立文件. 我看似乎也不那么绝对, 如果业务数据不多的话, 放在一个文件里, 用户也比较好管理吧

目标程序初始化

  • 一般不需要修改
  • 默认的代码就是杀掉config.xlsx/本地参数/appsName中的进程
  • 进程名是用逗号分隔, 从代码看没有对空格处理, 所以在config.xlsx中写这个参数的时候不要留空格

首次运行判断g_bFirstRun

  • 不需要修改
  • 配置初始化中赋值True, 在获取新数据中赋值False, 而由于配置初始化只运行一次, 意味着这个判断只会有一次为True. 这次为True的目的只是为了在初次运行前获取新数据

重试判断g_bRetryStatus

  • 不需要修改
  • 配置初始化中赋值False, 在重试计数中按最大重试计数进行翻转. 即: 未达到最大重试次数时为True,并把g_iCount++, 达到了为False并将重试计数器g_iCount清零.

重试计数

  • 这个块需要修改, 主要是使能截图上传代码
  • 这个块只能通过主执行流程的异常进入
  • 默认代码是重试判断和计数的操作
  • 有一部分被隐藏的可选代码,是按config.xlsx["常量设置"]["ExScreenshotsFolderPath"]的配置路径保存本地截图并上传给commander截图的.
      If (shotsPath <> "") And (Not IsNull(shotsPath))
          Upload.UploadScreenShot("image_"&sRet,shotsPath,True,{"sDescribe":"最后一次重试后的现场截图"})
      End If
  • 这个Upload.UploadScreenShot函数按其说明是会自动截图并上传的, 其实名字叫ShotScreenAndUpload比较好些吧...
  • config.xlsx["常量设置"]["ExScreenshotsFolderPath"]中写配置路径的\是不需要转义的,写一个\就行了
  • 重试计数后会进入目标程序初始化,目的应该是杀一下app清洁一下运行环境. 根据是否重试,决定再操作一遍还是操作下一组数据

获取新数据

  • 这个块是需要修改的
  • 主要是从自定义的xlsx文件中读取一行数据, 代码需要补充自定义的xlsx文件名和读取的位置, 以及多条数据读取是不是要循环一下? 要有个静态变量存储一下当前读到那一行了? 当然uibot没有静态变量, 故而又要定义一个全局的了...
    
    objExcelWorkBook = Excel.OpenExcel("",True,"Excel","","")
    arrayRet = Excel.ReadRow(objExcelWorkBook,"Sheet1","A1")
    Excel.CloseExcel(objExcelWorkBook,True)

g_dicTransactionItem["TransactionData"] = arrayRet

* 当然我觉得为了读取一行数据就开关一次excel(这么耗费CPU和时间的操作)似乎有些傻, 是我的话就在`配置初始化`里面一次从Excel读取所有数据,然后再进行内存操作, 所以上面这段excel读取代码可以删掉,重写为变量读取代码.

## 是否有数据判断
* **需要修改键值**
如下:
```vb
Not IsNull(g_dicTransactionItem["TransactionData"])
  • 其中TransactionData是需要修改为实际的键名的, 如出发地之类的,如果找不到这个键名就认为没有数据
  • g_dicTransactionItem这一项在配置初始化/获取新数据中都会初始化为null. 当然这样看在配置初始化中再初始化为null显得很多余, 且不说在flow定义全局变量的时候本来就会初始化一次, 这样就至少初始化为null 3次了.

异常处理

  • 企业流程需要修改, 添加截图上传操作
  • 这个模块只能通过异常进入, 包括配置初始化/目标程序初始化/获取新数据三个模块的异常
  • 异常处理后的结果就是流程结束

流程结束

  • 如果运行完没什么特别要做的可以不用修改
  • 不过这儿的注释里有几个非常重要和有趣的系统变量! 尤其是有版本号! 似乎系统变量/常量都是$开头的
      $BlockInput:  上一个实线连接的流程块的Return值,或者上一个虚线连接的流程块抛出的异常
      $UB.InstallPath: UiBot的安装路径
      $UB.Version: UiBot的版本信息,将会得到一个Dict变量,里面包含不同的字段,标明版本信息的不同组成部分。今后还会扩充
      $Flow.WorkPath:当前运行的流程或者子流程的所在路径。如果是流程,就是流程所在路径。如果是子流程,就是子流程所在路径。
      $Flow.ElaspedTime:当前运行的流程或者子流程已经运行的时间,以毫秒为单位。比如 $Flow.ElaspedTime 的值为100,代表从当前流程开始运行,到目前为止已经过了100毫秒。
  • 版本$UB.Version的值举例:
    {
    "InstructionBits" : 64,
    "Product" : "UiBot Creator Community 5.5.0"
    }

    因为能在worker和store上运行, 所以对应的版本显示应该有所不同.

高级认证学习笔记

编程规范

1. 注释

  • 文件(流程块)注释
    
    /*
    作者: 
    时间: 
    说明:
    设计步骤:
  1. */

  • 变量注释 //
  • import注释, 位于import后面 //
  • 调用命令注释, 位于调用命令上方 //
  • 设计步骤需要在对应的代码上方注释
  • 连续出现的操作命令需要注释(推荐)
  • 函数需要注释,如下:
    /*
    功能:通过用户名匹配数据表,得到对应的值
    入参:数据表、用户名
    出参:返回对应用户名的值
    */
    Function MyFun(dateTable,userName)
      Return "xxx"
    End Function
  • 条件和循环需要注释(推荐)
  • 增删改的代码上方需要注释,如下(推荐)
操作 注释方式
增加 //Add by xx. yyyy.mm.dd
...
//End
修改 //Mdf by xx. yyyy.mm.dd
...
//End
删除 //Del by xx. yyyy.mm.dd
//mdf by WL 2020.4.24
//false修改为true
Excel.CloseExcel(objExcelWorkBook,true)
//End

2. 驼峰命名

类型 要求
变量 首字母小写
全局变量 g_开头
布尔变量 is开头
布尔值 首字母大写, False/True(奇怪没有用全大写)
空值 Null, 但建议小写为null(嗯,怪怪的, 不打算服从)
数据类型 dict/arr等开头
函数名 首字母大写

3. 异常处理

  • 异常不要用来做流程控制,条件控制。
  • catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理
  • 捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。

4. 日志 Log.Info

* 必须对日志级别进行设置
* 在流程编写和测试过程中,日志级别设置为3级,便于流程运行过程中通过日志中的相关日志和调试信息进行代码调整;测试通过后,流程正式上线生产环境之前,将日志级别设置为2级,调试输出内容不作为正式日志内容。
* 流程块步入、步出日志。在每个流程块中,开始功能代码之前先写入日志,说明对应流程块开始执行;所有功能代码结束后,写入日志说明对应流程块运行结束。如下所示:
Log.Info("环境初始化开始")
…
Log.Info("环境初始化结束")
  • 需求步骤完成日志。若为在项目之中进行的开发工作,需求步骤完成日志必须与《流程设计说明书》中“2.流程步骤说明说明”章节描述的保持一致,例如:
    
    Log.SetLevel(2)
    Log.Info("银联POS流程环境初始化即将开始")
    //结束所有谷歌浏览器进程
    App.Kill("chrome.exe")

  * 关键操作完成注释。在部分容易出现异常的界面操作完成后,建议添加日志内容来体现动作的完成,例如:
```js
//点击下载按钮
Mouse.Action()
Log.Info("下载按钮点击成功")
  • 逻辑分支日志。在涉及单个或嵌套逻辑判断、循环语句,在不同逻辑分支或循环内需添加日志说明,例如:

我认为在If里面添加注释就好了, 所有的If都添加Log实在是多此一举, 尤其考虑If在循环中的时候, 大量数据会使得日志中充斥着无用的分支日志

// 如果没有文件,则发送邮件,结束流程
If Len(fileList) = 0
Log.Info("本次无需导入数据,准备结束流程")
exit()
Else
    Log.Info("需要导入数据,流程继续运行")
End If
  • 否则日志内容中不得出现流程中涉及的数据、凭证等其他信息,如开发或测试过程中需要对相关数据进行确认或调整,要求使用调试输出命令。
  • 用于流程调试或测试的数据,不能写入日志,如需进行确认或调整,要求使用调试输出命令

[插播]人机交互模式下的提示信息

确实有人的人机交互模式下, 按照中级的要求似乎要有右下角信息提示.Dialog.Notify("Content", "Title", "0") 最后一个是icon.
但Worker中的人机交互并不是一定有人守着, 因为Worker也有定时, 定时器到的时候人不在旁边也很正常. 所以Worker的人机交互指的是与Worker的交互而不是和Bot的交互

5. 单元测试

  • 【强制】单元测试是可以重复执行的,不能受到外界环境的影响。
  • 【强制】对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级别,一般是方法级别。
  • 【推荐】UiBot Creator包含单元测试命令,在测试过程中可以视情况使用该命令。
  • 【推荐】单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到 100%
  • 【推荐】编写单元测试代码遵守 BCDE 原则,以保证被测试模块的交付质量。
    B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
    C:Correct,正确的输入,并得到预期的结果。
    D:Design,与设计文档相结合,来编写单元测试。
    E:Error,强制错误信息输入(如:非法数据、异常流程、业务允许外等),并得到预期的结果。
  • 【推荐】在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例。

6. 代码托管

  • 在项目中进行开发工作时,为了方便代码的管理、共享以及安全,要求所有的代码借助第三方工具SVN或Git进行代码托管。
    托管包括/res, *.flow, *.task