蘭陵N梓記

一指流沙,程序年华


  • 首页

  • 归档

  • 关于

  • 搜索
close

飞哥讲代码28:C++内存泄露

时间: 2021-11-06   |   分类: 技术     |   阅读: 4567 字 ~10分钟

案例

C/C++把内存管理交给程序员,由于对象生命周期的长短不一,需要记住内存在真正不需要它的时候显示释放,让程序员承担很大的心智负担,不经意间就出现内存泄露。通常正常的业务流程是不会出现内存泄露的,因为跑用例时会挂上内存检测工具,但一些异常分支,用例难以覆盖的地方,是内存泄露的重灾区。若一旦出现,都难以定位。前一段时间走读某一老产品的代码,是C/C++混合代码,发现一些潜在内存泄露问题。

问题1,每个异常分支需要手动释放方法内申请的内存,代码脱敏如下:

pBuf1 = malloc(sizeof(XX1)); // 申请一块内存
if (cond1) { // 异常分支1
    free(pBuf1);
    return RET_ERROR;
}
// 省略其它代码
pBuf2 = malloc(sizeof(XX2)); // 申请另一块内存
if (cond2) { // 异常分支2
    free(pBuf1); // 每个分支,都要释放前面所有代码
    free(pBuf2);
    return RET_ERROR;
}
// 省略其它代码
ptr->buf1 = pBuf1;  // 把多块内存的指针赋值给结构体指针ptr的成员变量,ptr是出参,ptr内存以及它的成员指针内存释放是在其它地方
ptr->buf2 = pBuf2;
return RET_SUCCESS
阅读全文 »

软件开发漫谈4:敏捷开发

时间: 2021-10-16   |   分类: 技术     |   阅读: 4610 字 ~10分钟

背景

还是在国庆节前,与一位大学同学聊天,忽然聊到他公司自从引入一位印度主管之后,开始推广敏捷开发,言语中透露出对推行敏捷开发的反思。什么站立会议,Backlog墙,Burndown图,迭代回顾等,看似这些活动很美好,都是围绕提升团队生产率,让软件开发更"敏捷",但事实上还不如他们以前没有这些活动更高效。一个小团队的Leader反而成了这些活动监工,搞这些活动有时甚至不如自己亲自把活干了产出来得快。每个人只完成自己的任务,没有人会记得是谁认领了什么任务,团队反而缺少了应有的协作。从迭代计划来看,也许只是时间上需要迭代的划分,难以做到每个迭代可独立交付特征。这或许所谓的只有其"皮"。

我也有同样的感觉,联想我司10年前左右也在大力推广敏捷,并结合我司软件开发的特点,又在原有基础上进行改造。我们似乎在推广一种实践时,很容易跟风或是一刀切,人家这样玩,我们不跟着搞,似乎就是落后生产力了。总之推广是成功的,我们的优秀实践总结总会解决了XXX痛点,效率又提升了XXX。不过现在已没人再来提敏捷开发,不断的实践最终也留下一些"精华",如站立会议改成Espace晨会,按月迭代计划尽可能早的部件间联调,每个C版本的AAR总结等等。

阅读全文 »

软件开发漫谈3:开发者测试

时间: 2021-09-04   |   分类: 技术     |   阅读: 5560 字 ~12分钟

背景

目前各个团队在推行开发者测试,有些执行力与能力强的团队,逐渐开展起开发者测试。我们总是有各种各样的借口,没有管道时间,不具备本地测试条件,缺少测试技能等等。很多历史代码也不是我写的,缺少测试代码,再被动去补测试,看到明显的收益,抵触很自然。

开发人员不做测试吗?其实也不是,至少我见到的团队,开发人员都会对自己新写和修改的代码做测试验证。只是这个测试过程是手工的,通过搭建环境,替换软件包,再手工给接口发送消息等一些无法自动可重入的测试手段,效率低下。

曾经我们也推广过LLT测试,专职测试人员与开发人员饱和式投入之后,随着软件的演进,测试代码却没有随着持续维护与更新,久而久之变成比功能代码还腐烂,今天我们重新再提开发者测试,是否也难逃LLT一样的命运?

笔者虽然一直从事开发,但在十多年前被主管安排过从事支撑系统测试的工作,写过验收测试用例,写过TTCN的测试脚本,也作为测试执行者用过测试专有工具。现在再来看开发者测试,它们在测试思路、理念、工具都是不相同的。如何更好地开展开发者测试我也是满脑的困惑,参考一些资料,趁着周末有点时间整理,观点也是房屋中大象,权当漫谈的谈资。

阅读全文 »

飞哥讲代码27:此圈复杂度,改还是不改,是个问题

时间: 2021-08-15   |   分类: 技术     |   阅读: 2555 字 ~6分钟

背景

圈复杂度是一种代码复杂度的衡量标准。在我们的Clean Code的度量指标中很自然也少不了它的影子,通常我们会检查最大圈复杂度与平均圈复杂度。一般说来,人的记忆时长有限,当圈复杂度大于10时,就可能存在逻辑出错风险。圈复杂度也是条件复杂度,高复杂度的代码表现为条件分支多,导致代码可读性差,可测试性难,可维护性差等问题。整体的圈复杂度的确能反映代码整体是否清晰易懂,因此的确我们有必要分析与优化高复杂度的代码。

我们在实践开发中经常会遇到高圈复杂度的代码,会纠结一些单点的圈复杂度要不要修改的问题。需要对圈复杂度思辨:

  • 高圈复杂度是否一定高复杂
  • 高圈复杂度是否一定可读性,可维护性差

本文案例的代码并不复杂,修改圈复杂度也是老生常谈的问题。但在Clean Code的指标下,我们(包括我自己)似乎早已麻木地习惯小心谨慎,不少时间花在修改一些不太增值的代码上。虽说指标是死的,人不能死板,我们不能基于不信任的指标来管控开发可信的代码,具体问题具体分析嘛。

阅读全文 »

软件开发漫谈2:抽象设计

时间: 2021-06-19   |   分类: 技术     |   阅读: 3569 字 ~8分钟

背景

接上篇,代码Commit活动中鲜有代码设计类问题提出,抛开客观原因之外来看,要具备较好设计能力其实并不容易。抽象是软件设计基础,抽象是有层次,有角度,有级别。抽象的概念都很好,但也让人迷惑。大师们能够从具体的事物本身,抽象出各种概念。莫过于SOLID等设计原则以及各种设计模式,我们经常看到,经常谈论,可能的现状是难以真正深入理解,并在工作中应用。抽象看似明白,实操又不知如何下手。似乎抽象不可言传,只可意会。

在绘画领域,有一个流派是抽象主义,似乎通过简单线条、块面和色彩随意的的涂鸦。画家们精心的构思与创作,变成了我们外行人眼中的涂鸦,直呼看不懂,欣赏不来。或许同样在对软件开发中,看似简单架构或代码背后,可能隐藏着作者精心的思考与高度的抽象。抽象之后的结果往往大道至简,越是复杂的代码反而没有什么抽象。我们对软件解决的问题思考太少,也就难以进行抽象。

阅读全文 »

软件开发漫谈1:commit协作

时间: 2021-06-06   |   分类: 技术     |   阅读: 4574 字 ~10分钟

背景

我司代码Commit机制建设日趋完善,对代码的质量守护发挥越来越重要的作用。作为一名Committer,发现日常工作还有一些可以改进的。例如例行MR代码Review,除一些规范类、安全类与业务类的问题之外,鲜有代码设计类问题提出,以及即时修改。原因可能有多种,如:

  • 大多是增量功能开发,不需要新的设计
  • 每次MR的代码量很少,看不出设计意图
  • 设计类问题修改可能涉及面广,存在重构工作量而不愿意修改,也担心引发其它问题

这可能都是表象,其深层次可能是不同阶段的人群对代码不同程度的追求或者软件文化问题:

  • 刚加入软件开发的萌新,大多都是想着及时完成PL或主管给我的开发任务,一个迭代一个迭代地被动开展工作,不会有太多好代码的经验与思考。我们似乎也没有可向他们责全求备的,他们很努力。
  • 工作几年之后,有追求的程序员会思考如何把代码写得更好。甚至不惜一切代价,仔细的打磨自己的 “作品”。我们应鼓励这一种钻研精神,这样才能不断的提升自我满足岗位的需要。但进度要求可能逐渐磨灭对好代码钻研的追求。
  • 工作时间越来越长的老人,思考的层次也会随之变化,一部分可能会认为代码本身局部的好坏并不是最重要,关键是以最小的成本交付需求;一部分可能会看得比较深远,不能只满足当前的需求,还要考虑可持续发展,为将来设计。我们总会有理由赞成这个而反对那个,让老人难以发挥应有价值。
阅读全文 »

飞哥讲代码26:Python函数式编程

时间: 2021-05-15   |   分类: 技术     |   阅读: 4022 字 ~9分钟

背景

最近笔者写Python代码比较多,同时又有多种编程语言的开发经验,现在的语言设计上大多趋同。当需要对数据集合操作时,非常喜欢java的stream声明式处理数据,萌生在Python中模仿Java的写法。虽然java的API易用性与Scala/Kotlin相比,还是有很大的差距,但与Python比起来,还是强不少。

我们先来看一下Java的玩法:

// 过滤Type是GROCERY,按Value倒排序,聚合Id,归并新的集合
List<Integer> tanscationsIds = transcations.parallelStream()
        .filter(it -> it.getType() == Transcation.GROCERY)
        .sorted(comparing(Transcation::getValue).resersed())
        .map(Transcation::getId)
        .collect(Collectors::toList());

函数式是一种声明式编程范式,上面的代码就像SQL语句一样,代码操作数据集合非常直观。笔者在去年写了一篇 飞哥讲代码16:函数式让数据处理更简洁 简单介绍了函数式在数据集合操作上的便利。

在数据分析领域,Python生态中有Pandas这类非常优秀的库,它对DataFrame(可以理解一张数据库表存储的数据集合)提供非常简单的API,支持对数据集的过滤、聚合、归并、填充与计算等,很方便地对数据进行清洗和加工。但它也并不是像Java的Stream一样操作,示例如下:

阅读全文 »

飞哥讲代码25:突破内存限制

时间: 2021-04-11   |   分类: 技术     |   阅读: 3947 字 ~8分钟

背景

最近调研低成本的大数据量的数据分析框架,搜索发现有:

  • 使用Python包Vaex读入并分析100G数据
  • Vaex:突破pandas,快速分析100GB大数据集
  • 这场Spark、Dask、Vaex、Pandas的正面交锋,谁赢了?
  • Vaex:一种具有超级字符串功能的DataFrame Python库

这些文章都在介绍Vaex,第三篇文章中有多种分析框架不同场景应用的性能对比。Vaex由于它采取内存映射、惰性计算的设计,可以在百亿级数据集上进行秒级的统计分析和可视化展示,使得它能在数据分析领域有它一席位置。

作为一名屌丝程度员,在性能倍增的背景下,极其想扒一扒它的代码,探索它是如何做到的。笔者也简单做了一些的验证(数据文件采用Parquet),它的确是秒级完成千万级数据量基于列式存储的数值统计分析(求mean,std,var等)、多列之间的计算以及按列条件过滤。这些计算不需要使用大量的内存,但象join,groupby聚合这类复杂的计算,它还是把数据加载到内存中计算。它的API也没有Pandas灵活与丰富,所以并不能完全取代Pandas。

阅读全文 »
1 2 3 4 5 6 7 8
兰陵子

兰陵子

Programmer & Architect

164 日志
4 分类
57 标签
RSS 订阅
GitHub 知乎
© 2009 - 2022 蘭陵N梓記
Powered by - Hugo v0.101.0
Theme by - NexT
0%