那些坑爹的老代码,究竟改还是不改?!

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://csdnnews.blog.csdn.net/article/details/78399395

在软件研发中,我们总会遭遇一个场景,就是要去改变或添加一项功能到既不是咱们创建、也不熟悉、更与自己负责的系统部分无关的代码中时,会遇到麻烦,而此时的内心更是崩溃的。

那么,面对前任程序员留下的代码,究竟要不要改?改写老代码,究竟如何才能不留坑?


曾刊载于《程序员》的《神秘的程序员们》漫画一则

长久以来,业界流传着一个约定俗成的禁忌:如果你恨一个程序员,就让他去维护年久失修的老代码吧!提到老代码,相信所有程序员都有话要说。

或许每位程序员都有一颗封疆扩土的雄心,所以入职后面对着冗余复杂的陈旧代码,很希望将一切推翻重来。毕竟代码结构 Bug、运行缓慢乃至于过于挑战审美等问题,很容易让人抓狂。但是对一家软件企业来说,老代码就是资产的象征,是多年积累下来的核心和重要竞争力。

对于软件产品,先后几波人维护过代码是很常有的事儿。如果你重写的新技术、新语言或者新框架并不能给产品带来质的飞跃,技术领导者又为什么要同意重写项目代码?更遑论维护过程中资金链断裂、核心程序员离职等突发情况的存在。

基于以上的思考,对于老代码我们究竟动还是不动?业内有赞同也有反对的声音:

@mostone:
动当然可以动,但一般一个项目的代码都比较庞大,如果耦合度较高,修改的风险必然很大。

@u013553804:
大刀阔斧,全部推倒重来,当无可奈何的时候。

@u012377333:
老代码能不能动,就看老代码写的怎么样了,比如一些开源框架,里面的很多基础的代码都不需要动或者只是简单的添加和新的业务逻辑相关的代码。如果老代码没有基于编码规范进行,里面势必就埋了很多雷,谁踩谁死。这里就涉及到一个问题,每一次代码合并必须要进行代码review,让该项目的所有开发人员对代码达成一致意见后,这样的老代码才能愈久弥坚。

@chinglish:
革命的时机未到你就去革命最终会革了自己的命;革命时机到了你再去革命那才真的是承天应人破而后立。

@dreaper126:
脱离业务需求,脱离上层的支持,脱离一个宽裕的时间段,切忌不要拆雷,成了没一毛钱好处,败了你就成千古罪人。

@汪海洋的博客:
变量命名没点数,有时写着还手误;界面全靠神奇数,保准看到就发怵;私有公有混一处,代理委托亦糊涂;消息通知满天飞,委托方法一大堆;第三方库无出处,随手改动无备注;单个对象多职责,悲伤逆向流成河;产品突增新功能,一行代码变大神;来了任务有委托,多写一行都嫌多。

对于老代码你有什么样的观点?欢迎各抒己见,在留言区分享你和老代码的爱恨纠缠。

展开阅读全文

脚本运行超时,改代码还是改Server.ScriptTimeOut?

03-26

asp+accessrn数据库表goods_info有6万多条记录rn如果价格变动,要更新的字段有5个rn页面执行时间太长,会自动中断,这是为什么?rn多次发现,一秒中更新约8条记录,如果更新1~2千条记录没问题,时间1~2分钟。rn但有时候要要上万条记录变更数据,页面执行1~2钟就自动中断的,脚本运行超时。。。。。。我设置的是90秒超时rn要执行这么多记录总不能把响应时间设到无限长吗?<% Server.ScriptTimeOut=9999999 %>rn有没有其他办法?改代码可以吗?怎么改才可以?rn6万多条记录也不多啊,就算一秒钟更新10条记录,要执行1.6个小时????这个不太正常吧?rnrnrnrn我的代码:rn***************************************************************************************rnif request("action")="update" thenrnrntimeS=timer()rnset rs=server.CreateObject("adodb.recordset")rnrs.Open "select * from goods_info where g_id=''",conn,1,3 '根据条件变更条件筛选记录rnif rs.Bof and rs.Eof then rnMsg=" 没有要更新的记录!"rndTime=-1rncall WriteMsg()rnelserndo while not rs.Eof thenrnrs("p1")=rs("p1")*request("cRate") '更新零售价rnrs("p2")=...... '更新字段2rnrs("p3")=...... '更新字段3rnrs("p4")=...... '更新字段4rnrs("p5")=...... '更新字段5rnrs.Update--------------------------------------》是否必须一条记录一次update?rnloop rnrs.Closernset rs=nothingrnend ifrntimeE=timer()rncalTime=FormatNumber((timeS-timeE),2)rnaveTime=formatNumber(calTime/r,3)rnMsg=" 数据库更新完成!"rnMsg=msg&" 执行时间:"&calTime& "秒,平均"&aveTime&"秒/个记录"rndTime=-1rncall WriteMsg()rnrnend if 论坛

还是老错误啊!

04-07

“/20100126pms”应用程序中的服务器错误。rn--------------------------------------------------------------------------------rnrn未将对象引用设置到对象的实例。 rn说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 rnrn异常详细信息: System.NullReferenceException: 未将对象引用设置到对象的实例。rnrn源错误: rnrnrn行 294: sql = "select * from base_area2_type order by id asc";rn行 295:rn行 296: tablerows = [color=#FF0000]db.DBSelect(sql).Tables[0];[/color]//就是这儿的错误!但我感觉对啊rn行 297:rn行 298: for (int i = 0; i < tablerows.Rows.Count; i++)rn rnrn源文件: e:\20100126pms\ReportChart\Chart_Station.aspx.cs 行: 296 rnrn堆栈跟踪: rnrnrn[NullReferenceException: 未将对象引用设置到对象的实例。]rn ReportChart_Chart_Station.GetNewTable() in e:\20100126pms\ReportChart\Chart_Station.aspx.cs:296rn ReportChart_Chart_Station.Page_Load(Object sender, EventArgs e) in e:\20100126pms\ReportChart\Chart_Station.aspx.cs:52rn System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15rn System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34rn System.Web.UI.Control.OnLoad(EventArgs e) +99rn System.Web.UI.Control.LoadRecursive() +47rn System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061rnrn rnrnrn--------------------------------------------------------------------------------rn版本信息: Microsoft .NET Framework 版本:2.0.50727.832; ASP.NET 版本:2.0.50727.832 论坛

还是老问题。

09-28

异常详细信息: System.Runtime.InteropServices.COMException: 命令失败rnrn堆栈跟踪: rn[COMException (0x800a1066): 命令失败]rn Microsoft.Office.Interop.Word.DocumentClass.SaveAs(Object& FileName, Object& FileFormat, Object& LockComments, Object& Password, Object& AddToRecentFiles, Object& WritePassword, Object& ReadOnlyRecommended, Object& EmbedTrueTypeFonts, Object& SaveNativePictureFormat, Object& SaveFormsData, Object& SaveAsAOCELetter, Object& Encoding, Object& InsertLineBreaks, Object& AllowSubstitutions, Object& LineEnding, Object& AddBiDiMarks) +0rnrn//初期化rnWord._Application WordApp = new Word.Application();rnWord._Document WordDoc;rn rn//创建rnWordDoc = WordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref objTrue);rnrn//保存rn[color=#FF0000]WordDoc.SaveAs(ref filename, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing);[/color]//回收 --------跑到这里就出错,所有保存的方法都出错,包括save save2000rnWordDoc.Close(ref Nothing, ref Nothing, ref Nothing);rnWordApp.Quit(ref Nothing, ref Nothing, ref Nothing);rnSystem.Runtime.InteropServices.Marshal.ReleaseComObject(WordApp);rnrnrnrn补充一点,我的机器是 32位 windows2008 office2003 iis6. 服务器是 64位 windows2008 office 2003 iis7.0 兼容6.0 rnrn现在就是出这个错,能走到Saveas说明有权限去创建一个模板,但是就是在另存为的时候出这个错误,到底是那块的权限配错了啊?我权限用的是管理员的账号密码。希望高手指点指点。rn还有就是如果我open一个doc的时候也出错,但是那个错是:内存不足,什么什么的,,既不太清了,我觉得上个问题解决了,这个问题也就不是问题了。 论坛

还是那个老问题

06-04

为了提高速度,我已经添加了包括info_time在内的很多冗余字段,以下语句我希望能够查询一个时间段 '2009-03-01 00:00:00' 到 '2009-04-01 00:00:00' 的内容,但是按照E_role_info.info_reprint 这个字段排序!rn强制索引idx_E_role_info_roleID_reprint是在E_role_info(roleID, info_reprint)上建立的。rn由于没有用到相应时间索引,我本以为筛选出'2009-03-01 00:00:00' 到 '2009-04-01 00:00:00'的数据会用到filesort。rn但以下却没filesort。而且运行结果也很快!rnrn我想求证的是,mysql是不是在筛选WHERE E_role_info.roleID = 413382 的过程中,同时也在数据表中检查了E_role_info.info_time 是否符合E_role_info.info_time > '2009-03-01 00:00:00' AND E_role_info.info_time < '2009-04-01 00:00:00' ?rnrn[code=SQL]rnmysql> EXPLAINrn -> SELECT SQL_NO_CACHE STRAIGHT_JOIN E_info.infoID, E_info.info_title, E_info.info_time, E_info.info_reprint rn -> FROM E_role_info FORCE INDEX(idx_E_role_info_roleID_reprint) INNER JOIN E_info IGNORE INDEX(idx_id_time) USING(infoID) rn -> WHERE E_role_info.roleID = 413382 AND E_role_info.info_time > '2009-03-01 00:00:00' AND E_role_info.info_time < '2009-04-01 00:00:00' rn -> ORDER BY E_role_info.info_reprint DESC LIMIT 0, 10;rnrn+----+-------------+-------------+--------+--------------------------------+--------------------------------+---------+-------------------------------+---------+-------------+rn| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |rn+----+-------------+-------------+--------+--------------------------------+--------------------------------+---------+-------------------------------+---------+-------------+rn| 1 | SIMPLE | E_role_info | ref | idx_E_role_info_roleID_reprint | idx_E_role_info_roleID_reprint | 3 | const | 2707604 | Using where | rn| 1 | SIMPLE | E_info | eq_ref | PRIMARY | PRIMARY | 4 | news_data2.E_role_info.infoID | 1 | | rn+----+-------------+-------------+--------+--------------------------------+--------------------------------+---------+-------------------------------+---------+-------------+rn[/code]rnrn还有一个疑问,该语句中我在E_info后添加了IGNORE INDEX(idx_id_time), (注:idx_id_time是E_info(info_time))上的索引),这样才得以在上边的explain的结果中得到E_info用eq_ref的结果,这样算是比较好的效果了!rnrn但是如果不忽略idx_id_time索引,则结果如下:rn[code=SQL]rnmysql> explain SELECT SQL_NO_CACHE STRAIGHT_JOIN E_info.infoID, E_info.info_title, E_info.info_time, E_info.info_reprint FROM E_role_info FORCE INDEX(idx_E_role_info_roleID_reprint) INNER JOIN E_info USING(infoID) WHERE E_role_info.roleID = 413382 AND E_role_info.info_time > '2009-03-01 00:00:00' AND E_role_info.info_time < '2009-04-01 00:00:00' ORDER BY E_role_info.info_reprint DESC LIMIT 0, 10; rnrn+----+-------------+-------------+------+--------------------------------+--------------------------------+---------+-------------------------------+---------+-------------+rn| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |rn+----+-------------+-------------+------+--------------------------------+--------------------------------+---------+-------------------------------+---------+-------------+rn| 1 | SIMPLE | E_role_info | ref | idx_E_role_info_roleID_reprint | idx_E_role_info_roleID_reprint | 3 | const | 2707604 | Using where | rn| 1 | SIMPLE | E_info | ref | PRIMARY,idx_id_time | idx_id_time | 4 | news_data2.E_role_info.infoID | 1 | | rn+----+-------------+-------------+------+--------------------------------+--------------------------------+---------+-------------------------------+---------+-------------+rn[/code]rnrn我认为,E_role_info到E_info的联合是通过infoID,所以如果不用到建立于,E_info(infoID)上的主键索引的话,其type指标应该是ALL,进行全表扫描,但是上边却显示在E_info用idx_id_time为索引的时候type为ref,这是为什么呢? 论坛

没有更多推荐了,返回首页