Soft_Job 板


LINE

如题 目前做的project架构长这样 Loader1 Loader2 Loader3 ........... Loader30 Area 1 Area 2 Area 3 .... .... Area 10 就是同一个Loader 会算出结果给不同Area的人 有分成前端跟後端,前後端都是我维护 (前端 .Net Framework java script MVC,会 用到一点 jquery,其他大多套套件用现成的物件再加工,後端就纯C# query DB用的工具是公版的不用自己写,就负责input 要打的SQL跟DB,然 後output datatable或是对DB做insert/delete/update....) Loader每支老板认知都不算很大所以也是一人包办XD Loader每支的逻辑也类似: Start--->会记录log表示loader开始 Initial setting----> query一些接下来SQL会用到的config QueryRawData---->把上一个initial function的config带下来在这里组成SQL string 并且query进data table ProcessData--->对上一步的data 做运算然後转换成可能只有一个kpi值的结果 或是pre-sum过後的结果 (举例来说query hourly的资料转换成daily的资料) End---->只是记录log表示上面的function都执行完了 看似很稳定 但loader却需要不断的更版 原因是因为SQL全部都是写死的,接水其他系统的资料 https://imgur.com/a/xjTfPfG 以这个图为例,USER只看的到最终的TABLE,没有太多空间可以弹性修改query的条件 也没有像左上角有弹性调整query资料的方法 (有config但是很少) 所以需求常常长得像这样: "tinasfishs 啊你帮我改一下,我发现今天的KPI有错,因为 今天开始要加采计'AA' 这种类别,麻烦再帮我改" 原始SQL通常长这样 SELECT COUNT(1) CNT FROM STORE_SALES WHERE 1=1 SELECT * FROM STOR_SALES WHERE 1=1 ( AND TYPE IN ('A','AB','BC',....'DZ','AA') AND SALE_DATE BETWEEN SYSDATE-3/24 AND SYSDATE-1/24 AND MT_CODE IN ('2','5') AND...... CASE WHEN .... )A, ( SELECT EMPLOYEE_DEG,EMPLOYEE_NAME FROM EMPLOYE_L WHERE AREA='AREA1' AND RES_PRODUCT NOT LIKE '%AAZc' .... .... ... )B, ( SELECT EMPLOYE_ID,EMPLOYEE_SHIFT FROM SHIFT_ARRANGE_LIST WHERE RECTIME>SYSDATE-5 AND AREA='AREA1' if (AREA=='AREA1' or AREA=='AREA2') { RECTIME<SYSDATE-1 } )C WHERE A.SALE_EMPLOYEE=B.EMPLOYEE_NAME AND B.EMPLOYEE_ID=C. EMPLOYEE_ID SQL通常都很长而且用sub-query,会把商业逻辑埋在hard-code的SQL里面 不能用SQL处理的逻辑则是在ProcessData那步处理 假设绿色的地方是config,黄色的地方则是这次修改的部分 重点是改後端的SQL都需要重新上code,虽然有提供公版的工具把SQL另外储存 只要呼叫那个外部工具就可以把SQL取得 但前人为了开发方便 当然全部都把SQL直接摆在程式里 然後复杂的是,同样算这个KPI,各个AREA 的条件是不尽相同的 用蓝色字的地方就是举例,没有使用config而是用C# 的code 直接hard code 这两个 area 需要加此条件 所以也会衍生像是 "我们是AREA3,AREA1 跟 AREA2 看的那个条件我们从下礼拜开始也想跟着采计 ,你们可以重新上code吗" 有爬文像是Stored procedure 之类的做法,歹势对於这个架构完全不适用 理论上像这样各个area的条件有不少差异的情况下,应该是个别维护各area的loader 但这整套是写在一起的...,每次上code为了维护版控也会在各area同步上同一套 也就会发生改A坏B,假设area1跟area2 共用同一段SQL条件,答应area1删掉 其中一句之後,area2 就跑来说他们的KPI异常 这个专案负责接水30几支上游的TABLE,就有30几支LOADER..而且还在逐渐增加中 所以谈需求跟开发的时候,根本也不是从 "为什麽要新增AA这个条件,除了改SQL有什麽更好的方式" 去切入 因为那要去询问上游以及user为什麽要新增这个条件太花时间 而是 "帮我改SQL吧比较快"---> 所以从来都只在做改SQL这种很末端的工作 一个礼拜大概有4-5个这样的"假需求"---->我定义为只是改SQL,请user验验看是否 符合他们期望 user有时候也不确定改了条件是否就会对,改了也不能上code 总是改了再测测了再改 这样的需求都做完了,才有时间去处理可能真的是loader本身的问题 ----->效能的问题啊、要新增一支新loader 与user谈规格之类的....orz 谈规格也是我一人,顶多再加0.5个PM PM也跟我想像会把规格谈到不会让日後充满这些维护 刚好相反 最後规格谈一谈还是常常诉诸短解 能够hard code SQL就hard code,理想性的应该要跟上游负责系统的人看资料 怎麽接轨的沟通过程完全没有= = 我有坚持过想先看清资料流再做新需求也因为求时效性被打枪 有被训练得比较有警觉性,但一个SQL 至少20行,下面又有条件让user高兴改就改 实在很难用很大的框架去处理这样的事,SQL有记得拔出来放在另外存的地方 不用重新上code就很不错了 BTW SQL逻辑跟要接水什麽报表通常都是由USER提供 ----------- 有跟老板沟通过像这样接水别人资料的汇总型AP 应该要重构,或者是一支一支 拿出来看有什麽可以enhance的 但user常常会认知KPI错误就来说是系统问题,久而久之老板也好像觉得是我的问题 而没有深究之所以KPI会错误,就是因为SQL在上code流程的不弹性,还有让user在 不能弹性重上CODE的情况下还是一再想修改SQL (不能弹性的原因是要重上code老板都会看,跟他解释这个是要改SQL就会被 question,但老板也不看CODE也不会负责建议有建设性的方法,只会打高空问 说可不可以不要改SQL--->问我的格局只能做到这样...整个黑人问号) 私以为想修改SQL或是想改变KPI的算法,都应该是大家坐下来看data flow是什麽 是不是只是加了一句SQL就可以改变 但文化上大家也不太有耐心这样梳理问题 不太清楚老板是否了解目前系统的设计是长这样,总之在沟通上也觉得不太有救 想问问有没有维护或是开发过这种DATA LOADER的前辈 可以分享一下心得的QQ --
QR Code



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 114.25.93.94 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1669050189.A.15C.html
1F:推 neo5277: 我看到1=1了耶... 11/22 01:29
2F:推 neo5277: 也不要用* 11/22 01:30
3F:→ peter98: 把条件弄成dynamic 不要hardcoded 设定好权限 让个别 11/22 01:32
4F:→ peter98: user可以选要加甚麽条件在filter里 我做过这个 很难写 11/22 01:33
5F:→ peter98: 难在一堆无聊人士搞audit 设定权限他们也不懂 11/22 01:33
6F:推 neo5277: 辛苦啦,我是建议你让sql参数化单纯一点,把条件的东西搬去 11/22 01:34
7F:→ neo5277: c#用策略模式做 11/22 01:34
8F:→ neo5277: 然後多使用虚拟类别,多的kpi用介面去加 11/22 01:35
9F:→ neo5277: 这样你sql就相对单纯 11/22 01:35
10F:→ neo5277: 现在这样笔数多捞起来会很慢吧... 11/22 01:36
11F:推 neo5277: 然後你sql要板控的话可以加一个sql,专案在方案里 11/22 01:49
12F:→ neo5277: 最终还是sp化接参数再透过策略选择呼叫那一种就好 11/22 01:49
13F:→ neo5277: 好维护,改起来也快,而且会好阅读很多吧 11/22 01:50
14F:→ airtsubasa: 1=1是为了 後面串条件方便吧 应该是後面可能不会出现 11/22 06:52
15F:→ airtsubasa: 条件 11/22 06:52
16F:→ play714: 不太懂分那麽多支loader 的原因为何? 11/22 08:39
17F:推 CRPKT: 先把上游资料转成同样格式,query 的部分再跟着 area 版控 11/22 09:22
18F:→ CRPKT: 现在这样维护成本就是 loader 与 area 数量乘开 11/22 09:23
19F:→ CRPKT: 把东西拆到让维护成本变成加法是唯一的活路 11/22 09:24
20F:推 enthos: https://github.com/pardeike/Harmony/wiki 11/22 09:32
21F:→ enthos: Game Live patch:做多种MOD让使用者自行订阅 11/22 09:32
22F:推 giacch: Loader1.GetSQLText(Area1), Loader2.GetSQLText(Area1) 11/22 11:41
23F:推 wulouise: query可以独立分开放在档案里读吧? 11/22 12:08
24F:嘘 sniper2824: JavaScript 为什麽你要分开写 11/22 12:35
25F:→ brucetu: 你做好一版 马上把所有可能被影响的loader/area重跑 比 11/22 17:12
26F:→ brucetu: 对实际被影响的资料是否符合你预期 先建立这样的系统避免 11/22 17:12
27F:→ brucetu: 改A坏B没发现 再来谈重构 11/22 17:12
28F:→ brucetu: 会发生改a坏b表示你有共用的code却允许共用的其中一个需 11/22 17:14
29F:→ brucetu: 求端任意更改 这当然不正常, 如果一种东西会被多个需求 11/22 17:14
30F:→ brucetu: 端各自提需求修改 那这种东西不论有多相似 都应该建立单 11/22 17:14
31F:→ brucetu: 独的class 11/22 17:14
32F:→ brucetu: 你的整个重构会很复杂不是你一人一两个月就能完成 一定要 11/22 17:15
33F:→ brucetu: 先建立确保不会改A坏B的机制 11/22 17:15
34F:→ brucetu: 你这正常的架构就是要先定义原始资料类别有哪些, 聚合资 11/22 17:16
35F:→ brucetu: 料的filter有哪些 11/22 17:16
36F:→ brucetu: 你的loader程式应该要给每个最终报表有适当的命名 同时 11/22 17:19
37F:→ brucetu: 有文件纪录每个报表会有哪些单位查看 11/22 17:19
38F:→ brucetu: 每一支报表由哪些资料源以及哪些filter算出中间的结果以 11/22 17:25
39F:→ brucetu: 及最终报表 要有文件 11/22 17:25
40F:→ brucetu: 当有人跟你说 他要增加采计AA类别 你就去查程式 采计AA 11/22 17:30
41F:→ brucetu: 类别这个行为是哪一支filter在处理, 有其他单位用到吗? 11/22 17:30
42F:→ brucetu: 如果没有 那大概就是直接修改这支filter 最终报表就会是 11/22 17:30
43F:→ brucetu: 他要的结果 也不影响别的单位. 如果有其他单位用到 你可 11/22 17:30
44F:→ brucetu: 能需要拆分成两支filter给两个单位使用 或是你的这个filt 11/22 17:30
45F:→ brucetu: er可以吃参数 那就是两个area吃不同config即可. 最重要是 11/22 17:30
46F:→ brucetu: 不管你的架构如何 改完就是要测试确保没有动到不该动的 11/22 17:30
47F:→ brucetu: 东西 这就是测试的覆盖率的重要性 11/22 17:30
48F:→ brucetu: 最後建议 直接换工作 11/22 17:31
49F:推 jellyfishuan: 不太懂 老板听你这样解释之後还是认为是你的问题吗 11/22 17:58
50F:→ jellyfishuan: 通常这样看你叙述下来就知道是架构问题了吧? 11/22 17:58
51F:推 f821027: SQL WHERE 用 python 的 f-string 把 list 传进去,这样 11/22 18:43
52F:→ f821027: 只要更新这个list就好 11/22 18:43
53F:推 bills1987: 像是水流一样,资料一站一站往下流,就很好追踪!可能会 11/22 21:02
54F:→ bills1987: 变动的地方可以另开TABLE存放参考物件AA ,BB...後续就 11/22 21:02
55F:→ bills1987: 算新增参考,也只需更动参考TABLE内容,MAIN SQL部分只 11/22 21:02
56F:→ bills1987: 要写好关联,後续就不用一直改 11/22 21:02
57F:→ tinasfishs: 已经有参数化,loader唯一有设计的就是把同一支loade 11/22 23:58
58F:→ tinasfishs: r的可能10几、20几支SQL摆在同一个class,然後用retu 11/22 23:58
59F:→ tinasfishs: rn string的方式去return SQL,只是除了用class的壳 11/22 23:58
60F:→ tinasfishs: 包住&部分用参数之外就没做其他的了。参数有的带了6- 11/22 23:58
61F:→ tinasfishs: 7个结果还是没办法把SQL拆到自由度完全释放 11/22 23:58
62F:→ tinasfishs: 我的确很想by Area去把SQL list拆出来,但是可能和其 11/23 00:06
63F:→ tinasfishs: 他公司不同,SQL除了摆在公司共用的SQL池以外就是只 11/23 00:06
64F:→ tinasfishs: 有hard code一法,SQL池只是储存string跟参数位置, 11/23 00:06
65F:→ tinasfishs: 假设要把本来是hard code的条件改成带参数,就是原本 11/23 00:06
66F:→ tinasfishs: C#里面call SQL池的地方要改。例如string SQL=sql po 11/23 00:06
67F:→ tinasfishs: ol(type,gender)要改成SQL=sqlpool(type,gender,age) 11/23 00:06
68F:→ tinasfishs: 就要重新上code,不能自行维护一份txt档就好 11/23 00:06
69F:→ tinasfishs: 感觉前人在这样的infra环境下,选择hard code或是摆S 11/23 00:10
70F:→ tinasfishs: QL pool需要的effort是差不多的,为了快速完成,也不 11/23 00:10
71F:→ tinasfishs: 会去选择把TABLE里每个栏位都拆出来写成class…table 11/23 00:10
72F:→ tinasfishs: 跟table我觉得关联性很差,常常出现10几个column的ta 11/23 00:10
73F:→ tinasfishs: ble,我资料库不强不知道这算不算是架构不好的象徵QQ 11/23 00:10
74F:→ tinasfishs: 但大家的建议都很棒,我会多寻找机会点的!谢谢 11/23 00:12
75F:推 giacch: sql = "" + 11/23 00:55
76F:→ giacch: (age != null ? "" + 11/23 00:55
77F:→ giacch: "\n and age = @age" + 11/23 00:55
78F:→ giacch: "" : "") + 11/23 00:55
79F:→ giacch: ""; 11/23 00:56
80F:推 giacch: 蓝色的if可以写成上面哪样, 字串一直串 11/23 00:59
81F:→ giacch: 不想整个Code重上, 可以拆成不同project (dll) 11/23 01:04
82F:→ giacch: 若你将所有C# Code都写在一个cs档,就可以实现维护一份text 11/23 01:14
83F:→ giacch: 参数太多可以考虑用一个物件来放 11/23 01:21
84F:→ giacch: (type, class or Dictionary<string, object> args) 11/23 01:21
85F:推 hanshsu: c# call sqlpool interface 改成传 object 就可以解决改 11/23 11:16
86F:→ hanshsu: 来改去的问题? 11/23 11:16
87F:推 giacch: 楼上是讲我吗? "实现维护一份text"那一行只是玩笑话 11/23 11:28
88F:推 giacch: 不太懂楼上的意思 11/23 11:40
89F:→ lazarus1121: 另外花点时间写一支自己理解後的模组? 11/23 12:10
90F:→ lazarus1121: 然後两边比较结果,久了没问题就能把旧的取代 11/23 12:10
91F:→ qss05: 如果你会很常异动逻辑,通常会把核心做成view有需要再筛选 11/24 22:53
92F:→ qss05: 吧,这样就从资料库改就好,子查询也可以做成function放在 11/24 22:53
93F:→ qss05: 资料库 11/24 22:53
94F:推 ck237: 这个架构也太神奇了吧? 11/25 01:09
95F:推 jack0204: 为啥不从程式去处理要用SQL去处理? 11/26 09:11







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:WOW站内搜寻

TOP