MySQL创始人发邮件寻求中国帮助zz
感谢xuandun的投递
今早收到了MySQL的邮件,全文如下:
亲爱的拯救MySQL的中国签名支持者,
欧盟可能无法拯救MySQL, 中国和俄罗斯可能是拯救MySQL的希望之所在。中国拥有强大、独立以及自信的反垄断主管机关,因此,我本人在此请求您的帮助。对于您在 http://www.helpmysql.org/ru/petition 的签名,我们深表感谢。如果可以的话,我们需要您的进一步帮助:
(1)商务部反垄断局 http://fldj.mofcom.gov.cn/index.shtml 是并购反垄断审查的主管机关,包括本次对甲骨文收购太阳微电子的反垄断审查。如果您正在使用MySQL,您的意见将对于商务部反垄断局的审查非常重要。我们不能详细的指示您该如何如何对主管机关反映情况,因为这是不妥当的。但是我们认为,如果您能告诉主管机关您的公司如何使用MySQL (什么项目,什么规模、数据流量以及使用者数量等)以及您认为甲骨文收购MySQL之后会产生什么样的影响,将会非常有用。如果您知道MySQL是昂贵的甲骨文数据库的免费替代品,举例向商务部反垄断局说明将会很有帮助。特别是,您知道或使用MySQL作为筹码,或声称将使用MySQL,以此要求甲骨文数据库降低价格的情况,请一定向商务部说明。我们希望您能直接写信给商务部反垄断局,传真010-65198998。鉴于时间紧迫,我们鼓励您直接打电话给商务部反垄断局,电话是010-65198680。
商务部反垄断局会保护MySQL以及您作为使用者,客户和消费者的利益。在与商务部的沟通过程中,请您简单明了地说明您具体需要什么样的帮助。
(2)感谢许许多多像您一样支持我们的人,我们在中国已经收集到了650 个签名,请见:http://helpmysql.org/cn/stats 。 这是一个很好的开始。但是像中国这样一个支持开源的大国,应该会有更多人的签名。问题可能在于很多人可能认为这是欧盟委员会审查决定的事项,中国可能无法改变什么。事实上,中国商务部反垄断局可以做出自己的决定。
在中国,知道此事的人可能还不多,新闻报道也比较有限,比如http://tech.sina.com.cn/it/2010-01-04/21153736195.shtml 。如果您有兴趣,可以帮我们联系中国有影响力IT网站或杂志,告诉他们这次签名活动。
如果有更多的网站参与进来,就会有更多的人签署请愿书,虽然这只是第一步。切记确保文章中或网站中提到helpmysql.org,或者提供一个链接http://helpmysql.org/cn/theissue/customerspaythebill
对于您所做出的任何帮助,我在此预致感谢!
Michael Widenius
Creator of MySQL
一篇文章
文章为转载,有关机构如有意见,请联系 webmaster@baidu.com进行屏蔽。
Like many other well-known organizations, we face cyber attacks of varying degrees on a regular basis. In mid-December, we detected a highly sophisticated and targeted attack on our corporate infrastructure originating from China that resulted in the theft of intellectual property from Google. However, it soon became clear that what at first appeared to be solely a security incident--albeit a significant one--was something quite different. First, this attack was not just on Google. As part of our investigation we have discovered that at least twenty other large companies from a wide range of businesses--including the Internet, finance, technology, media and chemical sectors--have been similarly targeted. We are currently in the process of notifying those companies, and we are also working with the relevant U.S. authorities. Second, we have evidence to suggest that a primary goal of the attackers was accessing the Gmail accounts of Chinese human rights activists. Based on our investigation to date we believe their attack did not achieve that objective. Only two Gmail accounts appear to have been accessed, and that activity was limited to account information (such as the date the account was created) and subject line, rather than the content of emails themselves. Third, as part of this investigation but independent of the attack on Google, we have discovered that the accounts of dozens of U.S.-, China- and Europe- based Gmail users who are advocates of human rights in China appear to have been routinely accessed by third parties. These accounts have not been accessed through any security breach at Google, but most likely via phishing scams or malware placed on the users' computers. We have already used information gained from this attack to make infrastructure and architectural improvements that enhance security for Google and for our users. In terms of individual users, we would advise people to deploy reputable anti-virus and anti-spyware programs on their computers, to install patches for their operating systems and to update their web browsers. Always be cautious when clicking on links appearing in instant messages and emails, or when asked to share personal information like passwords online. You can read more here about our cyber-security recommendations. People wanting to learn more about these kinds of attacks can read this U.S. government report (PDF), Nart Villeneuve's blog and this presentation on the GhostNet spying incident. We have taken the unusual step of sharing information about these attacks with a broad audience not just because of the security and human rights implications of what we have unearthed, but also because this information goes to the heart of a much bigger global debate about freedom of speech. In the last two decades, China's economic reform programs and its citizens' entrepreneurial flair have lifted hundreds of millions of Chinese people out of poverty. Indeed, this great nation is at the heart of much economic progress and development in the world today. We launched Google.cn in January 2006 in the belief that the benefits of increased access to information for people in China and a more open Internet outweighed our discomfort in agreeing to censor some results. At the time we made clear that "we will carefully monitor conditions in China, including new laws and other restrictions on our services. If we determine that we are unable to achieve the objectives outlined we will not hesitate to reconsider our approach to China." These attacks and the surveillance they have uncovered--combined with the attempts over the past year to further limit free speech on the web--have led us to conclude that we should review the feasibility of our business operations in China. We have decided we are no longer willing to continue censoring our results on Google.cn, and so over the next few weeks we will be discussing with the Chinese government the basis on which we could operate an unfiltered search engine within the law, if at all. We recognize that this may well mean having to shut down Google.cn, and potentially our offices in China . The decision to review our business operations in China has been incredibly hard, and we know that it will have potentially far-reaching consequences. We want to make clear that this move was driven by our executives in the United States, without the knowledge or involvement of our employees in China who have worked incredibly hard to make Google.cn the success it is today. We are committed to working responsibly to resolve the very difficult issues raised. Posted by David Drummond, SVP, Corporate Development and Chief Legal Officer .
在office
又当爹又当妈的产品经理zz
转自艾瑞网,作者:艾瑞网专家-苗得雨。 文章写的很好,有很多很实在的例子。
一个成功的产品就像一个人的成长过程一样,会经历孕育、婴儿、少年、青年、成年、老年等几个不同的阶段,而产品经理就像无数操心的父母一样,在不同阶段要有不同的心态和处理方式,以帮助产品茁壮成长。
文/Eric Sink 译/顾全
在我贴出的一篇博客中,有这么一段:
最后说点完全不相干的事,别错过了6月3号微软技术大会上的即兴演奏会。我们几个SourceGear来的小跟班儿打算上台表演一曲Pinball Wizard。我弹原声吉他,我们的开发经理Jeremy Sheeley 弹贝司,而我们的产品经理Paul Roub弹EvilMastermind Schecter PT。
话说回头,那篇博客的第一个读者评论写道:
3个经理。哇。你们公司肯定还在增长,要么就比较大。
发表评论的仁兄很可能是用“经理”一词来指代“管人的人”。如果是这样,那是没错,我们公司的经理不止3 个,但是演奏Pinball Wizard 的3个并不都符合这一名号:
- Jeremy Sheeley的确是个经理。他管理着Vault 和Fortress 开发部门。
- 严格说来,我觉得我是经理。但是认识我的人会说,把我当成经理实在太抬举我了。
- 但是Paul Roub是“产品经理”。在SourceGear(还有我所知道的大多数其他公司)这里,产品经理并不[必然]管理他人。
因此,当我看到那个评论时,我告诉自己应该写篇有关产品经理角色的文章,也就是本文。
产品经理是什么?
简而言之,产品经理是市场营销人员,他们关注于战略和产品特征之类的东西。
人们一想到市场营销,念头就跑到标识、图形设计和广告等事情上去了。这些是市场营销中的沟通传播一面而已,也就是所谓的“营销传播”(marcomm)。
市场营销的其他方面是那些更关注产品本身的东西:
- 市场定位
- 产品差异
- 功能特性
- 竞争状况
- 市场研究
这些活动都是产品经理的领域。
我仍然记得自己当初学到这些区别的时刻。那时候我在Spyglass工作,一位同事问我:“我们为什么没有产品营销的人员?”
我说:“你是什么意思?我们有营销人员啊。Marc 和他那组人刚花了六个月来确定我们的徽标上该用哪种标准色卡红。这就是市场营销,对吗?”
我一窍不通的说法之后引起的探讨,让人很有启发。
管产品还是管人
“经理”一词令人迷惑。像刚才提到的,产品经理不一定管人。 为了要凸显产品管理和人员管理之间的区别,我打算先简明扼要地讲解一下软件公司里管理人员的问题。
对软件公司人员管理的简要讲解
别把他们当孩子。
这就完了?
对滴,就是这样。别把他们当孩子。如果你遵循这一规则及其引申,你就会成为能干的经理,并让你在软件业界的经理中百里挑一。软件从业者都是成年人了,他们不该被当成孩子一般对待。
而另一方面……
软件产品跟你的同事不一样,它们应该特别被像孩子一般地对待。它们叛逆任性,需要有严格的界限和大量的引导。 像孩子一样,产品也需要经历各个阶段。Joel Spolsky说:“做优秀软件,十年磨一剑”。这些十年并不都相同。
软件产品的成长历程有六个不同阶段,而期间的进展过渡,非常类似养育子女的过程。
- 每个阶段都需要不同方式。
- 有一个逐步从“严控”到“放手”的过程。
第一阶段:准备
在养育子女时,第一阶段是受孕怀胎。而在软件业里,这一阶段涵盖了第一次产品发布前的所有时间,其中心思想是“准备”。这一阶段中,你找到一个产品创意,梦想它长成以后的样子。
产品经理在第一阶段容易犯跟新爸爸一样的错误:他认为既然妈妈(开发团队)正怀着孩子(撰写代码),他就什么都不用干,而所有要做的,就是等着孩子大到能去打酱油了,是这样吗?
准备
作为产品经理,第一阶段可能是
你最重要的一步。如果想要产品成功,你有许多准备工作要做。
- 你需要找准产品定位。
- 你需要明确定义产品差异。
- 你也需要弄清楚这两点如何体现在产品的其他方方面面。
这富于挑战,而你必须现在就做,以后就太晚了。
失败案例
有谁还记得苹果Pinpin吗?
当我在大会上讲演时,经常被介绍说:“他在Spyglass领导的团队,开发了后来许可给微软成为IE的浏览器”。这是真的,但是却不是真相的全部。
有大概120 家不同公司获得Spyglass 的授权,发布了全部或部分基于我们浏览器代码的产品。除了一个产品,其他全部玉石俱焚。所以也可以同样准确地(尽管是很不客气地)介绍我是“本星球上与失败浏览器产品的关联最多的人”。
其中一个产品是苹果Pippin(虽然我迫不及待地要说,我的代码不是Pinpin失败的原因)。
Pinpin是产品营销的灾难式范例。它败就败在有人在第一阶段的活儿极其糟糕。该产品的定位从来就不清晰。
- 它是个游戏机吗?
- 它是个计算机吗?
- 它是个机顶盒吗?
对上述问题的回答都是肯定的。
Pinpin 努力要适合每个分类,结果却成了四不像。可以预见,Pinpin 的主要差异化特点就是在每个产品分类都表现差劲。对,它是个游戏机,但是贵得离谱,而且与市面上100%的流行游戏都不兼容。对,它也是个计算机,但是运行缓慢,马力不足。
第二阶段:照顾
在养育子女时,第二阶段是出生和婴儿期。而在软件业里,这一阶段涵盖了1.0版发布和之后的时间,其中心思想是“照顾”。这一阶段中,你耐过产品出世的最后痛苦。
产品经理在新产品初次发布中扮演着非常重要的角色。生育的痛苦由开发团队承受,但产品经理要对启动负责。信息发布准确是十分重要的。1.0版的发布、正如新婴儿的降生:非常非常多的痛苦,接着是稍纵即逝的纯粹幸福感,然后再有好一阵子无休无眠。
大多数B2B软件产品的1.0版本发布,更像是个开始,而不是结束。
照顾
婴儿出生后,照顾的责任压倒了父母。新生命是个完全的依赖者,自己什么都做不了。要是他想凌晨3点吃东西,那也是不得不照做的事。
很多1.0版产品也有相似的需要。用户需要技术支持,有时候非常紧急,时间也非常不凑巧,也是不得不照做的事。
像母乳喂养的妈妈的丈夫那样,产品经理可能不用对所有这些需提供的照顾承担基本责任,但他可以参与其中,这会让他和产品都从这一选择中获益。 在第二阶段,产品经理和新爸爸们通常也分享另一个相通的任务:反省。我所认识的每个爸爸都曾经怀抱着他的婴儿,思忖自己是否真的准备好了承担这份责任。
对于准备程度,产品经理在第二阶段需要自问:
- 产品定位准确吗?
- 产品差异化足够吗?
- 信息发布清晰吗?
第二阶段不是开始去做第一阶段本该完成工作的时候,却是复查的时机。做出改变,这时还不晚。
失败案例
大约十年前,我们公司上市了名叫SourceSurf 的1.0 版产品。它是一个基于网络的应用程序,用于浏览源代码库。如果你能穿越时空回到过去, 问问SourceSurf 它长大以后想成为什么,它会洞彻未来地说:“我想成为像Atlassian FishEye 那样的软件”。但是SourceSurf 没机会长大成人了,1.0版是它第一个也是最后一个主要发布。我们本该做的,是微调我们的策略并继续进行下去,然而当时我们看了看初步结果,决定就此放弃。SourceSurf 1.0做得不好,但是产品概念还是不错的。我们只是没能作出该产品成功所需的细微方向调整。
第三阶段:倾听
在养育子女时,第三阶段是所谓的“可怕的两岁”(有父母都知道,这一时期实际持续到孩子几乎四岁的时候)。而在软件业里,这一阶段通常涵盖2.0版发布周期。其中心思想是“倾听”。
这是反抗叛逆的时期,产品开始展示自己的意志。
我的大女儿在这一阶段时,有天我们叫她去吃晚饭。她悠哉游哉地爬上桌,瞟了眼我们准备的食物,吃惊地倒抽一口气说:“除了黄油,这儿没我爱吃的!”
这几年里显然孩子们需要被管教,但他们也需要被倾听。这是“童言无忌”的阶段,有些话很可爱,而有些则令人烦恼尴尬。不论如何,这一过程是成长的重要阶段。父母需要提供管教,但又不能挫伤小孩的情绪。这经常代表要去倾听孩子所说的各种奇谈怪论。
倾听
产品经理也需要在第三阶段花时间倾听。客户要求很多东西,需要听到这些反馈并将其整合进产品的下一次发布。在产品进入主流之前,仍有时间微调策略。
失败案例
第三阶段是产品失败的最普遍时期。有非常多的例子。几乎任何没跨过鸿沟而死在坑底的产品都是失败于第三阶段。我最爱用的两个例子是BeOS和Wingz。
BeOS是90 年代后期发布的新操作系统。技术上说,BeOS很酷,但是它掉进了坑里,因为在鸿沟另一头没有找到商机。
Wingz是80年代后期发布的电子表格软件。Wingz 具备Excel 直到今天尚没有的功能。但是要生存,它需要在一小群用户中流行并从此传播开来。我非常喜欢Wingz,但我认为大部分人都觉得它太古怪。
我经常在想,如果这些产品更愿意倾听最早期用户的反馈,并作出方向调整,那么他们或许会成功。这可能意味着,让这些产品变成他们的父母不曾梦想过的东西。
离题: 望鸿沟对面
自从我受雇于一家版本控制软件厂商, 现在对我来说最有意思的鸿沟情形是分步式版本控制系统。这一分类下的显著例子包括诸如Git、Mercurial和Bazaar等开源工具。今天,这些产品尚未成为主流。它们在某些社区内名声很响,但是从事软件开发的大批公司仍在使用集中式工具。
DVCS工具是否能跨过鸿沟呢?
第四阶段:对话
在养育子女时,第四阶段是从小学到青春期的时间。而在软件业里,这一阶段通常涵盖3.0版本,也就是产品可以被当作主流的首个发布。其中心思想是“对话”。
在这一阶段,父母经常对他们的孩子能做到的事情表现出惊诧:“小Bobby 真棒!七年前我们生了这个孩子,现在我能和他真正交流了!”第四阶段来到了,父母突然发现他们的婴儿俨然成了个小大人。
相似的,软件产品在第四阶段已经达到了大部分人都能使用的程度。它们是主流了。先前的发布只在早期试用者和有耐性的人中间流行,但3.0发布已经足够精致到成为大半个目标市场的有效解决方案。
第四阶段时,产品和孩子对竞争的关注,发展到了不健康的程度。当孩子进了学校,他们开始了解,可以将快乐建立在他人痛苦之上。他们需要花费很多年才能摆脱这一影响,学到精神健康和个人安宁是来自于后天教化的选择:不必过虑于他人,而是照管好自己。
类似的,第四阶段的产品可能不该那么过分关注竞争,如果此时还没有获得很好的差异化,也就不再可能得到了。照管好你自己的客户吧。
对话
对父母和产品经理而言,第四阶段最重要的是对话。
这是孩子需要信息的阶段,也是你要说任何事情他们都还愿意听从的最后阶段:父母需要与孩子讨论未来的风险。告诉他们诸如抽烟、性和吸毒以及成为芝加哥小熊队的粉丝等糟糕决定会带来的烦恼和后果。
类似的,第四阶段中产品经理的主要工作是提供信息。你的产品已经是主流了。人们想要它。但是为了让他们意识到他们的需要,你需要为潜在客户提供大量信息。你需要白皮书。你需要演示视频。你需要产品附加文档。诸如此类。
失败案例
作为第四阶段进展不佳的例子,我会引用我自己公司的旗舰产品,SourceGear Vault。Vault很受欢迎,也是我们公司的成功产品。但是要说到提供一个主流产品所需的各种信息,我们就搞砸了。就在Vault 3.0发布前后,这一产品开始通过“口口相传”获得大量关注。人们会到我们的网站获取产品信息,但是我们能提供的太贫乏了。
值得称道的是,我们意识到了失误,采取措施补救。我们招聘了一个产品经理专门处理此事。但我们仍然起步晚了,所以就算到了现在,Vault仍在追赶进度。
第五阶段:平衡
在养育子女时,第五阶段是青少年期,从青春期到高中的时间。而在软件业里,这一阶段通常涵盖3.0版之后的发布。其中心思想是“平衡”。在这一阶段,孩子不再想让你们叫他孩子了。这是通向成年的转变时期,充满了反叛。没有什么阶段比第五阶段更难熬了。每个父母都希望孩子最终独立,但很少能意识到这一历程将如何痛苦。青少年期与可怕的两岁期非常相似。
当孩子不能为所欲为时,他的愤怒可能十分暴烈。但是,他不是满地打滚、又踢又叫,而是大喊“我讨厌你!”,再摔上卧室的门。
平衡
但正像可怕的两岁期那样,这一阶段也是成长的关键时期。父母必须要达到两全其美的平衡。这时开始要少一点操纵,让少年对自己的生活多一些控制。
第五阶段里,孩子和产品把大量时间花在讨要他们所不需要的东西上:
- 可是爸爸,地球上哪个十几岁的孩子没有无限手机短信套餐呀!
- 可是妈妈,我怎么能再穿同一条裙子啊!我得买条新的!
- 可是爸爸,所有其他字处理软件都有语法检查器了!
作为第五阶段中的产品经理,你需要给产品一些自由。是时候为客户提供一些你多年来抵制的功能了。即使你觉得那功能不是个好主意,只要它不会毁掉产品,你就应当严肃考虑去做到这一点。
但是你仍旧需要划出些界限:
- 父母一定要开始让孩子成为他们想变成的样子,但是别让他们把自己的生活给毁了。设定足够界限,以保证他们安全完成成年的过程,避免一失足成千古恨。
- 相同的,软件产品在第五阶段发运一个糟糕的版本,也一样可以毁掉自己。产品经理需要成为质量捍卫者。版本3.0如何棒是毫无意义的,如果4.0缺陷多而不可靠,产品的名声可能就永远没法完全恢复了。
失败案例
低质产品毁掉自己的最佳例子就是微软的Visual SourceSafe。时至今日,几乎所有关于版本管理软件的笑话里,SourceSafe 还是点睛之笔。它被广泛鄙视,大家通常都认为它不可靠。微软买下SourceSafe 之前,它还是个受到景仰的杰出产品。这一产品没有成为最广泛使用的专利版本控制软件,实在是没有天理。SourceSafe重新定义了软件行业,比任何后来者提供的易用性都要多。但是在微软的养育之下,SourceSafe 毁掉了自己。5.0 和6.0 都是灾难性的。我敢打赌SourceSafe 是史上最受用户鄙视的赚钱软件。我们公司从全世界对SourceSafe 的不满中赚得盆满钵满。讽刺的是,最新版SourceSafe可能不该遭受这么多贬损。我还没用过SourceSafe 2005,但我了解它其实没那么差。他们修复了大量的问题。但是,这一产品已经成了大家都乐意去讨厌的东西,这就为时已晚了。世界已经不可能再信任SourceSafe。
第六阶段:放手
在养育子女时,第六阶段是成年期。而在软件业里,这一阶段涵盖产品成熟的时段。其中心思想是“放手”。这时你作为父母的工作基本结束了。从此往后,孩子的任何错误都是他们自己的问题,你不得不放手了。
同样的,产品步入成熟期后,产品经理也没有太多可做的了。
对父母和产品经理而言,这都是庆祝的时刻,一个长久而时时遇到困难的历程成功结束了。
放手
父母和产品经理经常会觉得很难放手,但是这么做很重要。你是个产品经理,你的工作是帮助定义和塑造产品的特征。当孩子“长大成人”,你就不要再帮他寻找他要成为什么样子,他已经成形了。
让营销传播、销售和支持部门就此接手一切吧。
经典失败案例
产品经理不愿放手的两个最明显例子是微软Windows 和微软Office。
这些产品都完成了,完成都好多年了。不幸的是,微软在很大程度上没能找到下一个产品。所以,由于微软没什么好做的,他们不断地向我们兜售我们不需要的新版本,杜撰各种理由强迫我们购买。
自然有些人会埋怨我所说的,史上营收最高的两大产品怎么成了失败案例。我没有这么说。我要说的是,这两个产品在第一到第五阶段都惊人地成功,但这无法改变事实,他们第六阶段的实施实在糟糕。
结语
产品经理与父母都各自承受着大量各不相同的观点的压力。你那里的书店对每一主题各自矛盾的书籍也是汗牛充栋。
本文包含了我对于养育子女和产品营销的大量观点。有些读者可能同意我,而另一些认为我错了。
问题在于,对于养育子女和产品营销,人人都知道怎么做,却没人真正知道怎么做。你四处阅读,然后尽力做好。而在养育子女时,做到最好应该就够了。
这是产品管理与养育子女完全不同的一点:绝大多数父母都是成功的。
很少有完全失败的父母。我们焦虑失眠,可最后事情大都会解决。如果你爱你的孩子,并做出最佳的努力,他们很可能成长得挺好。
相反的是,大多数产品都失败了。市场营销是个光靠努力和“全力以赴”并不一定足够的领域。
Pinpin 的失败不是因为没有产品经理——它失败于产品经理是个傻瓜。
微软没在Windows Vista 上对我们快马加鞭地驱赶,因为他们不在乎找到新产品。微软企图找到下个产品,他们非常地努力。他们搭上了最聪明的人迎接这个挑战。他们花费成百上
千万的美元来寻找,但是从未找到。
而Google找到了。
[mark]使用Webphere Business Integration V6.0产品进行多维度分析的一个解决方案
使用Webphere Business Integration V6.0产品进行多维度分析的一个解决方案
在ITPUB看到一篇不错的文章,描述简历一个OLAP应用的过程,mark下来慢慢看。
http://www.itpub.net/viewthread.php?tid=728306&extra=&page=1
zt美职业顾问公布15个谷歌面试题
http://www.sina.com.cn 2009年11月05日 18:07 新浪科技
新浪科技讯 北京时间11月5日下午消息,据国外媒体昨日报道,美国西雅图市求职顾问刘易斯·林(Lewis Lin)收集了谷歌向应聘者提出过的140个问题,其中15个问题让许多应聘者自叹弗如。
对那些身处经济衰退大潮中的初级经理和软件开发者而言,谷歌是一个避风港。但其招聘门槛较高,首先,谷歌更青睐长春藤联盟(由美国八所知名大学所组成)的毕业生;其次,即使应聘者已年过30,谷歌也很在意其GPA(平均成绩点数)分数;第三,谷歌需要的是那些想改变世界的人。
而且,即使应聘者满足了上述要求,也有可能在面试中被谷歌提出的问题所难倒。以下是15个让许多应聘者感到自己很愚笨的谷歌面试题。
问题:一辆校车能装下多少个高尔夫球?
应聘职位:产品经理
问题:如果让你清洗西雅图市所有的窗户,你会对此索价多少?
应聘职位:产品经理
问题:在一个重男轻女的国家里,每家每户都想生男孩。若一户人家生了一个女孩,便会再生一个,直到生下的是男孩为止。请问这个国家的男女比例是多少?
应聘职位:产品经理
问题:全世界共有多少位钢琴调音师?
应聘职位:产品经理
问题:下水道井盖为什么是圆的?
应聘职位:软件工程师
问题:为旧金山市设计一个紧急疏散方案。
应聘职位:产品经理
问题:时钟的指针一天内总共会重合多少次?
应聘职位:产品经理
问题:阐释“死牛肉”的意义所在。
应聘职位:软件工程师
问题:一个人开车来到旅馆,变得一无所有。究竟发生了什么事情?
应聘职位:软件工程师
问题:你想知道好友鲍勃是否有你正确的电话号码,但又不能直接问他。你必须在卡片上留言,让伊芙将卡片较交给鲍勃。除了问题以外,你还应该在卡片上写什么,才能既确保鲍勃能看懂留言,又使伊芙看不出卡片上写有你的电话号码。
应聘职位:软件工程师
问题:你是一艘海盗船的船长,你的船员要投票决定如何平分金条。如果与你意见一致的船员数量少于一半,你将被杀死。你应该如何提议分配金条,才能既分得较多赃物,又能活下来?
应聘职位:工程经理
问题:你有8个大小一样的球,其中7个重量相同,只有一个略重一些。给你一个天平,而且只准称两次,如何找出重量不同的那个球?
应聘职位:产品经理
问题:你在一幢100层高的大楼中,给了你两个鸡蛋。鸡蛋有时非常易碎,有时又异常坚韧。这意味着,如果在第1层扔下鸡蛋,鸡蛋或许会碎裂,而如果是从第100层扔下鸡蛋,鸡蛋或许安然无恙。这两只鸡蛋一模一样。你需要计算出,最高从哪层楼扔下时,鸡蛋不会碎。问题是,你需要扔多少次鸡蛋才能算出该楼层。整个过程中,你只允许打碎两个鸡蛋。
应聘职位:产品经理
问题:向你8岁的侄子或外甥解释什么是数据库,只能用三个句子。
应聘职位:产品经理
问题:你缩小到只有一枚五分硬币那么高,你的质量也成比例缩小以保持原有密度不变。随后你被扔到一个空的玻璃搅拌器里,搅拌刀片将在60秒后开始运转,你该怎么办?
应聘职位:产品经理(晓彬)
还有2天NBA又要开赛了
去年有惊无险地拿到了总冠军。

马上又要开赛了,期待新赛季的湖人。
暑期把喇嘛留住了,莎莎找回手感了,布朗信心高涨了,拜纳姆回来了。
更大的变化是,阿里扎很可惜的离开了,来了阿泰。我其实也挺喜欢阿泰,不过从看的几场比赛来看,阿泰在湖人的进攻体系里面总是隐形的,不过这也不能强求,毕竟他带来了更硬的防守和精神,没了阿里扎的鬼影神偷,但有可以把詹姆斯推出场外的攻击性防守。期盼湖人队化学效应来得更猛烈一些。

新赛季,不轻视任何对手,不畏惧任何对手。
建立霸业!

某前辈对敏捷的一些讨论
这是TL上Tinyfool博客中发出来的对敏捷的一些讨论,读起来没有长篇大论,但可以从很多软件过程中细微处来看敏捷以及软件开发过程,特mark下来,以供回味。
——————————————tinyfool 分割线—————————————–
文章链接:
http://www.tinydust.net/prog/diary/2009/08/blog-post_21.html
数据库设计经验谈(zz from 南大小百合 夜来香)
数据库设计经验谈(夜来香)
一个成功的管理系统,是由:[50%的业务 + 50%的软件]所组成,
而 50%的成功软件又有[25%的数据库 + 25%的程序]所组成,数据库
设计的好坏是一个关键。如果把企业的数据比做生命所必需的血液,
那么数据库的设计就是应用中最重要的一部分。有关数据库设计的材
料汗牛充栋,大学学位课程里也有专门的讲述。不过,就如我们反复
强调的那样,再好的老师也比不过经验的教诲。所以我归纳历年来所
走的弯路及体会,并在网上找了些对数据库设计颇有造诣的专业人士
给大家传授一些设计数据库的技巧和经验。精选了其中的 60 个最佳
技巧,并把这些技巧编写成了本文,为了方便索引其内容划分为 5
个部分:
第 1 部分 – 设计数据库之前
这一部分罗列了 12 个基本技巧,包括命名规范和明确业务需求
等。
第 2 部分 – 设计数据库表
总共 24 个指南性技巧,涵盖表内字段设计以及应该避免的常见
问题等。
第 3 部分 – 选择键
怎么选择键呢?这里有 10 个技巧专门涉及系统生成的主键的正
确用法,还有何时以及如何索引字段以获得最佳性能等。
第 4 部分 – 保证数据完整性
讨论如何保持数据库的清晰和健壮,如何把有害数据降低到最小
程度。
第 5 部分 – 各种小技巧
不包括在以上 4 个部分中的其他技巧,五花八门,有了它们希
望你的数据库开发工作会更轻松一些。
§ 第 1 部分 – 设计数据库之前
──────────────
■ 考察现有环境
在设计一个新数据库时,你不但应该仔细研究业务需求而且还要
考察现有的系统。大多数数据库项目都不是从头开始建立的;通常,
机构内总会存在用来满足特定需求的现有系统(可能没有实现自动计
算)。显然,现有系统并不完美,否则你就不必再建立新系统了。
但是对旧系统的研究可以让你发现一些可能会忽略的细微问题。
一般来说,考察现有系统对你绝对有好处。
■ 定义标准的对象命名规范
一定要定义数据库对象的命名规范。对数据库表来说,从项目一
开始就要确定表名是采用复数还是单数形式。此外还要给表的别名定
义简单规则(比方说,如果表名是一个单词,别名就取单词的前 4
个字母;如果表名是两个单词,就各取两个单词的前两个字母组成
4 个字母长的别名;如果表的名字由 3 个单词组成,你不妨从头两
个单词中各取一个然后从最后一个单词中再取出两个字母,结果还是
组成 4 字母长的别名,其余依次类推)对工作用表来说,表名可以
加上前缀 WORK_ 后面附上采用该表的应用程序的名字。表内的列[
字段]要针对键采用一整套设计规则。比如,如果键是数字类型,你
可以用 _N 作为后缀;
如果是字符类型则可以采用 _C 后缀。对列[字段]名应该采用标
准的前缀和后缀。再如,假如你的表里有好多“money”字段,你不
妨给每个列[字段]增加一个 _M 后缀。还有,日期列[字段]最好以
D_ 作为名字打头。
检查表名、报表名和查询名之间的命名规范。你可能会很快就被
这些不同的数据库要素的名称搞糊涂了。假如你坚持统一地命名这些
数据库的不同组成部分,至少你应该在这些对象名字的开头用
Table、Query 或者 Report 等前缀加以区别。
如果采用了 Microsoft Access,你可以用 qry、rpt、tbl 和
mod 等符号来标识对象(比如 tbl_Employees)。我在和 SQL
Server 打交道的时候还用过 tbl 来索引表,但我用 sp_company
(现在用 sp_feft_)标识存储过程,因为在有的时候如果我发现了
更好的处理办法往往会保存好几个拷贝。我在实现 SQL Server
2000 时用 udf_ (或者类似的标记)标识我编写的函数。
工欲善其事, 必先利其器采用理想的数据库设计工具,比如:
SyBase 公司的 PowerDesign,她支持 PB、VB、Delp he 等语言,通
过 ODBC 可以连接市面上流行的 30 多个数据库,包括 dBase、
FoxPro、V FP、SQL Server 等,今后有机会我将着重介绍
PowerDesign 的使用。
■ 获取数据模式资源手册
正在寻求示例模式的人可以阅读《数据模式资源手册》一书,该
书由 Len Silverston、W . H. Inmon 和 Kent Graziano 编写,是
一本值得拥有的最佳数据建模图书。该书包括的章节涵盖多种数据领
域,比如人员、机构和工作效能等。其他的你还可以参考:[1]萨师
煊王珊著数据库系统概论(第二版)高等教育出版社 1991、[2][美]
Steven M.Bobrowsk i 著 Oracle 7 与客户/服务器计算技术从入门
到精通刘建元等译电子工业出版社, 1996、[3]周中元信息系统建模
方法(下) 电子与信息化 1999年第3期,1999 畅想未来,但不可忘
了过去的教训我发现询问用户如何看待未来需求变化非常有用。这样
做可以达到两个目的:首先,你可以清楚地了解应用设计在哪个地方
应该更具灵活性以及如何避免性能瓶颈;其次,你知道发生事先没有
确定的需求变更时用户将和你一样感到吃惊。
一定要记住过去的经验教训!我们开发人员还应该通过分享自己
的体会和经验互相帮助。
即使用户认为他们再也不需要什么支持了,我们也应该对他们进
行这方面的教育,我们都曾经面临过这样的时刻“当初要是这么做了
该多好..”。
■ 在物理实践之前进行逻辑设计
在深入物理设计之前要先进行逻辑设计。随着大量的 CASE 工具
不断涌现出来,你的设计也可以达到相当高的逻辑水准,你通常可以
从整体上更好地了解数据库设计所需要的方方面面。
■ 了解你的业务
在你百分百地确定系统从客户角度满足其需求之前不要在你的
ER(实体关系)模式中加入哪怕一个数据表(怎么,你还没有模式?
那请你参看技巧 9)。了解你的企业业务可以在以后的开发阶段节约
大量的时间。一旦你明确了业务需求,你就可以自己做出许多决策了。
一旦你认为你已经明确了业务内容,你最好同客户进行一次系统
的交流。采用客户的术语并且向他们解释你所想到的和你所听到的。
同时还应该用可能、将会和必须等词汇表达出系统的关系基数。这样
你就可以让你的客户纠正你自己的理解然后做好下一步的 ER 设计。
■ 创建数据字典和 ER 图表
一定要花点时间创建 ER 图表和数据字典。其中至少应该包含每
个字段的数据类型和在每个表内的主外键。创建 ER 图表和数据字典
确实有点费时但对其他开发人员要了解整个设计却是完全必要的。越
早创建越能有助于避免今后面临的可能混乱,从而可以让任何了解数
据库的人都明确如何从数据库中获得数据。
有一份诸如 ER 图表等最新文档其重要性如何强调都不过分,这
对表明表之间关系很有用,而数据字典则说明了每个字段的用途以及
任何可能存在的别名。对 SQL 表达式的文档化来说这是完全必要的。
■ 创建模式
一张图表胜过千言万语:开发人员不仅要阅读和实现它,而且还
要用它来帮助自己和用户对话。模式有助于提高协作效能,这样在先
期的数据库设计中几乎不可能出现大的问题。
模式不必弄的很复杂;甚至可以简单到手写在一张纸上就可以了。
只是要保证其上的逻辑关系今后能产生效益。
■ 从输入输出下手
在定义数据库表和字段需求(输入)时,首先应检查现有的或者
已经设计出的报表、查询和视图(输出)以决定为了支持这些输出哪
些是必要的表和字段。举个简单的例子:假如客户需要一个报表按照
邮政编码排序、分段和求和,你要保证其中包括了单独的邮政编码字
段而不要把邮政编码糅进地址字段里。
■ 报表技巧
要了解用户通常是如何报告数据的:批处理还是在线提交报表?
时间间隔是每天、每周、每月、每个季度还是每年?如果需要的话还
可以考虑创建总结表。系统生成的主键在报表中很难管理。用户在具
有系统生成主键的表内用副键进行检索往往会返回许多重复数据。
这样的检索性能比较低而且容易引起混乱。
■ 理解客户需求
看起来这应该是显而易见的事,但需求就是来自客户(这里要从
内部和外部客户的角度考虑)。不要依赖用户写下来的需求,真正的
需求在客户的脑袋里。你要让客户解释其需求,而且随着开发的继续,
还要经常询问客户保证其需求仍然在开发的目的之中。一个不变的真
理是:“只有我看见了我才知道我想要的是什么”必然会导致大量的
返工,因为数据库没有达到客户从来没有写下来的需求标准。而更糟
的是你对他们需求的解释只属于你自己,而且可能是完全错误的。
§ 第 2 部分 – 设计表和字段
──────────────
■ 检查各种变化
我在设计数据库的时候会考虑到哪些数据字段将来可能会发生变
更。比方说,姓氏就是如此(注意是西方人的姓氏,比如女性结婚后
从夫姓等)。所以,在建立系统存储客户信息时,我倾向于在单独的
一个数据表里存储姓氏字段,而且还附加起始日和终止日等字段,这
样就可以跟踪这一数据条目的变化。
■ 采用有意义的字段名
有一回我参加开发过一个项目,其中有从其他程序员那里继承的
程序,那个程序员喜欢用屏幕上显示数据指示用语命名字段,这也不
赖,但不幸的是,她还喜欢用一些奇怪的命名法,其命名采用了匈牙
利命名和控制序号的组合形式,比如 cbo1、txt2、txt2_b 等等。
除非你在使用只面向你的缩写字段名的系统,否则请尽可能地把
字段描述的清楚些。当然,也别做过头了,比如
Customer_Shipping_Address_Street_Line_1,虽然很富有说明性,
但没人愿意键入这么长的名字,具体尺度就在你的把握中。
■ 采用前缀命名
如果多个表里有好多同一类型的字段(比如 FirstName),你不
妨用特定表的前缀(比如 CusLastName)来帮助你标识字段。
时效性数据应包括“最近更新日期/时间”字段。时间标记对查
找数据问题的原因、按日期重新处理/重载数据和清除旧数据特别有
用。
■ 标准化和数据驱动
数据的标准化不仅方便了自己而且也方便了其他人。比方说,假
如你的用户界面要访问外部数据源(文件、XML 文档、其他数据库等),
你不妨把相应的连接和路径信息存储在用户界面支持表里。还有,如
果用户界面执行工作流之类的任务(发送邮件、打印信笺、修改记录
状态等),那么产生工作流的数据也可以存放在数据库里。预先安排
总需要付出努力,但如果这些过程采用数据驱动而非硬编码的方式,
那么策略变更和维护都会方便得多。事实上,如果过程是数据驱动的,
你就可以把相当大的责任推给用户,由用户来维护自己的工作流过程。
■ 标准化不能过头
对那些不熟悉标准化一词(normalization)的人而言,标准化
可以保证表内的字段都是最基础的要素,而这一措施有助于消除数据
库中的数据冗余。标准化有好几种形式,但 Thi rd Normal Form
(3NF)通常被认为在性能、扩展性和数据完整性方面达到了最好平
衡。简单来说,3NF 规定:
· 表内的每一个值都只能被表达一次。
· 表内的每一行都应该被唯一的标识(有唯一键)。
· 表内不应该存储依赖于其他键的非键信息。
遵守 3NF 标准的数据库具有以下特点:有一组表专门存放通过
键连接起来的关联数据。比方说,某个存放客户及其有关定单的
3NF 数据库就可能有两个表:Customer 和 Order。
Order 表不包含定单关联客户的任何信息,但表内会存放一个键
值,该键指向 Customer 表里包含该客户信息的那一行。
更高层次的标准化也有,但更标准是否就一定更好呢?答案是不
一定。事实上,对某些项目来说,甚至就连 3NF 都可能给数据库引
入太高的复杂性。
为了效率的缘故,对表不进行标准化有时也是必要的,这样的例
子很多。曾经有个开发餐饮分析软件的活就是用非标准化表把查询时
间从平均 40 秒降低到了两秒左右。虽然我不得不这么做,但我绝不
把数据表的非标准化当作当然的设计理念。而具体的操作不过是一种
派生。所以如果表出了问题重新产生非标准化的表是完全可能的。
Microsoft Visual FoxPro 报表技巧如果你正在使用
Microsoft Visual FoxPro,你可以用对用户友好的字段名来代替编
号的名称:比如用 Customer Name 代替 txtCNaM。这样,当你用向
导程序[Wizards,台湾人称为‘精灵’]创建表单和报表时,其名字
会让那些不是程序员的人更容易阅读。
■ 不活跃或者不采用的指示符
增加一个字段表示所在记录是否在业务中不再活跃挺有用的。不
管是客户、员工还是其他什么人,这样做都能有助于再运行查询的时
候过滤活跃或者不活跃状态。同时还消除了新用户在采用数据时所面
临的一些问题,比如,某些记录可能不再为他们所用,再删除的时候
可以起到一定的防范作用。
使用角色实体定义属于某类别的列[字段]在需要对属于特定类别
或者具有特定角色的事物做定义时,可以用角色实体来创建特定的时
间关联关系,从而可以实现自我文档化。
这里的含义不是让 PERSON 实体带有 Title 字段,而是说,为
什么不用 PERSON 实体和 PERSON_TYPE 实体来描述人员呢?比方说,
当 John Smith, Engineer 提升为 John Smit h, Director 乃至最
后爬到 John Smith, CIO 的高位,而所有你要做的不过是改变两个
表 PERSON 和 PERSON_TYPE 之间关系的键值,同时增加一个日期/时
间字段来知道变化是何时发生的。这样,你的 PERSON_TYPE 表就包
含了所有 PERSON 的可能类型,比如 Associ ate、Engineer、
Director、CIO 或者 CEO 等。
还有个替代办法就是改变 PERSON 记录来反映新头衔的变化,不
过这样一来在时间上无法跟踪个人所处位置的具体时间。
■ 采用常用实体命名机构数据
组织数据的最简单办法就是采用常用名字,比如:PERSON、
ORGANIZATION、ADDRESS 和 P HONE 等等。当你把这些常用的一般名
字组合起来或者创建特定的相应副实体时,你就得到了自己用的特殊
版本。开始的时候采用一般术语的主要原因在于所有的具体用户都能
对抽象事物具体化。
有了这些抽象表示,你就可以在第 2 级标识中采用自己的特殊
名称,比如,PERSON 可能是 Employee、Spouse、Patient、
Client、Customer、Vendor 或者 Teacher 等。同样的,
ORGANIZATION 也可能是 MyCompany、MyDepartment、Competitor、
Hospital、Warehouse、Government 等。最后 ADDRESS 可以具体为
Site、Location、Home、Work、Client、 Vendor、Corporate 和
FieldOffice 等。
采用一般抽象术语来标识“事物”的类别可以让你在关联数据以
满足业务要求方面获得巨大的灵活性,同时这样做还可以显著降低数
据存储所需的冗余量。
■ 用户来自世界各地
在设计用到网络或者具有其他国际特性的数据库时,一定要记住
大多数国家都有不同的字段格式,比如邮政编码等,有些国家,比如
新西兰就没有邮政编码一说。
■ 数据重复需要采用分立的数据表
如果你发现自己在重复输入数据,请创建新表和新的关系。
每个表中都应该添加的 3 个有用的字段 *
dRecordCreationDate,在 VB 下默认是 Now(),而在 SQL Server
下默认为 GETDATE() * sRecordCreator,在 SQL Server 下默认为
NOT NULL DEFAULT USER * nRecordVersion,记录的版本标记;有助
于准确说明记录中出现 null 数据或者丢失数据的原因对地址和电话
采用多个字段描述街道地址就短短一行记录是不够的。
Address_Line1、Address_Line2 和 Address_Li ne3 可以提供更大
的灵活性。还有,电话号码和邮件地址最好拥有自己的数据表,其间
具有自身的类型和标记类别。
过分标准化可要小心,这样做可能会导致性能上出现问题。虽然
地址和电话表分离通常可以达到最佳状态,但是如果需要经常访问这
类信息,或许在其父表中存放“首选”信息(比如 Customer 等)更
为妥当些。非标准化和加速访问之间的妥协是有一定意义的。
■ 使用多个名称字段
我觉得很吃惊,许多人在数据库里就给 name 留一个字段。我觉
得只有刚入门的开发人员才会这么做,但实际上网上这种做法非常普
遍。我建议应该把姓氏和名字当作两个字段来处理,然后在查询的时
候再把他们组合起来。
我最常用的是在同一表中创建一个计算列[字段],通过它可以自
动地连接标准化后的字段,这样数据变动的时候它也跟着变。不过,
这样做在采用建模软件时得很机灵才行。总之,采用连接字段的方式
可以有效的隔离用户应用和开发人员界面。
■ 提防大小写混用的对象名和特殊字符
过去最令我恼火的事情之一就是数据库里有大小写混用的对象名,
比如 CustomerData。这一问题从 Access 到 Oracle 数据库都存在。
我不喜欢采用这种大小写混用的对象命名方法,结果还不得不手工修
改名字。想想看,这种数据库/应用程序能混到采用更强大数据库的
那一天吗?采用全部大写而且包含下划符的名字具有更好的可读性
(CUSTOMER_DATA),绝对不要在对象名的字符之间留空格。
■ 小心保留词
要保证你的字段名没有和保留词、数据库系统或者常用访问方法
冲突,比如,最近我编写的一个 ODBC 连接程序里有个表,其中就用
了 DESC 作为说明字段名。后果可想而知!DESC 是 DESCENDING 缩
写后的保留词。表里的一个 SELECT * 语句倒是能用,但我得到的却
是一大堆毫无用处的信息。
■ 保持字段名和类型的一致性
在命名字段并为其指定数据类型的时候一定要保证一致性。假如
字段在某个表中叫做“ag reement_number”,你就别在另一个表里
把名字改成“ref1”。假如数据类型在一个表里是整数,那在另一个
表里可就别变成字符型了。记住,你干完自己的活了,其他人还要用
你的数据库呢。
■ 仔细选择数字类型
在 SQL 中使用 smallint 和 tinyint 类型要特别小心,比如,
假如你想看看月销售总额,你的总额字段类型是 smallint,那么,
如果总额超过了$32,767 你就不能进行计算操作了。
■ 删除标记
在表中包含一个“删除标记”字段,这样就可以把行标记为删除。
在关系数据库里不要单独删除某一行;最好采用清除数据程序而且要
仔细维护索引整体性。
■ 避免使用触发器
触发器的功能通常可以用其他方式实现。在调试程序时触发器可
能成为干扰。假如你确实需要采用触发器,你最好集中对它文档化。
■ 包含版本机制
建议你在数据库中引入版本控制机制来确定使用中的数据库的版
本。无论如何你都要实现这一要求。时间一长,用户的需求总是会改
变的。最终可能会要求修改数据库结构。虽然你可以通过检查新字段
或者索引来确定数据库结构的版本,但我发现把版本信息直接存放到
数据库中不更为方便吗?。
■ 给文本字段留足余量
ID 类型的文本字段,比如客户 ID 或定单号等等都应该设置得
比一般想象更大,因为时间不长你多半就会因为要添加额外的字符而
难堪不已。比方说,假设你的客户 ID 为 10 位数长。那你应该把数
据库表字段的长度设为 12 或者 13 个字符长。这算浪费空间吗?是
有一点,但也没你想象的那么多:一个字段加长 3 个字符在有 1 百
万条记录,再加上一点索引的情况下才不过让整个数据库多占据
3MB 的空间。但这额外占据的空间却无需将来重构整个数据库就可以
实现数据库规模的增长了。身份证的号码从 15 位变成 18 位就是最
好和最惨痛的例子。
■ 列[字段]命名技巧
我们发现,假如你给每个表的列[字段]名都采用统一的前缀,那
么在编写 SQL 表达式的时候会得到大大的简化。这样做也确实有缺
点,比如破坏了自动表连接工具的作用,后者把公共列[字段]名同某
些数据库联系起来,不过就连这些工具有时不也连接错误嘛。举个简
单的例子,假设有两个表:
Customer 和 Order。Customer 表的前缀是 cu_,所以该表内的
子段名如下:cu_name_id 、cu_surname、cu_initials 和
cu_address 等。Order 表的前缀是 or_,所以子段名是:
or_order_id、or_cust_name_id、or_quantity 和
or_description 等。
这样从数据库中选出全部数据的 SQL 语句可以写成如下所示:
_______________________
Select * From Customer, Order
Where cu_surname = “MYNAME”
and cu_name_id = or_cust_name_id and or_quantity = 1
_______________________
在没有这些前缀的情况下则写成这个样子(用别名来区分):
_______________________
Select * From Customer, Order
Where Customer.surname = “MYNAME”
and Customer.name_id = Order.cust_name_id
and Order.quantity = 1
_______________________
第 1 个 SQL 语句没少键入多少字符。但如果查询涉及到 5 个
表乃至更多的列[字段]你就知道这个技巧多有用了。
§ 第 3 部分 – 选择键和索引
──────────────
■ 数据采掘要预先计划
我所在的某一客户部门一度要处理 8 万多份联系方式,同时填
写每个客户的必要数据(这绝对不是小活)。我从中还要确定出一组
客户作为市场目标。当我从最开始设计表和字段的时候,我试图不在
主索引里增加太多的字段以便加快数据库的运行速度。然后我意识到
特定的组查询和信息采掘既不准确速度也不快。结果只好在主索引中
重建而且合并了数据字段。我发现有一个指示计划相当关键——当我
想创建系统类型查找时为什么要采用号码作为主索引字段呢?我可以
用传真号码进行检索,但是它几乎就象系统类型一样对我来说并不重
要。采用后者作为主字段,数据库更新后重新索引和检索就快多了。
可操作数据仓库(ODS)和数据仓库(DW)这两种环境下的数据
索引是有差别的。在 DW 环境下,你要考虑销售部门是如何组织销售
活动的。他们并不是数据库管理员,但是他们确定表内的键信息。这
里设计人员或者数据库工作人员应该分析数据库结构从而确定出性能
和正确输出之间的最佳条件。
■ 使用系统生成的主键
这类同技巧 1,但我觉得有必要在这里重复提醒大家。假如你总
是在设计数据库的时候采用系统生成的键作为主键,那么你实际控制
了数据库的索引完整性。这样,数据库和非人工机制就有效地控制了
对存储数据中每一行的访问。
采用系统生成键作为主键还有一个优点:当你拥有一致的键结构
时,找到逻辑缺陷很容易。
■ 分解字段用于索引
为了分离命名字段和包含字段以支持用户定义的报表,请考虑分
解其他字段(甚至主键)
为其组成要素以便用户可以对其进行索引。索引将加快 SQL 和
报表生成器脚本的执行速度。比方说,我通常在必须使用 SQL
LIKE 表达式的情况下创建报表,因为 case number 字段无法分解为
year、serial number、case type 和 defendant code 等要素。性
能也会变坏。假如年度和类型字段可以分解为索引字段那么这些报表
运行起来就会快多了。
■ 键设计 4 原则
1. 为关联字段创建外键。
2. 所有的键都必须唯一。
3. 避免使用复合键。
4. 外键总是关联唯一的键字段。
■ 别忘了索引
索引是从数据库中获取数据的最高效方式之一。95%的数据库性
能问题都可以采用索引技术得到解决。作为一条规则,我通常对逻辑
主键使用唯一的成组索引,对系统键(作为存储过程)采用唯一的非
成组索引,对任何外键列[字段]采用非成组索引。不过,索引就象是
盐,太多了菜就咸了。你得考虑数据库的空间有多大,表如何进行访
问,还有这些访问是否主要用作读写。
大多数数据库都索引自动创建的主键字段,但是可别忘了索引外
键,它们也是经常使用的键,比如运行查询显示主表和所有关联表的
某条记录就用得上。还有,不要索引 memo/no te 字段,不要索引大
型字段(有很多字符),这样作会让索引占用太多的存储空间。
■ 不要索引常用的小型表
不要为小型数据表设置任何键,假如它们经常有插入和删除操作
就更别这样作了。对这些插入和删除操作的索引维护可能比扫描表空
间消耗更多的时间。
不要把社会保障号码(SSN)或身份证号码(ID)选作键永远都
不要使用 SSN 或 ID 作为数据库的键。除了隐私原因以外,须知政
府越来越趋向于不准许把 SSN 或 ID 用作除收入相关以外的其他目
的,SSN 或 ID 需要手工输入。永远不要使用手工输入的键作为主键,
因为一旦你输入错误,你唯一能做的就是删除整个记录然后从头开始。
我在破解他人的程序时候,我看到很多人把 SSN 或 ID 还曾被
用做系列号,当然尽管这么做是非法的。而且人们也都知道这是非法
的,但他们已经习惯了。后来,随着盗取身份犯罪案件的增加,我现
在的同行正痛苦地从一大摊子数据中把 SSN 或 ID 删除。
■ 不要用用户的键
在确定采用什么字段作为表的键的时候,可一定要小心用户将要
编辑的字段。通常的情况下不要选择用户可编辑的字段作为键。这样
做会迫使你采取以下两个措施:
1. 在创建记录之后对用户编辑字段的行为施加限制。假如你这么做
了,你可能会发现你的应用程序在商务需求突然发生变化,而用
户需要编辑那些不可编辑的字段时缺乏足够的灵活性。当用户在
输入数据之后直到保存记录才发现系统出了问题他们该怎么想?
删除重建?假如记录不可重建是否让用户走开?
2. 提出一些检测和纠正键冲突的方法。通常,费点精力也就搞定了,
但是从性能上来看这样做的代价就比较大了。还有,键的纠正可
能会迫使你突破你的数据和商业/用户界面层之间的隔离。
所以还是重提一句老话:你的设计要适应用户而不是让用户来适
应你的设计。
不让主键具有可更新性的原因是在关系模式下,主键实现了不同
表之间的关联。比如,Cu stomer 表有一个主键 CustomerID,而客
户的定单则存放在另一个表里。Order 表的主键可能是 OrderNo 或
者 OrderNo、CustomerID 和日期的组合。不管你选择哪种键设置,
你都需要在 Order 表中存放 CustomerID 来保证你可以给下定单的
用户找到其定单记录。
假如你在 Customer 表里修改了 CustomerID,那么你必须找出
Order 表中的所有相关记录对其进行修改。否则,有些定单就会不属
于任何客户——数据库的完整性就算完蛋了。
如果索引完整性规则施加到表一级,那么在不编写大量代码和附
加删除记录的情况下几乎不可能改变某一条记录的键和数据库内所有
关联的记录。而这一过程往往错误丛生所以应该尽量避免。
■ 可选键(候选键)有时可做主键
记住,查询数据的不是机器而是人。
假如你有可选键,你可能进一步把它用做主键。那样的话,你就
拥有了建立强大索引的能力。这样可以阻止使用数据库的人不得不连
接数据库从而恰当的过滤数据。在严格控制域表的数据库上,这种负
载是比较醒目的。如果可选键真正有用,那就是达到了主键的水准。
我的看法是,假如你有可选键,比如国家表内的 state_code,
你不要在现有不能变动的唯一键上创建后续的键。你要做的无非是创
建毫无价值的数据。如你因为过度使用表的后续键[别名]建立这种表
的关联,操作负载真得需要考虑一下了。
■ 别忘了外键
大多数数据库索引自动创建的主键字段。但别忘了索引外键字段,
它们在你想查询主表中的记录及其关联记录时每次都会用到。还有,
不要索引 memo/notes 字段而且不要索引大型文本字段(许多字符),
这样做会让你的索引占据大量的数据库空间。
§ 第 4 部分 – 保证数据的完整性
──────────────
■ 用约束而非商务规则强制数据完整性
如果你按照商务规则来处理需求,那么你应当检查商务层次/用
户界面:如果商务规则以后发生变化,那么只需要进行更新即可。假
如需求源于维护数据完整性的需要,那么在数据库层面上需要施加限
制条件。如果你在数据层确实采用了约束,你要保证有办法把更新不
能通过约束检查的原因采用用户理解的语言通知用户界面。除非你的
字段命名很冗长,否则字段名本身还不够。
只要有可能,请采用数据库系统实现数据的完整性。这不但包括
通过标准化实现的完整性而且还包括数据的功能性。在写数据的时候
还可以增加触发器来保证数据的正确性。不要依赖于商务层保证数据
完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完
整性规则之上。
■ 分布式数据系统
对分布式系统而言,在你决定是否在各个站点复制所有数据还是
把数据保存在一个地方之前应该估计一下未来 5 年或者 10 年的数
据量。当你把数据传送到其他站点的时候,最好在数据库字段中设置
一些标记。在目的站点收到你的数据之后更新你的标记。为了进行这
种数据传输,请写下你自己的批处理或者调度程序以特定时间间隔运
行而不要让用户在每天的工作后传输数据。本地拷贝你的维护数据,
比如计算常数和利息率等,设置版本号保证数据在每个站点都完全一
致。
■ 强制指示完整性(参照完整性?)
没有好办法能在有害数据进入数据库之后消除它,所以你应该在
它进入数据库之前将其剔除。激活数据库系统的指示完整性特性。这
样可以保持数据的清洁而能迫使开发人员投入更多的时间处理错误条
件。
■ 关系
如果两个实体之间存在多对一关系,而且还有可能转化为多对多
关系,那么你最好一开始就设置成多对多关系。从现有的多对一关系
转变为多对多关系比一开始就是多对多关系要难得多。
■ 采用视图
为了在你的数据库和你的应用程序代码之间提供另一层抽象,你
可以为你的应用程序建立专门的视图而不必非要应用程序直接访问数
据表。这样做还等于在处理数据库变更时给你提供了更多的自由。
■ 给数据保有和恢复制定计划
考虑数据保有策略并包含在设计过程中,预先设计你的数据恢复
过程。采用可以发布给用户/开发人员的数据字典实现方便的数据识
别同时保证对数据源文档化。编写在线更新来“更新查询”供以后万
一数据丢失可以重新处理更新。
■ 用存储过程让系统做重活
解决了许多麻烦来产生一个具有高度完整性的数据库解决方案之
后,我决定封装一些关联表的功能组,提供一整套常规的存储过程来
访问各组以便加快速度和简化客户程序代码的开发。数据库不只是一
个存放数据的地方,它也是简化编码之地。
■ 使用查找
控制数据完整性的最佳方式就是限制用户的选择。只要有可能都
应该提供给用户一个清晰的价值列表供其选择。这样将减少键入代码
的错误和误解同时提供数据的一致性。某些公共数据特别适合查找:
国家代码、状态代码等。
§ 第 5 部分 – 各种小技巧
──────────────
■ 文档、文档、文档
对所有的快捷方式、命名规范、限制和函数都要编制文档。
采用给表、列[字段]、触发器等加注释的数据库工具。是的,这
有点费事,但从长远来看,这样做对开发、支持和跟踪修改非常有用。
取决于你使用的数据库系统,可能有一些软件会给你一些供你很
快上手的文档。你可能希望先开始在说,然后获得越来越多的细节。
或者你可能希望周期性的预排,在输入新数据同时随着你的进展对每
一部分细节化。不管你选择哪种方式,总要对你的数据库文档化,或
者在数据库自身的内部或者单独建立文档。这样,当你过了一年多时
间后再回过头来做第 2 个版本,你犯错的机会将大大减少。
使用常用英语(或者其他任何语言)而不要使用编码为什么我们
经常采用编码(比如 9935A 可能是‘青岛啤酒’的供应代码,
4XF788-Q 可能是帐目编码)?理由很多。但是用户通常都用英语进
行思考而不是编码。工作 5 年的会计或许知道 4XF788-Q 是什么东
西,但新来的可就不一定了。在创建下拉菜单、列表、报表时最好按
照英语名排序。假如你需要编码,那你可以在编码旁附上用户知道的
英语。
■ 保存常用信息
让一个表专门存放一般数据库信息非常有用。我常在这个表里存
放数据库当前版本、最近检查/修复(对 FoxPro)、关联设计文档的
名称、客户等信息。这样可以实现一种简单机制跟踪数据库,当客户
抱怨他们的数据库没有达到希望的要求而与你联系时,这样做对非客
户机/服务器环境特别有用。
■ 测试、测试、反复测试
建立或者修订数据库之后,必须用用户新输入的数据测试数据字
段。最重要的是,让用户进行测试并且同用户一道保证你选择的数据
类型满足商业要求。测试需要在把新数据库投入实际服务之前完成。
■ 检查设计
在开发期间检查数据库设计的常用技术是通过其所支持的应用程
序原型检查数据库。换句话说,针对每一种最终表达数据的原型应用,
保证你检查了数据模型并且查看如何取出数据。
Microsoft Visual FoxPro 设计技巧对复杂的 Microsoft
Visual FoxPro 数据库应用程序而言,可以把所有的主表放在一个数
据库容器文件里,然后增加其他数据库表文件和装载同原有数据库有
关的特殊文件。根据需要用这些文件连接到主文件中的主表。比如数
据输入、数据索引、统计分析、向管理层或者政府部门提供报表以及
各类只读查询等。这一措施简化了用户和组权限的分配,而且有利于
应用程序函数(存储过程)的分组和划分,从而在程序必须修改的时
候易于管理。
谨把本文献给战斗在狐狸战线上的同志们!!!
– 夜来香
2002/05/30
追影
保研了,开始有机会过大家口中“猪一样的生活”了。不过我还是不习惯被人形容为“闲得蛋疼”的日子,翻出一堆书,决心要把所学巩固。
这是后中秋的第二天,国庆假期还有三天,但是现在是在放“大四假”,为期约为一年,还有几天国庆假期其实也就不重要了。下午看书闷的,上网点了部武侠喜剧,《追影》。(想看?)


是吴镇宇和吴佩慈拍的。
1.吴镇宇是个很有内涵(至少没让我看得像在装B)的演员;
2.让我选一个天下最美的女人,那就是吴佩慈了。可能和以前看亚视或者TVB时的一些回忆有关,但是具体原因我也想不清楚,只是觉得这个容貌,这个身材,这个气质。和对吴镇宇黄秋生一样,我不追,但是很欣赏。
3.挺搞笑的,幽默很到到位又不会太无厘头,武打效果很好又不会太夸张;
4.所谓的内涵好老土,追影这个思想倒没让我赞叹,只是整部电影风格很free,很独立,不会有什么商业气息,看起来舒服罢了。据说拍的时候剧本只有个框架,都是一边拍导演编剧制作演员一起拍脑袋想细节。这也是为什么拍得那么自然那么free啦。
电影是说一群人拼死活找到明太祖开国宝藏发现宝藏就是一把锄头,人家朱元璋说“被迫做皇帝只能在这里过着锦衣玉食他妈的不开心最喜欢耕田有锄头有天耕就是百姓最快乐的宝藏”。主旨就是讽刺人们追名呀逐利呀发现自己眼中的东西只是一文废纸,一个影子,不实在。
—————————–省略由电影及己过度语若干字————————–
放弃了公司的offer,选择了读研。但其实我心里不是没有数,我知道自己追求的,不是影子。
心上人说羡慕我可以做自己想做的事。那我就抓紧时间,做爱做的事,交配交的朋友,成为想成为的人。
我的步伐也许就像拍追影一样,走一步不知道下一步,可是我的眼睛始终盯着长远的那一方。
我的脑里装什么?
今天may展现其一直很冷的风格,发了一个分析器给我。刚好没事就做了一下:

女人是第一位呀。“吃的”很准!
2009广东移动实习应聘日记
小生在南京读大学,是技术类,计算机应用的。参加的广州分公司在南京的笔试和面试。
5月上旬:报名,询问了一下进去的同学。发现计算机应用部门的其实招的人才10个,而且招的本科生不多。(也可以从另一个角度想,本科生不多,所以现在要招一些进去…)
5月18日:笔试。从浦口NJU和十来个同学长途跋涉翻山越岭爬山涉水到了南理工,考试是在晚上,也许是就考一些智力题,数据处理题什么的,和其他公司的aptitude题目差不多吧,多了一部分英语考核。感觉难度不大,但是时间很紧,自己好久没参加过什么时间紧张的考试了,有点不习惯。
5月..日: 笔试之后几天,收到面试通知,地点在金陵饭店。
5月25日:金陵饭店,先去了十五楼一个房间等。似乎是把这一层给包下来了,刚来的都集中到一个地方等,轮到了就到另一个房间去面试。
- 一面:上午12点轮到了我,进到其中一个房间,里面坐着一个年轻的lady,红光满面,笑容可掬。坐下来,本来以为要自我介绍的,结果没有。然后就看看简历,问了一下情况。然后出了个问题让我回答(挖坑了)。我回答完以后,她根据我的答案告诉我一个结论,说我这样是怎样怎样不好,问我是不是。然后我反驳…跳出坑。。。其实心里当时就反应过来,这关面试的问题,无论你怎么回答,答出一个答案还是相反的答案,都是“错误的答案”,关键是要反驳她的过程当中表现出自己思维的过程、反应能力、应变能力。最后突然一笑,说“恭喜你通过这关面试。。”贴了个条子让我到下一面。
- 二面:由于上午我是最后一个一面的,所以二面安排到了下午。二面是专业技能的面试,对我而言就是SE相关的知识考核咯。里面坐着的是一个壮年男子,样子也很友好的。坐下来,看看我的简历,聊了几句“你也是NJU的呀”“哦,早上你们也有两个”“你们那个作业项目我也知道”等等。。。然后突然叫我自我介绍。没想到这里要自我介绍的,不过还好头脑够清晰,分点答了一下(生活上blablabla呀,工作上blablabla呀,然后因为前面两点花精力多,成绩开始不太好呀之类的。 扬长补短的句式。) 然后考核了一下技术,题目都不难的,就是根据你简历或者你说的话,考你熟悉的东西。我简历吹的比较多,可能前面几个他考过我们学院其他人了,说了一段话让我设计数据库,写出脚本。三两下写出来,壮年男子嘴里“OK,OK”。然后叫我到另一个房间等待。
- 三面:三面是一位年长一点的lady,(有各种传言,有说是公司副总的,有说是HR BOSS的)。这个比较有power,住的是30几楼的VIP套房。上到那楼,进门,敲了下门,发现这位lady在门口等,一起走进去,lady很有礼貌请我进去坐下来。这个阶段表面上没什么挑战性的,大家都说这个阶段就是问一些硬条件。成绩排名啊、社团经历啊、家里面情况、为什么不选其他公司啊、薪金期望啊之类的。在等的时候大家都说这个lady一直对着计算机在记录你说的东西,不会怎么看你。可是和我说的时候,问我社团的东西,还一眼看出来我是玩机之人,我答是,相视而笑。。。感觉这位lady还是很有深度和修养的。然后说再见,让我两个星期之后等通知。
然后就是等待,比两个星期多了两个星期…
6月23日,收到一封“调研邮件”,目的是“优化实习生项目”。填之,回复之。
还看到论坛上三面过了的人,有的人有这个通知有的人没有,心想事有八九成了吧。
6月25日,收到“实习邀请函”,填之,回复之。
总结or建议:
- 开始想着从软件学院出来的,应该是拼IBM\腾讯之类。但心想CMCC也有发展的空间,也是可以做自己喜欢的IT(报的部门就是ITC嘛。。),综合其他外在因素,决定来的。人生数十年,不必把自己限定在一个领域内,多开眼界也是好的。
- Never Lie。。。诚信是最重要的。无论从道德角度来看,还是从应聘的执行过程来看,都是。HR阅人无数,你是否撒谎,一看就知道。(当然一些接受过训练的人例外,例如控制面部肌肉、控制激素。。可以看lie to me…)
- 既然不能吹牛,那最重要的还是自己平时的修身养性。成绩是要靠平时好好抓的,想着靠自己能力,不靠学分绩这种想法其实是很片面的。礼仪要积累,日行多善呀,尤其面对三面BOSS时,可以看到人家举止很高雅。面试时语速呀、坐姿呀都有讲究。面试者不会刻意看你有没做到,但是你讲话太快不清楚、坐姿难看,细节比如不敲门,见面招呼,再见招呼等没有做好,人家是会不知不觉对你好感减少的。应对能力,就是要多参加一些活动,争取当众说话的机会,见的场面多了,面试自然不会紧张,语速控制也容易多了。
- 介于看到上面第三点的,可能都是要上战场了,说积累也许没用。那就GOOD LUCK吧。乐观之上。
- 整个过程当中感觉到,CMCC很看重成绩、学校牌子、学历、学生社团或干部经历。
为应用程序设计一个合适的架构(下)
步骤4 主要危险区域
确定架构中最容易出错的区域。可以通过质量属性和交叉问题对危险区域进行整理。
质量属性
找出对于应用和场景很重要的质量属性。比如,大部分应用程序都需要解决安全性与性能的问题,而这些问题还需要根据易用性、灵活性等可能更为重要的属性进行权衡分析。
以下是需要注意的重要的质量属性。
|
范畴
|
注意事项
|
|
有效性
|
如何设计故障转移支持
|
|
如何设计一个备用站点
|
|
|
怎样计划备份与恢复
|
|
|
如何设计运行时的更新
|
|
|
概念完整性
|
如何分离对外部的依赖性
|
|
如何整合旧技术
|
|
|
如何在不打断客户的情况下发展系统
|
|
|
灵活性
|
如何处理动态业务规则
|
|
如何处理动态UI
|
|
|
如何处理数据与逻辑过程中的变化
|
|
|
如何处理业务需要的变化
|
|
|
互操作性
|
如何让应用在独立发展的同时实现互操作
|
|
如何通过服务接口分离系统
|
|
|
如何通过层的映射分离系统
|
|
|
易维护性
|
如何减少层与组件之间的依赖性
|
|
如何实现一个插件式的架构
|
|
|
如何选择合适的通信模型
|
|
|
易管理性
|
如何了解主要的失败模式
|
|
如何对系统操作与健康状态进行监控
|
|
|
如何根据负载对系统进行调整
|
|
|
性能
|
如何确定缓存策略
|
|
如何设计层间的高性能通信
|
|
|
如何设计高性能数据存取
|
|
|
如何有效地管理资源
|
|
|
可靠性
|
如何处理不可靠的外部系统
|
|
如何审查请求与任务
|
|
|
如何对负载进行重定向
|
|
|
如何处理失效的通信
|
|
|
如何处理失效的操作
|
|
|
如何处理异常
|
|
|
重用性
|
如何减少层与组件之间的重复性
|
|
如何实现跨系统的共享
|
|
|
如何实现组件和层之间的功能共享
|
|
|
可扩展性
|
如何设计可扩展的层与级
|
|
如何扩展
|
|
|
如何处理传输与负载的测试点
|
|
|
安全性
|
如何解决认证与授权问题
|
|
如何防止恶意输入
|
|
|
如何保护敏感数据
|
|
|
支持
|
如何设计审查与记录
|
|
如何设计使用问题信息的记录
|
|
|
易测性
|
如何设计才能方便测试
|
|
如何设计单元测试
|
|
|
如何设计UI自动化
|
|
|
可用性
|
如何设计才能让用户有更多的权限
|
|
如何改善响应性
|
|
|
如何避免常见的用户体验问题
|
架构框架
架构框架代表了你在层与级上可能会遇到的交叉问题。这些也是最容易出现重大设计错误的区域。可以通过架构框架来发现需要额外注意危险区域。
你可以使用以下架构框架来发现需要额外注意的交叉问题。
|
领域
|
描述
|
|
认证与授权
|
如何选择认证策略
|
|
如何选择授权策略
|
|
|
如何在不同层与级之间传递身份消息
|
|
|
如何在不使用活动目录的情况下存储用户的身份信息
|
|
|
缓存与状态
|
如何选择合适的缓存技术
|
|
如何决定缓存哪些数据
|
|
|
如何决定在哪里缓存数据
|
|
|
如何检查过期策略
|
|
|
通信
|
如何为不同的层与级选择合适的通信协议
|
|
如何设计层之间的松耦合
|
|
|
如何实现异步通信
|
|
|
如何传送敏感数据
|
|
|
组合
|
如何为用户界面选择组合模式
|
|
如何避免UI模块之间的依赖性
|
|
|
如何处理UI模块之间通信问题
|
|
|
并发与事件
|
如何处理并发线程
|
|
如何选择积极并行与保守并行
|
|
|
如何处理分布式事件
|
|
|
如何处理长期事件
|
|
|
配置管理
|
如何确定需要配置的信息
|
|
如何确定在哪里储存配置信息
|
|
|
如何保护敏感配置信息
|
|
|
如何处理簇中的配置信息
|
|
|
耦合与内聚
|
如何选择合适的层策略来分离问题
|
|
如何在层里设计高内聚的组件并对其分组
|
|
|
如何确定松耦合是否适合层里的组件
|
|
|
数据存取
|
如何管理数据库的连接
|
|
如何处理异常
|
|
|
如何改善性能
|
|
|
如何处理二进制大对象(blob)
|
|
|
异常管理
|
如何处理异常
|
|
如何记录异常信息
|
|
|
如何在需要的时候进行通知
|
|
|
日志与器械
|
如何决定记录哪些信息
|
|
如何让日志可修改
|
|
|
如何确定需要什么等级的器械
|
|
|
用户体验
|
如何提高任务的有效性与效率
|
|
如何改善响应性
|
|
|
如何提高用户权限
|
|
|
如何改善外观与体验
|
|
|
验证
|
如何确定在什么位置怎样执行验证
|
|
如何验证长度、范围、格式、类型
|
|
|
如何限制及拒绝输入
|
|
|
如何整理输出
|
|
|
工作流
|
如何选择合适的工作流技术
|
|
如何处理同一工作流中的并发问题
|
|
|
如何处理工作流中的错误
|
|
|
如何编排工作流中的过程
|
步骤5 可用方案
定义了危险区域之后,你就可以创建第一个高层次的设计并着手创建一个可用架构。你可以返回第二步对可用方案及你所定义的关键场景和需求进行再次验证。
架构测试点一种是用来确定具体的设计方式的可行性的设计原型。你可以使用架构测试点来减少风险并迅速检验各种方式的健全性。根据关键场景和危险区域对架构测试点进行测试。
迭代与递增式的架构
这个架构过程应该是迭代和、递增式的。你的第一个可用方案是一个高层次的设计,可以根据针对关键场景、需求、各种限制等进行测试。在你创建了可选架构和架构测试点之后,你将会了解到更多的细节,从而丰富你的场景、应用视图和解决危险区域的方法。每个迭代周期都应该为你的设计添加更多的细节。
下一步怎么做
在你结束了架构建模之后,你可以这样:
如果你把可用架构和架构的测试用例保存在了一个文件里,那么请不要随便往这个文件添加任何多余的东西、避免过分的格式化,这样你可以随时对其进行更新。其主要内容应该包括你的目标、应用类型、部署方式、关键场景、需求、技术、质量属性和测试。
使用质量属性来帮助你的设计与实现。比如,开发人员应该注意与已确定的架构风险相关的反模式,并使用模式协助解决这个问题。
使用架构框架来计划并整理架构测试。
与相关团队成员交流你得到的信息。包括你的应用开发团队、测试团队、以及网络与系统管理员。
如何实现架构的敏捷
使用系统需求和用户需求对可以再次测试的用例的实例进行检验。一个优秀的需求应该能够贯穿架构中用户、业务和系统三个方面。使用用例来对设计进行测试,确定系统中虚弱的部分。系统需求从系统的角度描述应用场景。用户需求从客户的角度描述应用应该可以完成什么任务。这样,你就会根据用途描述需求,并根据质量属性进行检验。你应该在一个迭代周期内完成一个需求所描述的功能。随着架构模型的更新,你可能还需要创建新的需求描述。
在你制定需求描述的时候请注意以下几点:
·在项目的早期创建能够对架构的所有层进行检验的可选架构,从而减少风险。
·关于利用架构模型,根据场景、功能需求、技术需求、质量属性和限制条件调整架构、设计和代码。
·根据你当前的知所创建架构模型,并写出在接下来的需求和迭代周期中必须解决的问题。
·对架构做出足够多的调整后,可以考虑写一个能够反映这些调整的需求描述。把这些调整放到一起解决。
在创建架构的测试点的时候,请考虑以下几点:
·了解你所面临的最大风险,根据这些风险对设计进行调整。
·在敏捷方法中,信息共享是非常重要的;让你的交付成果能够实现更好的信息交流。
·创建架构的时候要考虑到灵活性与重构的问题。你可能需要对架构进行多次调整。
审查架构
对应用架构进行审查是一项非常重要的任务,因为它能够减少错误、尽早地发现并修复架构问题。架构审查是公认的可以降低项目成本、减少架构故障的有效措施。因此在创建架构的时候要让其尽可能地方便交流和审查。这不仅可以提高架构质量,也能减少每次审查所需的时间。
架构审查的主要目标是确定架构能够正确地实现所需的功能并符合质量属性。此外,它还能帮助发现并解决问题。
场景评估
场景评估是进行架构审查的有效方法。在场景评估中,主角是对业务最重要的场景,也是对架构影响最大的场景。以下是几种常用的审查方法:
软件架构分析方法(SAAM)
最初,SAAM是用来评估可修改的特性的。但是后来这一方法被延用到架构审查中,主要面向可修改性、可移植性、可扩展性、整合性以及功能覆盖率等质量属性。SAAM也被用来审查架构的性能、可靠性。
软件架构权衡分析法(ATAM)
ATAM法是SAAM的精炼、改进版本,用于审查架构决策的质量属性、以及具体质量目标的完成度。
主动设计审查(ADR)
这种架构审查方法最适用于未完成或正在进行中的架构。其主要不同点在于每次的审查目标是架构的某个区域而不是架构的整体。
设计中主动审查(ARID)
这种架构审查技术组合了ARD对进行中架构的一系列问题的审查,和ATAM与SAAM的对质量属性的场景审查。
成本效益分析法(CBAM)
这种架构审查方法主要是分析架构决策的成本、收益和对进度的影响。
软件可变性分析(ALMA)
对商业信息系统(BIS)架构的可变性进行评估。
架构系评估方法(FAAM)
这种架构审查技术评估的是信息系统类架构的互通性和扩展性。
沟通
架构设计完成之后,你必须和其他利益相关人讨论这个设计。利益相关人包括开发团队、系统管理员和操作人员、业主以及其它相关团体。有许多关于如何向别人描述架构的方法,下面就是其中一种:
4-1法 这种方法使用了架构的五种视图。其中四种是以不同的方式对架构进行描述。逻辑视图(比如对象模型)、过程视图(比如从并行和同步的角度)、物理视图(软件各层与功能的分布式硬件配置图)和开发视图。第五种视图展示的是软件的场景与用例。这可以让利益相关人了解到他们更为关心的某些方面。
原文链接:How To – Design Using Agile Architecture
转载自IT168 [ http://www.it168.com/ ]
本文链接:http://tech.it168.com/a2009/0427/273/000000273974_7.shtml
为应用程序设计一个合适的架构(上)
目标
学习如何为应用程序设计一个合适的架构
了解对设计进行审查的各种方式
概要
本文将依次介绍应用设计的六个主要步骤并讨论与逻辑选择相关的各种问题。文中还包含了检查设计时可供参考的表单。
输入
在设计应用架构的时候以下输入是非常有用的:
·用例与使用场景
·功能需求
·非功能性需要(如性能、安全性、可靠性等质量属性)
· 技术需求
·部署环境
·各种限制条件
输出
设计应生成以下结果:
·突出架构特点的用例
·架构的危险区域
·可用的架构
·架构测试点
步骤
图1即是应用架构设计的五个主要步骤。

图1 应用构架设计的主要步骤
这些步骤分别是:
步骤1 确定架构目标。清晰的目标能让你更好地考虑并解决架构相关问题。正确的目标能让你知道什么时候该结束,什么时候该迈向下一步。
步骤2 关键场景。使用关键场景来帮你确定最重要的因素,以及对可用架构做出评估。
步骤3 对应用的了解。了解你的应用类型、部署架构、架构特点及相关技术,以让你的设计更符合实际。
步骤4 主要危险区域。根据质量属性与架构框架确定主要的危险区域。这些区域是在设计应用的时候最容易出错的地方。
步骤5 可选方案。创建备用架构或架构测试点并按场景、危险区域、部署条件对其进行评估。
随着设计的发展,你会逐渐发现越来越多的影响架构的细节,架构也因此逐渐丰满起来。别想一步就完成整个架构的构建,也别被细节迷惑,要先为架构设计一个基本框架,把注意力放在主要步骤上。
步骤1 确定架构目标
架构目标即是组成设计过程、确定使用范围并帮你确定什么时候该结束的因素。在设定架构目标的时候请考虑以下基本点:
·从一开始就要对架构目标有个清楚的认识。架构与设计的各个阶段所花费的时间将取决于这些目标。比如,你是在搭建一个原型?测试潜在的方式?还是准备为新应用创建一个长远的架构环境?
·了解架构的消费者。要确定架构是否会被其他设计师、开发人员、测试人员、业务人员或管理人员使用。确定架构受众的需求,以让架构更为成功、更有影响力。
·了解条件限制。了解技术限制、使用限制、和部署限制。从一开始就要了解这些限制,这样你才不会在将来遇到一些意想不到的麻烦
步骤2 关键场景
关键场景包括使应用获得成功的最重要的场景,还有能突出架构特点的用例。
重要的场景标准如下:
1.这些场景是业务关键的,比其它功能具有更高的使用要求,或者具有很高的技术/工艺风险。
2.关系到功能属性和质量属性两个方面,或者具有交叉性的影响。比如CRUD操作对安全性非常敏感。
3.它们是最重要的场景,贯穿应用的各层(级),或者对应用整体都有重要的影响。
架构突出的用例标准如下:
1.这些用例对应用部署的成功和验收非常重要。
2.能够对设计进行足够的检验。
区别系统场景与用户场景的不同是很重要的。
系统场景指主要对应用与设备的内部操作产生影响的场景。比如在各层间传递的信息、连接数据存储、执行验证等。
用户场景指用户发起或受用户控制的场景。比如创建一个定单、浏览产品、或者更新客户记录。
突出架构特点的用例举例:
用在线商场的程序创建一个订单并接收定单被确认的信息。
使用库存管理程序更新某个产品记录,并更新所有相关的记录(比如价格列表)。
在CRM程序中搜索并显示某个客户的细节。
步骤3 对应用的了解
了解你的应用在完成的时候的大概情况。这将会使你的架构更实际,并与具体的条件限制和决定有更密切的联系。创建应用的大概视图应该包括以下步骤:
·决定应用的类型。首先决定所构建的应用的类型。它是一个移动应用、富客户端、服务、网络应用、还是组合应用?
·了解部署限制。然后,了解所部署的目标环境和它将对架构产生什么影响。
·确定重要的架构特点。确定你的架构将使用哪些类型。面向服务的架构?客户服务器?分层?消息总线或是某几种的组合?
·确定相关的技术。最后,根据应用类型和各种条件限制确定相关的技术。
决定应用的类型
选择正确的应用类型是应用架构设计的关键。需求和设备限制决定了合适的应用类型。以下几点将帮助你做出合适的选择。
·移动应用可以作为瘦客户端或富客户端。富客户端移动应用可以支持非联网或偶然联网的场景。网络应用或瘦应用只支持联网场景。设备资源将成为这种设计的条件限制。
·富客户应用通常是独立的应用,可以使用多种控制手段在图形界面上显示数据。富客户应用可以用于支持非联网和偶然联网的场景,因为这种应用是运行在客户机上的。
·富因特网应用可以支持多平台和多浏览器并显示多媒体和图形内容。富因特网应用运行在浏览器沙盒上,其对客户端的访问受到限制。
·服务应用用于实现客户与服务器之间的松耦合。服务可以让用户从本地或远程访问复杂的功能。服务操作使用基于基于XML的消息格式的传送机制。
·网络应用通常支持联网场景,通常支持多浏览器和多操作系统平台。
了解部署限制
在设计应用架构的时候,你必须同时考虑企业的政策和程序以及目标部署设备。在目标环境确定的情况下,你的应用设计必须能够反映出实际存在的各种限制。你在进行设计的时候必须考虑到服务质量(QoS)属性,比如安全性和易维护性。有时候由于政策程序上的限制或网络布局的原因,你必须作出一些折衷措施。
要在设计过程的早期确定这些需求和限制,这样你才能尽早地选择合适的部署环境、解决应用与设备架构之间的冲突。
1.分布式与非分布式架构
应用部署通常有两种方式:
非分布式部署 除了数据存储功能,其它功能和层都在同一服务器上。
分布式部署 各层与应用分布在不同的物理级上。
在大部分情况下,我们都建议采用分布式。虽然当一个过程需要跨越物理界限的时候需要对数据进行序列化,因此性能会受到影响。但是由于某些原因我们需要把功能分散到各服务器上。另外,你也可以根据服务器的位置选择最优化的通信协议。
非分布式部署
在非分布式的架构中,呈现、业务和数据存取代码虽然在逻辑上是分开的,在物理层面上却是位于同一网络服务器上的。图2描述了这样的场景。

图2 非分布式部署
优势
非分布式架构更为简单。
由于本地调用,非分布式架构具有性能上的优势。
劣势
难于与其它应用共享业务逻辑。
服务器资源是跨层共享的。这既有好的一面也有不好的一面–因为总有一层处理繁忙状态,如果各层合作良好,资源就能获得充分利用。但是一旦某一层要求更多的资源,其它层可能就会无法利用资源。
分布式部署
如图3所示,分布式部署可以让你把应用的不同层分布在各物理级上。

图3 分布式部署
优势
分布式架构易于扩展,并且可以独立地加载平衡业务逻辑。
各层有自己的资源可以利用。
灵活。
劣势
需要额外的序列化,并由于远程调用而产生网络延迟。
通常更为复杂、更为昂贵。
2.保持相同的过程
尽量避免远程调用。由于序列化和网络延迟等原因,跨物理界限(过程和机器)的远程调意味着昂贵的成本。如图4所示,你可以在当前的服务器中添加更多的硬件或者在网络应用级中添加更多的服务器。

图4 在网络应用级中添加服务器
你可以把应用的业务逻辑寄存到网络服务器上,或者一个物理意义上独立的应用服务器上。通过把业务逻辑放到网络服务器的网络应用过程中,你可以获得最佳的性能。只要你在应用设计中能够避免或可以利用服务器亲和力,你就可以使用这种方法进行扩展。
3.除非必须,否则不要把应用逻辑放在远程
除非你确实需要这么做,或者已经做过权衡对比,否则决不要把业务逻辑层分离出去。远程逻辑会增加性能成本。这是在网络中环行所造成的网络延迟和序列化必然导致的结果。
然而,你可能确实需要从物理级上将业务层分离出去,比如以下场景:
·你可能想把网关服务器和关键的合作伙伴放到一起。
·你可能需要为既有的一套业务逻辑添加一个网络前端。
·你可能需要在多个客户端应用之间共享业务逻辑。
·企业的安全政策不允许在前端网络服务器上安装业务逻辑。
·可能你的业务逻辑对运算速度非常敏感,所以你需要把这个处理过程减负到一个单独的服务器上
确定重要的架构特点
有许多会影响架构特点的因素。其中包括企业的设计与实现能力、开发人员的能力与经验、设备限制与部署场景等。
主要架构模式有几下几种:
·基于组件。将应用设计分解为可重用的组件,用户界面良好。
·分层。以层为单位将系统分解为各功能相近的组。
·消息总线。为所有连接到系统的组件定义一组通用格式,因此各组件无需了解接收方的实际信息。
·面向对象。一种将任务以对象为基础进行分解的程序设计方法。
·面向服务(SOA)。应用根据合约与信息以服务的方式呈现或使用功能。
一个完整的结构通常包含几种模式。比如,一个分层的架构可以与基于组件、面向对象或面向服务的架构模式一起使用。可以这样选择架构模式。
以下是选择客户服务器架构模式的情况:
·你的应用是基于服务器的,可以支持多个客户端。
·你创建的是通过网络浏览器呈现的网络应用。
·你的业务过程需要能被公司所有人使用。
·所创建的服务要供其它应用使用。
·你想让数据存储、备份和管理功能集中化。
·你的应用必须支持各种客户端类型和设备。
以下是选择基于组件的架构模式的情况:
·你已经有了合适的组件,或者可以从第三方获得合适的组件。
·你的应用永远都是用于执行程式化的功能的,可能不需任何输入。
·你的应用相对简单,无需一个完整的分层架构。
·你的应用是为了满足特定的需求而产生的,没有用户界面或业务过程。
·你想把使用不同代码语言编写的组件结合到一起。
·你想创建一个便于替换和更新私人组件的插件式架构。
以下是选择分层架构模式的情况:
·应用比较复杂,所以你想分组各种功能问题以简化问题。
·你想通过减少依赖关系来提高可维护性与扩展性。
·你已有通过服务接口呈现合适的业务过程的应用。
·你的应用必须支持各种客户端类型和设备。
·你想实现复杂的和/或可配置的业务规则和过程。
以下是选择系统总线架构模式的情况:
·当前的应用之间有互操作。
·你在执行一个需要与外部应用进行交互的任务。
·你在执行一个需要与寄存在另一个环境中的应用进行交互的任务。
·当前的应用执行一些特殊的任务,你希望把这些任务整合成一个操作。
以下是选择面向对象的架构模式的情况:
·你要根据实际对象和行为对应用进行模拟。
·你已有符合需求的合适的对象和类。
·你需要将逻辑与数据一起封装到可重用的组件中。
以下是选择面向服务的架构模式的情况:
·你能够访问到适合的服务,或者可以购买到托管公司的所需服务。
·你希望为包含各种服务的应用程序构建一个统一的用户界面。
·你在创建SS、SaaS或基于云的应用。
·你需要支持应用中各段之间的基于消息的交流。
·你需要以平台无关的方式呈现功能。
·你希望利用联邦服务,比如认证。
·你希望以目录的方式呈现服务,并且首次接触这个界面的用户也可以使用。
确定相关的技术
在选择技术时,需要考虑的关键因素是你的应用类型和你希望使用的应用部署结构及架构模式。技术的选择也受到企业政策、设备限制、资源能力等的控制。比如你想构建一个SOA模式的应用,那么WCF就是不错的选择。如果你要构建可以调用WCF服务的网络应用,那么ASPNET是不错的选择。你的技术选择和你的应用模式具有直接的关系。
不妨考虑一下以下问题:
·哪种技术能为你提供架构模式上的支持?
·哪种技术能为你提供应用模式上的支持?
·哪种技术能为你的应用提供质量属性上的支持?
转载自IT168 [ http://www.it168.com/ ]
本文链接:http://tech.it168.com/a2009/0427/273/000000273974_3.shtml
科比的绝杀被刘易斯“帽”
昨晚K书太晚了,今天早上起来的时候已经10点多,跑去上课,第四节只看了文字。
ILK上筒子们都说这场裁判吹的不好,不公平。
不过总决赛这种强度,裁判总是会倾向于让球员自己解决吧。(看乔老爷绝杀爵士,不也是把那谁推倒了才绝杀的嘛)
ANYWAY,总算拿下来了。还胜两场,今年就圆满了。

密码保护:美丽的杯子
java基础总结1
最近把以前学习java的过程总结了一遍,发到这里来记录一下。
1.JAVA8中基本数据类型,4整2浮1布尔1字符char,与机器无关,int是4字节,long是8字节,byte是1字节,short是2字节
2.函数中变量只声明没有初始化不能使用;成员变量会自动初始化******;数组中变量会自动初始化
3.整数除以0报异常,浮点数除以零是Infinity或者NaN
5.可以在for语句的第一第三控制部分用逗号分隔表达式
6.JAVA中字符串1
7.Date adate = new Date();
new Date()创建一个新的对象,并返回这个对象的引用,存储在adate这个对象变量中
与C++不同的是,JAVA可以显式给一个对象变量赋值为null引用,表明没指向堆里任何的对象。C++不能给引用赋值。
8.java中赋值都是浅拷贝,深拷贝要用clone()方法。
9.成员初始化的次序:static初始化块->声明初始化->初始化块->构造器
10.java中用finalize()释放资源。这个方法在垃圾回收之前被调用,执行这个对象拥有的资源的释放工作(当然这要你自己写),然后下一次垃圾回收时把对象自己占的资源(指
new出来的资源)释放。但要注意的是:对象可能不被垃圾回收,你不知道它什么时候去回收。
牢记:垃圾回收只与内存有关,其他资源例如文件呀,网络连接呀什么的不要放在finalize()里。
当在java中调用了非java代码(这种称为“本地方法”)分配了资源时,需要在finalize()释放。
11.super不可以作为参数来传递,this可以。因为super不是一个对象,而是用来让编译器调用超类方法的关键字。
12.没有抽象方法也可以是抽象类,抽象类里也可以有非抽象方法。抽象类只是限定其不能用来构建对象而已。
然后,抽象类可以作为类型,指向具体类。
13.Object那些事
equals()要求自反、对称、传递、不改变对象、o.equals(null)要返回false.
14.局部内部类的范围是声明它的程序块;内部类如果是私有则只有outerclass能访问;如果是public,要x.new inner();(其中x是outer的一个对象);内部类访问外部类的字段要
outer.this.field.
15.匿名内部类:
Type a = new interface(){ 实现… };
Type a = new superClass(参数){ 实现… };
匿名的内部类不能有构造器
java中对象的克隆
java中对象默认为浅拷贝,要深拷贝时需要重载clone方法。在重载时一般要先调用super.clone().这个super.clone()指的是Object类里面定义的clone方法。它根据实际对象的大小来分配空间,并且把内存里面的内容复制过去。如果是基本类型则直接复制,对象类型则只是复制一个引用。
Object类的clone方法是一个native的方法。它先检查当前对象是不是已经实现了Cloneable的接口,如果没有,抛出一个异常;如果已经实现了这个接口,则产生这个对象的类的一个新的实例,并且用这个对象的内容去初始化那个新的实例。源代码里的注释如是说。
* The method clone for class Object performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface Cloneable, then a
* <tt>CloneNotSupportedException is thrown. Note that all arrays
* are considered to implement the interface Cloneable.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the
* contents of the fields are not themselves cloned. Thus, this method
* performs a “shallow copy” of this object, not a “deep copy” operation.
public class Main {
public static void main(String[] args) {
B1 b1 = new B1();
b1.a = 11;
b1.b = 22;
b1.c = 33;
b1.d = 44;
b1.e = 55;
B1 b2 = (B1) b1.clone();
System.out.println(b2.a);
System.out.println(b2.b);
System.out.println(b2.c);
System.out.println(b2.d);
System.out.println(b2.e);
}
}
class B1 extends A1 {
public int d = 4;
public int e = 5;
public Object clone() {
System.out.println("B1's clone() is called");
B1 b1;
b1 = (B1) super.clone();
return b1;
}
}
class A1 implements Cloneable{
public int a = 0;
public int b = 1;
public int c = 2;
protected Object clone(){
System.out.println("A1's clone() is called");
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
上述代码的执行路径为:13 – 29 – 34 – 46 – 49 ->Object.clone() ->…..
输出:
B1’s clone() is called
A1’s clone() is called
11
22
33
44
55
Cloneable是一个Marker Interface,它里面是空的,仅仅用来让Object.clone()检查一个对象是否可以被克隆。
上述例子中,29行和46行的clone()调用都不会有问题,与Cloneable无关。仅到了49行后才有影响。
A1或者B2当中至少有一个实现了Cloneable接口,否则会抛异常。
但是必须记住,除Object类以外,clone()仅仅是一个普通的方法而已。他们不会去检查是否实现Cloneable(当然良好的习惯要求我们多谢一句instanceof^^)
如果代码改成这样:
public class clone {
public static void main(String[] args) {
B1 b1 = new B1();
b1.a = 11;
b1.b = 22;
b1.c = 33;
b1.d = 44;
b1.e = 55;
B1 b2 = (B1) b1.clone();
System.out.println(b2.a);
System.out.println(b2.b);
System.out.println(b2.c);
System.out.println(b2.d);
System.out.println(b2.e);
}
}
class B1 extends A1 {
public int d = 4;
public int e = 5;
public Object clone() {
System.out.println("B1's clone() is called");
B1 b1;
b1 = (B1) super.clone();
return b1;
}
}
class A1{
public int a = 0;
public int b = 1;
public int c = 2;
protected Object clone(){
System.out.println("A1's clone() is called");
return new B1();
}
}
输出就会变成:
B1’s clone() is called
A1’s clone() is called
0
1
2
4
5
虽然A1和B1都不是Cloneable的,但不会报错。
我在南大的七年 from Mind Hacks
—— 跨进南大校门的第一天,我知道,我自由了。
父亲是个对新事物有强烈兴趣的人,村里第一台电视机是他自己组装的,当时全村人都跑过去看,电视机只能收到一个台,CCTV。座机电话是第一个装的。大哥大刚出现的时候,他也是第一个买来用的,那个时候的移动电话真是贵得离谱。
父亲告诉我的第二件最重要的事情是:遇到任何问题,找书去就行。他在自己的专业中完全是自学的。在不属于自己的专业中(后来买了电脑之后需要学习如何架设公司网站,如何网上营销,如何进行电子财务管理,如何使用各种作图软件制图等等)也全都是靠买书自学。
为什么说到这两件事情,因为这是对我一生影响最重大的两个习惯。第一个习惯给了我学习新东西的强烈动机,有了热忱和兴趣,做事情就不觉得累,就自得其乐。第二个习惯则给了我学习任何新东西的方法——不会么?查书去。(当然,学习一门专业并不完全通过看书就行,但这毫无疑问是至关重要的一个途径。)
高三的时候,父亲买了电脑,我立时对这个神奇的事物产生了强烈的兴趣,每期的《电脑爱好者》和《电脑报》都会买来细细看,有时看到各种小工具、技巧还会摘抄下来,回去在自己家里的机器上捣鼓。那个时候我并不知道这样单纯的兴趣会把我引向一条专业的程序员道路。
高三时间变得越来越紧,分配给兴趣的时间越来越少,但兴趣的火花一直都没有熄灭。
跨进南大校门的第一天,我知道,我自由了。
这个自由并不是说我可以做任何事情了,而是我得到了一个重要的决策的自由权,即关于如何利用我的时间。
高考的时候我报了计算机系,但分数差了几分,失之交臂,被调到第二志愿专业——信息与计算科学。当时以为这个专业跟计算机相关的,结果发现是数学系,后来听不少同学提到都上了同样的当。
这里出现了一个歪打正着的事情:我本意并不是上数学系,如果当时知道这个专业是数学系,我可能就不会填报了。但正是因为这个错误,我在数学系好歹也受了一些数学基本功的训练(尽管这个训练的基础是大一上的不多的几节数学分析课,以及每次临考前宿舍哥们例行的“包夜”看书),回过头来看这个基本功在后来还是帮了不少的忙,甚至有一阵子我对数学本身到了很感兴趣的程度。不得不说,这段学习的经历是很锻炼抽象和逻辑思维的。另一方面,困难如数学都学了,对其他学科就不觉得难,不会望而却步。
这是我成长过程中的幸运之一。后面还会提到,还有好几次更大的幸运。
大一上学期很快过去,应该是在大一下学期的时候,学校要开一门C++课程。我利用假期先把课本基本啃掉了,当时动机也很简单,先啃掉,就不用上课了嘛。
另一件事情是我经常喜欢去逛书店,看到侯捷的《深入浅出MFC》上面很多人说这本书好,我当时也对C++有一些基础认识和好感,所以就买下来啃了。一方面侯捷先生写的书的确图文并茂,深入浅出,有意思,另一方面理解一样复杂的东西是个智力挑战。所以看着看着倒是觉得兴致盎然。却不知就这么和C++结下了不解之缘。
这是另一个歪打正着:为什么说是“歪打”呢?因为MFC的设计也并不能说就是C++的Best Practice,另一方面若是以用为本的话也未必就要把MFC的原理摸个透。所以搞不好现在看来我就不会细看这本书。为什么说是“正着”呢?因为理解一个费解的东西本身需要长时间投入注意力,无形中练了理解能力和思维体力(专注),另一方面虽然MFC不是最佳设计,但理解里面的代码却加强了对C++本身的认识,这是基本功;也加强了对C++的兴趣,这是动力,后来这个动力驱使了我去看了大量的系统底层知识,从操作系统代码一直看到硬件体系结构。
大二发生了几件重要的事情:一是我在程序员上发表了第一篇技术文章,是剖析Boost源码的。我已经不记得什么时候、通过什么途径知道Boost这个库的了,总之是知道了,然后也是由于受到侯捷先生源码剖析的影响,也去看源代码,发现很难,越是难就越是觉得有趣,跟踪代码到临晨四点居然越看越精神了,后来火速写了一篇源码剖析。发给《程序员》杂志的技术主编孟岩先生,孟岩先生给了很大的鼓励,于是我很来劲。后来一鼓作气分析了N个库,写了一系列的Boost源码剖析的文章,在网上随处可以搜到这个系列。
这是第二个歪打正着,按理来说,研究语言技巧并不是程序员最佳的时间投入方法。所以现在我可能不会去做这件事情,会认为有更好的时间投入途径。但当时就一头扎了进去。为什么说也是正着呢?因为虽然这也许不是最佳的投入时间的办法,但总归比什么都不专注要强得多,至少这么一深入,对语言的缺陷和陷阱有了更深刻的认识、也锻炼了对代码的亲切感、跟踪调试的耐心(是的,耐心,而不是技巧)。
所以后来我在博客上总结自己学习编程中走过的弯路,孟岩先生说到,是不是弯路,不是那么容易界定的。
的确,也许真的有更好的路,但事前真的很难判断哪条路是最优的,我们能做到的,是把一条路走透了、走深了,只要不是一条太不靠谱的路,深入的过程中总会有很多的收获。只要不是太顽固,善于反省,总有一天也会逐渐意识到越来越靠谱的路。
除了发表第一篇技术文章之外,大二我还用业余时间做了一些技术翻译,寒假里我坐在家里每天晚上翻译半章《Effective C++》,当然,后来我把译稿提交给出版社的编辑时被告知文笔还显生硬。
同一时间,我继续啃N多C++以及底层知识的书,一段时间我的书架上全是这类书,根本不像数学系的学生。非典那阵子,把饭钱都拿来买了书,为什么买得这么疯,也是因为受父亲的一个影响,他告诉我买书不用心疼,因为是长远投资,收益远远大于这点金钱投入。那段时间我边看边写一些代码玩,有模仿Windows核心编程的小程序,也有尝试并失败的小游戏,也有拿来对宿舍玩的游戏文件分析的工具,还有为上机考试写的库,总之玩得不亦乐乎;不像很多知名的程序员在学校里面就写了被广为使用的工具,那个时候我完全没有这个意识,也不知道什么是开源,自己自娱自乐而已,所以没有系统训练编码量和编码素养,比较盲目。
大二下半年还发生了一件重要的事情,我在CSDN上开了一个博客,开始写学习C++和编程的过程中的一些总结。这个博客我一直写到今天,伴随了我整个7年的学习和成长,回过头去看就像时光机一样,能够看到一路过来我都关注了些什么东西,是怎么想的,以及对一些事情的看法是怎么改变的。这些东西如果不记录下来,就会逐渐忘掉,也就无法参照过去的自己,对未来提供更好的借鉴了。所以我一直把记录当做一个很重要的工具。另外我也通过这个博客认识了很多朋友,得到了很多的帮助。
后来,学校提供了转系到软件学院的机会,我立即报名了。后来的两年在软件学院度过。但其实反正我也是自己安排时间,所以无甚区别。
大三大四发生了几件重要的事情:一是荣耀先生邀我合译《Imperfect C++》,我很乐意的接了下来,可没想到这本书比我想象得要密度大得多,六百页,而且排版也很密,我给自己安排了每天6、7页纸的量,大概花了半年多译完。中间有一段时间停滞,荣耀先生给我鼓劲,告诉我一个重要的方法:如果觉得做不下去了,就硬着头皮坚持做,然后就类似于麻木了,适应了,那种望而却步的感觉会逐渐自动退去。惊人的简单,但事实就是如此,硬着头皮,过了那个情绪上最艰难的时候,也就适应了。这本书译完之后,还是有不少的收获,但我总觉得对性格上的磨练才是最有价值的收获。
二是我开始看英文版的书。之前,由于高中不靠谱的英语教育的原因,我恨死了英语,大二的校内四级课程还挂了科,直到大四才补考。但对技术本身的热爱压过了对英语的反感,我还是硬把一整本影印版啃下来了,而且津津有味,这本书就是Jeffrey Richter的《Applied .NET Framework Programming》。这个事情的重要性在于,后来我就不再反感和恐惧英语了,这是其一,其二是我开始意识到英文世界的技术资料有多么丰富,所以虽然本身看上去不是一个太起眼的事件,但却是我获取信息方式的一个Tipping Point,一旦熟练掌握了语言这个平台,背后就是一扇大门,通向一个海量的信息源,后来我的信息获取绝大多数便来自于英文,其中尤数wikipedia和英文版的书为多。另外还有一个收益后面会提到。
大四快毕业的时候又发生了一件事情,微软的Eric Jiang通过我的博客找到我,推荐我去微软面试,我随随便便就把粗糙的简历给发过去了,差点因为简历太粗糙被HR直接过滤掉。远程电话面了两轮,远程Coding一轮,然后记得就是飞到北京面试,住在北航招待所。北京的面试又面了好几轮,有考察底层知识的、有考察C/C++的、.Net的,还有考察算法的,编码素养的。总之就是公认的基本功考察。最终我还是没能通过面试。个人自己后来总结的结论是算法基本功太差,连什么是动态规划都不知道,编码素养也不够。这部分也是因为本科的学习方法太业余,什么好玩干什么,倒不是说兴趣驱动不好,只是缺乏系统的规划,不清楚也不关心这个领域的蓝图,也弄不清什么是重点。后来在读研的时候恶补了一把算法,好歹弄清了一些基本的概念和思考方法。编码素养的问题也是到了读研的时候才开始思考和学习,现在仍在学习。
另外,在本科阶段,其实我也浪费了很多时间,事实上,是只花了很小一部分时间来学习。之所以还多少学了点东西,完全是仰赖了专注的习惯。而这个专注的习惯其实又是从小受父亲耳濡目染的,父亲会花一整天揣摩一个问题,父亲跟我说过他以前组装电视机时的故事——一切都似乎组装正确,但电视机就是不工作。他苦思冥想,不得其解,当晚,半夜从睡梦中醒来,想到了问题的症结所在。所以,我在啃一些底层知识时如果弄不懂,也会一遍遍读,然后用走路吃饭坐车的时间在脑子里一遍遍去琢磨。我有很多重要的习惯受到父亲的影响,这些习惯自己一般觉察不到,但却默默影响了平时的一点一滴的时间分配和学习轨迹,这些习惯从纸上很难学到,但耳濡目染却会自然而然地学会。
每当有人觉得我本科就做了不少事情的时候,我就会说其实我本科真的浪费了很多时间,而另一方面,这也说明,要掌握一门专业知识,其实每天一点时间,专注、积累和持之以恒也就够了。后来研究生阶段才算真正开始惜时了,于是经历了两年密度很高的学习和思考,心智才成熟了不少。
大四的时候,和很多人一样,我也考研,因为一来也很茫然,二来也希望能够继续有一个宽松的环境继续沉浸在自己的兴趣中。但四年来我都是自己安排时间,逃掉了无数的课,已经对模式化的做题考试产生了抵触,所以考研的复习也没怎么认真准备,那年考研的数学题又偏难,一下慌了神,结果居然把一整页题压在稿纸下忘了做了,心理准备有多不充分可见一斑。考完数学我很沮丧,那么大分值的题目没做,数学肯定过不了了,接下来的专业课就没去考了。后来想想其实还是应该去考一考,多少能为下一年积攒经验。
后来就工作了,没去成微软,经同学张振推荐,就去了南京西门子。心里的打算还是边工作边考研,为什么考研,动机也简单,我心理还没准备好,本科只顾着埋头学好玩的,也不看路,不知道自己想要什么样的工作,想做什么样的事情。去西门子之后更加觉得如此,觉得效率很低,做的事情也并不是我乐意的,每天还要在班车上浪费两个小时,于是没过多久就辞掉了工作。打算复习考研。那个时候大概还有半年多的时间才到考研,所以我中途不紧不慢地又翻译了《Exceptional C++ Style》,占用了不少时间,到最后时间很紧了,就剩两三个月,我才开始认起真来,回想起来这是糟糕的时间管理。结果我不得不作了最坏的打算:顶多调剂去软件学院读研(我报的是计算机系),考虑到我反正是自己安排时间,差别应该不大。幸运的是,最终一分不差地过了线,算是蹭到了计算机系里。虽然如此,还是觉得这种惊险不要发生的好,以后或者其他事情上就不会有这么幸运了,及早准备总是很重要的。
读研期间的两年半,是我自己觉得心智年龄成长最迅速的一段时间。这里也有几个很幸运的事情。一个事情是我的导师陈家骏先生给了我很大的自主,于是我得以有时间安排一些重要的学习,这段时间对我来说很重要,我学习和思考了很多东西,为个人以后的发展作了很多准备,倒是没帮导师做什么事情。所以,硕士毕业离开的时候是既感激也愧疚。
另一个事情是认识同实验室的师兄陈怀兴,严格来说是他先来找我聊天,可见那个时候我仍然还是没有意识到与人交流的重要性的,后来,建立了TopLanguage讨论组之后越发意识到与他人交流的重要性,也开始主动寻找和参与交流,希望以后自己也能组织交流。陈怀兴对算法很有造诣,也是TopCoder上的常客和牛人,那个时候我也正在为以后的工作面试准备一些算法基础,所以经常找他讨论,获益很多。有一句话说:看一个人,只要看他读的书和见的人。还是很有道理的,这两者是一个人成长中最有价值的信息来源。
研一下半年,女朋友找工作的时候需要用到营销方面的知识,于是我去替她找书,偶遇《影响力》这本书,这本书打开了我的视野,让我开始关注一个很有价值的领域:我们如何思考,如何正确地思考。这个领域有很多有意思和有价值的书,我利用近一年的时间,陆陆续续看了近40本相关的书(我把这些书整理了之后以豆列的形式放在豆瓣上),对思维的特点和缺陷,以及如何思考有了很多的了解,这些知识后来很大程度上使我更清晰地认识自己,和自己在学习和生活中面临的各种问题。
也是研一下半年,我建立了一个Google Groups,起名TopLanguage,一开始的时候是因为平常没人讨论问题,憋得难受,希望有人能够说两句,无心插柳柳成荫,后来这个讨论组的交流越来越多,如今已经近两年,组内成员超过了4,000人,两年里我也从中收益颇多,其中最大的收益有两个:一是和人讨论能够激发自己进一步的思考,也促使自己更清晰地表述自己的观点或问题。倒不是说别人就一定告诉你什么新东西,而是讨论对你自己的思维的刺激。二是交流中认识了不少朋友,后来快毕业的时候也受帮助颇多。我一直把TopLanguage的创建看作研究生阶段做得最有意义的事情之一。
此外,我有意识地提前准备了英语,因为我相信如果想要去好的外企,口语不过关很可能成为一块短板(当然,英语作为承载最多技术知识的平台语言还有更大的价值),包括阅读、书写和口语。我想了一个方案,可以不用额外花时间来学习英语:阅读的训练蕴含在平时的英文技术资料的阅读中,尽量读英文的,一来英文资料更一手和全面,二来也顺便练阅读。书写的训练蕴含在去国外邮件列表发技术贴和自己写的英文博客文章中。口语的训练则蕴含在平时的娱乐中——美剧,有一个暑假我几乎天天开着Friends睡觉,另外学校有国外过来的团队演讲我不再错过,而是主动参加,有一次还带他们出去逛南京,说了一天英语,回头在路上听中文都像英文。虽然和外国友人交流的次数不多,但似乎对口语感觉的提高还挺大。后来在微软亚洲研究院的面试最后一轮就是英语的,而且是偏技术的,好在提前准备了,所以毕竟还是顺利地表达出了想表达的意思。
去微软亚洲研究院面试,是因为幸运地认识了微软亚洲研究院技术创新组项目主管邹欣先生。邹欣先生和他组织的团队在那段时间写了《编程之美》,书中有很多很有意思的题目,而我那段时间恰和陈怀兴讨论算法,在讨论组上也组织了专题的讨论,有了一点粗浅的思考,于是和邹欣先生邮件交流,由于对邹欣先生的技术创新组做的事情很有兴趣,所以找工作的时候便向他毛遂自荐。
承蒙邹欣先生推荐,时隔三年,我再次获得了去微软面试的机会。这一次,由于研究生期间作了一些长远准备,所以心里有底了很多,也就比较冷静了,由于当年知识体系的漏洞被我花功夫补了补,所以面试比较顺利。面试的时候邹欣先生更为详细地介绍了技术创新组的工作,我更加感兴趣了,所以尽管已经有另外几个也不错的选择,但心里还是迅速地做了决定。大约一周后,HR通知Offer,我毫不犹豫就接受了。
我想,虽然有很多人本科就明白自己想做什么,我多花了两年多,总还不算太晚。
java字符串体会1
JAVA中字符串是不可改变的,(final char[]),这样编译器可以安排共享的字符串。如果拷贝一个字符串变量,两个串将共享相同的字符。
编译器和JVM一般会根据代码的实际情况来安排共享存储。
import java.util.Scanner;
public class stringisfinal {
static String stStr = "hello";
public static void main(String[] args){
String a = "hello";
String b = "hello";
String c = a;
String d = aStaticString();
String e = aInputString();
System.out.println(a == b);//true
System.out.println(a == "hello");//true
System.out.println(a == c);//true
System.out.println(c == b);//true
System.out.println(a == d);//true
System.out.println(a == e);//false
System.out.println(a == stStr);//true
System.out.println(a.substring(0, 4) == "hell");//false
System.out.println(a.substring(0, 5) == "hello");//true
}
public static String aStaticString(){
return "hello";
}
public static String aInputString(){
Scanner cin = new Scanner(System.in);
return cin.next();
}
}
可见,对于编译时能够确定的串(a,b,c,d,stStr,”hello”),而它们的值又是一样的,JVM把它们放在同一个位置来共享;
对于aInputString()返回的e,由于不确定,所以是临时创建的对象。
对于最后两个,可以先看看String的substring()方法的定义
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
对于a.substring(0,4)虽然也是编译时在这个程序中是确定的,要求编译器编译时知道a.substring(0,4)的内容就是”hell”是要求过高了,而且也许不放在一起可能有更灵活的目的(我学得比较浅,就请读者指教了。)
而a.substring(0,5),由
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex – beginIndex, value);
可以看出,子串长度刚好是原串本身的长度时,返回的是this,所以就不难解释前一个比较是false而这个是true了。
