[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"list-\u002Farticles\u002Ftech\u002F3":3},{"items":4,"total":121},[5,20,27,37,46,56,66,76,84,92,101,111],{"id":6,"type":7,"slug":8,"title":9,"date":10,"category":11,"tags":12,"body_markdown":14,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},120,"article","what-about-mini-program","【问答】小程序上线后市场反应如何","2017-01-19 09:04","tech",[13],"小程序","\n来自知乎问题[小程序上线后市场反应如何](https:\u002F\u002Fwww.zhihu.com\u002Fquestion\u002F54884655\u002Fanswer\u002F141701284)\n\n尘归尘，土归土。正在回归正常。\n\n小程序一直在强调自己线下场景的定位，奈何开发者、媒体总是不信邪，非要赌小程序会有流量红利，会给自己带来线上流量。甚至在微信明确说微信中没有入口，没有应用商店之后，仍然有一大波人围着不愿散去。\n\n现在打脸了吧。线上流量红利真的一点没给。于是这波围观的人一哄而散，甚至还会留下一堆唱衰的评价，“你看，我就说这玩意没鸟用吧”，殊不知，正是自己的期望过高导致现在的巨大落差。\n\n回归到小程序自己的定位来说，其实非常明确，就是线下场景。具体的微信公开课Pro上已经详细阐述过，这里就不复制了，有兴趣的自己找。\n\n\u003C!-- more -->\n\n而线下场景的铺开，是需要一个漫长的过程的，所以现在看起来很冷。这其实应该是微信预料中的事情，甚至可以说是微信刻意安排的，微信不希望小程序变成纯线上产品，因此只能顶过第一波舆论洪峰，挡掉大家对线上流量的期待，接下来踏实地推动线下场景，最终让小程序变成“一个生活方式”。\n\n\n我个人比较看好这件事情，拭目以待。\n\n## 评论的回应\n\n### 小程序竞争不过APP\n\n别老站在开发者的立场看问题嘛。站在用户的立场来看，当你在某个店里想要看看店里的服务，你愿意去下载一个app吗？还是选择用微信扫描一下就能立马获得高质量的服务产品？开发者是跟随产品走的，产品是跟随用户走的，用户在哪动力就在哪。\n\n### 小程序和web相比没有本质区别\n\n网页慢，加载慢，运行也慢，另外能力也比较受限。张小龙亲口说，小程序比web的优势就是体验好很多很多。\n\n我就是做web前端开发的……你自己试试写写小程序，再写写web，体验真的不一样。开发起来小程序恶心死，但是用起来小程序真的秒杀web。当然，不排除有很少量的做得确实很好的web，但是这个量太少太少了，而且往往最后还是由网速来决定到底好不好用。小程序通过框架直接拉高了最低标准，写得再烂的小程序用起来也不会烂到哪去，而且加载全部是从微信的服务器（甚至有可能是私有协议不是HTTP，猜测），比较好地保证了体验的平均水准。\n\n具体为什么快可以有很多分析，比如从微信的CDN是不是比你自己的服务器加载快？打包的资源是不是比一个个css\u002Fjs加载快？私有协议是不是比HTTP快？native的canvas是不是比web的快？jscore是不是比webview的js引擎快？数据驱动ui更新是不是比手动更新DOM快？因为实现方式上有巨大的差距，这样去猜到底是哪里快了意义不大。就算如你所说，只是预加载让它显得快，那用起来比web畅快也是事实，用户并不关心你是怎么快起来的。\n\n对不起，我的立场是站在用户这边的，并没有要证明小程序比web先进的意见，你可能误会我了。我也是web开发者，我当然知道web能做的事情很多，我当然知道有顶尖的开发者和顶尖的作品，但是从我扫过的后在微信中打开的页面来看，基本上都是乱七八糟。\n\n### 线下不需要小程序\n\n问：我想知道店里的服务直接问服务员不就好了么?\n\n答：线下不等于商店。ktv 演唱会 桌游 客运站 候机室 自助店 饭店 麦当劳……都是线下。\n\n问：在火车站本来随处可见最新时刻表，点餐加菜直接叫服务员比用手机方便，叫DJ房间有按钮，演唱会门票加印曲目信息比额外开发小程序成本低，投票互动这个属线上场景，不是线下场景。\n\n如果只是线下场景才能用，小程序定位太尴尬了，和公众号功能重合，小程序可以做的，公众号都可以做到，要小商家再次投入成本重新开发个和公众号功能差不多的东西，谁会去做。\n\n张小龙如果实现让公众号不用修改直接转换为小程序，或者简化小程序开发，或许会有人用。\n\n答：是的。火车站随处可见时刻表，但还是有人用手机查对吗？还是有人用12306买票对吗？叫服务员是方便，但还是有人喜欢用手机慢慢点菜是吗？叫DJ是方便，但总得点歌是吗？演唱会门票印东西是方便，但黑得啥都看不见的时候还是有人喜欢在手机上看节目单是吗？\n\n并不是线下手段已经用不了了，小程序来拯救世界的。微信支付普及前去商店不是也可以付现刷卡吗？\n\n大规模的社会变革从来不是断崖式的，而是渐进式的，一开始都会有无数人怀疑，现在不是挺好的吗，你们干嘛要瞎折腾。\n\n问：对于火车站，已经有独立全功能的12306app，再开发一个小程序对火车站有什么好处，对于用户，我手机直接打开12306，除了查时刻还能订票改签，用功能阉割微信小程序的意义在哪里？\n\n我没有否定手机应用在逐渐改变生活的趋势，只是觉得小程序在现阶段只是个失败的尝试。\n\n现阶段小程序的所有线下应用场景，公众号都能实现，商家在已经有公众号的情况下不会额外投资转用小程序。\n\n现在小程序都开放一个月了，到底有几个用户在用小程序了，原来是怎么用手机还是怎么用，线下没有入口，线上全面被app碾压，所以张小龙才被迫开放线上模糊查询。\n\n如果腾讯真的有魄力利用小程序在安卓版微信做一个应用市场，放开应用程序大小的限制，在国内管住流氓行为，那才是革命性的改变，微信甚至可能影响iOS的份额，成为系统级的存在，可惜腾讯现在还在打擦边球，所以半死不活。\n\n问：我觉得你有必要去看下微信公开课pro的场景分析，不想再一遍一遍重复了。另外也不想讨论，已经有xxx，所以xxx是否必要的问题了。另外你也不要臆断有几个用户在用，前几天了解到百万级用户量小程序已经不是一个两个了。还有其他问题吗？\n",null,0,"2026-08-28 04:37:17","published","",{"id":21,"type":7,"slug":22,"title":23,"date":24,"category":11,"tags":25,"body_markdown":26,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},121,"why-mini-program-use-self-developed-tech-stack","【问答】为什么小程序自己做了一套开发体系","2017-01-13 13:37",[13],"\n来自知乎问题[微信小程序为什么不用HTML5、CSS，自己搞了个WXML、WXSS，很多框架用不了，好处一点不知道？](https:\u002F\u002Fwww.zhihu.com\u002Fquestion\u002F51809406\u002Fanswer\u002F140747129)\n\n## 引子\n\n假设我们把问题稍微改一下哈：\n\n> iOS应用为什么不用HTML5、CSS，自己搞了个OC \u002F swift \u002F autolayout \u002F storyboard，很多框架用不了，好处一点不知道，以前项目根本没法移植，而且我们习惯的jquery、auicss、图标等完全用不了，也没见OC \u002F swift \u002F autolayout \u002F storyboard有什么好处，完全理解不了。。。\n\n嗯。我只是改一下题目，不回答。可自行思考。\n\n## 用web做小程序的可能性和限制\n\n为什么没有人问上面改过的问题，而小程序就有人问呢？只是因为小程序和web长得很像，所以就觉得要用web来做吗？那长得像的话是不是就能直接用web做呢？\n\n答案是，大部分是可以的。比如文本、图片、输入框等等，都可以。\n\n但是，也有一部分小程序的功能是web完全不具备的，例如扫码、获取设备信息、获取罗盘信息、等等。\n\n此外，还有一小部分是web做起来很困难的。比如上面有人提到的地图、fixed的文本输入、视频相关、sticky定位等。\n\n除了能力上的限制以外，还有相当一部分是来自于性能上的限制，也即虽然很多东西用web确实可以做，但是性能是很差的。\n\n\u003C!-- more -->\n\n## 打补丁可以吗？\n\n如上面提到的一些能力缺失（以及半缺失），如果使用web的话，是不是打补丁也可以解决呢？答案是肯定的。\n\n但转念一想，如果要靠打补丁的方式去做，那为什么还要选择使用web呢？如果你深入使用过微信公众号的JS SDK就会发现，其实大部分你需要认真用JS SDK的时候（只做分享信息设置的不算），这个页面就已经没法在其它环境中复用了。也就是说，不管怎样，你已经是为微信专门写了一套代码。\n\n## 抛弃标准\n\n（这是一段政治不正确的文字）\n\n对微信来说，如果使用web来做小程序，就意味着要照顾庞大的web标准体系。虽然对大部分的前端工程师来说，使用到的web能力并不是太多，但对浏览器来说，web标准是一套非常繁杂非常闹心的东西，要支持一套完整的web标准体系并不是一件容易的事情。\n\n当然，你可以说腾讯不是有X5了吗？那好，我们抛开实现上的复杂不说，只说支持web标准和小程序的关系。\n\n如果要在web标准的基础上来做，那么打补丁这件事情会变得不愉快。\n\n例如fixed的输入框这件事情，假设客户端可以自行改变容器的高度和定位，在focus的时候做一些hack处理，那么大部分情况下体验是不错的。但是因为web标准在这里，你就不能随意更改一个元素的定位和尺寸。\n\n再比如视频，X5中为了用(shang)户(ye)体(li)验(yi)，重写了视频元素的行为，默认情况下全屏播放，且非全屏的情况下也只能是页面最高层元素，无法被别的元素覆盖。对于看视频、看电视剧、看电影的人来说，这本来是一个不错的用户体验，但是这一棒子却将用视频做页面效果、做直播（边看边聊）的人打死了，导致X5的这一行为至今被骂到死。\n\n这样的例子非常多，如果你既要完整照顾web标准，同时还要在用户体验、性能上做优化，还要在此基础上打补丁，将是一件几乎不可能完成的事情。即使能费九牛二虎之力做得七七八八，也可能随时面临用户的投诉：“为什么这个行为和浏览器不一样？”\n\n而反观小程序的现状，在完全不管web标准之后，想不支持CSS级联就可以不支持，想改canvas API就能改，想增加wx.showToast()就能直接加。\n\n甚至在加载方面也完全不用考虑web的事，一股脑扔给微信，像app一样整体下载就可以了。\n\n这对产品和开发团队来说完全是甩开膀子随便干的节奏。因此对小程序的产品和开发团队来说，放弃使用web来做是一件性价比非常高的事情。\n\n## 重塑开发规则\n\n因为没有了web标准的束缚，小程序团队可以从头制定开发规则，从而在源头上对质量进行一定的把控。\n\n例如小程序可以强硬地要求，fixed的textarea必须添加一个特殊的class，这样小程序就能自己去解决这一场景下的技术难题，而不用绕很远的路去做各种兼容。\n\n例如小程序可以要求textarea不可以出现在scroll-view中，从而避免一些技术难题。\n\n此外，小程序还可以从框架上强制地要求必须不能动态操作页面元素。至于理由是什么，可能和运营规则有关。\n\n总而言之，因为有了一个全新的开发体系，微信相当于直接伴演了上帝的角色，以前web开发中碰到的任何问题都可以有N多方法马上解决。\n\n## 重塑运营规则\n\n上面都是作为技术人员的一些废话。小程序之所有不选用web，个人认为最重要的原因是要重塑运营规则。\n\n众所周知，web以开放互联著称，这意味着任何人可以在web上发布任何程序，并且每一个web都可以和其他web应用互相跳转。此外，web页面的内容是可以随时通过后端或者前端进行控制从而动态显示的。当然，web因为这么多年的发展，标准庞大，能力众多，实在是不能胜举。\n\n这些能力固然是非常棒的，也是web开发人员引以为豪的地方。但是对小程序来说，却未必是一件好事。\n\n看看当前公众号的现状即可知道：刷流量、跳广告、伪造各种页面、发布违规页面等行为屡禁不止。这正是微信最不爽的地方。\n\n因此，小程序的目标很明确，就是重塑一个微信规则下的web。这里的web只能提供服务，不能营销，不能引流，不能动态改内容逃避打击，不能跳转，不能违规。所以的事情只能按白名单能力（小程序开发文档）来做，白名单没有的，想都别想。而且即使白名单中有东西被坏人利用了，还有一道人工审核来进行把关。不按规则来的，对不起，全部打死。\n\n对营销狗（网上取的词，无贬义）来说，小程序毫无用处，因为它几乎将营销的口子全部堵死了。而对用户来说，这才真正是该有的体验。\n\n所以，个人以为，这才是小程序要重建一套开发体系最重大的意义。\n",{"id":28,"type":7,"slug":29,"title":30,"date":31,"category":11,"tags":32,"body_markdown":34,"permalink":35,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":36},119,"git_revert_merge","[译]Git回滚合并","2015-05-26 12:50",[33],"Git","\n如果工作流严重依赖分支合并的话，也难免会碰到需要回滚合并的情况。而且回滚还分为两种情况：永久回滚，或者回滚后在稍后重新合并。\n\n假设有如下分支图：\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge1.png)\n\n> 注：Git分支图中的箭头表示依赖关系，并不是分支发展路线。发展路线和箭头是相反的。也就是图中是从C1开始一直发展到C12的。\n\n假设要回滚C10。\n\n第一种解决方案是将`master`回退到C8，然后将两个特性分支`jk\u002Fpost-checkout`和`db\u002Fpush-cleanup`合并过来。\n\n```sh\ngit checkout master\ngit reset --hard [sha_of_C8]\ngit merge jk\u002Fpost-checkout\ngit merge db\u002Fpush-cleanup\n```\n\n完成之后，分支图如下：\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge2.png)\n\n接下来就可以继续在新的`master`上工作，然后在适当的时候将`tv\u002Frebase-stat`合并回来。\n\n\u003C!-- more -->\n\n## 回滚合并\n\n如果在很久之后才发现要回滚，或者其它人已经在合并之后提交了代码，分支图会是这样：\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge3.png)\n\n这种情况下要么回退一次合并，要么退回去，再重新合并，然后将新的变更（C9和C10）cherry-pick过来。后者容易让人迷惑，做起来也不容易，尤其是在合并之后提交很多的情况下。\n\n`git revert`能很好地处理合并的回退。你需要指定需要回退的那次合并提交记录，并指定保留合并中的哪一条线（parent）。假设我们需要回退合并`jk\u002Fpost-checkout`的记录，则这样做：\n\n```sh\ngit revert -m 1 [sha_of_C8]\nFinished one revert.\n[master 88edd6d] Revert \"Merge branch 'jk\u002Fpost-checkout'\"\n 1 files changed, 0 insertions(+), 2 deletions(-)\n```\n\n完成后会产生一个新提交，这个提交回滚了合并过来的内容。其结果和一个包含被合并过来分支改动的cherry-pick（反向操作，即回滚）差不多。\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge4.png)\n\n## 回滚“回滚”\n\n假设在回滚之后，我们需要再次合并这个分支。如果你直接合并的话，什么都不会发生。\n\n```sh\ngit merge jk\u002Fpost-checkout\nAlready up-to-date.\n```\n\n更令人困惑的是，如果你回到分支，再做一些修改后再合并，则只有新产生的修改会被合并过来。\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge5.png)\n\n这种状态是一种非常奇怪的状态，有可能导致冲突或者难以理解的错误。此时你真正想做的事情应该是回滚“上一次对合并的回滚操作”。\n\n```sh\ngit revert 88edd6d\nFinished one revert.\n[master 268e243] Revert \"Revert \"Merge branch 'jk\u002Fpost-checkout'\"\"\n 1 files changed, 2 insertions(+), 0 deletions(-)\n```\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge6.png)\n\n现在我们将分支恢复到了合并之后的情况，如果分支上有新的改动，就可以直接合并了。\n\n```sh\ngit merge jk\u002Fpost-checkout\nAuto-merging test.txt\nMerge made by recursive.\n test.txt |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n ```\n\n![分支图](\u002Fassets\u002Fgit_revert_merge\u002Funmerge7.png)\n\n最后，建议使用`git merge --no-ff`合并分支，这样可以保持 分支不是快进的，使它可以回滚。\n\n> 原文地址\u003Chttps:\u002F\u002Fgit-scm.com\u002Fblog\u002F2010\u002F03\u002F02\u002Fundoing-merges.html>，本文并未逐字逐句翻译，仅根据理解摘录了重要部分。\n","\u002Farticle\u002Fgit_revert_merge.html","https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Fgit_revert_merge\u002Funmerge1.png",{"id":38,"type":7,"slug":39,"title":40,"date":41,"category":11,"tags":42,"body_markdown":44,"permalink":45,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},118,"git_and_gitflow","团队使用Git和Git-Flow手记","2015-05-11 14:23",[33,43],"Git-Flow","\n去年10月份，在我们被产品节奏逼到墙角无路可走的时候，我们在几乎没有准备的情况下，在团队中引入了Git。目前时间已经过去半年，回顾这半年的时间，基本还是运作得比较顺利。当然过程中也少不了踩坑，因此记录一些心得。\n\n## Why Git?\n\n如果用一句话来说的话，我们是冲“分支”而来的。背景如下：\n\n团队的固定版本节奏为两周一个版本，一周半的时间开发，半周时间测试发布。如果使用软件工程中的概念来说的话，这是一个比较典型的瀑布式流程，即“需求->设计->开发->测试->发布”，然后周而复始，过程中几乎没有重叠。\n\n伴随着瀑布式的流程，代码也只有一份，“开发->改bug->发布”，周而复始。\n\n直到去年10月，公司做了一场声势浩大的营销活动，灾难开始了：一方面需要以并不确定的研发周期支持各种运营活动（运营时间不等人，必须快速写快速发），一方面是运营活动带来大量客户，与客户相关的流程也陷入频繁修改发布的过程。此外支持各种终端需求也集中爆发，需要web侧快速跟进上线。当然，还有一个东西，就是上面瀑布流程中两周发布一次的“主版本”。当这么多版本交叠在一起时，我们发现必须要引入分支来管理研发过程。于是果断切Git。\n\n\u003C!-- more -->\n\n## 困扰\n\n引入Git的过程并非一帆风顺，中间也有不少困扰。\n\n### 概念和特性\n\n首先是Git的概念繁多，而且很多命令并不直观。尤其是有一些和svn很像的命令，需要一段时间去理解。比如svn的`commit`会推送到服务器，而Git不会，这会导致解释Git的`push`命令并不是那么容易。\n\n另外Git会在操作可能导致修改丢失时拒绝操作。\n\n比如当前分支上有个文件A，当前状态为A1，我们将它做一点修改，并没提交，此时状态为A2。切换到另一分支的状态B1，如果A1和B1不一致，就需要覆盖当前文件，从A2切到B1，此时就会导致状态A1到A2的改动丢失，Git会拒绝操作。\n\n类似的场景很多，只要Git发现有改动会丢失就会拒绝操作，而如果改动不会丢失，才允许操作。这种是否允许操作的不一致性也会困扰团队成员。解决的方案是引入stash操作，或者鼓励成员多提交。\n\n### 分支思维\n\n然后是从单线开发转入多线开发的思维转变。\n\n在切Git之前，我们的代码都是只有一个主线的（其实有另外一份代码，但是是以Copy文件夹的形式存在，更多的意义在于“备份”）。而在切换Git之后，一方面概念繁多，一方面还要时刻去关注代码所处的分支状态。甚至会有很多成员在一开始很怀疑分支的有效性，总会担心自己辛苦写的代码一不小心切完就再也找不回来。这个问题也同样需要一段时间来适应。\n\n### 日常操作\n\n另外就是对于日常操作的困扰。\n\n对比svn，Git的日常代码提交增加了add和push的过程，略显繁琐。但繁琐并不是很大的问题。真正的问题在于Git对版本和文件完整性的要求导致不允许对未提交的文件进行合并。直观的表现就是本机修改了文件无法直接与远程合并，必须要先提交，再合并远程，最后再推送。如果本机有部分文件无法提交的话，还需要增加stash相关的动作，整个流程就变为“add->commit->stash->pull(merge或rebase)->push->stash pop”，而svn的则是“update->commit”，光看看路径的长度就懂了。\n\n这个问题并没有什么好的解决办法，只能是让成员不断练习、练习、实践、实践，然后习惯。\n\n当然也有部分Git客户端会简化这个操作，比如Github客户端（[Mac](https:\u002F\u002Fmac.github.com) [Windows](https:\u002F\u002Fwindows.github.com)）和[SmartGit](http:\u002F\u002Fwww.syntevo.com\u002Fsmartgit\u002F)还有命令行工具[LeGit](https:\u002F\u002Fgithub.com\u002Fkennethreitz\u002Flegit)都提供了一个操作叫`sync`，就是把上面列的这一长串流程放到一起了。\n\n### 二进制文件\n\n在从单线开发转到多线并行的开发后，一般情况下可以在各个分支独立处理自己的事情，最后由Git来进行合并。但是如果碰到二进制文件，事情就变得完全不一样，比较典型的案例就是雪碧图。\n\n当多个分支都要修改雪碧图的时候，如果独立在各分支中修改，最后再合并，场景一定很壮观。因为Git没法处理二进制文件的合并。\n\n对这个问题，短期的解决方案是，涉及到二进制文件改动时，在各个分支同步修改。\n\n是的，一点都不优雅，所以长期的方案是，干掉二进制文件合并的场景。比如对于雪碧图来说，如果将图都拆开，在开发阶段不作合并，则代码合并也不会出问题。因为改动都是“增加了icon1.png”“删除了icon2.png”，只有两个分支同时增加或者修改同名文件才会出问题，如果不合并雪碧图，则几乎不存在这样的场景。因此这个问题较好的解决办法是将雪碧图放到构建阶段，由自动化打包工具来完成。\n\n## 经验\n\n### 使用Git-Flow\n\n在没有分支管理经验的时候，全盘引入别人的成功经验是可取的。我们一开始也是全盘引入了[Git-Flow](http:\u002F\u002Fwww.oschina.net\u002Ftranslate\u002Fa-successful-git-branching-model)，虽然并不是100%完美，但很大程度上避免了前期刚切入Git时的混乱期。\n\n期间我们发现Git-Flow并没有对测试介绍做出指导（何时在哪个分支做测试），导致 我们唯一的测试服务器上经常出现版本混乱，于是我们尝试加入了tests分支，但事实证明这个分支并不能很好地与其它分支协作，于是作罢，仍然基本采用Git-Flow的流程来做。（回想起来，当时测试服务器上出的问题并不是Git-Flow带来的。测试应该是在release分支拉出后再做，而如果是单独测试特性，则直接在feature分支做。如果需要同时测多个东西，则需要多台测试服务器，于是后来我们也增加了很多测试服务器来解决这个问题。）\n\n公司内也有其它团队使用Git，但是不采用Git-Flow，结果就会经常为拉分支和合并分支的事情而困扰。\n\n### 有关release分支\n\n在一开始看到Git-Flow的时候，我以为release分支是一个存活期非常短的分支，只是拉出来打打版本号，然后立马就消失了。但是后来逐渐认识到，release分支其实相当于对develop分支的一个冻结副本，release拉出来的时候就意味着上面的需求都已经冻结，在release上唯一可以继续做的改动只有这些需求的bug修复。而release一旦拉出后，develop上就可以继续执行新功能开发，这样新功能开发和版本测试发布可以并行，所以测试的介入的理想节点是release版本。\n\n如果是瀑布式模型，测试和新功能开发不重合，则可以不需要release版本。目前我们团队内还没有使用到release分支。\n\n### 有关develop分支\n\n在理想情况下，一个版本开始的时候develop和master是完全一样的。此时开始在develop上做开发，相当于这是一个大版本，上面拉出来的各种feature分支都是在做这个大版本开发的一部分（它们最后也合回develop，和直接在develop上开发的效果是一样的）。而如果一个大版本正在开发，此时需要再来一个并行的大版本（比如碰到了长线需求），也即正在开发的独立大版本不止一个，则理论上需要并行的多个develop分支。这是Git-Flow的各种介绍文章中均没有提到的问题。\n\n所以，当碰到有多个并行大版本的需求时，如果要准备开发第二个大版本的需求（也可以简化为“独立发布的需求”），则必须**不能**使用Git-Flow从develop拉出feature分支。此时应该使用hotfix分支（相当于另一个develop分支）。\n\n### 有关hotfix\n\n在看过上面一段后，应该能明白，hotfix的地位和develop其实是一样的，只是develop存在的时间更久一些（“大”版本嘛），还会拉出功能分支，接受功能分支合并。简单说，他们的区别就是develop更“重”一些，hotfix更轻量一些，本质上都是从master来，回master去。\n\n### 有关master\n\n在有紧急bug的时候，Git-Flow要求拉出一个hotfix分支来处理，而不能直接改动master。但从我们实践的经验来看，master上并不是不能做修改，有时候为简单起见，也可以在master上直接改，只是做完修改需要合并回develop，合并完之后和拉hotfix分支再完成等效。\n\n## 一些习惯\n\n### rebase和merge\n\n建议本机和远程分支（相同分支）同步必须用rebase，因为不用rebase就会使用merge，这样会导致（逻辑上的）同一分支在版本记录中变成分叉的多个分支（然后这些分支合并的消息全是`merge xxx branch of http:\u002F\u002Fremote.server\u002Fxxx.git`），不利于追踪版本记录。\n\n但是，从实践的经验来看，rebase在发生冲突时解决方案并不是那么友好。首先是此时的“my version”和“theirs version”并不和想象的一样。（详情可参考rebase文档，很可能“theirs”其实是自己的代码。）然后，在极端情况下rebase会导致代码丢失（目前原因未知）。\n\n上面说的是本机和远程的相同分支使用rebase。如果是不同分支的合并则必须用merge，否则会导致历史记录不可读，因为再也找不到合并之前各个分支到底是在哪里。\n\n另外还有一个需要注意的点，假设有这样的场景：现在有两个分支A和B，本机A的状态为A1，远程的比A1新，为A2，此时需要将B合并到A。按照上方所说，本机和远程的A分支同步使用rebase，B合并到A使用merge。\n\n如果先将B merge到A，则本机的状态为A1，然后是B。此时再拉远程的A2，会导致B合并过来的记录丢失（在分支图中看不到合并的痕迹。）因此碰到这种情况，既需要和远程同步，又需要合并其它分支的情况，一定要先rebase再merge，否则会丢失merge记录。\n\n### commit和stash\n\n如前文所述，svn的习惯（update->commit）行不通，因此需要先stash或者commit。鼓励团队成员多commit，即使没写完，也可以在下次提交时使用`--amend`将两次提交进行合并。\n\n之所以鼓励commit而不是stash，是因为stash并不在版本记录中，理解起来并不那么容易，对比和合并也不是特别方便。\n\n此外就是前文说的，Git sync是个好功能，但是从实践的情况来看，sync时并不一定会选择rebase，而merge会导致版本记录可读性变差。\n\n### 有关tags\n\n如果有需要从Git中提取代码的情况，则通过tags来操作是非常好的，因为可以很方便地追踪代码版本情况。如果不打tags，也可以使用提交的hash值，也可以追踪，只是人眼看起来没有那么直观了。而如果使用分支名，技术上也可行，但是会导致追踪困难。（试想，你能很轻易地找到前天晚上master在哪里么？）\n\n而如果有发布系统来记录每一次发布的情况，则可以不用tags，因为发布系统可以记录当时提交的hash值，追踪起来也很方便。\n\n## 小结\n\n坑都是要自己踩的，认真踩下来，结果还不错。谨以此文献给正被Git团队协作困扰的团队，希望能提供一些参考。\n","\u002Farticle\u002Fgit_and_gitflow.html",{"id":47,"type":7,"slug":48,"title":49,"date":50,"category":11,"tags":51,"body_markdown":53,"permalink":54,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":55},117,"how_to_debug_efficiently","如何高效debug","2014-06-29 12:19",[52],"调试","\n> 这是一个公司内网上的问题，原意是题主觉得debug非常费时，影响了项目的效率，问如何改进。当时也在内网随手码了几点，回头又看了一遍觉得很有共性，可以再扩展一下单独写写，于是诞生此文。因为专业所限，本文的部分细节也只限于web前端，但思路和其它语言是相通的。\n\n首先，程序员要调整好心态。\n\n事实上，debug是程序员工作的重要组成部分，甚至在产品的某些阶段是唯一的组成部分，所以不用把调bug看成是拖累产品进度、降低效率的凶手，这是一件必须要花时间认真去做的事情，它就是你的工作，也是整个项目进度过程中必不可少的组成部分。所以在debug的时候也可以更加平心静气一些，不用那么急躁。\n\n当然，这个心态的改变也会涉及到项目进度安排上的一些调整，比如在排期的时候就要预估debug的时间，而不能仅仅只安排编码的时间。此外，还需要给自己做好时间管理，尽量能排比较大段的不被打扰的时间来debug。\n\n把心态放平之后，有的bug可能解决起来真的就没那么耗时了。在心态平和、思路清晰、无人打扰的情况下，一般修起bug来都有如神助，效率高得连自己都不太敢相信。相反，往往越是着急的时候越是难定位到bug的真正原因。\n\n\u003C!-- more -->\n\n然后说提高调试效率的一些办法：\n\n## 练好基础\n\n这个不论对开发还是调试效率都有决定性影响，一旦基础扎实了，在编写代码的过程中就能避免非常多的bug，在调试过程中也很敏锐地察觉到异常之处。\n\n这里所指的基础其实包含了两个部分：一部分是编程语言的基础知识，只有掌握好才能知道一个问题如何用最低成本、最正统、最能扛住需求变更、最不容易出问题的方式写出来。另一个部分则是良好的编码习惯，基本上各个语言都有各家总结的一些编码规范和习惯，并且也会解释为什么建议这么写，如果掌握好的编码习惯，一般而言可以避免非常多编码细节导致的bug。\n\n比如，关于数组去重，如果你去网上随便找一段代码，很有可能找到利用对象的key来去重的代码：\n\n```javascript\nArray.prototype.delRepeat=function(){\n\tvar newArray=[];\n\tvar provisionalTable = {};\n\tfor (var i = 0, item; (item= this[i]) != null; i++) {\n\t\tif (!provisionalTable[item]) {\n\t\t\tnewArray.push(item);\n\t\t\tprovisionalTable[item] = true;\n\t\t}\n\t}\n\treturn newArray;\n};\n```\n\n如果你直接去用的话一般不会有问题，但如果你的数组是`[1,'1']`就会发现这个方法秀逗了，根本原因是数组的key必须是字符串，`1`在被当作key时会被转成`'1'`，导致二者无法区分。如果你不了解对象的相关机制，就很难发现这个bug。\n\n再比如，如果你习惯花括号另起一行，那么在函数中返回一个对象就很容易写成这样：\n\n```javascript\nfunction A()\n{\n\treturn\n\t{};\n}\n```\n\n但事实上由于JavaScript的分号补全机制，这里最后返回的是`undefined`，而如果将花括号跟在`return`后面则不会存在问题。这就是典型的编码习惯可以避免的bug。\n\n练好基础的工夫必然是在工作之外的时间，因为基本上工作时间是满负荷输出，不太有时间去接触新东西，如果你每行代码都需要先Google一下再写，那想必你的老板也会不乐意。所以给自己充电的时间就只能是在工作之外，这是件非常考验人的事情。\n\n## 用好工具\n\n工具包括三个方面：\n\n### 质量工具\n\n质量工具对于前端来说是特别必要的，甚至比其它语言更必要，因为HTML、CSS、JS都是没有语法检查没有编译过程的，基本上编写完就直接丢上线了。所以为了保证代码质量，我们可以引入一些检查工具来辅助控制代码质量。\n\n至于具体的工具，可能是IDE，可能是命令行下的各种lint，也可能是集成构建过程中的语法检查过程，还可能是在线的语法检查器等，方法不一而足，但做的事情都是差不多的。\n\nHTML检查的话主要是W3C的标准验证（\u003Chttp:\u002F\u002Fvalidator.w3.org\u002F>），也有各种牛人编写的HTML Lint之类的工具。\n\nCSS检查的话主要是CSSLint，此外不规范（无效）的属性在Chrome开发者工具的console中会显示警告。\n\nJS检查的话主要是JSLint\u002FJSHint。\n\n此外还有一些针对特殊文件、语法而做的工具，比如用于检查json语法的jsonlint之类，种类繁多，不一一列出。\n\n以上这些工具基本都有对应的grunt、gulp插件，也有IDE插件，可以直接集成到编码过程或者构建过程中。\n\n质量工具除了语法检查类的之外，还有一类是属于“规范”类的，即用来统一项目的编码规范，比如editorconfig，建议每个项目都能引入，它可以更好地控制项目的缩进、换行符、编码之类的规范。\n\n### 调试工具\n\n其实调试工具不仅仅是一个工具，要用好的话还得掌握调试方法。这一节的核心思想就只有一句话“代码调试真的要靠调试，而不能靠猜”。见过非常多的前端同学，在某个逻辑与预期不一致的时候基本都是对着源代码猜，是不是这个地方单词写错了？是不是这里循环少了一次？是不是后台返回的数据是空的？然后用各种奇葩的方法一遍遍地改代码，直到终于让结果符合预期了，才算“调试”完毕了。\n\n怎么样才算是“调试”呢？那就是你可以看到你写的每一句代码最终跑起来是什么样的。具体而言，HTML主要检查生成的DOM树结构，CSS主要看样式的层叠关系及最后应用的样式来自哪里，JS主要看代码每一行的结果和预期是否相符。\n\n以Chrome dev tool为例，看HTML的问题主要在Elements面板，看CSS的问题主要也在Elements面板（有时候也需要在Resource面板），看JS的问题则主要在Source面板。\n\n比如两句简单的代码：\n\n```javascript\nvar words = location.hash;\n$('#test').append(words);\n```\n\n如果页面上没有出现你想要的文字，该怎么样？很多人这个时候就开始猜了，是不是`location.hash`兼容有问题？是不是jQuery没引入？是不是`$`被覆盖了？是不是不支持取ID？是不是`append`用法不对？\n\n很有可能你拿调试工具断一下点，看看每个表达式的结果，你就会发现，其实原因是`$('#test')`取不到。然后恍然大悟，原来没有把DOM操作放在DOM Ready中！\n\n因为不是调试工具教程，所以细节不多说，放个截图，我说的就是这一堆。\n\n![调试工具截图](\u002Fassets\u002Fhow_to_debug_efficiently\u002F1.png)\n\n另外强烈建议将画圈的按钮点一下让它高亮，这样可以在代码报错之前立即自动断点下来，避免因为报错而导致页面刷新、表单提交之类的动作，使得调试变得困难。\n\n> 如果看不懂上面一堆在说什么，那么这一段的目标读者就是你了，你需要好好学习一下前端调试方法和工具的使用了。\n\n与上面说的类似，移动端的调试也有很多方案，比如weinre、MIH Tools之类，iOS和Android也有各自的USB调试方案。\n\n多多掌握这些调试方法和工具能够真正在你想找问题的时候事半功倍。\n\n### 生成工具\n\n有时候我们的代码中还会有一些假数据或者写死的数据，或者是一些根据数据生成的代码（比如拼接HTML），或者是一些模板化的代码，此时如果借助工具来生成数据或者代码，会比手工编写靠谱得多，也可以避免很多错误产生。\n\n比如\u003Chttp:\u002F\u002Fwww.json-generator.com\u002F>、\u003Chttp:\u002F\u002Fshancarter.github.io\u002Fmr-data-converter\u002F>、\u003Chttp:\u002F\u002Fwww.colorzilla.com\u002Fgradient-editor\u002F>、\u003Chttp:\u002F\u002Fmatthewlein.com\u002Fceaser\u002F>都是非常好的生成工具。\n\n## 用好搜索\n\n如果在调试之后定位到某个很诡异的地方，实在无法解释或者找不到原因的话，不妨搜索一下看看，一般这种诡异的问题都已经有前人碰到了，在stackoverflow或者是开源代码的官方讨论区基本上都能找到答案，绝大部分也可以找到规避方法或者替代方案。\n\n这里值得注意的是，你仍然需要先调试再搜索，因为在你调试之前，你对问题的描述只能是“现象”，但是调试之后一般可以定位到某个具体的代码或者对象或者API，去搜索对象或者API的行为比搜索“现象”得到的答案往往会更接近真相。\n\n## 多总结\n\n每调完一个重大bug就会有比较大的成就感，一般这也是进行总结的最佳时机。\n\n每个程序员都应该有总结bug和原因的习惯，比如为什么会造成这个bug，如果是编码习惯的问题能否规避，能否利用工具在编码阶段就解决掉？如果是逻辑上的问题，能否推给产品、交互去重新梳理，避免类似问题？\n\n总结之后最好还要有提炼和分享，比如bug是由于不为人知的特性或者API导致的，能否对与之相关的任务进行封装，或者能否将这个坑埋掉，然后共享给组员让大家避开这个坑，甚至回馈给组件作者让更多人避免这些坑？如果能将你的成果分享给大家，就避免其它人再掉入同一个坑，而如果将这个坑埋掉，就可以让地球上的程序员永远不再掉进这个坑，想想都是一件很幸福的事情。\n","\u002Farticle\u002Fhow_to_debug_efficiently.html","https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Fhow_to_debug_efficiently\u002F1.png",{"id":57,"type":7,"slug":58,"title":59,"date":60,"category":11,"tags":61,"body_markdown":64,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":65},116,"about-file-format","【科普文】有关文件格式","2013-11-26 09:27",[62,63],"文件","格式","\n![题图](\u002Fassets\u002Ftech\u002F2013\u002Fabout-file-format\u002F01.jpg)\n\n这篇文章是在知乎回答的一个问题“为什么计算机需要各种各样的格式？能否有一种通用的格式来替代它们？”觉得挺有意思的，可以引起一些在信息架构方面的思考。如果有一天机器有了智能，那么也许我们的格式真的都不再需要了。\n\n首先，格式肯定不是伴随计算机而生的，它并不特指文件格式，而是指一种“规格”“规范”“约定”之类的东西。比如你写合同，最少要有合同正文和甲乙双方签字，这个就是合同的格式；比如你去银行办业务，要填表单，这个就是银行需要的格式；再比如你要写一首古诗，每句要换个行，这也是格式。这些都跟计算机无关，格式是普遍存在的。\n\n其次，格式存在的意义是什么？如上面的所有东西，都可以归为“文档”，或者更通用一些，叫“文本”。理论上，你也可以不需要任何格式，合同就从头到尾，把约定的事情讲清楚就行，去银行也写一段文字，上面交代清楚自己的资料，写诗就从头写到尾一大段，也行。没有格式，这些事情也可以做，那为什么还需要格式？因为有了格式，效率可以更高，比如你一看合同，就知道我该重点看条款，应该在结尾签名，一看银行表单就知道我应该在这栏填姓名，这栏填身份证号，一看分四行每行七字就知道这大概是一首诗了。格式的意义在于规范，让不同的东西有自己的规范，以便更好地书写、检验、读取，比如如果没有银行表单，你可能怎么也不知道要写证件号码，可能写了也不知道还要写发证机关，而有了这个表单（格式）之后，一切都变得好办了，你好写，工作人员也好检查填得对不对，也方便它录入电脑办理后续手续。\n\n\u003C!-- more -->\n\n回到计算机中的文件格式，和上面的格式是一样的，因为文件有不同的用途，约定自己的格式有助于更好地写入、检验和读取。比如你要生成一个文本文件，那按照文本文件的格式，直接ASCII编码，将编码写入磁盘就OK，比如要生成一个BPM文件，那按照BMP的格式，分四个部分，先写BM，再写文件的元数据，再写颜色表，再写图像数据。这样其它软件读取的时候，一看.txt就知道直接ASCII解码，当文本显示就行了，一个.bmp就知道分四个部分读，读完计算出像素值再显示出来。其它格式都依此类推，有了这些格式，生成软件和读取软件可以更好地处理不同类型的文件。\n\n最后，计算机能否有一种通用格式呢？其实这个问题其实不能用“能”或者“不能”来回答。计算机的文件格式是可以分层的，比如最底层，大家都是二进制，0101而已，没区别，全都是一样的格式，这正是这些不同格式的文件可以被放在同一个磁盘上的原因。在这之上是文件系统的格式，文件系统可以将这些0101以不同的策略来分布在物理磁盘上，也可以没事自己做做压缩、搬迁神马的。再之上是这些二进制数据0101的含义，同样的一段数据，可能在作为文本的时候表示“1”，但在作为图像的一部分的时候表示“一个黑色的点”。所以在“含义”这一层，不同用途的文件是一定会有不同的格式的，即便它们用了什么火星来的技术，使用相同的物理格式来保存，最后也一定在逻辑含义上有区分，而这些区分具体到我们日常理解的逻辑，便成了不同的文件格式。\n\nP.S.1: 在上面例子中，人与人之间交互可以使用不分格式的“文本”来做，是因为人具有自然语言书写和理解的能力，比如你写“我的身份证号是xxx”，或者写“身份证xxx”，别人都可以理解，但计算机不能，所以计算机必须通过严格约定的格式来区分不同格式，在逻辑上不存在通用格式。\n\nP.S.2: 将一个文件用base64编码，便得到一段上面说的“火星技术”类似的东西，即不管什么文件看起来都是一样的格式，但一旦被使用，仍然需要base64解码，变成不同的文件格式。追求这样一种看起来通用的格式，并没有什么正面意义，反而增加运算量和人的识别难度。\n","https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Ftech\u002F2013\u002Fabout-file-format\u002F01.jpg",{"id":67,"type":7,"slug":68,"title":69,"date":70,"category":11,"tags":71,"body_markdown":75,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},113,"hello-farbox","hello farbox!","2012-12-27 09:47:48",[72,73,74],"博客","搬家","farbox","\n应该是从07年开始写博客的吧，最早是在[新浪](http:\u002F\u002Fblog.sina.com.cn\u002Fshuhan0520)。当时还纠结了好久好久，因为自己是一个不爱随大流的人，当大家都一窝蜂地开博客的时候，我就有种从心底升起的反感。不过后来想想，其实无所谓，重要的是我自己记录下的那些文字，而不是其它，或者其它人。\n\n后来可能是09年，觉得新浪博客玩得不过瘾了，自己搭了一个PJBlog，也就是在新浪留的最后一篇文章中的域名shuhan.sssky.net，不过好景不长，一段时间后又觉得PJBlog实在是有点难用，加上当时正值求职前夕，遂自己写了一个当时觉得很风骚的仿XP界面的抒寒居网站。这个站后来在面试中也应该为我加了不少分。\n\n再后来就工作了，渐渐不再使用ASP，于是抒寒居也就不再维护。自己也因为忙于工作，很久不再写博客，于是很长一段时间因为服务器关闭而导致博客一直打不开。\n\n直到昨天，遇到[FarBox](http:\u002F\u002Ffarbox.com)才深深觉得，这就是我想要的！不需要后台，不需要空间，不需要维护。所有需要的只是写下文字，按一下CTRL+S，其它的一切都搞定了。\n\n以后就在这里写博客了，FarBox！\n",{"id":77,"type":7,"slug":78,"title":79,"date":80,"category":11,"tags":81,"body_markdown":83,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},114,"predict-on-internet","2012中国互联网预测","2012-12-04 18:58",[82],"互联网","\n来自知乎问题[即将逝去的2012年，中国的互联网发生了哪些重要的事情，这些事情将会对今后将产生哪些重要的影响？](https:\u002F\u002Fwww.zhihu.com\u002Fquestion\u002F20635900\u002Fanswer\u002F15705606)\n\n1、微信用户突破2亿，有理由相信微信会开创移动互联网的新格局，包括再造app store或者创造出移动互联网第一个成熟的盈利模式，或者开创中国互联网产品国际化推广新成就都是有可能的。\n\n2、淘宝2012年交易额突破10000亿，占到GDP的2%，这将成为互联网购物史上的一个标志性事件，有很多意义可以说，比如网购已经切实走进人们生活，比如天猫的成功已经表明低价不是网购唯一的吸引力，比如支付宝强大的现金流后面可能衍生出来的更多游戏模式（当然，也有可能因为政策原因难产），比如线上购物开始面临和线下同样的来自各方面的管理（质检、税收等），比如对物流提出更高的要求从而使物流行业也产生格局变化等。\n\n3、优酷土豆合并，可以算是作为2011年烧钱运动结束的一个明显标志，从此视频行业从烧钱中解脱出来，开始采用联合版权购买等方式来降低成本，也开始有恃无恐地投放广告、试水收费电影。总体来说竞争减少，合作增多，也许会为在线视频行业带来新的机遇。\n\n4、360搜索，会慢慢改变国内的搜索格局，百度的日子会不好过。\n\n5、小米手机退烧，被指期货，今后小米走的这条路未必顺利，尤其是在魅族、华为等厂商下决心打硬仗的时候。（必须承认，小米在手机本身上下的功夫不及后两者。）\n\n想写第6条的，但总还是觉得2012年的中国互联网太平淡。迅雷未上市、资本市场遇冷、网络反腐问政、腾讯电商独立、阿里巴巴私有化、金山一系列积极的动作都没有看到太多对互联网业界的意义。\n",{"id":85,"type":7,"slug":86,"title":87,"date":88,"category":11,"tags":89,"body_markdown":91,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},115,"why-photoshop-so-complex","为什么Photoshop这么复杂","2012-10-04 09:28",[90],"Photoshop","\n来自知乎问题[为什么像 Photoshop 这种如此复杂难懂的软件可以垄断图像编辑领域 20 年？\n](https:\u002F\u002Fwww.zhihu.com\u002Fquestion\u002F20510915\u002Fanswer\u002F15335855)\n\n首先，你要对你的问题领域进行限定：是在专业图像处理领域垄断，其实民用级并不一定垄断，类似美图秀秀、QQ影像之类的软件用户并不少。\n\n原因：\n\n1. 因为是专业软件，所以必然涉及到专业概念，例如颜色模式、图层、通道、颜色叠加模式、色阶、曲线、白平衡等等，因为没有这些专业概念，你根本做不了专业的图像处理。\n2. 从专业的角度来解释难用的问题：除了上面说的概念多以外，功能细化，分布广、散也是PS一个重要的特性，而事实上，它也只能这么做。我们先说，为什么你觉得有些软件好用，从交互的角度来说，无非是因为这些软件梳理了用户的核心任务、常用操作，对这些操作进行了优先级排序和路径合并（比如将两步合并为一步），然后将重点的地方突出出来，将不重点的地方弱化，所以你觉得好用。但是这一招在PS里行不通，因为用户的核心任务既不是P图也不是美肤也不是美瞳也不是去红眼也不是web设计，你根本梳理不出来用户打开PS的目的，唯一可以确定是“图像处理”。因此，PS只能将足够细化的功能一一列出来，由用户自己来操作组合。（这也是为什么PS做一个很简单的效果也需要N多步骤的原因。）功能非常强大的东西必然会是细碎的操作。\n3. 解释PS跟iPhone的区别。上面说到功能非常强大的东西必然是细碎的操作，有人会拿iPhone说事。iPhone的强大并不在于它的软件，而是在于它将很多的硬件（多指触控屏、光线感应、GPS、陀螺仪等）带入了手机，并且用软件来配合它们进行工作。事实上分析一下就可以发现，这些东西几乎不涉及到交互流程或者是用户交互，它只是为手机提供了一种能力。iPhone的强大还表现在硬件好、触控流畅、生态系统完善，这些特性都具备我刚分析的特征，即几乎不涉及用户交互。而PS，它从头到尾都是在做一个与用户交互的东西（“P图”），两者的“强大”不是同一个概念。\n\n最后一点题外话，虽然我的PS功底很水，但是还是有一些关于如何学好PS的建议：\n\n1. 学习好专业的图像领域的概念，即上面答案中第一点提到的（可能不全）。\n2. 理解好PS中每一项功能的用意以及对图像产生什么影响。\n3. 实践，走向高手之路。\n\n推荐一个视频教程，李涛的《PhotoShop高手之路》，里面对PS的概念和功能有详细解说。\n",{"id":93,"type":7,"slug":94,"title":95,"date":96,"category":11,"tags":97,"body_markdown":100,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},110,"auto-backup-database","数据库自动定时备份","2010-02-19 13:09:00",[98,99],"备份","数据库","\n原理很简单，用FTP把数据库下载下来，然后放到备份空间去。\n\n至于备份空间哪里找嘛，115网盘倒是个不错的选择，速度很快，而且重要的是，传上去的文件不能用FTP修改删除，只能在WEB中转移到永久空间，如果不转移就只保留三天，于是每天备份一下，没问题就不管它，有问题了就能找到三天之内的数据。\n\n但是，要到3级才给开通FTP。\n\n备份.bat代码：\n\n```bat\necho open sssky.net>beifen.ftp\necho shuhan>beifen.ftp\necho ***（密码）>beifen.ftp\necho cd \u002Fshuhan\u002Fweb\u002F00_other>beifen.ftp\necho get mydiary.mdb mydiary%date:~5,5%.mdb>beifen.ftp\necho close>beifen.ftp\necho open cnc.ftp.u.115.com>beifen.ftp\necho 1237565>beifen.ftp\necho ***（密码）>beifen.ftp\necho cd \u002Fupload>beifen.ftp\necho send mydiary%date:~5,5%.mdb>beifen.ftp\necho bye>beifen.ftp\nftp -s:beifen.ftp\ndel mydiary%date:~5,5%.mdb\ndel beifen.ftp\n```\n\n然后在自己经常能上网的电脑上，或者是服务器上每天定时执行这个就OK了。\n",{"id":102,"type":7,"slug":103,"title":104,"date":105,"category":11,"tags":106,"body_markdown":110,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},108,"how-to-develop-wubi-input-method","五笔应该用怎样的思路去开发","2009-12-22 14:35:32",[107,108,109],"开发","五笔","输入法","\n先说明一下，本人使用五笔已经近10年了，前前后后用过微软的王码86、五笔加加、陈桥五笔、万能五笔等等好多版本，最后还是锁定在五笔加加PLUS2.81上了。\n\n做出这个选择有两方面的原因。\n\n一方面是词库，五笔加加PLUS利用附带的工具可以自己选择和替换词库，我用的一个2.8万的词库，不多不少，感觉最好。之前用王码86感觉词库太少。\n\n另一方面是界面，五笔加加的界面看着很舒服，可以换皮肤是一个次要因素，主要因素是简洁，上屏速度快，给人干练的感觉，字打快的时候非常舒服。\n\n前几日一个朋友见我打字，问了一问题：五笔为什么快？\n\n我不知道搜狗五笔的开发者（看到QQ五笔也发布了，感觉也没做到很好，所以也同时在想QQ五笔的开发者）有没有思考过这个问题。\n\n答案是五笔的重码少，基本不用选字，大家可以想想如果你用拼音打字，你的大部分时间是花在哪里的，其实键盘的敲击时间是很短的，大量的时间是花在选字上的。王永民先生当年苦心研究的本质其实就是怎样去减少汉字的重码问题。\n\n明白这一点，我们再回头来看搜狗五笔（也包括QQ五笔），能够不选字直接上屏的字词已经远远少于五笔本来的样子，因为加了太多的词库。这一点肯定是受拼音影响太深了，因为拼音有重音，词库越大，在一定范围内，几个音节联合起来得到期望的字词的概率也越大，而五笔本来就是一个以单字为主，辅以少量词汇的输入法，当你注入太多的词汇时，只能增加选词的负担。\n\n所以我的观点：大词库是五笔的大忌，而不是应该拿来炫耀的！\n\n当初搜狗拼音因为有搜索的统计，凭词库（当然还有语言模型）一夜红遍大江南北。但是这个思路放在五笔上是行不通的。\n\n那么，五笔应该怎么走。我有两个观点。\n\n第一，五笔本来是一个不太能再深挖的领域，速度已经接近极致，再快是很困难的，所以不妨在其他方面做做文章，比如用户体验等等，不要再纠缠词库和速度。\n\n第二，如果非要加入词库，不妨借鉴拼音，加入语言模型的识别，也就是说，把五笔的单字输入模式（或者叫四码模式更恰当一些？）改成联合输入模式，就像当初的拼音，大家都在以词为单位时，微软的拼音是以句为单位的。比如“我是中国人”，编码为“Q W K L W ”，那么能不能改成“QWKLW ”（注意空格的区别）整体识别输出？当然，其中有些困难比如编码的拆分是可以预见的，但我想这个思路是不是可以试验一下，如果效果好，五笔的一片新天地又出来了。\n\n还有一个，这种模式的速度与五笔固有模式的速度相比有没有优势？我没有答案。\n\n长久积累的一些想法，供大家思考。也希望能得到有识之士的批评指正。欢迎讨论。\n\n> 本文发布在搜狐五笔论坛，原帖地址：[http:\u002F\u002Fwubi.sogou.com\u002Fbbs\u002Fviewthread.php?tid=146582](http:\u002F\u002Fwubi.sogou.com\u002Fbbs\u002Fviewthread.php?tid=146582)\n",{"id":112,"type":7,"slug":113,"title":114,"date":115,"category":11,"tags":116,"body_markdown":120,"permalink":15,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"cover":19},107,"diy-a-antivirus-udisk","真正让你的u盘百毒不侵（换电脑也不怕）","2009-12-16 18:02:26",[117,118,119],"病毒","杀毒","u盘","\nU盘病毒可以说已经成为了一个非常严重的问题，且不说有多少不能识别U盘病毒的人为其所害，即使像我这种能够识别U盘病毒的人也为一次又一次地删除病毒，恢复文件夹属性弄得没有耐心了，于是想到弄一个一劳永逸的办法。\n\n为照顾不太懂这方面的同学，我们先解释一下目前U盘病毒经常会做哪些事情。\n\n## 病毒的行为\n\n首先，病毒会将U盘根目录下的文件夹隐藏，然后生成同名的EXE文件，图标为文件夹的图标。比如U盘根目录下有一个文件夹名为“学习”，那么病毒会将它隐藏，然后生成一个“学习.EXE”的可执行文件，图标和WINDOWS默认的文件夹图标一模一样。如果在开启了“显示隐藏文件”和“显示已知类型文件的后缀名”的电脑上，能清晰地看到这一事实。如果你看不到，也不要紧，看一下属性，文件夹和文件的属性是不一样的。千万不要随意点击，不然点一次就是运行一次病毒。\n\n然后，大部分的病毒会在根目录写入AUTORUN.INF，这个文件的作用是用来实现病毒的自动运行的，具体机制见搜索。有了这个文件，U盘右键里的“打开”、“资源管理器”之类的就不再安全了，因为可能是运行病毒的途径。这里顺利多说几句，防止AUTORUN.INF起作用的方法很多，第一是软件，360安全卫士，USBCleaner之类的软件还有诸多杀毒软件都有这项功能，第二是从其他地方进入U盘，比如在开始菜单点右键进入资源管理器，或者直接按WIN+E进入资源管理器，或者在地址栏输入U盘盘符如“I:”，或者在CMD中进入U盘盘符然后输入“start.”等等。总之不要随意双击U盘图标或者通过右键进入。\n\n## 对症下药\n\n解释清楚了病毒的机理之后就可以对症下药了，关键的一步是阻止病毒在U盘里面写入文件。如果只是在你自己电脑上用，就很简单了，N多软件可以让WINDOWS只读不写，但是U盘经常会插到别人电脑上，如何在别人的电脑上禁止写入就是本文要探讨的问题了。\n\n如果你的U盘或者读卡器有写保护开关，那你就不用往下看了，因为你只要打开写保护，U盘就不能写入任何文件了，当然也不会中毒。\n\n没有写保护的U盘如何操作呢？本来想到了好几个思路，第一，让U盘在WINDOWS下识别成光盘，只读不写，这种方法可以实现，但是实现之后自己对U盘里面文件的操作将变得非常麻烦，第二，用加密软件，让U盘变成非WINDOWS下常规的读写方式，这个没有去试，不知道有没有这样的软件，第三，将U盘的剩余空间填满，不给病毒留空间，但是想了一下不太现实，首先要生成占位文件不是一种非常方便的事情，其次自己对文件的操作不方便，而且可能让程序异常，第三也不能保证小体积的文件无法写入。\n\n最后只能想到用NTFS的权限大法了。试验了一下午终于成功，跟大家分享一下。\n\n首先要将U盘格式化成NTFS格式，当然，备份好自己的文件就不多说了。可以当我们右键点击U盘图标要格式化的时候，发现格式中没有NTFS！这个问题网上给出了好几种解决办法，有一种是用软件，没去试，另一种是改设置，试验成功。打开U盘的属性，硬件，然后选中U盘（如果不知道哪个是U盘的话就都记下，然后把U盘拔了看少了哪个），属性，策略，改为“为提高性能而优化”，再格式化就有了NTFS了。压缩建议不开，因为开了拷文件会很慢。\n\n第二步就是设置权限，在U盘图标上点右键，属性，安全，将所有用户删除，然后再添加你的电脑的常用用户，也就是你登录系统输入密码时的用户，如果不知道的话右键我的电脑，管理，本地用户和组，然后看哪个是。对这个用户给予所有权限。再添加一个EVERYONE用户，对这个用户不给写入、修改之类的权限，但是要给读取的权限。\n\n到这里我们的主体工作就已经基本完成了，换台电脑试试，怎么样，是不是不能写入任何文件了？\n\n嗯。毒是防了，可是除了我们自己的电脑外，在别处不能拷文件进去了，那还要U盘干嘛？下一步就是解决在别处电脑上拷文件进来的问题。\n\n其实也是想了好久的，后来实在是发现病毒写文件和我们自己拷文件没有本质的区别，只是位置不一样，于是我们也只好专门开一个文件夹来拷文件了。\n\n将U盘插回自己常用的电脑上，然后新建一个文件夹，专门用来在以后拷文件。然后对这个文件夹设置权限，方法和前面一样，打开这个文件夹的属性，安全。直接点击高级，下面有两个选项，第一个去掉，是为了让这个文件夹和根目录的权限不一样。然后修改EVERYONE的权限。将“应用到”改为“只有该文件夹”，然后加上一些写入什么的权限，不要给“写入属性”“写入扩展属性”之类的权限，不然它会被病毒隐藏，这一步是修改了这个文件夹本身的权限。确定后再添加一个权限，用户名是EVERYONE，应用到“只有子文件夹和文件”，可以把所有的权限基本都给，除了最后的更改权限和取得所有者，当然还有最上面的所有权限。这一步是设定这个文件夹里面的文件的权限。也可以修改一下，比如给写入不给删除，这样这个文件夹里面的文件就只能写不能删了。\n\n好了，设置完了，这样你的U盘就彻底防毒了。要拷东西时就拷进指定的文件夹就OK。稍微有些不爽的是不能直接使用“发送到”功能写入U盘。\n\n> 本文所有菜单的文字均按WINDOWS XP的写的，如果是更高版本的系统可以自己看着办，方法都差不多。另外，这样制作出来的U盘是无法在WIN98和WIN ME下读取的，不过相信这个年代没有用这系统了的吧。另外UBUNTU是支持NTFS的挂载的，所以理论上在UBUNTU下可以读取，权限就不清楚了，这具具体没试验过。另外其他的LINUX也没试验。\n\n欢迎提出改进方案或者更好的方法！有问题欢迎探讨。\n",41]