乘时间机器,看敏捷旅程

微机原理-基于8086电压报警2.5V仿真系统设计 *单片机设计介绍,微机原理-基于8086电压报警2.5V仿真系统设计。 阅读详情

BOSCO系统是一个在线品牌管理系统,项目客户是一家跨国酒店集团,旗下拥有多个世界著名的酒店品牌。BOSCO系统将服务标准化、标准符合度审查、改进流程管理等酒店品牌管理的工作内容整合到一个信息系统中,来提高相关人员的工作效率。目前BOSCO系统已经被全球十个酒店品牌、超过1000家酒店使用,用户超过8000人。

BOSCO系统的开发基于Ruby On Rails,在项目的开发过程中应用了敏捷开发方法。在开发此系统的8个月中,经历了15个迭代和3次发布。通过这种与客户紧密合作的工作方式我们按时交付了系统,并得到了客户的高度认可。笔者作为开发团队的一员,从开发者的角度对基于Ruby On Rails的敏捷开发实践总结出一些心得体会,其中有成功的经验,也有失败的教训,愿与敏捷开发爱好者分享。

在我们的系统中,有一个有趣的类,叫做TimeMachine,用于修改UAT服务器的系统时间。但现在,让它带我们穿梭时空吧。

TimeMachine.go_to("2008-04-15")

半路接手——关键字:Knowledge Transfer,结对编程

2008年4月,BOSCO系统漂洋过海来到中国。此时,它已经在美国经过了3个月的开发,且完成了第一次发布。现在要开始它的移植过程(从美国团队的大脑移植到中国团队的大脑)。给我们的资源并不多,只有3个项目原有工作人员:一个BA(业务分析师),两个Dev(开发人员)。但时间却相当有限:一个月。

虽然BOSCO系统的开发时间并不长,但Rails强大的表现力使系统已经足够庞大,我们也担忧Knowledge Transfer能否在约定的时间内完成。而且中国的开发团队中,真正有Rails开发经验的只有一人。如何在这么短的时间内,掌握这么庞大的系统,成了摆在眼前的挑战。

很多遇到过此种情况的开发人员,都不会对以下几种经历感到陌生:

●  阅读大量关于系统原理和项目架构的文档,但它们并不能直观、准确地反应项目情况。

●  参加各种标榜着“Knowledge Transfer”且耗时长久的会议,但收益甚少。

●  独自面对系统时不知从何下手,不断地寻求原有开发人员的帮助。

●  由于不熟悉系统造成在开发过程中不断犯错,贡献了很多“垃圾”代码,并影响了系统开发进度。

其实对于开发人员而言,掌握一个项目最重要的是提升对项目本身的“熟悉度”。此熟悉度代表对陌生的技术知识、代码的编写风格、开发的习惯、程序的架构、环境的搭建等等的掌握和了解。而结对编程是快速掌握这些知识技能的秘诀,还是拿事实来说话吧。

两个星期之后,先行和两个美国Dev结对的同事已经能够带新人了,而且开发速度不亚于两个美国 Dev。短短两个礼拜,中国团队对项目的整体架构,不说了然于心,也是熟门熟路;对于一些story,也能得心应手开始实现。这是我们自己也预想不到的速度。

之所以能在如此短的时间内掌握项目,就是拜“结对编程”所带来的好处所赐。有人会说,结对编程到底有什么魔法?其实没有魔法,它只是简单实践了很多人都懂得的道理:学习一件东西最快速的手段就是动手去做。而结对编程,不仅能让你有立即动手去做的机会,而且边上还有个让你观察学习、给你指导的老师。这是我对结对编程的初次体验,让我非常兴奋。还记得一个朋友给我电话告诉我“项目中的新人不能快速掌握知识”时,我告诉他:不要犹豫了,结对编程吧。我相信,一旦你开始尝试,你就不愿意停止。

TimeMachine.go_to("2008-05-15")

加速前进——关键字:最佳实践

随着Knowledge Transfer期满、美国同事离去,客户一度很担心中国团队能否掌控项目,能否保持开发速度。但在快速接手项目之后,项目开发随即进入了加速通道。在完全接手项目的第一个迭代之后,中国团队已经赶上了美国同事的开发速度。在这个过程中,除了因为团队的快速学习能力之外,还有我们保持的一些最佳实践让我们赢得了胜利。下面让我简单介绍其中一些。

一致的开发机器。我们有6个开发人员,也就是3对pair。Pair的3台机器都是漂亮精致的Mac Mini。当然这不是重点,重点在于,3台机器都有一致的开发环境:一致的程序目录,一致的安装软件,一致的快捷命令等等。完全一模一样的配置使pair在进行切换时,不会对另外一台机器感到丝毫的陌生,这有助于开发人员迅速进入开发状态。

快捷化常用命令。在开发时,我们每天都要进行无数次相同的一些操作:进入Rails开发根目录,启动Web server,签入代码等等。比如当你要进入Rails开发目录,你就得打入命令:cd /Users/rails/workspace/bosco/rails_root。这是一个简单的命令,但同时也是一个繁琐的命令,特别是当我们每天要进行多次这样的操作时,就会浪费大量的时间。这时,如果你为它加一个alias,把这个枯燥的操作用一个简单的命令“rr”代替,它会帮你节省多少时间呢?效率的提升有时就源于一些简单的改善。

不做简单重复的劳动。每天的工作总会有一些事情需要简单重复的劳动。比如当你要验证一项功能时,你需要手工打开网页,然后按着流程一步一步操作,来看实现是否正确等。每当此时,我们的选择是:绝不做简单重复的劳动,而是实现一个自动化的脚本来帮助我们进行这些操作。自动化不同的任务,可以选择不同的工具,比如Selenium、Ruby、Shell等等。后来我在《The Productive Programmer》中读到Neal Ford大师如是说:“手工执行简单重复的任务会让你变傻,会消耗你的注意力,而注意力是最重要的生产力之源。找出一种聪明的方法来自动化这些任务,这会让你变得聪明,因为你能从中学到一些东西。”

每天早上的code diff:在早晨的站立会议结束后,我们并没有马上着手清扫story。所有开发人员会挤在一台机器前,查看前一天的code diff。大家会看到所有成员在前一天的工作中修改的代码,相关的开发人员会对自己的代码作出解释。当有人对一段修改有疑问时,我们就会对此段代码进行讨论。或者是实现上的一些逻辑漏洞,或者是一些不规范的代码编写,或者是一些可能的性能改进,我们总能对一些代码提出疑问,并提出改进意见。Code diff过程是对站立会议以及结对编程的补充,是对代码质量的进一步检验,有助于团队对代码的了解,也促进了代码质量的提升。短短十分钟,何乐而不为?

每周的技术session:每周的技术session是我们一直保持的良好传统,团队从中受益匪浅。项目中总会遇到一些难题,或许是一种陌生的技术,或许是一个难解的问题。而此时,总会有人站出来说:“让我来讲讲这个吧”。或许这项技术对于主持者也是完全陌生的,但不要紧,接下来一周紧张的学习已经足够(这也会促使他更加快速地学习)。一周之后,主持者就为我们带来了一道“丰盛的大餐”。在session中,团队成员都会踊跃发言,并乐于抛出任何疑问让大家讨论。讨论是最能产生火花的,来自每个人不同的思考会让你对问题了解得更加深刻。讨论帮助我们解开了一些困扰已久的疑问,并加深了对一些技术的理解,比如:CSS,Memory Cache, REST, Ajax,Ruby的对象模型等等。通过技术的讨论和学习,团队成员的整体开发能力得到了提升,这极大地促进了项目的开发速度。

团队需要勇于尝试一些实践来促进团队的开发效率和提升团队的整体能力。上面所提及的有些实践都是我们在平时的工作中摸索、体会和总结出来的。比如每周的技术session,就是在成功地开展了一次之后,被保留和坚持下来了。

如何发现一些值得尝试的实践?这看似很难,其实很简单。在项目中遇到的问题,工作中偶然发现的一些事情,别人的经验,或者是你自己的一些想法,都可能是对一项实践的启发。你唯一要做的,就是勇于尝试。“从来没有人这么做过”,或者“别人都不这么做”不是你不这么做的理由。

TimeMachine.go_to("2008-08-01")

当项目开发进入第5个月,我们遇到了一些真正的困难,它们分别是“历史”story和系统性能优化问题。

当项目遇到困难时,正是审视敏捷实践的最好机会。TDD,简单设计,持续集成,重构等等,让我们看看这些实践在项目开发中显现的力量吧。

笑看历史——关键字:简单设计,TDD(测试驱动设计)

历史story:作为全球质量管理员,我要查看一个酒店的标准审查历史记录,从而跟踪并比较酒店在各个时期的标准符合度。

简单分解一下这个story,它要求提供的功能是:

●  系统在一些比如标准变化、酒店审核等事件发生时能保存当时的数据。

●  系统应该提供一个界面,让用户通过选择特定的日期查看历史信息。

跟通常一样,我们经过estimation(当时估的是5个points,并不太大)以及tasking(简单的设计)之后,开始实现这个story。

刚开始,这个story如预期一样顺利开发下去了。一天,两天,到了第三天,我们突然发现在实现一些功能时有点举步维艰。但通过一些“邪恶”的手段,我们还是解决了那些问题,虽然觉得并不是最佳实现。到了第四天,在实现另一些功能时,我们陷入了绝境:实现得过于复杂让代码改动极其困难,通过了这边的测试,那边的测试就失败了,如此反复。还差两天迭代就要结束了,这个story却深陷泥沼,团队陷入担忧之中。我们决定重新跳出来看一下原来的设计。

基于实现中遇到的困难,我们讨论了原先的设计,发现一些缺陷,并迅速找到了更好的方案。新设计雏形初具,再次动手吧。改动代码,很多原先的测试应声失败了。好事情,失败的测试告诉我们哪里出了问题,过去修正那些失败的测试吧。红,绿,红,绿,按照这样的节奏,出乎所有人意料的事情发生了:一个下午,仅仅是一个下午,我们把历史story完成了!

因为这个设计并不在技术层面,而在业务层面,所以在这里我并不想多讲story的详情。但发生这样的问题,是否会让你怀疑敏捷实践“简单设计”呢?如果你有此怀疑,我的想法就正好跟你相反,因为通过这个story让我更加相信“简单设计”的好处。

首先,即使现在回头看,我们还是认为就算当初花几倍的时间去做设计,也难免犯同样的错误。其次,检验设计优劣的最佳工具就是代码本身,及早地应用设计于代码,让代码来告诉你设计正确与否。这正是在这个story陷入泥沼时我们的反应:实现不能继续,来看看设计的问题吧。再次,之后我们的设计之所以如此成功地符合了业务的需求,是因为前一次失败的经历让我们对代码有了更进一步的了解,对问题有了更清晰的洞察。谜团是在行进中解开的,并不是一开始就能知晓。最后,我想我们唯一应该改进的,就是在发现开发出现困难时,能更早地跳出来,从设计角度分析一下问题。

新的设计实现能在一个下午完成,是因为高测试覆盖率为正确的重构实施提供了安全保障。测试总能迅速地提醒我们哪些地方出了错,以保证重构的正确。其次,良好的代码结构,也是代码能如此快速地修改完成的原因。这些都是TDD带来的好处,TDD不仅能提供高测试覆盖率,也能带来良好的代码设计。这就是越来越多的人把TDD称之为测试驱动设计(Test-Driven Design)的原因。

TDD给设计带来的一些好处:

●  TDD迫使你在编写代码之前,考虑更多对象之间的交互。

●  TDD迫使你把对象的创建封装在一个更好的层次上。

●  TDD会让你写出更加小而内聚的方法,从而使方法的重用以及纠错变得更加方便、快速。

百倍加速——关键字:性能,重构,YAGNI

随着项目进入后期,功能的开发已经基本完成。此时,我们面临系统的性能问题:发布一个标准竟然要5个小时,令人无法忍受。由于发布标准需要在一个事务内完成,而且要修改大量数据。所以在这5个小时内,数据库的很多表都被锁定,系统几乎处于瘫痪状态。于是,顶着巨大的压力,我们开始了性能优化之旅。

先通过添加日志找出最耗时的操作,然后仔细跟踪和分析这块代码。我们随即发现了一个耗时十分钟的操作,这个方法的时间复杂度是n2。但这段代码犯了一个低级错误,它可以被优化成一个n复杂度的方法。立即修改,修改后由于消除了大量重复操作,它的耗时竟然不超过一秒。“秒杀十分钟”就这样诞生了。随着我们进一步的跟踪和分析,多处设计上的问题暴露出来。几天的改进之后, 5个小时的操作缩减到了1个小时。

但显然,一个小时的操作还是不能为客户所接受的。于是,继续优化。马上,我们就发现标准发布操作对很多标准都进行了重新算分,但实际上只需对有改动的标准算分即可。而没有改动的标准,可以把它的得分结果存于数据库,下次用到时从数据库读取即可。通过这个“缓存”,我们再次大大提升了速度。运行之,整个操作竟然只需5分钟!5个小时的操作,到现在的5分钟,百倍加速也!

这个性能优化问题是个典型案例,它给了我们很多启示。首先,在遇到性能问题时,先别忙着埋怨平台的速度,还是先看看设计里面存在的问题吧。其次,也是我们可以改进的一点是:在TDD“红-绿-重构”的标准开发节奏中,如果我们多花一点时间在“绿”之后进行重构,就可以避免犯一些低级错误。

或许有人会说,如果你在刚开始就做更多的设计,就能避免到最后出现这样的性能问题。但我想说,非也,你忘了:你将不需要它(YAGNI)。预想开发是个迷人的陷阱,或许可以在刚开始就花费十倍的时间去避免这个性能问题的产生。但问题时,在刚开始你怎么知道哪些是必要的设计,而哪些是浪费呢?敏捷团队注重的是给客户创造真正有价值的业务,而不是花费大量时间去制造一个“华而不实”的系统。

“只在确实需要时才提供功能”,这是我们遵循的准则。

最后,性能改进之所以如此顺利,得益于我们遵循的一些敏捷实践。比如TDD带来的高测试覆盖率,保证了重构的正确性。在BOSCO项目的开发中,不乏这样的大型重构,我们从不害怕修改代码,因为有坚实的测试代码为重构撑起了安全网。而反之,重构促进了代码结构的优化,提升了系统性能。

从这两个问题我们可以看到:

●  敏捷实践促进了系统设计的灵活,代码结构的优化,系统质量的提升。

●  各项敏捷实践之间其实是相辅相成,相互促进的。

BOSCO脚印

通过对BOSCO系统代码的统计数据,我们可以看到:

●  代码设计的优良:平均每个类不超过十个方法,每个方法不超过五行代码。如果除去特殊的Helpers模块,平均每个类不超过7个方法。

●  高测试覆盖率:测试代码与功能代码的比例是1.5:1,行覆盖率达到90%以上。

●  开发人员的熟练度:每对pair每天6次的提交速度足以证明开发团队对于系统的熟悉度。

由于Ruby On Rails是一个特别擅长开发Web应用的框架,考虑到其所具备的强大表现力,我们相信此系统的复杂度不亚于很多规模在十多万行代码的系统。

TimeMachine.go_to("2008-09-17")

时间定格在BOSCO项目第三次发布的那一天。除了需要一段时间的bug修复和数据准备之外,发布并没有给工作带来太多不同。我们从未因为发布的到来而惊慌,也从未在发布时忙得不可开交。正如团队一成员所说,每次我们都是在等待发布,安静地等待着发布的到来。因为合理的安排和控制,让一切尽在掌握中。

发布成功,欢呼之余,让我们回头看看项目中的哪些实践保障了发布的顺利完成吧。

客户协作——关键字:PM、BA,还有Dev

曾经有一个同事突发感想说:“在ThoughtWorks做程序员是幸福的”。这不禁让我有很多感触,是的,在ThoughtWorks做程序开发是一件幸福的事情。当你有任何关于业务逻辑上的疑问时,坐在身旁、招之即来的BA总能给你准确地解答;当你坐着投入地进行开发时,可能你从未想过,之所以有这么良好的环境,是因为PM帮你阻挡了一切不该有的干扰。

PM和BA在背后付出的需求分析、客户交流等工作,让开发人员能把大多数时间和精力花在编码上。

BA在每天的站立会议之后,会有一个跟客户之间的BA站立会议。在这个会议上,他们会讨论各个业务的细节,力保每个业务细节的正确性。正是业务的正确性,让每天的开发工作能顺利进行。

PM每天会用很多时间跟客户交流项目进度,确保客户了解项目状态。并在每天工作结束之后总结一封报告邮件,这封邮件包含了对一天工作的总结,各个story的进度情况等。通过这封邮件,客户能及时地了解进度情况。

那Dev能在客户协作方面贡献什么呢?有人觉得,开发人员的任务就是从BA那里拿到story,并严格按照需求开发,而无需做与客户协作沟通等工作。其实这并不准确,Dev完全可以在客户协作方面发挥自己的作用,因为对于整个系统架构的了解,Dev有时候比BA,甚至比客户自己还了解他们真正需要的是什么。当我们拿到需求时,我们可以从开发者,以及整体系统架构设计者的角度考虑一下需求的可行性、必要性。有时我们会直觉有些需求并不是客户真正想要的,或者我们可以通过另外更简单的方式给客户提供同样的功能。经过一些分析,以及跟BA的讨论之后,BA通常会接受我们的观点并与客户进一步讨论。在这个过程中,Dev起到了帮助客户认清真正需求的作用。这是一个双赢的结局,开发人员不需要为一些不必要的功能而增加不必要的工作,影响架构的稳定性;同时,客户可以不必为一些价值不高,甚至没有价值的功能而付出昂贵的代价。

所以,客户协作并不只是PM和BA的工作,Dev作为系统的开发者,应该从他们的角度帮助客户找到对客户真正有价值的业务。

同时,信任,是客户协作的基础。团队与客户之间只有真正信任了,才能更好地合作。我们和客户之间的相处,就如朋友,在平时的工作中甚至会经常拿对方开开玩笑。

团队合作——关键字:Retrospective,Feedback,持续改进

大家都说,这是我们呆过最开心的一个团队,因为从不缺少欢声笑语。而我觉得,这更是一个正直的团队。无论谁有优异的表现,我们从不吝啬赞扬;无论谁犯错时,我们也会毫不犹豫地指出。

每两周一次的retrospective提供了一个寻找团队问题的好机会,在每次的回顾反省中,我们都会找出一些项目中的问题,并在接下来的工作中给予改进。这样团队才能保持持续的进步。

 图注:Retrospective有助于团队总结经验,持续改进

有人会问,为什么在我所在的团队中就不能保持这样良好的气氛,无法保持正直的态度呢?究其深层次的原因,首先需要公司的制度让团队的成员处于平等的地位,不应该有谁是在“管理”谁。PM,BA,Dev之所以需要不同的职位,只是因为工作类别不同而已。PM负责管理客户期望,BA负责需求分析,而Dev负责的是项目实现。

其次,团队作为一个整体,不应为任何问题追究到个人,而应把它归为团队集体的责任。平等的地位和责任集体所有制,会让每个成员更具主人翁精神,也会让团队更加紧密地凝聚在一起。团队成员的相互信任和紧密合作是项目成功的根基。

TimeMachine.go_to(“Future”)

敏捷方法并没有高深的理论,有的只是一些简单的实践。正是这些简单的实践,提升了开发人员的效率,促进了项目质量的提升,保证了项目最后的成功。

在未来的路上,让我们一起寻找更好的敏捷实践吧。

 

本文来自优快云博客:http://blog.youkuaiyun.com/programmer_editor/archive/2009/06/20/4283187.aspx

Qt —— QWebEngineView加载谷歌离线地图(包含离线地图瓦片下载制作、附谷歌地图开发文档)   关注 微信公众号搜索"Qt_io_"或"Qt开发者中心"了解更多关于Qt、C++开发知识.。 笔者 - jxd 阅读详情

相关推荐

BeikeShop跨境电商独立站系统V1.5.0免授权全开源版

BeikeShop 一款开源好用的跨境电商系统,BeikeShop 是基于 Laravel 开发的一款开源商城系统,主要面向外贸/跨境电商行业提供商品管理、订单管理、会员管理、支付、物流、系统管理等功能。BeikeShop商城 Beike多语言商城 多货币商城B2C商城系统 代码100%开源 PHP商城系统 H5/PC商城 跨境电商系统 跨境商城系统 电商商城系统 Laravel 9 框架插件化开发,MVC架构 支持插件市场。Event 机制实现Hook功能,自定义可视化装修。

817

《程序员》11期最新上市:云计算,未来的趋势

 本期特别策划:云计算,未来的趋势2008年,最热门的技术话题是云计算。各大软件厂商不约而同地表示,云计算是未来的趋势。于是,趋之若鹜的开发人员纷纷开始讨论云计算,讨论大规模计算的架构设计,讨论动态IT管理。然而,云计算是否会像它的名字一样飘忽不定,还是确有其事?为什么各种不同的云计算有截然不同的理念?当然,AWS、GAE、蓝云、红狗这样的名字背后代表的深层次含义,确是每一个厂商都非常清楚

《程序员》官方BLOG 1万+

2026四款AI原生IDE实测:Trae、Qoder、CodeBuddy、Cursor能力边界深度解析

AI原生IDE正从代码编辑器演进为开发者智能工作流中枢,其核心在于对上下文理解、AST编辑意图建模与多模态任务调度的工程化实现。区别于传统插件式AI辅助,真正的AI原生IDE需具备知识库嵌入、符号图索引、操作链固化等底层能力,从而支撑Figma转码、N+1查询修复、跨语言迁移等复杂场景。Trae强调中文语境与企业规范的强绑定,Qoder聚焦AST级编辑轨迹预测,CodeBuddy通过IDE/插件/CLI三态划分控制权边界,Cursor则以云端Agent实现开发任务的时空并行。本文基于真实项目压测,揭示免费版

ctk87443的博客 2448

《程序员》11期精彩预告:云计算——未来的趋势

封面报道:云计算——未来的趋势2008年,最热门的技术话题是云计算。各大软件厂商不约而同地表示,云计算是未来的趋势。于是,趋之若鹜的开发人员纷纷开始讨论云计算,讨论大规模计算的架构设计,讨论动态IT管理。然而,云计算是否会像它的名字一样飘忽不定,还是确有其事?为什么各种不同的云计算有截然不同的理念?当然,AWS、GAE、蓝云、红狗这样的名字背后代表的深层次含义,确是每一个厂商都非常清楚的。在各

孟迎霞 优快云 1345

记一次Redis出问题及解决方案

Q1: redis服务关闭前确认数据还是在的,重启后发现一条数据都没了,key* 查也是空的 A1: 经仔细检查发现redis.conf配置文件配置的数据存储目录配置的是dir ./ 也就是相对目录,也就是说在哪个目录执行redis-server redis.config启动命令 redis数据就会存到哪个目录,同样就会加载哪个目录下的数据文件(dump.rdb),前后两次启动命令的位置不一样导致第二次启动没有加载到(dump.rdb)文件,从而导致查不出数据 Q2:springboot 集成r

u010013928的博客 3058

lammps案例:热导率模拟案例讲解(NEMD方法)

lammps计算热导率大体可以分为三种方法:EMD、NEMD、rNEMD。 本文介绍非平衡模拟(NEMD)热导率的计算方法。 NEMD下热导率计算公式为: k=dQ*dZ/dt k:热导率 dQ:能量通量。 dT/dZ:温度梯度。 非平衡态下计算热导率的原理是在材料的两端或者中间设置热源和冷源。 在热源输入热量,在冷源抽取等量的热量,在这个过程中计算材料内部会有热量的传递,产生温度梯度。 在lammps模拟中得到能量通量和温度梯度,代入公式即可求得热导率。 热量的输入方式有多种,如fix langevin

lammps_jiayou的博客 1万+

Agentic Data Scientist Python API指南:3行代码把AI数据科学家嵌入你的项目

本文讲解如何用 Python API 将开源多智能体框架 Agentic Data Scientist 嵌入你的项目:只需 3 行代码,就能在程序中自动完成数据分析、方案规划、持续验证与报告生成的完整工作流,是面向新手的最快上手教程。 ## 什么是 Agentic Data Scientist?🤖 Agentic Data Scientist 是一个**自适应多智能体(Multi-Agent

gitblog_00795的博客 411

FGC_grasp复现

FGC_GraspNet复现

qq_39568387的博客 385

用OpenClaudia做竞品分析:SEO审计、内容差距与外链对比的全方位拆解

想做竞品分析,却不想在十几个营销SaaS工具之间来回切换?OpenClaudia 是一个免费开源的 AI 营销技能库,它为 Claude Code、Codex 等 AI 编程代理提供了 70 多个营销技能,其中就包括一套完整的**竞品分析工具箱**:竞品策略拆解(`competitor-analysis`)、SEO 审计(`seo-audit`)、内容差距分析(`content-gap-analy

gitblog_00264的博客 1007

GB9706.1-2020应用部分如何理解?

医用电气设备对应用部分的温度限制,绝缘考核,漏电流限制要求相对设备的其他部分来说都会要求比较严格。所以,划分设备的应用部分显得非常重要。现实中,医疗器械种类繁多,形状各异,比如大家熟悉的,小的如血压计,大的设备如CT。有些时候,我们应该如何根据应用部分的定义来确定ME设备的哪些部分是应用部分呢?还有GB 9706.1-2020中关于“应用部分”的定义中注2我们又该如何理解? 看过GB 9706.1-2020的朋友应该都已经注意到,相比老版也就是07版的9706.1,应用部分的定义是相对变...

喵叫兽的博客 8294

NSIS教程(8): 基于第三方界面库的安装包界面

前面的几篇文章介绍了NSIS的传统界面的安装包和现代界面的安装包的制作方法,也提到了NSIS支持自定义页面(即使用page custom)的特性,自定义页面需要用户自己创建对话框、控件、添加控件响应等等,虽然NSIS提供了nsDialogs.nsh来支持这些功能,但使用起来还是不太方便(需要专门了解这个插件诸多用法),而且不够灵活,所以本文介绍一种终极的自定义界面的安装包解决方案,即完全使用第三方

while(1) { smile(); } 9万+

CnOpenData 线上招聘网站信息数据

CnOpenData线上招聘网站信息数据库是一个覆盖中国主流招聘平台、时间跨度长、更新频率高的劳动力市场需求侧大数据集合。本数据库汇集了,为学术界和业界提供了一扇实时观察中国劳动力市场动态的窗口。

CnOpenData_wj的博客 2590

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

从瀑布到流水线:DevOps 入门与 GitLab + Jenkins + Docker 落地实践

先看清软件开发生命周期(SDLC)的全貌,再对比瀑布模型与敏捷开发,随后进入持续集成与 CI/CD 的机制内核;最后落到实操——在 GitLab、Jenkins、Docker 组成的四机实验环境里,走完源码托管、自动化构建、镜像封装与远程部署,直到参数化构建与版本回滚。概念与命令并重,既是入门地图,也是操作手册。

年轻的时候很穷,经过我多年的努力,终于不再年轻。 222

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

训练数据示例

针对“规格书生成测试用例脚本”的任务,在 LLaMA-Factory 中使用即可。关键是把“规格书内容”放进input字段,把“期望的脚本输出”放进output字段。

liuxs2009的专栏 55

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

DNS 不是把域名翻译成 IP:递归解析、TTL 缓存、CNAME 与报文排错实战

本文通过离线Python实验,拆解DNS递归解析、缓存机制与报文结构,揭示“DNS不是全局映射表”的本质。重点解析递归器角色、TTL衰减、CNAME链处理、负缓存隔离及修改记录延迟生效等核心问题,结合实战排错案例,阐明缓存层级、事务匹配、截断处理与安全边界,强调从应用到权威的逐层排查逻辑,实现可复现、可验证的DNS教学系统。

此人很懒,什么都没有写~~ 337

【LTE L3 笔记 09】LTE物理信道-PRACH

课程来源:B站《【2022】华为HCIA-LTE无线工程师认证学习中级视频》笔记为个人整理,含课件截图,仅供学习交流。

lyouhuan的博客 185

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 108

密码存储不是 MD5 加盐:PBKDF2、scrypt、参数升级与安全验证实战

本文通过实战演示密码存储的正确做法:摒弃MD5加盐,采用PBKDF2与scrypt等高成本密钥派生函数,结合随机盐、版本化记录与严格解析,确保离线破解成本可控。模块实现安全验证、参数校验、透明升级与统一错误处理,强调算法选择需兼顾安全性与可维护性,提供教学级密码存储方案,助力构建可迁移、可审计的认证边界。

此人很懒,什么都没有写~~ 218

软件测试用例模板怎么写:从用例设计到执行记录的全套指南

测试用例是测试工作的核心产出,它决定测试覆盖了多少、漏掉了什么。但大多数人的测试用例写得像流水账——只有正常路径,没有异常场景;只有操作步骤,没有预期结果;只有功能测试,没有非功能测试。本文拆解测试用例的标准结构,说明每个字段的含义和写法,给出覆盖功能测试、性能测试、安全测试的完整用例范例,并列出测试用例设计的五个高频遗漏点。

wuwangzhiduoshao的博客 131

【鸿蒙专题与实战】测试体系:单元测试、组件测试与 UI 测试

本文系统讲解鸿蒙开发中的三层测试实践:底层单元测试(用Hypium框架,优先覆盖纯函数、边界与异常)、中层ViewModel逻辑、顶层仅测3-5条关键UI路径。强调测试应“越往下写得越多”,因单元测试快且成本低,而UI测试慢易出错。通过实例说明断言拆分提升定位效率,结合覆盖率报告(hvigorwtest --coverage)发现盲区,核心是“用覆盖率找漏测,而非追求数字”。附五步落地清单:建测试文件、按优先级补用例、精简UI测试、生成报告、定位未覆盖行。下一篇将开启实战项目:从需求到上架全流程。

信息安全领域优质创作者|操作系统领域专家 154

MCP实战06:传输实战、测试与部署

你的 MCP Server 写完了,怎么确认它真的能被宿主正确调用?这课给传输层实战三件套:MCP Inspector 可视化调试、协议级自动化测试(pytest 断言 JSON-RPC 报文结构)、stdio/HTTP 双传输部署。测试不是可选项——工具描述错一个字段宿主就调不对,你能给 Server 建起自己的回归测试。

Blockbuster-drug 699

【LTE L3 笔记 05】LTE同步信号

课程来源:B站《【2022】华为HCIA-LTE无线工程师认证学习中级视频》笔记为个人整理,含课件截图,仅供学习交流。

lyouhuan的博客 110

Go1.27升后Config.Rand怎么改测

Go1.27起tls.Config.Rand弃用;确定性测试改用testing/cryptotest.SetGlobalRandom,附仓库扫描与go test冒烟。

Amax3747的博客 396

电芯串并联与BMS保护

串联升压、并联扩容,规则一句话,但整包能用多少由最弱的那节电芯说了算。这篇先算最弱电芯的账,再讲清三层保护,最后给对应的BMS测试用例:欠压、压差、均衡怎么测。BMS项目里有个常见场面:两台同配置的样车,电芯是同一批的,跑出来续航和限功率点却对不上。拆包量单体,一台里有一节电芯的容量比其他低了8%。整包表现被一节拖住,就是串并联的规矩在起作用。这篇先把规则和算例讲清,再讲保护分层,最后落到测试用例。

qq_43241255的博客 227

《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试

本文详细实现了ChatGPTProvider对接OpenAI ResponsesAPI的全量响应sendMessage接口,涵盖模型可用性校验、请求参数解析、JSON报文组装、HTTP客户端配置(含代理与超时)、网络请求发送及响应解析全流程。通过GTest编写测试用例,发现并修复了因Content-Type重复设置导致的400错误,揭示了不同厂商网关对请求头规范的宽容度差异,最终提出一套兼容多模型服务商的标准写法,提升了代码通用性与鲁棒性。

2501_91275995的博客 550
上一篇: 大型网站架构演变和知识体系
下一篇: 有关敏捷的若干思考
lerit
博客等级 码龄19年 200粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值