#4 楼 @HungYuHei 可靠,但是忘了主密码会死得很惨——现在好写了,有 iCloud——只要你信它。
OK,我先说第一个问题:需求是否合理不过问,无条件实现。
在这个问题下,测试能帮助我们什么呢,比如说覆盖方法或模块的边界条件就是很好的例子。假如说你不写测试,在需求未变的情况下出了 bug,排查再修改的时间会更“浪费”。但如果有之前的测试做底子,你只需要用测试重现 bug,然后再重构就好了,目的性和指向性极强。
至于说需求变更导致测试和代码都要重写,这个我只能说很遗憾,测试原本就是为了忠实于需求的,需求本身都变了,测试能不变吗?你觉得因此而多写了代码(测试)很累,这是可以理解的,不过为了以后着想,以及为了团队所有成员的协作着想,这是值得的。
最后,如果需求总是变来变去,请不要责怪测试,因为这是你们团队整体的问题,或者是和其他利益相关方的沟通问题。
第二,需求会涉及多个模块,要改都得该。
这……是测试的错吗?或许你们应该从设计角度来考虑一下现在的代码实现,看看耦合度是不是太高了?或者类和模块的抽象度和通用度不够/可以改进?
大体上你可以有两种“武器”来解决依赖性问题的测试,一种是验收测试(有时候可以在一些情况下和集成测试互换概念,但这样并不好,所以 RSpec 和 Capybara 才会单独分离出 Features Spec),它不太关注系统模块中的耦合情况,而是从输入/输出的角度来做一个黑盒测试;比如说,从用户在界面上的操作开始,到用户看到的视觉反馈结束,隐藏中间的系统实现过程。
还有一种就是单元测试了,单元测试则完全不应该受系统模块的耦合约束,需要相互依赖调用的可以使用 stubbing / mocking。
所以说,就算你无法改变高耦合这样的项目现状,你也完全可以采取不同的测试策略来减少耦合带来的修改联动性;注意,不是说实现代码不用改,而是把测试分离开避免修改的联动性导致测试被连带修改。这样一来,被联动的代码只要其对应的业务逻辑(需求)没变,测试就不需要大改特改。
然而说到底,我还是觉得这是代码设计层面不够好,好的设计不应该总是“牵一发而动全身”,除非需求变化的太频繁,太剧烈——还是回到最初,这不是测试的问题,而是团队本身或沟通的问题。
最后,“Typing is not the bottlebeck”,不要误解“因为写了测试,所以我要多打/多改一倍的代码,浪费时间”,这种想法根本上就是带有偏见的,狭隘的。
===回答你最后一句话===
越是时间紧急,越要写测试,特别是创业项目——人无远虑,必有近忧!
如果你的 TM 一直在备份,那就可以恢复的一模一样,但前提是你保存密钥的路径没有从 TM 里排除掉。
另外 TM 备份的文件实际上是可以浏览的,找个能用的电脑打开 TM 盘进去看看就知道了。
我觉着吧,这讨论越来越复杂化了,完全违背了主楼转载文章的精神嘛……
这是两种不同的回复结构组织形式,你给出的是一个个人的博客,对于回复的信息往来它关注的两两之间的交互过程,特别是博主和他人之间的交互过程,因此用了那种嵌套式的组织形式。在这种形式下,所有的回复信息的时间顺序是可以交错的,打乱的,因为关注的维度不是以时间线为主。
在 Ruby-China 这样的论坛则不然,回复都是众发的,对于信息的组织关注重点不是两两之间(对于两两之间的回复,会在回复的顶部明示,或者用 @ 来提醒)。对于所有查看这些信息的人,严格的按照时间顺序排列回复而不要打乱交错会有助于用户完整的了解所有参与者的交互过程,不至于发生理解混乱——这是因为除了楼主之外,并没有一位“主角”存在。当然了,如果可以在每一个帖子里突出显示楼主的回复会得到更加好的体验,但是打乱顺序并潜逃的方式未必真的合适。
至于加线框,老实说:真心丑,若想在视觉上突出个体差异,这种设计算勉强及格吧。
iPad 看书很累。手累。躺床上看容易砸着自己……
没错,Gary Bernhardt 是我最喜欢的选手……俺喜欢用选手这个词 >.<
#3 楼 @Levan 我有个个人的建议,自己做的第一个项目就冲着失败去,不要试图第一次就追求完美,否则你的第一次永远都写不完。至于你想问的原则,我要说的确有,但是不一定适合你(这个也不是绝对的,也许以后水平高了又会觉得适合了)。等你完整的写了一个应用之后,适合你的原则自然而然就成型了,而且你还会很清楚的知道该朝哪个方向进一步改善。
比如说 "outside in BDD" 就是普遍推荐的开发原则,但是对于一个从未完整做出过应用的初学者来说,没有人指导真的很难做到严谨的 "outside in",我觉得 ok 啊,遵循不了那是能力问题,先跳过一下下也不是不可接受的。如果你真的认同这些原则,那就尽可能去做,做不了就跳过。
“完美主义”是“事物发展初期”的大敌,因为完美主义者通常都比较“娇气”,而做事情在初始阶段总是充满了“陷阱”,完美主义经常会陷入到自我的挣扎中去而无法自拔。所以我的建议是在这个阶段忘掉追求完美的浪漫情怀,把自己武装成”泥腿子“去斗争吧,顺利的存活过这个阶段,一切就会逐渐明朗起来。
哦,至于你主楼的问题,我认为从哪里开始都可以,这不是问题。如果你的目标是做一个有用的,好用的应用,那么重要的不是从哪里开始(从哪里开始都不会影响最终的结果),而是你把这件事真的想清楚了,理解透彻了。
===补充===
因为我猜楼主是用 Rails 写应用程序的,所以忍不住再说几句。
我认为 Rails 真正的魅力在于:快速实现想法,灵活应对变化。对于你的项目来说,Rails 很可能不是最适合的开发框架,也很有可能不是最终(完全)采用的开发框架——如果你的应用能顺利的渡过快速增长期的话。所以在开始阶段去精雕细琢是得不偿失的。
Rails 本身为我们提供了很多拿来就用的工具和机制,尽管你时常听别人说“Rails 自带的 xxx 不好,xxx Gem 比他更好……”,或者“Rails 的 M/V/C 不够 xxx,应该这样 xxx...”等等,我想说的是, 他们讲的没有错,但是对你来说不重要。 你还没完整的把想法实现呢,在乎那些“增强/优化/最佳方法论”有何意义?
快速实现想法,灵活应对变化——这才是 Rails 的核心价值,什么性能劣势,功能缺陷都没有关系,你有足够的时间和工具去解决它们,前提是你得有能用来解决的平台,即——你的产品!否则一切都是纸上谈兵。
那些告诉你 Rails 哪里哪里不好,什么什么更好的人,他们的观点来源于自身的经验,他们渡过了产品的诞生和初期发展阶段,摸爬滚打之后总结了这些东西,但是并不适合你啊!你和他们最大的差别就是,你连枪都没开过,就已经琢磨他们怎么在战场上枪枪爆头了……
还是那句话:快速实现想法,灵活应对变化。这是 Ruby 和 Rails 带给你的最宝贵的财富。
#7 楼 @blacktulip 可是你只需要学习一次,受用却是无限的。
向原数组内未相连的部分插入分隔符(比如 nil)也可以这样做:
# Suppose an array given like this
array = [1,2,3,5,6,8,9]
# Then put an delimiter
result = Range.new(array.first, array.last).map do |element|
array.include?(element) ? element : nil
end
在之后对于 result 的处理,如果没有 ActiveSupport 的扩展,那就只好手动去 chunk 了吧。
#16 楼 @guyanbiao 截图里的字体?Source Code Pro
我来锦上添花好了,放个给极度懒人用的大招:
autocmd InsertEnter * setlocal paste
autocmd InsertLeave * setlocal nopaste
这个的效果呢,就是当你进入 Insert
模式的时候自动开启 paste
,此时你从外面复制粘贴进来的东西就会保持原有队形了。之后你回到 Normal
模式的时候,Vim 会自动关闭 paste
。
这个比较适合不喜欢按快捷键的纯粹懒人,不过请小心,一直处于 paste
开启的状态下虽然不影响基本的功能,但是可能会影响其他的插件正常工作哦!
最好的办法还是使用键位映射在你需要粘贴的时候手动开启 paste
,不过可以保留离开时自动 nopaste
的功能,省点事儿,因为有时候你开启 paste
复制完,然后退出 Insert
时忘记了 nopaste
,那么下次再进入 Insert
的时候还是 paste
的。
不过实际使用中最好把 autocmd
的命令用一个自定义的 augroup
包起来,并在最开始用 autocmd!
重置一下,以避免重复修改 .vimrc
造成的 autocmd
重载多次。
具体的作法我放个图:
截图里还给了一个有用的设置,让从 Insert
模式下离开的时候没有延迟,Vim 默认的设置会有点迟钝的感觉。
key 重复了
你说你看着看着就被新东西卡住了……读源码本来就是这样的啊,如果从头到尾都没什么东西能卡住你,那也就不用看了。