12月日常开发小结


一、异常信息

之前做了一个异常通知的需求,简单来说就是程序执行异常了发送一封邮件和通知给指定的人员,我的做法也很简单,在利用异常捕获在catch中将捕获到的异常发送.

上线之后有同事说异常了没有发,我也不知道是不是真的异常了没发,因为之前自己测了好多遍通过了的,抱着将信将疑的态度去结合日志分析代码,后面发现确实是这样.

代码如下:

public Task Execute()
{
    try
    {
        CalculationRawData();
    }
    catch (Exception ex)
    {
               PushException?.Invoke(this, new ExceptionResponse(Company, nameof(CalculationJob),ex));
    }
        return Task.FromResult(0);
}
            
 public void CalculationRawData()
 {
     try
     {
         //dosomthing
     }
     catch (Exception ex)
     {
         Logger.Writelog("ex.InnerException.Message");
     }
 }

为什么没有被发送?

根据上面2段代码分析出,在CalculationRawData方法中虽然捕获了异常但是并没有抛出,所以导致Execute没有接收到异常,自然也不会调用发送接口.
所以日常开发中对异常的处理只用一个统一的入口,在业务中尽量不要对异常进行处理,因为处理不好会导致真正有用的问题信息被吞了,增加排查成本.

二、implicit 和 explicit

讲道理工作这些年,这2个关键字基本没用过,应该不止我一个人吧!!

implicit 关键字用于声明隐式的用户自定义的类型转换运算符。 如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换。

explicit 关键字声明必须通过显示的调用用户定义的类型转换运算符来进行转换。

1.implicit
 //自定义转换类
 public struct TimeRange
 {
     public DateTime StartTime { get; set; }
     public DateTime EndTime { get; set; }
     public TimeRange(DateTime startTime, DateTime endTime)
     {
         StartTime = startTime;
         EndTime = endTime;
     }

     public static implicit operator double(TimeRange timeRange)
     {
         return (timeRange.EndTime - timeRange.StartTime).TotalHours; ;
     }
 }
static void Main(string[] args)
{
    DateTime star = DateTime.Now;
    DateTime end = DateTime.Now.AddDays(1);
    //根据起始日期和结束日期算出间隔时间,默认隐式转换
    double result =  new TimeRange(star, end);
}
2.explicit
static void Main(string[] args)
{
    DateTime star = DateTime.Now;
    DateTime end = DateTime.Now.AddDays(1);
   //根据起始日期和结束日期算出间隔时间,必须显示声明转换
    double result =  (double)new TimeRange(star, end);
}

三、快速转换

1.快速将Int数组转换为String数组
int [] arr = new int[] { 4,2, 4,6 };

string[] result = Array.ConvertAll(arr, Convert.ToString);
2.快速将List<string>转换为List<int>
 List<string> list = new List<string>() { "1","2","3","1"};
 var result = list.ConvertAll(int.Parse);

四、这可能是真的

其实并不代表是这一个月的小结,有一部分其实也有挺长一段时间了,所以记录一下。

1.为什么会产生Bug

就我自己根据这些年的开发经验和亲身经历和做过的项目,如果一旦程序出问题,无论是从承担责任或者解决问题的角度来说,从设计>开发>测试>运维>实施>直到用户,第一个祭天的永远是开发人员,确实因为东西是你做的,设计人员会说已经跟你讲清楚了,运维和测试人员会说谁知道你写的什么东西,Bug测都测不出来,最后连实施都会和用户一起鄙视你" 这tm什么垃圾软件"。

首先我得阐明我的态度,这不是针对谁,因为每个人都很不容易,并且很努力,有些观点可能不太容易被认可或者接受,但是确实是这么回事,因为这个东西是见人见智的,胡说胡有理,如果有人真的很在意,可以当做一个吐槽来看.
现实虽然就是这么无奈,但是我们必须去面对,因为只有剖析出问题所在,才能更清晰的看到本质,以至于得到实实在在的提高,在此作为一个开发总结了一下,产生Bug主要有以下几大原因:

1. 模糊的需求

有时候有一个需求来了,并没有仔细的去阅读需求,也没有仔细去和提出需求的人进行需求交底和反向交底,因为在普遍开发的认知里,写需求的人都是不懂需求的人,加上在无数次的"这是哪个xx提的需求?","为什么要这样啊?","真tm xx"

经过了长时间岁月的打磨,导致大部分在阅读需求时只是囫囵吞枣式的快速扫描一眼, 扫描过程中只摘取一些敏感字眼,然后全凭自己想当然,久而久之养成了一种先入为主的习惯,然后做出来的需求就是......额 ,不敢想象.

如何解决?

一定要仔细客观的阅读并核对用户提出的需求,然后独立分析进行反向交底,哪怕是一张很抽象的图,或者几行字都行,因为你说的话有可能在当时只是你自己认为自己讲清楚了,恰恰并不是每个人都能明白你的意思,又或是你压根就没说清楚,就算多耗点时间也没关系,磨刀不误砍柴工,如果可能拉上测试,至于为什么,那就是避免你后续做完之后,再讲第二次,第三次,懂的都懂.

2. 超乎寻常的自信

我觉得作为开发自我认可的标准并开发不是写代码多6,解Bug做需求多快,而是迷之自信,最骚的是不接受反驳,写完就提测,不说单元测试,连基本的过一遍都没有,恰恰这样却带来了不少坏处,理想的情况就是在测试阶段问题被发现了,然后一堆Bug,不太理想的情况就是测试也没测出来,然后被用户测出来了...

如何解决?

1.在写完之后,自己先整体CodeReview一遍,通常可以发现一些写法和设计缺陷并及时修改,然后最少测试3遍,测试3遍,测试3遍.

2.对于大的功能模块,写出开发版本的测试用例,写了你才能更好的进行单元测试.

3. 锻炼自己的编码内功

对API不熟悉,掌握程度不够导致出现的比比皆是,所以在用任何一个自己感觉不熟悉的api时,一定要查清楚他的方法,例如获取字典集合中取一个不存在的key "a1"对应的值,不熟悉的人经常写出直接取keyValuePairs["a1"]那就直接错了,正确使用keyValuePairs.TryGetValue("a1",out int c),像这样的细节还有很多,不一一列举,只是想表达这个意思

 Dictionary<string, int> keyValuePairs = new Dictionary<string, int>();
 keyValuePairs.Add("a", 2);
 keyValuePairs.Add("b", 3);

4. 不及时复盘

为什么说要及时复盘?可以将日常开发的一些小技巧,或者解决过的典型Bug和解决办法,例如常见的

1.未将对象引用到实例.
2.参数长度超出数据库可存储的范围.
3.索引越界.
4.某个特殊的业务导致需要特殊处理.

都记下来,然后定期或者不定期的拿出来复盘一下,或者在新需求做完之后,把记录拿出来作为标准检查一下,保证之前犯过的错,和解决过的问题不会再出现。

5. 不要带着情绪做事情

这个自行脑补吧,因为每个人都有自己的个性和脾气,你可以不认可所有人,也可以认为所有人都是垃圾,但是在工作中不要表现出来带着情绪做事,这样会对你周围,或者对你自己有很大影响,谨记"要么忍,要么滚"!

6. 测试不靠谱

为什么说测试不靠谱,不是特意为鄙视或者挑起冲突而说的,也只是客观的,因为在绝大部分的小公司中的测试都是针对业务线的,加上水平也层次不齐,遇到一个经验相对丰富,会写Sql或者对绝大部分测试工具或者性能测试熟悉的你就偷着乐吧,因为我遇到的有一部分连用例都不写,我不知道是不会写,还是说嫌太麻烦了,上来一通乱点,以至于连自己点到哪里了都不清楚。

假如无法改变,又必须解决呢?

1.提高代码健壮性,减少bug把问题风险降到最小.

2.换个环境可能会好一点,但也有可能更糟糕...

引用来源:https://www.cnblogs.com/yuxl01/p/15732619.html

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
管理员
上一篇:.NET 通用多条件动态参数查询方法 - SqlSugar ORM
下一篇:手把手教你学Dapr - 6. 发布订阅
评论列表

发表评论

评论内容
昵称:
验证码:
验证码
关联文章

12日常开发小结
使用.NET 6开发TodoList应用(12)——实现ActionFilter
.NET中大型项目开发必备(12)--使用MQ消息队列
C#计算两个日期之间的整
Epicor 12.0.* 升级到12.1.100
浏览器限制最小字体为12号的解决办法
未在本地计算机上注册"Microsoft.ACE.OLEDB.12.0"提供程序
Winform开发框架日志管理
SAP S/4HANA MM模块培训 12 - 配额安排、供应源分配与配额评分
SAP S/4HANA MM模块培训 12 - 业务伙伴、成本对象与供应商发票
C#代码编码规范手册 软件开发规范 开发指南
SAP S/4HANA MM模块培训 16 - 源视频重复说明(与第12篇相同)
devexpress图表Chart开发日志
C# ASP.NET Core开发学生信息管理系统(二)
Winform开发框架简介
C# ASP.NET Core开发学生信息管理系统(一)
开发一个功能
C# ASP.NET Core开发学生信息管理系统(三)
.NET中大型项目开发必备(8)--高效分页
.NET中大型项目开发必备(6)--IUtility工具介绍

热门标签
.NET Core .NET Reactor ag-grid AI发布 api安全 ASP.NET Core C#DLL加密 C#播放声音 C#代码混淆 C#代码加密 ChromeDriver Codex DateTime DBeaver devexpress devTool DLL混淆 edge.js EF EFCore Electron element-ui el-form el-table excel FastReport FileStream FolderBrowerDialog FolderSelectDialog form提交 git gridcontrol gridview input javascript json字符串 JS转换对象JSON jwt JWT授权 linq log Math MCP mitmproxy MVC MySQL Navicat netstat nginx node_modules NSwag Nuget Nuget镜像 number PowerShell pyinstaller python pythoncom python爬虫 python抓包 pywin32 redis Requests-html RestSharp Selenium sql SQL Server Swagger to-cms Visual Studio VSCode vue VueRouter vue路由 VUE页面通讯 Webpack Windows Windows服务 winform wmi xlrd yaml YESCMS YESWEB开发框架 白象 表单提交 播放声音 打开URL 代码混淆 弹窗提醒 端口占用 对象转换 分布式 公共字典 机器码 进程排查 静态资源 开发指南 路由参数 密钥 配置教程 配置文件 权限 人工智能 任务 任务调度 日期间隔 日志 日志记录 省市区 授权验证 数据库 四舍五入 文案 文件读取 文件夹选择 文件目录选择 问题排查 行政区域数据 页面通讯 中间件 CSharp 事务锁 工单系统 并发控制 重复提交 CMS Markdig Markdown markdown-it marked 技术选型 VS Code 开发工具 源代码管理 版本控制 Docker PostgreSQL 时区 部署排查 CMS架构 EF Core 主题系统 二次开发 插件系统 容器 运维命令 镜像清理 Linux NAS 远程挂载 飞牛 fnOS S/4HANA SAP GUI SAP HANA SAP R/3 SAP入门 SAP版本 ERP SAP SAP MM 库存管理 物料管理 采购管理 入门教程 SAP S/4HANA SPRO 企业结构 采购组织 MM01 物料主数据 物料类型 BP分组 业务伙伴 供应商主数据 ME41 RFQ 库存物料 采购流程 ME51 消耗性物料 科目分配 采购申请 AC03 ML81N 外部服务 服务主数据 Business Partner SAP培训 ME51N MM模块 Lean Services MM-SRV 外部服务采购 PIR 供应来源 采购主数据 采购信息记录 ME31K 框架协议 计划协议 采购合同 ME01 供应来源确定 货源清单 MEQ1 供应源确定 配额安排 配额评分 MD04 MD21 MRP 计划文件 需求计划 批量程序 MD01N MD02 MRP Live MD05 MM 物料计划 优化采购 供应源 采购订单 ME2A 供应商确认 采购监控 Flexible Workflow 凭证释放 采购审批 释放策略 实地盘点 物料凭证 货物移动 MIGO 收货 移动类型 已撤回 供应商退货 货物发出 STO 库存转储 转移过账 生产订单 预留 GR/IR MIRO 供应商发票 物流发票校验 OMR2 税码 FI PP SD 实操教程 MRBR OMR6 发票差异 交货成本 后续借记 MI01 实物盘点 盘点差异 公司代码 工厂 组织结构 OMS2 主数据定制 自动科目确定 BP角色 CVI 伙伴确定 编号范围 凭证类型 字段选择 FBN1 OMBT OMC2 会计凭证 OMJJ BOM 委外加工 项目类别L MRKO 供应商寄售 特殊库存K MRKON PIPE Pipeline 特殊库存P ERS MRIS 发票计划 周期性结算 里程碑付款 变更追踪 版本管理 采购凭证 SFTP WebDAV 网盘 飞牛fnOS AMPL HERS MPN 中文教程 库存确定 可用性检查 缺件检查 Output Management 消息确定 输出确定 分割评估 库存计价 评估类别 评估类型 PB00 RM0000 条件技术 采购定价 MM-FI集成 OBYC 库存估价 文本类型 文本采用 EFB EVO MSV SU3 用户参数 发票校验 合同参照 履约保留款 特别总账 预付款 Fiori Launchpad SAP Fiori 应用导航 用户体验 LSMW LTMC Migration Cockpit 数据迁移 BRFplus OPD Output Control My Inbox 审批流程 灵活工作流 SAP PP 外部加工 SAP QM 检验批 质量信息记录 采购收货 SAP PM 维护BOM 维护订单 SAP SD SAP Service 端到端流程 MM模块培训 FI-MM集成 供应商管理 审批配置 FICO入门 SAP FICO 财务配置 供应商税务 预扣税 House Bank 银行对账 客户清账 应收账款 FI控制 验证与替代 印度 GST 税务配置 F110 FBZP EWM入门 SAP EWM 仓库管理 OX14 成本核算 物料评估 后勤配置 物料组 价值更新 数量更新 PP-PI 流程制造 生产计划 容差配置 SAP事务码 SAP基础 TCODE Basis 事务代码 MMNR 编号区间 采购实操 组织架构 OMSF SAP实操 FI配置
联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码