每一块钱都是平等的

每一块钱的价值都是一样的,这是常识。但是人们会有很多心理认知颠覆这一常识。

首先,人们会根据钱来得是否容易来决定是否需要珍惜这笔钱,比如十多年前,我有一个长辈,喜欢小赌怡情一下,一般输了钱回家就默默的,要是赢了钱,手上必定拎着几斤猪肉,因为反正钱是赢来的,不吃白不吃嘛。所以你知道澳门开赌场有多挣钱了,输钱了的自不必说,赢钱了的也会挥霍一番。可能辛苦搬砖挣来100块的舍不得用,要是地上捡的,那就可以铺张浪费一番了。可是仔细想想,100块就是100块,无论怎么得来,从投资理财的角度来看,都是没有任何差别的。

反过来想,贷款买房时,争取零点几的利率折扣,就是很多万块的差价,如果这笔钱要靠在菜市场讨价还价来节省,可能一辈子都不够,但是却有人会在买菜时对几毛钱斤斤计较,买房时却放松了警惕,没意识到小数字背后的大数字。

金钱的这种平等在某种意义上是有些残酷的,作为一般等价物,金钱抹去了人在付出劳动时的差异,只留下一个赤裸裸的数字,甚至连善恶也是不分的。

我不想讨论伦理的话题,只是想说,从投资理财的角度来看,每一块钱都是平等的。无论钱从哪里来,它都要进入你的资金池,获得同等的地位,在消费的时候,应该从你的资金池的能力出发,决策消费的必要性和档次,而不是因为某笔钱来得容易就专款专用了。

不理解这一点的人去投资股票,会像赌博的人一样,账面上浮亏的时候默默不出声,万一要是账面上浮盈了,甚至股票还拿在手上就先预支一笔钱来庆祝了,忘记了投资的长期性,浮盈的有可能会再变成浮亏,只要一日在股市,就难以称得上真正盈利了,这或许也是股市看似简单实则很难的原因,在很多方面它都是反人性的。作为一个价值投资者,必然要克制自己过度的欲望,合理的支配自己的每一块钱,战战兢兢的和市场先生做朋友,没有所谓的明确的成功的界限。

努力的二八定律

很多人都会认为自己不善言辞,不善于跟人沟通,作为一个性格偏内向的人,我曾经深受这种社会认知的毒害,当一个人被贴上这样的标签后,他与口若悬河的人就成了两个世界的人,甚至慢慢接受沟通无能的设定后,也就认命了。一个人的特性往往比标签要复杂的多,而且更重要的是,人不是一成不变的,即使我们承认人的沟通交流能力天生就有高低之别,但是所谓先天不足的人就真的只能沟通无能吗?

很多人不敢上台讲话,他们以为那些在台上滔滔不绝的人都是天生如此,说起来我最近几年偶尔也能在台上滔滔不绝一番,但是其实我的手和声音都是发抖的。

实际上,没有必要每个人都成为希特勒一样的演讲帝,只要能准确的传达自己的思想给别人就好了,而做到这一点,恰恰是可以通过努力实现的。那些讲课满堂彩的老师,大多是备课及其充分的,有些人连什么时候讲个笑话活跃气氛都是事先想好的。所以,如果你的目标是表达能力超过80%的人,那么持续努力就好了,对每一次交谈和讲话都打腹稿、写逐字搞,努力提升自己的思维层次和学识水平。

由此扩展一下思考,实际上在很多领域,我们只要努力,都可以轻松超越那个领域内80%的人,因为绝大多数的人是不努力的,或者他的经验都是接触这个领域的头几年学的,表达能力是学说话的前几年有意识在学的,工作经验是参加工作头一两年掌握的,工作十年不一定经验就超过工作一年的,正如我们说了很多年的话,竟然还是觉得自己不会说话一般,不带脑子不费心思的话,时间雕刻不下印记,只是过去了而已。

在大多数领域,只要足够努力,你就可以超过80%的人成为前20%,这就是努力的二八定律,尤其是在一些“软知识”领域,这些知识不是物理、数学,而是学校不教的,比如怎么讲话,怎么投资,怎么去爱别人。当然,在任何一个领域要成为顶尖都不容易,可是也没什么必要吧,如果能把自己的所谓“短板”通过努力变成20%的优秀,对人的整体提升效果可能已经相当惊人了。

C++/CLI优秀资源列表

C++/CLI是个奇怪的技术,简单一点说它是.Net版本的C++,但是.Net平台已经有C#这样的霸主语言了,还要C++/CLI干啥呢?我觉得最大的意义可能在于将C++程序移植到.Net平台,从我个人封装clips(C语言开发)到.Net的经验来看,C++/CLI由于兼容普通C++代码和.Net的,带来了很多方便,麻烦在于指针之类的都要考虑普通C++和C++/CLI两套体系。会C++和C#的人学会这门技术并不难,因为它的概念在C#中是一一对应的。以下是我现学现卖时搜集的一些比较好的资料。

个人理财的15条原理

《个人理财》这本书,是美国大学的本科教材,内容相当丰富,涉及现金管理、股票债券基金保险、买房买车、养老计划甚至遗嘱,很可惜我没有在十多年前的本科学到这本书,不过好在现在看了,还来得及教我孩子。

这本书由于写的是美国的情况,所以很多内容只有原理性的参考价值,具体应用需要参考中国的实际情况,所以我也只是大致翻了一遍,但是它总结的个人理财的15条原则贯穿全书,是具有很强的普世性的。这里摘录列举一下,顺便简单说说我的理解。

  1. 风险与报酬的权衡:风险与收益一般来说是正相关的,所以忽悠高收益低风险的理财师基本上可以定义为骗子。但是也不是那么绝对的,通过知识差信息差是有可能低风险较高收益的,反之,低收益的产品也可能是高风险的,比如某些网贷平台。
  2. 货币的时间价值:不理解复利没法理解投资,中国人情借钱,十年前借1万,十年后还1万,如果按年华收益7%算,也基本上翻倍了。
  3. 多样化有助于降低风险:所谓东方不亮西方亮。但是要注意投资品种间的相关性。
  4. 不是所有风险都是一样的:多样化并不能消除系统性风险,如果经济整体崩溃,买什么股票债券基本上都完蛋。
  5. 竞争性投资市场的根源:通过竞价机制,市场一般是有效的,打败市场非常之难。所谓猪也是这么想的就是这个原理了,我经常听到有人说希望在股市中获得50%到100%的年化收益,只能祝他们赌博愉快。
  6. 税收因素对个人财务决策的影响:开赌场的赚钱。
  7. 流动性的重要性:高流动性带来溢价,低流动性带来折价。一般要留3~6个月的生活费,T+0或者T+1可以投资货币基金、逆回购等品种。
  8. 没有计划将一事无成:我从2015年底开始做财务总结与计划,感觉效果很明显。
  9. 知识是最好的保障:不要当韭菜。
  10. 保护自己免受重大灾害或灾难的威胁:消费险是保险的本质。
  11. 投资的时间尺度:股票投资至少能拿5年,比特币我至少拿20年。
  12. 委托代理问题——注意推销技巧:我觉得不看广告看合同比较靠谱。
  13. 优先付给自己:拿到钱,先想到储蓄投资或者自我提升。
  14. 金钱并不是一切:这是正确得废话。
  15. 开始行动吧!投资理财越早越好,以前没开始的就要今天开始。

尽人事安天命的概率学原理

为什么马云那么有钱?

你去找各种心灵鸡汤故事的话,会看到很多分析,一般都要从马云的童年说起,仿佛他时命定的商业巨子。

如果你分析一下中国三十多年来的历史进程,出现类似马云的人物几乎时必然的,中国有世界上最大的市场,再加上信息革命的浪潮,出现新经济富翁是必然的,所谓大风起兮猪飞扬是也。

那么问题就变成了:为什么这个人是马云?从历史来看,这不过是一个随机事件,不是马云,就是李云、张云。所有的鸡汤故事都是事后诸葛亮,把所有能联系起来的因素都和最终的成功联系起来,因为鸡汤要让读的人有那么一瞬间的幻觉:我也能成功,只要我照着书上说的去做。

关于成功这件事,我觉得古人已经把道理说尽了,那就是:尽人事安天命。我想从概率的角度再解读一下。

一个人的成功始终是个概率事件,命运中的不可控因素太多,谁也不能保证把控自己的命运,让马云回到过去再平行宇宙中再来一次,或许一个微小的变化就会让他不再能进入首富行列。但即使这样,我相信他也会过得比大部分人要充实,因为他毕竟比大多数人要努力思考并践行自己的思考。

成功是一个概率事件,而努力则能提高这个概率,尤其是持续努力,50%成功率的事情连续两次就能将成功概率提升到75%,因为人生和赌博不同,往往抓住一次机会就能一飞冲天了。比如那个做Flobby Bird发了小财的越南人,在那之前做了十几款App一个都没火,他也只不过是通过自己的坚持等到了一个成功。

真正有用的道理听了可能并不直接让人直接就兴奋起来,尽人事安天命就是这种道理,它要求你尽自己最大的努力,却又对成功不抱过多的期望,浮躁的人们又有几人能做到呢?

既然我努力了也不一定成功,那为什么我还要努力?

努力能提高成功的概率,天上掉馅饼也要出门捡才行。

如果一直努力,始终不能成功怎么办?

首先成功应该视为对努力的一种回报,努力之后的回报有大有小,是概率事件,所以应当更关注成长,其实本质上没有一个明确的成功与否的界限。退一步看,即使始终“不成功“,一个人能努力活一辈子,不枉此生,已经接近了生命的意义,应当视为上天的恩赐。

2016总结

2016年总的来说是越来越努力的一年,付出的努力也基本上得到了回报。

工作

带领小团队完成了2015年的2个软件项目,2016年小团队承担了5个软件研发项目,而且工作主要集中到了下半年,实在是不堪重负,部分项目只能草草交差了事,不过也有亮点,个人完成了3个项目的架构设计,其中1个是在同事前期开发的基础上重构出来的,组织了团队的日常交流,涉及面向对象设计和机器学习算法等,团队成员得到了成长,到年底基本上不再负责具体的项目。如果明年还继续这个工作,一定要保证每个项目2~3人的配置,以免粗制滥造。

学习

业余时间在coursera刷完了《学会学习》、《机器学习》、《算法一》,这些课程都相当好,尤其是《学会学习》值得向每一个想要学习的人推荐。借助boolan网复习了一轮《设计模式》,有大量的编程经验后再回头学体会比较深刻。

出于自己及育儿需求,集中阅读了比较多的学习理论与心理学方面的书籍,包括《玩耍精神》、《刻意练习》、《学习之道》、《精进》、《自控力》、《如何高效学习》等。但是还需要慢慢消化吸收,充实自己的治学体系。

另外还值得一提的书有《父母效能手册》、《人类简史》、《调试九法》、《程序员修炼之道》。

订阅了李笑来的得到专栏《通往财富自由之路》,虽然说教味比较浓,但是确实有很多可取之处。

Python语言学了一个皮毛,能够应付一些算法问题。

投资

对投资已经单独写了总结,不再赘述,需要补充一点就是看投资方面的书,几乎是一本万利的事情,主要有《指数基金投资指南》、《个人理财》、《低风险投资之路》等,几乎每本都带来了直接的收益。

健身

年中计划用悦跑圈记录跑步100公里,结果只记录了约90公里,当然如果加上未记录的部分,是超过了100公里,年初体检时发现轻度脂肪肝,所以立志少吃多运动,基本上都做到了,目前130多减重到120多。

娱乐

2016年豆瓣标记观看影视作品57部(实际上可能只有50部左右),其中电影院观看了14部,考虑到时间宝贵,以后挑片子只能更加谨慎。去了张家界和拉萨旅游,去拉萨是计划外。

家庭

和家人的沟通越来越顺畅,除了聊天还开辟了写文章交流思想的新方式。着急小朋友虽然各项能力发育程度不一,但在妈妈和外婆的照顾下茁壮成长,独立人格值得珍惜,只是在沟通交流方面需要更多的耐心和担待,辛苦妈妈了,我也要尽更多的责任。

其他

一个小惊喜,拿到了公司辩论赛的最佳辩手,尽管在台上我一如既往的竞争到手抖。

2017重大计划

  1. 换工作,这需要一些充电工作,通过纳米学位学会Android开发,业余开发1~2个App发布到市场,用java语言刷完leetcode算法题,适当学习Java语言满足Android开发和刷题的需求;
  2. 伴随换工作的还有住房问题需要解决;
  3. 继续深入学习投资,主要教材《聪明的投资者》、《手把手教你读财报》,以家庭基金形式运作投资,每月底发布净值和投资小结,减少归并投资账户。
  4. 继续完善自己的治学体系,重点学习批判性思维,主要教材:《Beyond Fellings》、《学会提问》。
  5. 每天一篇blog,每天github提交代码。
  6. 长跑200公里,累计300公里,基于HIT、NEAT等理念在时间紧张时设法保持运动,维持体重,争取不感冒。

互联网获取信息的三种方式:漫游、订阅、检索

前几个星期,我把手机上几乎所有App的通知都关掉了,然后在接下来一个星期里,使用各种App时,它们不断提醒我要打开通知,不要错过重要的信息。我没理它们,也似乎没错过什么重要信息。在这个所谓的信息时代,我们每天收到的信息可能比古代的皇帝还要多,但真正需要的有多少非常值得怀疑,你以为你在信息的海洋遨游,其实只不过是被人收割你的注意力和所谓无聊的时间。互联网是相当强大的一个工具,想要很好的使用这个工具则需要自身的强大,否则很容易成为工具的奴隶。本文将辨析互联网获取信息的三种方式:漫游、订阅、检索。

1 漫游

这里的漫游一定程度上指的就是不带有明确目的在互联网上瞎逛。这种方式是互联网对信息获取方式的最大的颠覆,也是最大的一把双刃剑。超链接出现后,信息间联系方便而无限扩展,传统的信息组织方式大多是线性、树性的,而互联网的信息组织形式是网状的,它带来了很多好处:

  1. 网状能够模拟一切复杂的结构,所以提供了更真实的表现信息结构的可能性,比如维基百科比传统的百科全书在结构上的优势;
  2. 信息内部与外部的界限更加模糊,“参考文献”更易获取,在互联网上做一个专题比传统媒体要容易得多;
  3. 提供了无限的遇到惊喜的可能性,在漫游的过程中,可能发现以前自己不了解的东西,产生思想的碰撞火花,破除信息孤岛和自己的认知屏障。

但是这种方式的缺陷也是很明显的:

  1. 被太多的垃圾信息占据了过多的时间,很多制造信息的人居心叵测,各种标题党无时无刻不再窥窃你的注意力;
  2. 获取的信息非常零散,不成体系,互联网信息依然以免费为主,相比书籍信息质量依然相对低下;
  3. 漫游这种方式很容易伴随浮躁情绪,带来所谓的信息过载,以励志文章代替立志,以了解代替理解,以知道代替知识。

要想让漫游这种方式发挥好的作用,最需要的是自身的强大,包括价值观与批判性思维等,才能不断在信息海洋中吸收养分,否则就会被淹没。

2 订阅

订阅这种方式是互联网之前的传统媒体与人交互的主要方式,但随着互联网的发展,也成为互联网上获取信息的方式之一。大多数信息提供者希望用户能够订阅,建立长期关系,这样才能获得利益,它的形式可能是关注、推送等。比如,微信的公众号乃至朋友圈是对信息漫游的一次复古和反动,微信公众号文章甚至连分享的超链接都故意是不稳定的,试图打造自己的小生态。订阅有很多变种,最前卫的一种是机器学习带来的推荐机制,本质上是基于个体兴趣的一种订阅,无论订阅是复古还是前卫,它都有它的优势:

  1. 订阅是一种筛选机制,能集中注意力关注自己真正关心的人和事,或者通过关注靠谱的人帮助自己过滤信息;
  2. 订阅很容易加入付费机制,建立高质量的知识服务,在高速迭代的同时保存信息的高质量。

但是订阅也带来了风险:

  1. 圈子化,不论是主动筛选还是机器筛选,最后听到看到的都是自己愿意看到听到的,把自己喜欢的理解为全世界的真相是有很大风险的;
  2. 看似主动订阅的背后有着很大的被动,人们倾向于维护自己的选择,当了一个人的粉丝可能回去粉饰他的错误,如果投入了金钱,则会更加坚定最初的选择。

3 检索

检索是学术研究必备素养,我觉得也是一个现代人活在互联网时代的必备素养,搜索引擎是互联网上超链接之后最伟大的发明。通过检索,一个获取信息的人才能真正把互联网当成一个工具:

  1. 方便的检索使得掌握孤立知识变得价值很低,比如一些电视知识竞赛中类似于“中国的铁轨有多宽?”的问题,因此介入一个新的领域变得很容易;
  2. 检索具有强烈的目的性,信息为我所用有了一个好的起点,不会再有在网上逛了两小时却记不起自己看了什么的现象出现;
  3. 检索常常能能立即解决问题,只要你不是遇到问题的第一个倒霉蛋。

检索能发挥作用,除了提高检索的基本技能外,最重要的还是自身治学水平的提高,否则也会陷入以检索代替思考的误区,满足于互联网这个外脑带给自己信息,自己不能综合运用,提出创意。

4 综合

为了厘清概念提出了三种方式,真实的场景往往是三者的结合,比如在新浪微博关注了某程序员(订阅),他提到了某种新的编程语言很有意思,还给出了一个链接,于是随手点开看看(漫游),发现真的不错,于是Google搜索到语言官网等很多信息(检索),集中学习了1小时。但也可能是,在新浪微博关注了某程序员(订阅),他转发了某个搞笑视频,于是随手点开看看(漫游),结果看了一个有一个,一个小时候后不知道自己在干啥。

这些获取信息的方式都有它的优势,关键是使用时应当“有意识”,让自己的脑子时刻提醒自己的状态,即使是最自由的漫游状态,也应当设定一定的时间限制,否则无数的注意力黑洞会让你的时间死得不明不白。

互联网是一个强大的工具,甚至会对弱者实施碾压,如果不持续提升自己的判断、分析能力,只会被不断的收割注意力,不断的被洗脑,觉得世界上充满了很有道理的话,但依然过不好这一生。

《锻炼的真相》笔记

地平线系列:关于锻炼的真相 Horizon: The Truth About Exercise (2012)

  1. 运动所能消耗的热量其实并不多,减肥光靠运动不行,关键还要少吃。
  2. 血脂最大的危害还不是皮下脂肪,而是积聚在内脏的脂肪。
  3. 运动除了消耗热量,还能带来其他好处,比如运动过再吃东西会提高某些脂肪代谢相关酶的活性,血脂含量会低不少。
  4. 运动对不同的人产生的作用是不一样的,某些作用是基因决定的。
  5. HIT,即短时间高强度的运动(可以短至每周三分钟,每次二十秒)可以大幅度改善很多人的血糖代谢能力,预防糖尿病,和改善供氧能力。
  6. 改善NEAT,即非运动代谢,可以让我们更健康,其关键点就是不要久坐,绝对不要超过一个小时,应该不时的站起来动一动,走一走。
  7. 总的来说,锻炼会逐步迈入个性化时代,每个人都要找到适合自己的方法,千万不要因为讨厌去健身房或专门花大块时间锻炼就放弃了锻炼,像HIT和NEAT都是无需特别的大块时间的科学的锻炼方法。

《调试九法》:调试是个技术活

一般当工程师把一个东西称为艺术甚至玄学的时候,说明这个东西难度很大,没有太多规律可以遵循,调试就属于此列。几乎每个程序员都有被bug搞到死去活来的经验,有时候颠来倒去,问题似乎解决了,但也不知道为什么,就把它当作不可解释的玄学现象,最烦人的一种bug是偶尔出现难以复现的,学名海森堡bug。

不过毕竟软件还是属于科学技术的范畴,调试也应当是门技术活。《调试九法》是一本少见的讲调试技术的书,九个普遍性的原则不仅适用于软硬件开发维护,甚至还能运用到日常生活,为了找到这本书我也是费了点神,幸好图灵社区还有正版的电子书卖。

说实话,作者举的很多例子偏硬件,所以理解起来有点隔膜,但是九个原则确实很实用,在我以前的开发调试经历中可能也不自觉的总结过一些,但是看了本书,还是有拿到武功心法的感觉。看过之后,下面再把九个原则遍历一下,加深理解。

1 理解系统

这是最重要的一条原则,要分析bug,自然要理解系统是如何运作的,这就需要学习掌握一些基本原理,对具体的类库、工具、技术都需要认真的去读相关文档。我最近几年才养成了认真读官方文档的习惯,搜索引擎的发达,使得我们养成了面向google编程的习惯,面对问题,总是想一蹴而就的解决,结果往往是走了很多弯路,因为舍不得花时间看路标。本书还特别强调“逐字逐句”读手册,简直是对浮躁的人当头棒喝。不理解系统就开始调试和不理解原理就写代码是一脉相承的,俗称“面向巧合编程”。

2 制造失败

这条原则讲的是复现bug的重要性与方法,一个bug,肯定是在某个特定的条件下发生的,抽丝剥茧找到这个特定的条件,就成功了一半。以我的硬件维护经验来看,发现bug的人如果能详细的记录整个过程是非常有帮助的。有很多bug出现的条件比较苛刻,所以程序员的口头禅之一就是“在我这里没问题啊”。针对这类bug,首先最好能找到模拟方法,比如加快软件运行交互的速度,进行压力测试等,其次就是在软件内部能有详细合理的bug记录机制,便于从内部找到复现的条件。

3 不要想,而要看

这一条强调的是观测的重要性,面对现实比胡思乱想重要。语言影响思考,所以遇到bug的口头禅应该是“我看看“而不是”我猜可能是因为“。我们应该想尽办法去看清楚出bug的细节,所以成熟的程序中都应该有用于调试的基础设施,个人经验至少日志是必不可少的,初级程序员习惯于完全靠打断点调试,问题是断点本身会改变程序执行的流程(尤其是多线程的情况下)。当然,猜测依然是有用的,可以帮我们缩小观察的范围,或者至少拟定一个观察的优先级,这样经验就能发挥作用,但是不管怎样,经验不能替代观测。

4 分而治之

二分查找法可以把查找的时间复杂度从线性变成对数,不仅是程序中的查找算法,也是调试时的方法论,一个系统有了这个意识后,关键是如何划分系统,又回到了原则1。至少在打断点调试时,要找到出bug的位置,也是可以用二分法的,或者插入日志记录时也可以应用这个原则。另外,书中还提到了bug间相互影响的现象,我觉得甚至又bug跷跷板的现象,解决之道是一个都不要放过。调试bug时发现代码质量实在太差,重构一下有时候也是有必要的,否则浮沙之上筑不了高台啊,甚至经过有效的重构,bug很自然的就发现并消除了。

5 一次只改一个地方

这条原则类似实验科学中的对照原则,一次只考察一个变量,比对正常情况和异常情况,一定不能忽略任何一个测试条件的差异。上一条说bug一个都不放过,但也得一条条过,重构的时候也要注意不要对不懂的代码乱改一气,很多代码的危险性在于牵一发而动全身,我觉得这也是修复bug时的最大风险,往往是消除一个bug同时增加几个bug,还是回到原则1,要理解系统。不过有时候,理解前人的代码谈何容易,这也启示我们写代码时要多积德,不要以为代码就是给编译器看的,而应该是给以后维护我们代码的人看的。

6 保持审计跟踪

这条原则讲的是记录的重要性与方法,我想这就像医生问诊一样,需要问合适的问题,给出具体的有效答案。我的个人经验是一旦开始调试bug,可能整个人就彻底陷进去出不来,通过记录的方式可以把自己从思维的泥潭中抽身出来,不断修正调试bug的计划与方法。对一些专用系统软件,需要培训软件的使用者如何用有效的语言来记录出现bug的情况,如果没有记录,那么调试的人就需要用适当的问题帮助使用者唤醒记忆。此外,我觉得半夜调不出的bug需要睡一觉,让发散思维自动起作用,一般早上就解决了。

7 检查插头

这条原则大概说的是所谓”低级失误“了,类似我妈跟我说电脑音箱不响了,我首先得问电源开了没这种。又比如把main函数写成mian函数,有一次我打断点调试就是不进断点,后来发现是因为有两段代码比较类似,我断点打错地方了。根据场景和经验,问问自己是否犯了该场景下常见的低级失误,往往针对能立竿见影的解决很多问题,就像很多电器设备说明书的故障FAQ中,也会强调检查插头。可以说,低级失误低级的是难度,而不是频度。

8 获得全新观点

这条原则说的是求助和交流,这里面很重要的是通过他人的观点来破除自己的思维定势,所以最好是只给别人详细描述现象,不要说自己的猜测,以免污染别人的判断。对程序员而言,这时候面向google编程的力量是惊人的,可能九成的问题都不需要你真正的再去提问,而是找到合适的搜索词去搜索即可,对中国程序员而言,用英文搜索是必须的技能,当然搜到东西后真正理解也是非常重要的,不能见到药就吃。如果遇到的问题google真的搜不出来,证明你层次稍微高了点,这时候可以上stackoverflow之类的社区提问。

9 如果你不修复bug,它将依然存在

这条原则说的是不要心存侥幸,不要因为bug只是闪现了一下就采取鸵鸟策略,该来的总会来,不是不报,时候未到。当然实际情况可能很复杂,软件工程本来就是时间、成本和质量的妥协体,但即使放过某些bug,也要分析出这样可能造成的后果,建立充分的防护机制,因此在很多软件认证体系中,都会有软件安全等级标准。这里还涉及bug复现和举一反三的问题,需要确认真正找到了bug的原因提供了有效的修复手段,并排查所有类似的问题。比如修复了一个内存泄露问题,就要修复所有导致这类泄露的代码。

附记:如何写出适合调试的代码

从调试的原则反观,对软件构建本身也很有帮助,毕竟调试只是查漏补缺的,最好还是写出来的代码少一些bug,为了调试的时候方便多预留一些手段。这里也简要总结一下个人经验,可能需要不断完善。

  1. 程序中应该提供日志机制,在程序的debug版便于输出调试信息,即使在release版,也要记录软件发生问题(如C#中抛出异常)时的详细情况;
  2. 要写出适合人类阅读的代码,否则后续维护的人看都看不懂,要如何调试?怎么写《代码大全》中说得最详细了,我觉得除了各种习惯写法之外将心比心也是很重要的;
  3. 使用各种类库或工具时,尽量弄懂原理,仔细的阅读官方文档,比如有些类库会详细说明如何防止内存泄露,如何应对多线程情况,看清楚再用,就会少种下祸根,至少不用等到调试的时候再无头苍蝇一样猜测原因;
  4. 写便于测试的代码,这样在调试时,容易剥离问题,或者使用二分法,这方面TDD编程实践讲得比较充分,我个人也需要加强。

如何序列化泛型List为xaml

Xaml实际上是一种加强版的Xml,Xaml最初是为了描述WPF控件而设计的,但其实具有一定的通用性,用Xaml序列化对象,可以自动维护对象间的引用关系,大大减轻工作量。

1. WPF控件中泛型List的序列化

Xaml序列化对象最直接的应用是保存和加载WPF界面与控件。考虑类似以下的自定义控件类,它包含了一个泛型列表属性。

public class WpfObject : Label
{
  public WpfObject()
  {
    Children = new List<string> { "hello", "wpf" };
  }
  public List<string> Children { get; set; }
}

WPF控件的序列化方法如下:

WpfObject w1 = new WpfObject { Content = "Hello, wpf" };
string xaml = System.Windows.Markup.XamlWriter.Save(w1);
File.WriteAllText("label.xaml", xaml);
WpfObject w2 = (WpfObject)System.Windows.Markup.XamlReader.Load(File.OpenRead("label.xaml"));

由于XamlWriter类的不完善,不支持泛型列表的序列化,上述代码将抛出异常:

无法序列化泛型类型“System.Collections.Generic.List`1[System.String]”
Cannot serialize a generic type “System.Collections.Generic.List`1[System.String]”

所以需要包装泛型列表属性,使其能序列化,最简单的方法是使用派生类,代码如下:

public class Children : List<string>{}
public class WpfObject : Label
{
    public WpfObject()
    {
        Children = new Children { "hello", "wpf" };
    }
    public Children Children { get; set; }
}

使用前述同样的序列化代码即可。

2. 普通对象中泛型List的序列化

自.Net4.0后,微软在System.Xaml.XamlServices命名空间重新设计了Xaml序列化,使其更好的支持一般的对象,不过比较讽刺的是,这个命名空间的序列化却不能很好的支持WPF控件,所以依然只能用本文第1部分的方法去hack。

考虑以下类型:

public class CommonObject
{
    public List<string> Children { get; set; }

    public CommonObject()
    {
        Children = new List<string> { "hello", "common" };
    }
}

它的序列化很简单直接,代码如下:

CommonObject p1 = new CommonObject();
string xaml = System.Xaml.XamlServices.Save(p1);
File.WriteAllText("parent.xaml", xaml);
CommonObject p2 = (CommonObject)System.Xaml.XamlServices.Load(File.OpenRead("parent.xaml"));