Forrest's profile阿福PhotosBlogFriends Tools Help

阿福

Forrest Ye

2/11/2010

forresty.com

高调推出 forresty.com

目前还没备案,在墙外,速度比较慢。

欢迎来踩。

同时,不会在这边再写文章。不过应该会setup一个机制当有新文章的时候更新msn状态。

1/31/2010

10寸大的iPod Touch将改变世界

Alan Kay对媒体说,10寸大的touch将改变世界

iPad推出了,果然符合苹果的惯例:把能做到极致的做到极致,把不能做到极致的放弃不做。用我的话讲就是:有气节。

于是multi touch和重力感应继续横行,新开一个书店排挤亚马逊,无缝支持iPhone和iPod Touch的应用,然后接下来不出意外的话app store终于要开始做fragmentation了。

然后无法搞到完美的多任务仍然没有。同样没有摄像头,没有无线充电。

为什么multi touch那么重要?

因为它重新定义人机交互。鼠标的推出是人机交互的一大进步,但是仍然是有缺陷的。如Riobard在apple4us上说,鼠标的操作实际上是非常困难的,只是我们都习惯了而已。在饿了么的时候,我看到了很多餐厅的老板初次接触电脑,鼠标都用不好的样子。

那么对于高级用户来说,multi touch的方式快还是键盘快捷方式快?

我觉得键盘肯定要被抛弃。所以这个问题答案很明显,关键在于时间:)

那重力感应为什么那么重要?

因为它能做到让它适应你,而不是你去适应它。为什么现实世界中的一本书有上下方向?因为它没有其他选择……那一个像Kindle、Archos这样的电子产品为什么要有上下方向?因为这样实现起来比较简单,并且做产品的人要么不够聪明,要么偷懒(要成为一个好的程序员,我们必须又懒又勤奋),要么不敢承担起变革失败可能要承担的责任。

为什么不使用Mac OS X,而是用iPhone OS?

虽然Mac OS X和iPhone OS从技术角度来说是非常接近的,但是有一个本质区别:Mac OS X是开放的,而iPhone OS被App Store绑死。绑死未必是坏事。App Store伟大在于,不仅让苹果的股东们爽死了,也让开发者爽死了,同时也让绝大多数的用户爽死了。小部分不爽的用户,不好意思,越狱去吧:)

既然这么爽,没理由iPad不继续发扬光大吧。

结果他们顺便出了一个iBooks Store。变本加厉了,我喜欢。亚马逊真可怜:)

不使用e-ink技术,仅仅10小时的续航时间看书可以么?

某位买了Kindle的兄台跟我说,e-ink有多好多好。实际上,爱惜眼睛的人看什么东西都不会连续看超过几个小时,书里面再多的颜如玉都没用;爱书不要命的人对着文曲星、手机、touch都能看个通宵。e-ink不是本质,它只是一项技术。

10个小时的续航时间……难道还不够么。我猜iPad整个背板就是一块大电池,该适可而止了…… - -

为啥没有多任务?

因为很简单。苹果还搞不出完美的多任务体验。多任务的最大问题在哪里?耗电,拖慢系统速度,从而严重降低用户体验。Google的工程师已经nb得不行了,还是不能解决耗电和多任务拖慢系统速度的问题,Apple的工程师很强大,但是平心而论应该还是Google的牛一点。

然后其实,多任务的模型对用户来说确实有点复杂。作为一个高级用户,第一次使用Windows Mobile的时候发现程序被我X掉了还在后台运行的时候,我还是思考了一会的。

不要让用户思考

为啥没有摄像头?

前置摄像头没有的原因估计跟不支持多任务一样,苹果认为还不能把视频会议的体验做到最好,于是先不搞。后置摄像头。。在没有前置摄像头的配合做到augmented reality的时候,你难道想拿一个10寸的iPad拍照啊?

无线充电也是。还远远达不到苹果的标准。

其实苹果最NB的地方是搞了一个生态系统。前面提到了让苹果、开发者和用户都爽的不行的App Store,我相信接下来加入fragmentation的App Store会更加NB,并且我相信iPad不仅仅会改变出版行业,还会改变游戏产业,并且最终改变移动计算这一整个领域。

当一个公司只需要把原有的产品稍微改改,就可以大捞特捞一笔的时候,为啥要跟自己过意不去呢?10寸大的iPod Touch就能改变世界了,至于那些缺陷,在V2和V3里面再补吧。骂iPad的童鞋们,如果你是苹果,这么好挣的钱难道你不挣么?

在这里冒昧地给Google一点建议:People who are really serious about software should make their own hardware (还是出自Alan Kay之口). Android这么搞下去,几乎注定是搞不过苹果的,除非寄希望苹果自己出问题。

哎,我是多么的想去苹果干活啊。

1/28/2010

豆瓣应该有一个类似trackback的机制

这样随便谁谁写了一篇关于某本书或者某个电影的评论,只要给了豆瓣上这个item的链接就会被抓走并且显示在那个item里。

免得一份评论要一文多发。

看来DRY的理念到处都在啊。

1/27/2010

离职工作总结

首先,有件事情要说一下:我离职了。原因搁下不说。

总结一下这一年来做的事情:

开始做这个事情之前,饿了么是一个电话订餐平台。

现在,饿了么是一个缺陷很多的未完成的产品,但是总算逐步走上正轨。

开始做这个事情之前,我是一个半吊子pm,一窍不通的product designer,蹩脚的web developer。

现在,我可以很自信的说,我是一个good product designer & software developer.

具体完成的工作内容有:

完善了项目和发布周期管理机制:我们使用开源的基于Ruby on Rails的Redmine系统进行项目管理,经过摸索从无规律的不定期发布,逐步地转变成每两周发布,到离职前的每周发布。有简单的svn分支控制和自动化build脚本支持。

较为成熟的需求收集、分析和定义方式:定期和餐厅沟通发现问题并且提出解决问题的方案,不定期观察订餐用户使用网站的方式和同类网站的最新进展。

产品和用户体验设计:其实这点蛮简单的,就是不断地发现问题并且解决问题。

编码:采用的是迭代开发不断演化的产品发布模式,于是编码过程涉及到大量的代码重构,故经常研习《重构》一书,温故而知新。开发环境为Windows下使用putty ssh到局域网内Linux主机使用vi进行编码。网站基于php的symfony框架,JavaScript使用JQuery。

测试:每次发布时的人工测试。离职前正着手开始进行整站的自动化测试工作,很遗憾该工作仅完成了一小部分。每天早上有自动的daily regression test.

服务器管理和维护:部署环境的性能调优和日常维护等。

技术支持:由于餐厅用户的计算机水平较差,经常要做一些计算机基础知识普及工作,占用了不少时间。在技术支持的过程中不断地简化产品使之更加易用和稳定。

团队建设:这点我说了不算。

交付的产品有:

订餐用户侧网站,餐厅后台网站,饿了么客服后台网站,餐厅后台出单机http驱动,餐厅后台USB语音盒http驱动,餐厅后台管理系统一键安装包等。

其他附加产品:

自动化build和多功能脚本,快捷截图发bug工具,小型餐厅后台管理终端机(已弃用),自动化数据挖掘工具(已弃用)。

其他:

构思出ele.me这一域名及饿了么品牌,并且在me域名开放注册的第一天抢先注册成功。成功注册eleme001.com,并且联系购买eleme.com未果。同时做了很多PR相关的工作。

关键数据:

30+ releases

1000+ redmine issues

4500+ svn revisions

80000+ SLOC,覆盖php, javascript, CSS, C, C#, Java, bash script等语言

------------------------------------------------------------------------------------------------

这一年看了很多书,我把其中感觉比较有用的列了出来,在豆瓣上创建了一个豆列

这会我正在虹桥机场等飞机回家。同时,我要开始找工作了。

人生如梦。

1/11/2010

生活逐步有序

每天在差不多的时候起床,每天在差不多的时候睡觉。

每天晚上要么跑步,要么做俯卧撑。

体质好了很多,精神也好了很多。

不再一味追求工作时间了,不懂得休息的人是不懂得如何更好的工作的。

发现让生活逐渐有节奏的一个好方式是,设计出一系列的例行公事,然后放到Google Calendar上,定期自动提醒。于是每天有固定时间锻炼身体,每周有固定时间洗衣服,每月有固定时间理发。当这些日常的事情不再需要经过大脑思考了之后,就有了更多精力处理更加重要的事情。

有点像以前我一直说:我们要经常做测试,经常做测试!数据库要经常备份,经常备份!最终最好的解决方案还是写cron脚本去做这些事情。

貌似爱因斯坦从来不记电话号码(包括他自己的),乔布斯始终只穿那件黑色圆领衣服,也是差不多的道理。

现在比较困扰的是,貌似很多事情,特别是技术上的一些问题只能自己去尝试自己去犯错然后在不断的失败中学习,周围没有太多人可以让我去学习借鉴。

不过或许是因为这一年来太自虐了,和其他人的沟通都不够了。希望接下来能逐步重出江湖:)

逐渐地感觉自己从只看到森林,慢慢地变成只见木;又慢慢地变成现在的见木又见林。

然而那又怎么样呢?知易行难。见木又见林,不代表能成为一个好的伐木工。况且或许我现在看到的只是一颗小盆栽,或者我还在温室里打转。

要成为一个好的程序员,我们必须又懒又勤奋。

12/28/2009

Making mistakes everyday

又是一周过去了。

这周,在伟大的《时间管理:给系统管理员》的指导下,生活有序了很多:)

但是每天仍然在不断地犯错。这周的两个重要感悟是:

1. 曳光弹很重要

2. 实用主义至上

好了,抵制完美主义,马上收手。就写到这里。

12/13/2009

Pragmatic Software Development Tips

昨天拿到这本《程序员修炼之道》,如获至宝,一口气读完了。不知道多久能消化完书里面的内容。估计接下来的几年还会多次重读,温故而知新:)

现在只是不爽没有早点看到这本书。

---------------------------------------------------------------------------

以下是书中精华部分:Tips列表

Pragmatic Software Development Tips

 

Care About Your Craft
Why spend your life developing software unless you care about doing it well?

Provide Options, Don’t Make Lame Excuses
Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done.

Be a Catalyst for Change
You can’t force change on people. Instead, show them how the future might be and help them participate in creating it.

Make Quality a Requirements Issue
Involve your users in determining the project’s real quality requirements.

Critically Analyze What You Read and Hear
Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project.

DRY—Don’t Repeat Yourself
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Eliminate Effects Between Unrelated Things
Design components that are self-contained, independent, and have a single, well-defined purpose.

Use Tracer Bullets to Find the Target
Tracer bullets let you home in on your target by trying things and seeing how close they land.

Program Close to the Problem Domain
Design and code in your user’s language.

Iterate the Schedule with the Code
Use experience you gain as you implement to refine the project time scales.

Use the Power of Command Shells
Use the shell when graphical user interfaces don’t cut it.

Always Use Source Code Control
Source code control is a time machine for your work—you can go back.

Don’t Panic When Debugging
Take a deep breath and THINK! about what could be causing the bug.

Don’t Assume It—Prove It
Prove your assumptions in the actual environment—with real data and boundary conditions.

Write Code That Writes Code
Code generators increase your productivity and help avoid duplication.

Design with Contracts
Use contracts to document and verify that code does no more and no less than it claims to do.

Use Assertions to Prevent the Impossible
Assertions validate your assumptions. Use them to protect your code from an uncertain world.

Finish What You Start
Where possible, the routine or object that allocates a resource should be responsible for deallocating it.

Configure, Don’t Integrate
Implement technology choices for an application as configuration options, not through integration or engineering.

Analyze Workflow to Improve Concurrency
Exploit concurrency in your user’s workflow.

Always Design for Concurrency
Allow for concurrency, and you’ll design cleaner interfaces with fewer assumptions.

Use Blackboards to Coordinate Workflow
Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants.

Estimate the Order of Your Algorithms
Get a feel for how long things are likely to take before you write code.

Refactor Early, Refactor Often
Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem.

Test Your Software, or Your Users Will
Test ruthlessly. Don’t make your users find bugs for you.

Don’t Gather Requirements—Dig for Them
Requirements rarely lie on the surface. They’re buried deep beneath layers of assumptions, misconceptions, and politics.

Abstractions Live Longer than Details
Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies.

Don’t Think Outside the Box—Find the Box
When faced with an impossible problem, identify the real constraints. Ask yourself: ``Does it have to be done this way? Does it have to be done at all?’‘

Some Things Are Better Done than Described
Don’t fall into the specification spiral—at some point you need to start coding.

Costly Tools Don’t Produce Better Designs
Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits.

Don’t Use Manual Procedures
A shell script or batch file will execute the same instructions, in the same order, time after time.

Coding Ain’t Done ‘Til All the Tests Run
‘Nuff said.

Test State Coverage, Not Code Coverage
Identify and test significant program states. Just testing lines of code isn’t enough.

English is Just a Programming Language
Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on.

Gently Exceed Your Users’ Expectations
Come to understand your users’ expectations, then deliver just that little bit more.

Think! About Your Work
Turn off the autopilot and take control. Constantly critique and appraise your work.

Don’t Live with Broken Windows
Fix bad designs, wrong decisions, and poor code when you see them.

Remember the Big Picture
Don’t get so engrossed in the details that you forget to check what’s happening around you.

Invest Regularly in Your Knowledge Portfolio
Make learning a habit.

It’s Both What You Say and the Way You Say It
There’s no point in having great ideas if you don’t communicate them effectively.

Make It Easy to Reuse
If it’s easy to reuse, people will. Create an environment that supports reuse.

There Are No Final Decisions
No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change.

Prototype to Learn
Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn.

Estimate to Avoid Surprises
Estimate before you start. You’ll spot potential problems up front.

Keep Knowledge in Plain Text
Plain text won’t become obsolete. It helps leverage your work and simplifies debugging and testing.

Use a Single Editor Well
The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable.

Fix the Problem, Not the Blame
It doesn’t really matter whether the bug is your fault or someone else’s—it is still your problem, and it still needs to be fixed.

``select’’ Isn’t Broken
It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application.

Learn a Text Manipulation Language
You spend a large part of each day working with text. Why not have the computer do some of it for you?

You Can’t Write Perfect Software
Software can’t be perfect. Protect your code and users from the inevitable errors.

Crash Early
A dead program normally does a lot less damage than a crippled one.

Use Exceptions for Exceptional Problems
Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things.

Minimize Coupling Between Modules
Avoid coupling by writing ``shy’’ code and applying the Law of Demeter.

Put Abstractions in Code, Details in Metadata
Program for the general case, and put the specifics outside the compiled code base.

Design Using Services
Design in terms of services—independent, concurrent objects behind well-defined, consistent interfaces.

Separate Views from Models
Gain flexibility at low cost by designing your application in terms of models and views.

Don’t Program by Coincidence
Rely only on reliable things. Beware of accidental complexity, and don’t confuse a happy coincidence with a purposeful plan.

Test Your Estimates
Mathematical analysis of algorithms doesn’t tell you everything. Try timing your code in its target environment.

Design to Test
Start thinking about testing before you write a line of code.

Don’t Use Wizard Code You Don’t Understand
Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project.

Work with a User to Think Like a User
It’s the best way to gain insight into how the system will really be used.

Use a Project Glossary
Create and maintain a single source of all the specific terms and vocabulary for a project.

Start When You’re Ready
You’ve been building experience all your life. Don’t ignore niggling doubts.

Don’t Be a Slave to Formal Methods
Don’t blindly adopt any technique without putting it into the context of your development practices and capabilities.

Organize Teams Around Functionality
Don’t separate designers from coders, testers from data modelers. Build teams the way you build code.

Test Early. Test Often. Test Automatically.
Tests that run with every build are much more effective than test plans that sit on a shelf.

Use Saboteurs to Test Your Testing
Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.

Find Bugs Once
Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.

Build Documentation In, Don’t Bolt It On
Documentation created separately from code is less likely to be correct and up to date.

Sign Your Work
Craftsmen of an earlier age were proud to sign their work. You should be, too.

12/2/2009

好产品往往是用很烂的代码写出来的

“好产品往往是用很烂的代码写出来的”

忘记最早是在哪里看到的这句话的,最近深有感悟。

在开发的过程中,我们总是无可避免地会遇到需要在“代码质量”和“产品质量”之间做权衡的时候。作为一个程序员,我们往往会追求代码本身的美感,而忘记这个程序能够产生的价值。从用户的角度来说,除非他脑子进水了或者是一个geek,不然用户永远不会管你服务器用的是Linux系统还是万恶的Windows,服务器端的代码用的是php还是高贵的RoR,你是用Ctrl+C & Ctrl+V从网上到处抄来的代码,复用了别人已经开发好的系统,还是用尽了各种设计模式和PEAA中学来的各种架构模式、绞尽脑汁严格控制代码中空格和tab的区别以及行末是否有多余空格等亲手一行一行敲出代码来。

用户关注的是你这个产品能不能满足他的需求,是不是有很好的用户体验。

这让我想起了Chrome里处理ed2k链接的方式。Chrome现在是我最喜欢的浏览器,但是每次我要到verycd.com上面去找一张专辑或者一部电影(我承认我侵犯版权了,我忏悔……),我都会很不爽。

为什么?因为在找到一个资源之后,我要么需要在页面空白位置点击右键,然后查看源代码或者“检视页面元素”,手动找到这个链接,复制这个链接,填到eMule里;或者我要打开我万不得已才打开的IE,或者我要打开我臃肿的做开发的时候才用到的Firefox。在这个支付宝和建行都已经支持Chrome的年代,这种事情实在让我很难以接受。

为什么?因为Chrome不认ed2k的链接。

为什么?很明显,ed2k的链接对待"|”这个符号不太符合标准,由于Chrome的代码用一种通用并且优雅的方式对待所有URL Scheme,而正好ed2k链接是一个比较尴尬的特例,于是它的“|”符号被转义了。

去读那个issue里面的用户评论吧,我基本上笑死了:)有用户在问这不就是一个if语句么,而马上开发者就说这样很脏,开始讨论是不是有一种通用的方式去对待这一类特殊的URL Scheme。然后有人说貌似只有ed2k链接比较变态啊,不存在一类特殊的URL Scheme,而是只有一个。这下尴尬了,不存在从代码角度来说很“优雅”的解决方案,至少短时间内找不到。而这时一个看起来比较senior的开发者就出来讲了一大堆Chrome内部对URL的处理方式,试图解释为什么这个bug还没有被修掉。后来又有用户出来说了:

Comment 45 by NoamNelke, Oct 30, 2009

I'm all against special-casing in general, but at least until a better solution is 
found or agreed upon - please, just do it...

Google code上的Chromium项目已经有了超过29000个Issue,这个Issue的Id是160,是一个在Chrome 0.2时代就存在的bug。

这个Issue在Google code上的chromium项目里的优先级是P3,就算Chrome的用户只有极少数会像我这样去点击ed2k链接,但是

至于么?不就是一条if语句么?

看来Google的APM/PM还不够多呀。

-----------------------------------------------------------

另外一件事情是,Windows里有一个名字叫abc的数据结构 ,而且还是一个API。

我就想,负责这块代码的工程师们得有多大的毅力和自制力去维护它,并且在MSDN上搞出这么专业的文档。

虽然我很想笑,但是我真的要向你们致敬。

-----------------------------------------------------------

说到这里,大家应该满清楚了。其实问题就在于,我们写代码是为了满足别人的真实存在的需求,还是自己内心充满寂寞的成就感。

在我精神分裂了一年之后,我不太灵光的脑子终于把这个问题想清楚了:)

当然,这不是意味着,在饿了么产品质量是P1,代码质量是P2。在饿了么,代码质量绝对是P1,而产品质量则是P0。你可以先用dirty hack的方式满足产品的需求,但是回头还是得尽快用重构的方式,避免给将来带来太大的麻烦。

当然,饿了么这个产品现在还远远没有达到及格线的标准。如果满分是100分,现在最多只有30分。

不过幸好目前许多工作正在幕后默默地进行着,预计近期能够越过这条线:)

-----------------------------------------------------------

Raymond童鞋加入之后,我代码写得越来越少,也逐渐有了许多时间处理各种其他事情,和进行思考。在经历了身兼PM+dev lead,磕磕碰碰惹下无数麻烦,带来无数问题,体质变差精神分裂的一年之后,我终于逐渐开始洗手不写代码了。希望从此大家能重拾对我的信心:)

作为一个*nix programmer(虽然SC和PW童鞋还不赞同),我最近很信奉Unix的一条哲学:do one thing and do it well. 或许真的有人可以很好的身兼PM和Dev Lead的角色,但是我还是太嫩了,并且或许这辈子都不可能做到。

但是这未必就不是一件好事,赫赫。

写了这么多,回头看看自己的网站还是那么的不尽如人意,实在是丢脸啊。我做不成一个好PM+dev,那我就努力至少成为一个好PM吧。

 

imac27teardown

(图片来源:http://www.slipperybrick.com/tag/imac/

11/17/2009

First Thing First

事情总是太多,而精力总是有限的,每天能做的事情实在太少。

如果每天有个50小时该多好。

当然这是不可能的,所以还是努力学习GTD吧,做到要事优先。

逐渐习惯了健康有序地安排自己的生活,逐渐懂得了有时候需要追根究底不达目的不罢休,有时候却是欲速则不达。

路还很长,要怎么能够又走得快,又走得稳呢?

还是继续努力地把雪球滚起来再说吧。

11/2/2009

新民晚报报道饿了么

DSCF0191

2009年11月2日 《新民晚报》B9就业导航版:)

 
Photo 1 of 6