技术

【Web 开发向】我会如何回答我自己常提出的面试问题?

前一段时间因为工作的原因(其实就是前端开发稀缺,找不到比我更高级的前端开发去给候选人面试了),我经常被叫去面试一些前端开发,其中有我们自己的职位的候选人,也有供应商团队的人员。因为我个人观念的原因,我很少像其他面试官那样去面试一大堆技术题目,或者疑难解答之类,更多的都是开放式的主观题,结果常常问得一些候选人(尤其是一些外包公司靠提前培训推销人头的)完全不知道如何回答。有朋友问我,这些问题的标准答案是什么?我的回答是没有标准答案,既然是开放性的主观题嘛。但之后我时不时地又会去想到,如果是我自己被我自己面试的话,我会怎么去回答呢?

抱着好奇的心态,我试着整理了一些自问自答的题目,当然其中省略了一些姓啥叫啥之类的基本问题,和一些根据对方回答临场发挥的衍生型问题。

面试的一般是类似 Senior Web Front-end Developer 之类的职位。

P.S. 写着写着不自觉地就开始想要吐槽了,于是追加整理了一些我平时最常得到的答复……

P.S.2 因为模拟的是面试,所以我有意地避免很仔细地推敲用词,毕竟这种场合是要临场发挥的。所以会有一些逻辑不精确、前后重复、前言不搭后语的地方,我有意保留了没有修改。

在 Web 前端领域,你有哪些语言和框架是基本掌握的,或者说掌握程度达到可以在项目中实际使用的?

常见回答:
  • 「jQuery」(90%的人都没有忘记它)
  • 「最近还看了下 AngularJS」(我们公司的项目在用 AngularJS,当时2代 Angular 已经出来了,React、Vue 等也都开始大热,80%的人只提到 AngularJS 而其他的都不知道让我很怀疑其真实性)
  • 「ionic」(唯一有一个人提到过,我当时都没了解过 ionic,结果是我自己不得不去搜了一下)。
我的回答:

目前用得最熟的是 Vue,之前项目中用过 AngularJS,一代的那个,也用过 Backbone,不过日子有点久远,可能要稍微花一点时间重新捡起来。语言的话 HTML、CSS、JS 肯定会,但我已经不太直接写了。像JS 方面最近比较爱用TypeScript,CSS 这边则比较喜欢用 Sass,项目中都在实际使用了。HTML 的话之前用过一段时间 Ruby 平台的 HAML 和 Slim,前几天试了试 Jade,就是前几天改名 Pug 的那个,但总觉得不是很舒服。

你是怎么学到了这些的?

常见回答:
  • 「之前工作中遇到的吧」和「之前看到有点感兴趣就自己看了看」(最常见的两种回答)
  • 「之前外面读了个培训班他们教的」(有个很实在的人这么说的……帮人干活还要倒贴工资的可怜人……)
我的回答:

Backbone 和 AngularJS 是工作原因,之前在外包公司时有个项目的客户是一群技术很好的美国人,他们用的这些,我就跟着偷学了。他们一开始用的 Backbone,但后来换了个 Leader,他更熟悉 AngularJS,刚好赶上重构,就换掉了。

其他的基本都是因为一些原因而自学的,大多数是在接触 Backbone 和 AngularJS 之前就学了的,但 Vue 和 TS 是在那之后。AngularJS 那个项目后期的时候我自己在看当时新火起来的 React,因为在帮隔壁 Team 的忙,他们在用。期间一次在 Twitter 上看到一个朋友提到,就去看了一下,觉得意外的好用,刚好那时候离职了,就转去学 Vue 了,顺便也啃了下 Webpack。TS 在那期间其实就试着学过一次,但当时要学的东西太多忙不过来就先搁置了,学了 Vue 之后又开始重新学的,初衷其实只是想要 IDE 的提示和自动完成用起来更舒服一点。

你用什么 IDE 和编辑器?

常见回答:
  • 「Eclipse」(我还真不信,说 Aptana 可信度还高一点……)
  • 「Sublime」(还挺常见的回答,但当我问他们 Sublime 一个 License 要多少钱时全都是一脸懵逼状……)
  • 「EditPlus」(有些年纪大的会提到,好多年前我也用过,而且没付钱……)
  • 「WebStorm」(我没问他有没有买╮(╯_╰)╭)
  • 「记事本」(好多人这么回答,觉得自己很酷么……)
  • 还有人提到过一个很小众的国产的专门针对 Web 开发的编辑器,名字我忘了……
我的回答:

写代码我一般都是用 IntelliJ 的,就 JetBrains 的那个,比其他免费的好用太多,就掏钱订阅了一下。除了小修小改外我很少会用文本编辑器写代码,真的需要的话一般是用 Notepad++ 或者 VS Code。哦还有一种例外情况就是在服务器上,我用 Vim,不过用得不是很熟,只知道基本的命令。

除了 Webpack,在之前还用什么类似的工具么?Gulp、Grunt 之类的?

常见回答:
  • ???(多数人并不知道 Grunt 啥的是什么鬼)
  • 「Grunt / Gulp」(少量人知道)
我的回答:

其实我第一个接触的类似的构建工具是 Ruby 平台的 Middleman,就是刚刚提到的用 Backbone 的那个项目。就是从那个项目我开始意识到可以用 HAML、Sass、Coffee 之类的语言直接去写网站,并且就像在 Rails 里那样实时看到效果而不需要每次都编译半天,发布时又可以直接编译成静态文件。之后那个项目在换到 AngularJS 时一并把平台换成了 Grunt。之后我自学的 Gulp 和 Webpack,后来因为 Angular2 的关系还学过一下 rollup。现在我一般是 Webpack 和 Gulp 一起用的。

哦对了其实因为现在是 TS、Webpack、Babel 来做模块管理了,以前 Middleman + Backbone 时代客户用的是 RequireJS,但我真的不喜欢。很庆幸后来换到 AngularJS 后就没必要做这个了,简单 concat 一下就好了。

除了这些 NodeJS 的工具外,你自己会去写 NodeJS 么?

常见回答:
  • ???(多数人并不知道 node.js 是什么鬼)
  • 会吧(少数人的回答,没什么信心的语气)
  • 之前写过些简单的工具什么的,还有 Express 之类(有个真的比较 Senior 的人似乎是这么说的)
我的回答:

会。你知道前端跟后端有个很大的区别就是能离开后端独立玩的东西很少,要学什么或者练什么时很难没有后端,所以我也学过写 WebService,最早用 Ruby 和 Python,后来也学过 Go 之类,但最常用的当然还是 NodeJS。除了真的 WebService 外我每个项目也都会写一个用假数据的 MockAPI,用来测试。这个也是我从那个 Backbone 的项目借鉴来的。后来因为写太多了我就单独写了个 npm 包来做这事情,这也是我唯一一个在 npm 上公开发布的内容。

除了这个之外,我也常用 NodeJS 去写一些小工具,比如我之前写过一些清理冗余照片的、Excel 和 Json 转换的、从数据源生成特定格式数据的之类。其中有些也试过写成 node-webkit 或者 Electron。

你是直接写 HTML、CSS、JS 的吗?还是会用一些别的语言去写然后编译过去?

常见回答:
  • ???(很多人并没听懂我的问题,其实我也不知道应该怎么更好地描述这个问题,又不能直接把语言名字报给他们听)
  • 没有(除了上面一个外几乎全都是没有了)
  • Sass / Less(偶尔有些人学过,因为 Bootstrap……)
我的回答:

HTML 这边我学过 HAML、Slim 和 Pug(之前叫 Jade 的),CSS 这边我学过 Sass、Less、Stylus,JS 这边我学过 CoffeeScript、TypeScript,那个跟 TS 竞争的 Flow 什么的应该不算语言吧?

HAML、Sass、Coffee 我是学 Rails 的时候学到的,HAML 我不是很满意所以后来学了 Slim,换到 node.js 平台后又试了 Jade(后来改名 Pug 了),但我都不是很满意。现在我大概随心情有时候写 Pug 有时候直接写 HTML。

CSS 的那几个我远更喜欢 Sass,不是 Scss,是缩进的那个。我不喜欢大括号(笑)。现在除非特殊情况比如要用 Ant Design 之类只有提供 less 没有办法的,不然我都是写 Sass。不过有时候要跟 team 共享的话我还是会写 Scss,怕 Sass 有些人接受不了。

JS 的话我以前很喜欢 CoffeeScript,后来因为作者比较固执(他家的 Backbone 也几百年没更新了),一直不肯接受新的 ES 特性,有了 babel 后我就不再写 coffee 了。再后来写了 TypeScript 后上瘾了。

除了这些之外,是不是还有什么 Web 前端技术你有简单了解过或有所耳闻呢?都是怎么知道的?

常见回答:
  • 呃……啊……(很多人什么都没说出来)
  • YUI……(有些年纪大的还记得它,但我记得有一个很年轻的人这么跟我说,这个可怜的孩子之前在日企,就是觉得技术太落后才想出来的……)
  • Bootstrap(上镜率挺高,确实也算没错)
  • React(有一两个人知道)
我的回答:

呃……只是听说过都算的话有点多,就只算至少简单写过一点 Hello World 的那些吧。按时间顺序么最早最早的时候 jQuery 和 YUI,Flex 和 Silverlight 不知道算不算,我还真做过整站 Flex 的项目,这些都是在我大学毕业第一份工作时的事情了,其实那时候我是美工,主要工作是 PS 画图而不是写代码,但国企小公司你懂的,能者多劳嘛……

后来我第二份工作不是特别忙,Leader 是个牛人,就让我空余时间去学的 Ruby(其实我那时候是想学 Python 的)。然后顺理成章学了 Rails,后来又觉得 Rails 太重了,改成了 Sinatra 之类。再后来因为 Windows 上 Ruby 的开发环境很麻烦,加上 NodeJS 开始流行了,我慢慢的就不玩了,之后后面做自动化测试时还用过。不过因为 Rails 的关系,当时学了 Sass/Scss、CoffeeScript,HAML。顺便那个 Team 里还狠狠锻炼了我的 Linux 技术,终身受用。

后来换了个 Team,比较小,没有人带,基本都是在消化之前学的东西,并没有学太多新的技术。非要说的话就是因为之前 Team 用的 CVS 我非常不喜欢,于是花了很多精力学了 Git 和 Hg,那时候 Git 在国内还没现在那么流行,有问题都没人问。

再后来就是那个 Backbone 的项目了,那个项目刚刚说了客户是一群技术控,到那时候才算正式从做网页转向写 JS,感觉打开了新世界的大门……按那个项目用了 Middleman、Backbone、Scss、HAML、Mustache(同时用 HAML 和 Mustache 的感觉真的很怪),还有 RequireJS,听说客户本来还想用 Coffee 但后来发现高估了团队的技术能力就放弃了。 那时候学 Backbone 又是周围完全没人会,又不能老去问客户,只能很艰苦地自己啃下来。

项目第二阶段时改成了 Grunt、AngularJS,附带了一堆 AngularJS 的生态,比如 restangular、ui-router、ui-bootstrap 之类。这次 AngularJS 是一样的问题,只能自己啃,其实我因为对之前的项目结构不满意,早就私下在研究其他方案了,就有预习过 AngularJS 和 Ember,但仍然感觉很难学(笑)。另外这次加了 UT,用的 Jasmine 还有 Sinon。其实我之前自己写过 UT,一开始是 Qunit,后来用 Mocha、Chai,但我已经不记得是什么时候学的了。

第三阶段时我本职工作里倒是没什么大的技术变化。但因为有些关系很好的做 Tester 的同事要去做自动化,所以学了一些自动化的东西。当时他们是用的 Java,但我不喜欢 Java,所以用的 Ruby 平台的 Cucumber、Capybara 之类,然后 Selenium 和 Watir 也是都玩过的。另外 RSpec 真的太迷人……直到现在我仍然觉得用 Ruby 写测试是最漂亮的。

再后面的工作又回到了没人带路的阶段,刚才提到的自学的 React 和 Vue,然后接触到了 Webpack、Babel 和 TypeScript,又是新世界的大门的样子……

你觉得你平时的工作是编程占比重多一点还是绘制页面占比重更多呢?

常见回答:
  • 画页面吧(项目早期供应商推了很多这种人过来,花了很久才跟他们说清楚我们要前端开发不要美工)
  • 写 JS 吧(后面推来的基本都是写 JS 的了)
我的回答:

第一份工作是设计页面多,美工嘛,不过设计完了还得自己把静态页面画出来……在那个 Backbone 的项目之前是绘制页面多,之后就几乎全身心投入 JS 编程里去了。讲真我现在在 Web 前端开发最大的软肋就是不怎么了解页面效果实现之类的东西,都是 Bootstrap 啊 Material 啊现成的一套了事,反正都比我自己设计的好看(笑)。

那你个人的爱好或者说期望是希望哪方面更多一点?

常见回答:
  • 还是偏静态一点吧
  • 偏 JS 吧
  • 好像都可以吧,我不是很有所谓

偏 JS 的比较少,另外两个差不多多……

我的回答:

现在的比重讲真还蛮符合我的期望的,讲真我现在是离后端越来越近了。

你上一个岗位里的主要工作内容是什么呢?

常见回答:
  • 设计页面,然后画出来,交给后台开发(国产美工,我的第一份工作……前期推来很多这种人)
  • 画静态页面,交给开发(比美工还少了个设计,我的第二份工作……)
  • 开发 JS(后期推来的基本都是开发了,但更多的也说不出什么)

另外还有少数人提到跟客户沟通、确定需求之类的,一般都是身处一个很小的 team。

我的回答:

(假想我面的是现在公司的岗位,所以跳过现在的工作)

我的本职工作还是 JS 开发吧。当时我们 Team 有8个开发,但有4个人一开始是基本不会写 JS 只能画静态的,老板是想要分工一半人做页面一半人写代码,结果客户不买账……

另外因为客户要求用如 HAML、Scss 之类的技术,只有我会,所以我还给大家培训……

然后 Git,还是只有我会,于是又得培训。然而 Git 其实是个需要深入理解去领会的东西,很多人跑去拿本子抄命令,这样根本没用,于是在之后的两年里我还是得不停地给大家解决各种各样的 Git 问题……

然后 Linux,还是只有一两个人会,除了我另一个是 Leader 而他要出差……因为客户的开发环境是 Linux 虚拟机,于是帮大家装机和解决环境问题的人还是我。直到现在我还在吐槽我一个那么讨厌 Java 的前端开发找了个帮 Java 开发安装配置 Tomcat 的工作……当然这个是开玩笑,我们的真正的 Java 开发还是很厉害的,主要是我们 Front-end 团队的开发和测试,尤其是后来测试被要求写 automation(用 Java 写的),而他们之前是做 manual 的,很多人根本没接触过编程。

另外因为我们的 Leader 连续在客户那里出差,所以我常常得顶替一下 Leader 的角色,虽然说实话我那次做得比较差,我在管理人方面的天赋并不高,但好的一面是还是学到了很多宝贵的管理知识和经验。

你有没有学过一些后端的或者其他的开发技术呢?

常见回答:
  • 学校里学过 xxx(很多人会这么说,但学过什么我觉得并没有什么关系)
  • Java、.net、PHP(人气最高的语言群体,很正常)

基本没有人提到任何语言之外的框架、技术之类,也没有人提到任何相对比较小众的语言,连 Python 和 Ruby 都没人学过。

我的回答:

学校里教过 C、C++、Java、.net 之类,可以无视。大学时因为跟朋友合伙搞论坛,所以学过 PHP,已经全忘了。后来学 Silverlight 后又去学了桌面端的 C# + WPF,还顺便学了 F#,当然也全忘光了。然后学的 Python 和 Ruby,这些是还能拿出来凑合用一下的。Python 当时用一个新的叫 Eve 的快速搭建 WebService 的框架用得很舒服,还贡献过代码,也用 QT 写过桌面的,就一个文本框一个按钮(笑)。 Ruby 刚刚提过就是从 Rails 转的 Sinatra、Mongoid 之类,还有些自动化的东西。

第二家公司开始几乎后端都是用 Java 的,我不喜欢 Java,但因为对后端的东西好奇,加上后来出现了 Android,所以先是试着自学了 Scala 写 WebService 和 Android,但学不会(果然我还是不适合函数式,之前 F# 也学得一头雾水),后来 Kotlin 拯救了我。

再后来因为兴趣的关系自学了一点 Go,勉强可以写点简单的小 WebService 出来。还简单看过一点 Rust 和 Dart。哦对之前因为去 nVidia 面试的关系还自学了一点点 Lua。

你写单元测试写得多么?

常见回答:
  • 没有写过(大多数)
  • 不多(少数)
我的回答:

严格来说不多,除了项目要求的之外(当初 AngularJS 那个项目是有 UT 覆盖率要求的)。我一般是给一些特别关键的核心逻辑代码写少量的 UT。另外有时候遇到一些逻辑特别复杂容易出错的模块时我会用 TDD 来写,这样反而比较省时间。

你对网页自动化测试有多少了解?

常见回答:
  • ???(一脸懵逼,100%)
我的回答:

直至我上次做自动化测试时,网页自动化测试相比 API 自动化测试仍然很不成熟不稳定,我是这么认为的。变数太多以至于完全自动化很难,一般跑的时候最好还是要有人看着。而且出了问题 Debug 很困难,经常会有灵异问题,比如我之前 Team 里大家用同样的浏览器同样的网页同一个版本的 WebDriver 但他用 Java 写我用 Ruby 写一模一样的 case 结果我能通过他就说 element not found,至今没找到原因。听说 Chrome 和 Firefox 要出 Headless 版本了,希望到时候能有改观。总得来说我觉得如果 API 自动化还没做的话应该先做 API 自动化,那个的投入产出比要高得多。

另外我还有一个切身体会就是网页自动化的 case 最好让页面开发自己写,这样他们才会真的体会到好好地去组织规范 ID、Class、Name 之类的属性还有 Label 标签什么的这些老生常谈的语义化有多重要了,总有一堆人喜欢在那里嚷嚷样子对了不就好了什么的,然后就是给别的 Team 挖坑。

你用版本控制工具么?

常见回答:
  • Git(用过的人不多但总算还是有的)
  • SVN(毕竟老牌,还是有一些人用过)
  • 小乌龟(这么说的人还不少,所以其实就是用了半天连名字都没关心过,不知道应该作何评价)
我的回答:

用,现在基本固定 Git 了,有一段时间很喜欢 Hg。其实我蛮早的时候就接触 SVN 了,第一份工作时就有,没错就是我还是美工时……不过第一份工作时主要用的是微软的 SourceSafe,SVN 只用了很短一小会儿,第二份工作时用的 CVS,还是纯命令行的,后面还有个银行的客户非要买个什么很奇葩的商业工具,莫名其妙,用得我非常不爽,之后就去怒学了 Git 和 Hg。

你之前的团队大概有多少人?是怎样的构成?我是说有多少前端多少后端多少测试多少 PM 之类。

常见回答:
  • 不知道(很多人真的并不知道自己团队有多少人!)
  • 大概有 x 个人吧(但并不知道他们是干什么的!)
  • 有 x 个开发吧,还有设计、PM 什么的……啊?测试?好像有一个人吧(常见一个测试伺候七八个开发的)
我的回答:

最近的工作其实团队并不成型,我属于一个游击手的角色,就不说了。之前一个 Team 里如果限定在 frontend 的话一开始是有8个 dev、5位 tester,其中4个 dev 是不会写 JS 的,当初老板设想的是4个人做页面4个人写 JS,但似乎客户并不买账(笑)。另外我们的 tester 是 manual 和 automation 都要做的。

整个项目组还有一个 backend team,一个 mobile testing team 是做移动端自动化测试的,还有个 integration testing team,说得好听是 integration 其实做的活就是 backend automation testing,他们中的很多人直到最后都没见过前端界面长啥样,我们 FE team 的 tester 才是真的在做 integration testing。我们有个 PM,澄清一下是 Project,不是 Product,不同公司用的缩写不一样。他至少会管我们 FE team,但视情况不同也可能会参与其他 team。然后我们的 ODC Manager 也跟团队走的很近,最艰苦的日子基本每天都在一个 war room 里过日子。

听起来团队还挺轻巧的样子,你们是用什么方式管理的?是跑敏捷的么?

常见回答:
  • ???(一脸懵逼,软工课已还给老师)
  • 不知道……(有些人我详细询问了他们 Team 平时干些啥后觉得应该是跑 Scrum 的,但他们并不知道不了解也不关心)
我的回答:

账面上算是,跑的 Scrum,但其实我觉得不是,Scrum 没有 PM 不是么(笑)。我们的客户技术是很好但似乎并不擅长做项目,而且也没有跨洋外包合作的经验。我觉得用 Scrum 是他们的一厢情愿,也许因为那时候 Scrum 很流行听起来很酷,虽然我私下也经常吐槽他们只是因为懒得写文档。团队里自上而下(包括客户自己的人)都不知道自己应该干什么,技术团队跟需求源隔离,原因很多,比如时区、语言,还有甲乙方隔阂,客户关系紧张的时候老板是不会放心让底层员工直接接触客户的,这也就是为啥我们会有 PM……

客户偷懒不写文档,管理层、产品、设计、搭档其他外包公司团队都是换了一批又换一批,代码多次推翻,大方向数次改变,到后面没人知道最初的需求是什么样子,而且大家做了无数无用功后对项目赶到疲倦无望,没有成就感,士气低落,Leader 和 Manager 们每天都很头疼。团队和团队间还有客户那边人和人之间毫无沟通,欺上瞒下现象严重,我们的 Tester 曾吐槽说有开给别的外包 Team 的 P1 的 Bug 人家直接改成 P3 然后大摇大摆把 Story 给 Close 了,JIRA 里堆满了一年前的 Bug。

我一直觉得这项目如果老老实实跑瀑布啥事都没有。

你用什么项目管理工具、issue tracking 什么的吗?

常见回答:
  • 没有(很常见,嗯)
  • 有的(但并不知道名字……)
我的回答:

刚才说的 JIRA,最近几个项目都在用,以及 Atlassian 的一整套:Confluence、Stash(最近跟 Bitbucket 合并了)、Bamboo 之类。不过我自己是觉得这类东西太重了,事实上这些年大家都对敏捷着迷,团队里全是技术和产品,并没有足够多的专业 PM 来组织和消化这么多数据。指望开发自己去消化这些数据我觉得不切实际,我呆过的大多数 team 连个 retrospective meeting 都开不好……

我自己的话觉得 Github 自带的那个就已经挺不错了。

你平时工作中遇到技术问题会更喜欢怎么做?是挖文档呢?还是翻框架源代码呢?又或者是网上搜索、问答社区,或者问同事问朋友?

常见回答:

这个各种回答都有,就不一一列举了,但基本都是很虚的一两句话。

我的回答:

实践中我一般首选文档,然后是上 Google,当然搜索最终有80%可能不是落到 Stackoverflow 就是去到文档里我粗心遗漏的哪个角落。如果还是不行就只能去翻源码了。

有一些特殊情况例外,比如 TypeScript 类型定义这种翻源码非常直接高效的情况我会直接翻源码。

倒不是我不喜欢问人,而是我周边实在没太多朋友能问的,有时候觉得挺孤独的……

长远来看,你是比较希望往产品的方向发展,还是往管理的方向发展呢?还是说你打算一直走技术的方向?

常见回答:
  • 没想过(很多人)
  • 产品吧(在产品、管理、技术三条线中最热门)
我的回答:

如果不出什么意外的话我会一直坚持做技术。不过我并不排斥产品和管理,我自己对项目管理很感兴趣,也经常跟我的 PM、Manager 偷学、讨论一些项目管理的东西。事实上我觉得每个做技术的人都应该学一点项目管理的知识,不说别的,首先至少可以用于在糟糕的环境下自保,每个人都难免运气不好掉进一个糟糕的 team 里的。而产品这块其实是跟行业有关系,不同行业我感兴趣的程度也会不同。但我这人好奇心比较重,即使是我最不感兴趣的行业,我仍然还是会想要学到一点东西。

总得来说我还是希望当技术人员,但不是一个除了技术就一穷二白的技术人员。

个人感受

之前面试了这么多人,还是有很多共性缺点的。我觉得最不好的一点就是话很少,对每个问题都是一两句话甚至一两个单词来回答,知道的也不详细讲一讲、不知道的也不解释一下或者扯下其他的东西掩饰下,这样给人一种很肤浅的感觉。「我刚毕业第一份工作的时候学过 jQuery,那时候还很流行,虽然现在好像退居幕后了」一定是好过「jQuery」的。我怀疑这跟甲乙方关系以及资历都有很大关系,之前面试过一些甲方职位的人,相对就放得开很多,但这些人的资历也远更深,从穿着打扮从谈吐气质方面都明显要更高几个档次,所以应该也不只是甲乙方关系的原因。

另一个就是很多人很明显就是蒙起头来做事,对自身手头的 task 之外什么都不了解、不关心。我很难想象一个人在一家公司工作一年连自己一个小 Team 里有几个人都不知道,对自己工作中使用的技术是什么、其周边生态、发展前景一概不关心的人工作起来到底是什么样子,但第一印象肯定是对待工作敷衍应付。

其实就算是面试乙方人员,我也遇到过年纪很轻但很能说很会扯的,虽说有点浮夸,但至少给人一种积极的、好学的印象。如果在面试中给面试官留下「这个人只做本职工作别的都不关心」的印象真的是很不利的。

还有一点就是既然我们都是要求招 Senior 以上的 Position 了,自然是要求有一定的 Lead/Manage 的能力的,这也就是我会问 Team 里有几个人、做什么、Team 是怎么管理的相关的问题的原因。我并不指望招到一个已经会做管理的人,但至少还是希望能找到一个被管理过的人,见过猪跑、照着猫还能画画虎的人。

两栏自适应带头尾

回想起刚刚工作的时候,作为一个一入HTML/CSS的门就跟着CSS设计风格走的人,各种经验其实还不是很丰富,想要说服公司里的那群Table党,其实并不是什么容易的事情。尤其是当他们举出一些对table布局来说很轻松的case时,我却拿不出应对的方案。其中有两个让我纠结很久的问题,一是自适应页脚(当页面不足一屏高时显示在屏幕下,当页面超过一屏高时跟在内容后面),另一种是自适应宽度的多栏布局。

后来渐渐的,经验开始丰富起来,也离开了之前的单位,新的单位中从零开始的设计变少了,更多的是维护工作,也就渐渐地把网页设计的基本功给淡忘了。最近因为朋友买了域名开始着手设计个人网站,我才突然有性质再捡起一些无意间丢掉的东西来。

首先想到的就是上文提到的两种情况,当时经验浅薄,也没什么见识,这件事情会着实困扰到我。而最近我在Github上抄袭设计(做我那个RewindBug)时,留意到了Github的页脚设计。放到自己提炼的简单情况下来,稍微做了些修改,得出了一个让我还觉得的结果。至少,这个布局结构比我预想的还要健壮一些,除了为了保险起见加的clearfix外没有使用任何hack代码,同时包括了自适应两栏和自适应页脚,居然能在最低IE6下很好地工作……

[pyg l=”html” s=”autumn” tabwidth=”2″ linenos=”table”]





something here

something here.



[/pyg]

在 Sinatra 中使用 RESTful

最近在学习Sinatra。今天遇到了关于RESTful的问题,用过Rails的各位应该都对这个不陌生了,不过重量级的Rails有内置helper帮我们在模板里生成那些东西,轻量级的Sinatra可不会,我们要自己动手。

仿照Rails,在views模板中加入了 <input type="hidden" name="_method" value="put"> ,然后submit一下试试,然后发现还是被判断为一个post请求……

上网查了资料,说是如果用的是Modular风格的话,必须自己动手加入 use Rack::MethodOverride 。试了下,果然可以。

但是又觉得这个方法太傻了一点,于是又在Sinatra官网仔细晃了一圈,发现原来settings里有这一项 :method_override ,加入代码,搞定。

app.rb:

# encoding: utf-8
require "sinatra/base"
require "sinatra/contrib"
require "slim"

class RestTry < Sinatra::Base
  set :method_override => true
  register Sinatra::Contrib

  route :get, "/" do
    slim :rest, :locals => { :method => request.request_method }
  end

  run!
end

rest.slim :

doctype 5
html
  head
    meta charset="utf-8"
    title Sinatra REST Trying
  body
    p Method: #{method}
    section#get
      form action="." method="get"
        input type="submit" value="GET"
    section#post
      form action="." method="post"
        input type="submit" value="POST"
    section#put
      form action="." method="post"
        input type="hidden" name="_method" value="put"
        input type="submit" value="PUT"
    section#patch
      form action="." method="post"
        input type="submit" value="PATCH"
    section#delete
      form action="." method="post"
        input type="submit" value="DELETE"
    section#options
      form action="." method="post"
        input type="submit" value="OPTIONS"
    section#custom
      form action="." method="post"
        input type="submit" value="CUSTOM"

Rewind Track Wiki

1. 概述

1.1 起源

本项目完全基于个人兴趣,从 Rewind BBS 衍生而来。

“Track” 这个名字很容易引起误解,让人误以为这是一个 “BugTracking” 系统,其实并非如此。事实上当我最初开始打理自己的个人网站时,我在网站上留了一个叫 “Track” 的链接。这个链接的目的是为了陈列自己的设计作品,不论优劣,只是为了记录自己的生涯,就想家庭相册一样的感觉。

但是后来我渐渐地远离了设计师的道路,尽管仍然专注于 HTML/CSS 技术,却比以往更多地偏向于编写代码,本就浅薄的设计功底很快也就完全荒废殆尽了,这个陈列作品的角落也完全荒废了。

然而,有一件事一直让我放不下。因为作为一个陈列室,必定要有一个主页来列出所有的陈列对象。我最初是打算每次有新的作品加入时,手工修改静态的 HTML主页(我一开始就预想到很少会有更新),然而我却一直懒得给这个主页做一个详细的设计,最后在网站搬迁时,索性就把这个只有HTML没有半个字节 CSS和JS的主页都删了,留了个 Nginx 的 autoindex 页面出来。

于是最近,虽然我还是没有任何新的设计作品加入,但我决定要写这样一个简单的程序,动态地管理这个主页。如果这个网站最终无法陈列我的设计,那好歹让它陈列一下它自己好了……

1.2 需求概述

目前有2套方案,暂未最终决定

  • 方案1: 完全基于文件系统,没有任何额外的数据源。根据文件系统下的目录结构进行整理归档。这套方案比较简单,而且刚好可以帮助我练习一些平时不太熟悉的模块使用。不过最终的展示效果如何仍是疑问。
  • 方案2: 基于简单的 SQLite 数据库,添加陈列作品时人工录入必须的数据,并最终根据这些数据整理归档。这套方案灵活性更高,但是复杂度也较高,而且是否有必要也还是个问题……

让 Rails 3.1 默认使用Sass

因为比起用符号(大括号)控制的代码层次,更喜欢清晰的缩进式层次,因此想把Rails默认的SCSS改成SASS,希望通过诸如 rails g scaffold sth 生成出来的样式文件是Sass格式而非Scss格式。

在Google上奋斗了2个小时,除了在Stackflow上找到一篇文让我还略受启发外(但这篇文中许多人提出了许多种不同的解决方法,不知为何我用下来居然全都失败了),其他的几乎很难找到。

然后我开始读railties的源码……研究了半天generator,一无所获……最后都找到base.rb里去了。此时我开始意识到可能方向发生了错误,转而往更高层的方向寻找,最后终于在sass-rails/lib/sass/railtie.rb中找到了

config.sass.preferred_syntax = :scss

这行代码跟Stackflow网站上某人提出的办法相差无几,于是按照他的方法放入我的rails应用的/config/application.rb中,就在Application类中,跟在其他config.xxx后面,把:scss改成:sass,然后运行rails g scaffold orz,果然见到invoke sass,狂喜~

require File.expand_path('../boot', __FILE__)

require 'rails/all'

if defined?(Bundler)
  Bundler.require(*Rails.groups(:assets => %w(development test)))
end

module MyApplicationName
  class Application < Rails::Application
    config.encoding = "utf-8"
    config.filter_parameters += [:password]
    config.assets.enabled = true
    config.assets.version = '1.0'
    config.sass.preferred_syntax = :sass
  end
end

[牛角尖]用hg-rebase仅挪动一个branch的最旧一部分 – 改

前一段时间入门hg时碰到了这么一个问题,当时还写了一篇文:

[牛角尖]用hg-rebase仅挪动一个branch的最旧一部分

当时我就觉得这一操作感觉异常繁琐,应该还有改进的余地,今天无意中果然发现了改进的方法:

1、上次我在第一步时使用了这个命令:

hg rebase -s 2 -d default --keep

图三

“-s 2″ 参数将版本2开始的整个分支都rebase了,应该改用”-r 2″,这样将仅rebase版本2,而3和4不变。因此我们看到在图三(上图)中的版本6和7就不会出现。另外还有一点,因为默认是rebase到当前分支,所以如果当前是在default上,那”-d default”也可以省了。

改进后的版本如下:

hg rebase -r 2 --keep

2、然后,直接使用如下的rebase命令:

hg rebase -b dev --keepbranch

图二

这次直接使用了-b而非-s,换句话说也就是连版本2一起整个rebase了上去,所以–detach也就没有必要了(事实上如果不用-s也不可以用–detach)。然后神奇的事情发生了,因为版本5和版本2的changeset相同,default直接fastforward上去了,于是这次只用了2个命令就完成了这一转移,同时也避免了使用非常危险的strip~

WPF使用System.Windows.OpenFileDialog选择文件夹

这几天在重温C#.Net-WPF,拿个以前废弃的项目练练手,其中遇到一个问题:

WPF自身的命名空间System.Windows中没有打开文件夹的对话框,只有OpenFileDialog可以打开文件。

网上搜了很多帖子,无外乎三种答案

  1. 使用以前WinForm的FolderBrowserDialog:为了避免命名空间冲突导致的代码繁琐(两边都有OpenFileDialog)以及出于一些洁癖的原因,我这次决定坚决不使用WinForm,反正自己做项目也没工期什么的,大不了不做了~
  2. 扩写System.Windows.OpenFileDialog:要么自己扩写,要么用一些别人写好的开源组件,一个是太麻烦,另一个心里总觉得不太舒服
  3. 使用微软官方的扩展包Microsoft.WindowsAPICodePack:这个看起来很不错,但是也有缺点,就是完全要求Windows版本>=6.0,而公司的电脑还是杯具的5.1,只能放弃

正在纠结之际,国外著名社区 Stack Overflow 上看到这么一篇帖子:

原帖地址

一位大佬想出了一个看起来很orz的方法,不过反正也没其他解决方案,姑且一试。

这位大佬将Filter设置成一个非常非常长的扩展名从而起到隐藏所有文件的目的:

openFileDialog1.Filter = "folders|*.neverseenthisfile"

然后把文件名设为一个”r”换行符来骗过OpenFileDialog,这样只要不改动文件名就能直接按打开按钮。当然同时还需要把CheckFileExists给false掉……

我修改了他的原型代码后得到了如下版本:

OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "folders|*.sado;fjsdal;fj";
ofd.FileName = "r";
ofd.CheckFileExists = false;
ofd.CheckPathExists = true;
ofd.ValidateNames = false;
if (ofd.ShowDialog() == true)
{
	ofd.FileName = ofd.FileName.TrimEnd('r');
	int lastSeparatorIndex = ofd.FileName.LastIndexOf('\');
	ofd.FileName = ofd.FileName.Remove(lastSeparatorIndex);
	txtCOutputPath.Text = ofd.FileName;
}

运行后成功取到了目录,并且哪怕不当心在文件文本框里输入了内容也可以正常工作了。本以为事情到此为止,我甚至都把这篇博文发表了出来(第一稿是到这行的前一个句号就结束的),到家后再试才发现家里的娜娜不买账!!!

仔细研究后,发现貌似娜娜不认ValidateNames属性,不论这个值是true还是false,她一定会检查文件名是否合法……好在她并不在意文件是否真的存在,所以代码稍加修改还是可以用:

OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = CoffeeScript._ofdOutputFilter;
ofd.FileName = "Filename will be ignored";
ofd.CheckFileExists = false;
ofd.CheckPathExists = true;
//ofd.ValidateNames = false;
if (ofd.ShowDialog() == true)
{
	//ofd.FileName = ofd.FileName.TrimEnd('r');
	int lastSeparatorIndex = ofd.FileName.LastIndexOf('\');
	ofd.FileName = ofd.FileName.Remove(lastSeparatorIndex);
	txtCOutputPath.Text = ofd.FileName;
	return true;
}
return false;

不过这种做法还是有一定问题的,如果用户不当心选中了一个文件夹,那他后面的麻烦就大了……看来这个问题还需要再研究一下……

[牛角尖]用hg-rebase仅挪动一个branch的最旧一部分

本文已有追加内容:[牛角尖]用hg-rebase仅挪动一个branch的最旧一部分 – 改

最近刚刚开始学习git和hg,对于git的历史修订功能爱不释手,但是在hg下想要如此偷天换日就没那么方便了。幸好现在有了诸如rebase、mq等扩展,事情变得容易了许多。

事实上国内的hg学习资料很少,本人英文水平很残,今天想实现一个功能,Google半天却无解,只好自己想了个歪门邪道的办法绕路实现,总觉得hg应该有内置什么方法可以直接实现,苦于不认识任何VCS的达人,无处求教啊。

实际情况是这样的,因为我依旧喜爱使用branch而不是bookmark或者mq来实现本地的开发分支,然后当把dev分支rebase到主分支时,我希望分段逐步rebase,而不是一股脑全rebase过去(为了整理注释),于是就出现问题了,不知道如何实现……举个实例如下:

thg-glog01

现在想要将dev分支的最旧节点2给挪到主分支上去,保留3、4不动,因为2是一个有意义的、完整的提交,而之后的3、4则是未完成的、无意义的提交,需要以后用rebase –collapse来合并,也就是想要如下效果:

thg-glog04

找现成命令,失败……于是改为研究绕路走,最后用如下方法折腾出了结果:

1、首先第一次rebase把整个dev分支挪到default的头上去,加了–keep参数来保留dev分支本身不在rebase后被删除(也就是说本质上是把dev分支复制了一份到default上):

hg rebase -s 2 -d default --keep

thg-glog02

2、第二次rebase,把要保留的版本3-4“复制”到版本5上(版本5对应的是版本2),这次加了–keepbranch让新复制出来的版本也属于dev分支(不加的话就是default了,如上一条),加上–detach来把版本3-4从版本2上剥离下来,避免带过来不想要的merge信息:

hg rebase -s 3:4 -d 5 --keepbranch --detach

thg-glog03

3、到此为止,我想要看到的那条历史树已经有了,只不过它还藏在一堆其他的垃圾版本中,是时候砍掉他们了,使用杀手锏strip干掉多余的版本2、4、5:

这里注意如果先strip掉了2,那么4、5就会自动递减为3、4,随后需要strip的就是3、4而不是4、5了。如果先strip掉了4、5,那接下去还是strip 2 不受影响。

thg-glog04

这样的做法其实真的是非常麻烦的,如果那位高人知道什么捷径,烦请指点一下啊。

另,rebase、strip之类一般只能用来清理自己的垃圾数据,可千万别对着战友们的劳动成果手起刀落啊……

我为什么不讨厌QQ?

/* 前言:博客好久没更新文章了,难得想要起笔居然是写这么个话题,我自己都有点囧……不过说实话这篇文我很久就想写了,早在3Q大战之前就一直有这个想法,但是一直没动笔。3Q大战时特有这冲动想写,但一时忙(忙着打游戏呢)也就忘了,今天偶然和朋友聊到这个问题,想趁热打铁写下来。 */

本文只讲个人喜好和客观事实,不打算主观划定优劣,青菜萝卜各有所好,欢迎符合主题的讨论,喷子自重(虽然我这里很少有人来不过生活在喷子的国度总让我心里不踏实)

我个人不能算是个Geek,作为个半吊子程序员(对PHP、C#、Python、Ruby、C都略有接触但仅仅停留在接触)和 HTML/CSS Developer,我顶多算是偶尔跟一些国内外的Geek、Geek爱用的东西打打交道(比如在Debian下搭搭开发环境啥的)。

关于IM,在PC/Windows平台上我是QQ、MSN的老用户了,同时也是Gtalk、YIM(Yahoo Messenger)、Skype(仅限于文字聊天)的低级用户;在移动平台上我是Kakaotalk、Whatsapp、Kik、Hanashi、Talkbox、Huddle(G+自带那个)的低级用户。排除移动平台的IM不说(他们的定位和PC/Windows上的IM不同),在PC平台上的几个IM里,如果让我按照自己的喜爱程度排名,我会选择 QQ > MSN > Gtalk > Skype(文字聊天) > YIM。是的,在这些IM中我是最喜欢用QQ的(再次强调是PC/Windows版)。另外还要强调一点,这个喜欢与否是排除用户群体来说的,“我很多朋友都用QQ而在别的IM上没人”这个理由,在我看来只能成为“用QQ的理由”,而不能当作“喜欢QQ”的理由

据我所知,在Geek和准Geek圈子里是有很多人非常非常讨厌QQ的,原因很多,虽然在我所了解的范围内看来有一些比较牵强。所以这些我放后面逐个穿插着来说,先说说为什么我会喜欢QQ。

首先是功能。这一点是昨晚跟 @Shyc2001 聊到用户体验的问题时谈到的,所以先来说这个。

QQ的用户体验,虽然我觉得还不至于如一些人所说的“极差”,但确实不咋样。但是我认为有一个很重要的问题他们没有意识到,或者说被有意回避了,那就是功能和用户体验的平衡。功能和用户体验并没有直接的冲突,但是在一些情况下,功能变多确实会导致用户体验的下降。举一个例子来说:一旦你把某个功能加入了产品,那么你就必须保证用户在需要它的情况下可以方便地找到它;而如果你把它们全都堆在显眼的位置,那我必须说视觉效果也是用户体验非常重要的一部分,并且堆了一定数量之后也未必真的就容易找了,具体后果可参考任意中国的Gov官方网站。当然,上述只是两者之间复杂的互相影响互相牵制的关系中的一小部分而已。

而功能和用户体验,我认为这是一个“椟”和“珠”的关系。在“椟”的差距巨大而“珠”差距可以接受的情况下,我们会选择一个“椟”更好的产品,但是作为一个产品本身,“珠”才是最重要的本质。所以我先来说下“珠”的问题,待会儿再回过来说“椟”。

我之所以喜欢QQ的最重要(也可能是仅有)的两个原因就是它完善的群功能和内联贴图功能。注意前面我强调出来的两个词,我之所以以让文章视觉效果打折扣为代价把他们强调出来是有理由的,之前碰到过很多人跟我说“MSN也能贴图啊”、“Gtalk也能群聊啊”之类的,但是都不符合这两个关键字。(还有一些功能相关的后面放在用户体验那一块里说)

// 用户才是功能的选择者,一辈子都不光明正大地和同学来往(不需要班级群)、不玩游戏(不需要游戏群)、和同事总是敌对关系(不需要Team群)、总是有耐心等待邮件同时总是一想到对方可能错过你的消息就吃不下睡不着的人可以跳过这一部分。这段话并非贬义,特定的生活条件下确实有不少这样的人。

可以通过对比来说明我有多重视这两个功能。先来说群功能,我使用QQ时超过99%(是的,我可以很负责地说这个数字只会偏小不会偏大)的时间、接收文字、发送文字都发生在群里,首先我要说的是“群”和“多人聊天”完全是两码事,所以请不要拿Gtalk的多人聊天来说事。在我用过的PC/Windows平台的IM中,QQ、MSN、Skype都有官方群功能(Gtalk有山寨群),那么来稍微对比一下。

// 群-MSN

MSN是很晚才加入官方群功能的,直至今日一些老版本的MSN依旧不支持群,几乎所有Android菜场里找得到的客户端都不支持群(近期手机系统我只用过Android),甚至包括官方的Web版MSN也不支持群。

前些年,有些公司通过一些第三方服务器的手段来实现了MSN的非官方群功能(Gtalk下也有),然而这些群普遍广告泛滥(毕竟他们是需要盈利的),与客户端的集成性能很差,只能通过现有的功能去模拟,比如MSN群用震动功能呼叫控制面板,然后弹出网页或者用命令行来管理群(不然怎么办?反编译MSN?),另外其实现方式是通过一个第三方服务器上的BOT来自动转发消息给其他对应联系人,第三方托管服务器还存在稳定性问题、速度问题、安全性问题等等其他隐患,因此这一条路只能算是临时的应急措施,凑合下可以,当真用不行。

而MSN的官方群功能怎样呢?除了前面提到的软件支持问题外,实际上就算官方支持的客户端稳定性也不好,经常会发生群明明有人看起来却离线的问题,需要用任务管理器强制结束wlcomm程序来强刷解决。然后在群内无法使用一些高级聊天功能,比如贴图(不说内联贴图了,什么图都不能贴),如果我要在MSN群里贴图怎么办呢?首先自己找一个截屏工具(网上应该很多,Win7自带一个不过不好用),截图然后找个图床上传,我喜欢min.us,然后把地址复制下来,再贴给对方,而且效果也不是内联的。另外值得一提的是:MSN群有群空间,可以上传照片和文件,虽然用网盘需要单独开个浏览器很麻烦,但是至少是有了,而且空间还比QQ群的要大,这方面可以认为是不比QQ差太多。

// 群-Skype

然后再来看看Skype,其实我觉得严格来说Skype并没有和MSN、QQ对比的义务,它的定位不同。Skype本质上是个网络电话的软件,文字聊天只是附带品。这个附带品也确实有附带品的样子,其功能基本上和Gtalk这个轻量级IM没有什么区别,甚至连更改文字字体和颜色这种基本的个性化功能都没有,一眼望去一片白底黑字,还得去看用户名(Geek往往会非常受不了这些忽大忽小时红时蓝的文字,而个性化对其他一些用户来说非常非常重要。比如对我来说,我会在Photoshop里精心挑选字体颜色,对于字体和字号的选择也非常谨慎,我认为这一方面是自己审美观的最直接体现,同时也是自己实时动态的一种,如最近喜欢橘红色胜过蓝色,明天可能不一样了。同时这还造就了另一种现象——QQ用户往往会首先根据说话者的字体、字号、颜色来判断这人是谁,而不是用户名,这让一帮Geek死活无法理解),顺便一提,MSN想把一个比较精确的颜色指定为字体颜色需要自己动手修改注册表,另外MSN下不能修改自己的字号,只能修改整个聊天界面的字号。

受这一客观条件的影响,事实上Skype的群跟多人聊天并没多大区别。除了个性化以外,相对MSN来说,好处是可以直接在群里群发文件了,至于图片……按Ctrl-V贴上去后你会发现变成群发一个图片文件了……

// 内联贴图

内联贴图其实只是贴图的一种方式,并不是说它就比其他的贴图方式要好,各种方法都各有所长,只是我最喜欢这个方式而已。还是拿桌面上的QQ、MSN、Skype来做比较,因为他们刚好是3种方式的典型。

内联的贴图方式好处包括:即时性强、上下文关联性强、浏览方便、时间精确。主要的缺点在于要实现这些优点对于客观条件(网速等)的要求较高,如果实现不了那就一无是处了。另外QQ在这方面的实现本身还有一个额外的缺点——不带确认。

来随便举个实例,教一个不是很会电脑的同学在Win7下更改驱动器盘符。那最后显示在聊天窗口里的顺序应该是这样的:

  1. 右键计算机,点管理
  2. [一张右键菜单的截图,鼠标指在管理上]
  3. 左边树里找磁盘管理
  4. [一张左边菜单树选中磁盘管理的截图]
  5. 在右下角找到你要的盘
  6. [右键周围大致图样+右键菜单截图]
  7. 等等……

在MSN里是这样的:

  1. 右键计算机,点管理
  2. 左边树里找磁盘管理
  3. 在右下角找到你要的盘
  4. 等等……
  5. 画面右边一个单独的窗口,里面一堆没顺序的图片……

在Skype里是这样的:

  1. 右键计算机,点管理
  2. xxx发送文件:剪贴板1.BMP
  3. 左边树里找磁盘管理
  4. xxx发送文件:剪贴板2.BMP
  5. 在右下角找到你要的盘
  6. xxx发送文件:剪贴板3.BMP
  7. 等等……

而在Gtalk里是这样的:

  1. 右键计算机,点管理
  2. http://min.us/xxxxxxxxx
  3. 左边树里找磁盘管理
  4. http://min.us/xxxxxxxxx
  5. 在右下角找到你要的盘
  6. http://min.us/xxxxxxxxx
  7. 等等……

再附带一个用法,大家都知道很多QQ用户喜欢发表情图,相比MSN的表情图,QQ的表情可以很大,而如果今天偶然发现一张图很适合当表情怎么办?打开表情列表,添加表情,浏览到那张图,添加,确定,然后贴表情?NO!直接贴图,然后对着贴出去的图右键→保存为表情……

QQ贴图的缺点是什么?首先是不带确认。我想大多数QQ用户都说过类似“叉烧”,“没出来”,“图叉了”之类的话吧?为啥要说?因为你不说对方不知道你没看到……QQ发图是不带确认的,发图的人根本不知道对方是否能收到图片,而如果对方没收到,他也搞不清楚是发图的人网络不好,还是收图的人网络不好,还是疼讯服务器大姨妈。这一方面MSN从来就做得非常出色,从早期把图片当文件发送时就有进度条,现在依然有。

还有什么缺点?还是想像一下刚才的场景:

  1. 右键计算机,点管理
  2. 左边树里找磁盘管理
  3. 在右下角找到你要的盘
  4. [一张右键计算机的截图,鼠标指在管理上]
  5. 等等……

我想如果你面对的真的是一个需要你截图来向他说明的小白的话,这张延迟出现的图足以让他找不着北……

而这些不管怎样图还是出来了,有些情况下你这儿发了图,然后就没下文了,没有人收到过这张图,这个世界上再没人知道你发过图……这个问题在群或者手机上使用时很常见。

QQ的贴图还有2个特点值得一提:

1、QQ的贴图是会保存在聊天记录里的,如果哪天那位小白又需要改东西了,他可以直接在聊天记录里找之前图文并茂的对话。

2、QQ发图是压缩过的,这个未必是好事,但是有时候确实有用,尤其是在直接截屏发送的情况下,你会发现MSN等软件发过去的会是一张BMP,数兆大的24位位图图片……而QQ会发送一张大概在70左右压缩JPG图片,大小往往只有几十KB,满桌面截图也不过上百K。反过来,如果你真的需要在QQ上发送一张无损的图片怎么办?那你只能老老实实发送文件了。

// 椟

好了,接下来我说下“椟”的问题。

之前我也说过,QQ的用户体验很差。用户体验其实是个很泛的东西,要说狭义一点,他可能仅仅是指某公司里某个UE部门所负责的那一块东西;广义上来说,它则可以指任何可能使用户变得愉悦或不愉快的特性。

首先来看使用引导。IM工具,聊天功能本身并没有什么特别难的地方,可说整个业界是有默契的,无非就这么两种操作。然而QQ有一个其他所有IM工具都不具备的特性——超重量级。我觉得这个世界上再找不出一个比QQ更重量级的IM软件了,它甚至连远程桌面都包括在内。而他对疼讯来说,作为疼讯公司的看家产品,QQ承载着推广整个疼讯产品线的重任。我们可以发现,几乎任何一个疼讯公司的产品,除了面向企业用户的如RTX等软件外,都可以在QQ中找到一个链接,或者一个广告,或者一个按钮等等。我说QQ的功能丰富,确实它有一些其他IM软件所不具备的优秀功能,但它所包含的无用的功能更多。这对疼讯的用户体验小组来说是个巨大的挑战,你既要保证一个功能可以引起用户的注意,从而挖掘潜在的用户,又要尽可能降低这些功能对其他用户的干扰,避免激起用户的不满。

这也就是为什么我当年会很喜欢那个狂人DIY版的QQ,因为它可以帮助我砍去QQ中我不需要的部分,从而提高用户体验。可以想一下,一个QQ的聊天窗口,最上面一排按钮,一般人会用到几个?反正我一个都用不上,我估计一般人顶多也就用到那么一两个。更别提那些诸如QZone、通信录、硬盘、音乐、游戏、QQ秀、QQ宠物(这两个现在还有人在用么?)等等其他产品。

那么疼讯在这方面的成绩怎样呢?我觉得算是差强人意。疼讯没有太多强制性的东西,顶多弹弹新闻,对用户影响不算特别大,那个会弄得电脑一卡一卡的硬盘扫描在3Q大战后也可以关了,主界面的按钮基本都可以自定义,虽然全扔掉后那块空白还在那里,但是多少总还不至于特别碍眼,聊天界面也就顶部的一堆按钮和广告,由于聊天时注意力主要集中在窗口底部,加上疼讯在统一产品风格方面的效果还不错(我是一点都没觉得这些按钮好看,但是至少风格统一了,放在一起还算河蟹),所以影响也不算太大。而每次有新产品推出,疼讯还是会加入一些还算温和的提示信息,在平衡点方面取的还可以,至少我是这么觉得的。

然后,外观方面。刚刚有说到,虽然疼讯的美术风格我不怎么喜欢(除了QQMail等稍微成熟向的产品还不错),但他们的美术风格都还算统一,至少图标和广告的风格比较统一,当这些图标、广告被堆在一起时,这样的统一有助于让总体视觉效果相对河蟹一些,不会有特别突兀的东西。而QQ的主界面外观,我想那些会更喜欢QQ2005风格的人多半都是后文我会提到的某种讨厌QQ的人。

至于性能方面,我个人认为现在也还算是合格的。目前的QQ版本中很少会发生用了一半未响应等情况,也没见过因为运行QQ而拖慢系统速度的情况。当然如果你想让这么一个重量级的软件拿去和Gtalk比速度,我觉得你是难为它了……

还有就是隐私方面的事情,我想认识我的朋友应该都知道,我是非常反对过度的一刀切的隐私保护的。所有的网络通信都严格保密,我觉得完全没有这样的必要。另外我对于互联网上广泛流传的一些不知真假的流言持保留态度,或者说穿一点我判断那些流言属于严重夸大,比如所有的消息都要经过公安部门审查什么的,我是不相信中国的人力资源廉价到这种地步,故无须在意。

/* ================ 分隔符 ================ */

以上是我对QQ这个软件本身的一些看法,综上所述,哪怕剥离用户群体这一因素不考虑,QQ仍然会是我在PC/Windows平台上的首选IM。至于为什么很多人会不喜欢QQ呢?

其实我觉得不喜欢很正常,严格来说也不需要理由。有句话说得好,你能从自己喜欢的恶棍身上找出100个优点,也能从讨厌的圣人身上找出100个缺点。我总结下来其实大致就是这么几点:

    1. Geek情结:这一点包含了很多东西,原来想借地方说一下的是我一直觉得存在于我身边很多人身上的一种Geek情结。不过现在我决定单独开一篇文
    2. 喜欢轻量的IM:这个再正常不过了,青菜萝卜各有所好,但不能因此随便喷人家对吧?
    3. 不喜欢这外观:同上
    4. 担心隐私问题:上文有提到,流言这种东西说实话信不信全看个人,没有权力也没有义务去说服其他人同意自己的看法。
    5. 情感问题:Geek情结的一个针对疼讯的扩展。我在想如果一模一样的一个软件挂的是Google而不是疼讯的牌子会不会有人改变看法。很多人因为疼讯爱抄袭,或者因为某些口碑问题比如隐私啊啥的打心底里很讨厌这家公司。但是我还是很想说,客观的好坏可以作为主观喜恶的理由,反过来则不可。

不知不觉写了这么多,今天上班一个上午的时间荒废了。虽然Review一下发现写得一团乱,但是把自己想说的话说出来的感觉确实是不错的,要知道我昨晚因为想这件事差点没睡着觉~

感谢风(@funagi)帮我查出了一处文本错误!