技术

两栏自适应带头尾

回想起刚刚工作的时候,作为一个一入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)帮我查出了一处文本错误!

我身边的Geek情结

经过风(@funagi)的提醒,补充声明此处的Geek特指计算机高手({1-名-4} : 〈俗〉(コンピュータやネットに関する)上級者{じょうきゅう しゃ}、ベテラン、ヘビーユーザー )

前两天跟 @Shyc2001 提起过我的这个想法,其实这个词是并不是哪找来的学术词汇,是偶然间从我脑海里蹦出来的。

Geek情结是什么?学术上的定义我不知道,在我看来其主要表现为对一些技术相关的品牌或行为极端的推崇或反感(所谓极端就是对于不喜欢的东西否定其一切),并且害怕自己和小白同流合污,在Geek圈子外越是大众化的东西他越抵触,时刻强迫自己表现得像一个Geek。我觉得这完全可以说是一种个性,就像喜欢某种文字某种颜色一样,白底黑字12px宋体也是一种个性,只不过我觉得这种个性更加强烈,强烈到略有扭曲。

“喷”是有Geek情结的人普遍的一个属性,天朝是喷子的圣地,但是这不意味着国外爱喷的Geek情结者少,事实上相当多。

我最经常接触到的明显的Geek情结有:

  1. 操作系统情结:某些Linux用户看到Windows如看到过街老鼠一样,坚定地认为Windows一无是处,是人类社会的癌症
  2. Windows界面情结:某些Windows用户看到新的Windows界面如看到瘟疫一样,不能设定为Win98风格的产品一概不用
  3. 浏览器情结:某些先进浏览器用户很爱把IE贬得一文不值,并且故意不愿意承认微软这些年在互联网标准上的努力。近期还扩展到Chrome和Firefox用户大战,而且明显的Chrome用户更加激进一些,Opera用户其次。
  4. 命令行情结:某些人认为VI(M)是天底下唯一一个可以称为编辑器的软件,其他的都是渣
  5. Linux专业向情结:我认为很多对新版Ubuntu(比如Unity等)的抵触可以归咎为这一类,这些人普遍认为Linux应该显得更技术用户向一些,而不是在外观上花功夫,而Ubuntu想要做的就是让Linux摆脱“Geek系统”的印象
  6. 国籍情结(其实我自己也有一点点):国外的软件就是好,国产的就是渣。老外抄人家的设计叫虚心学习、承前启后,国人抄人家设计叫剽窃抄袭、我寨威武。用国外软件是Geek身份的象征,用国产软件的就是小白。

还有一些衍生的比较边缘的类Geek情结:

  1. 手机系统情结:你以为果粉里没有Geek?才怪!iOS阵营和Android阵营互喷的时候虽然脑残粉(不仅仅是果粉,Android这边也有很多脑残粉)占据了主力大军的位置,但是软件开发人员或者有软件开发基础的专业人员之间的阵营互喷也并不少见。其实Geek情结在Android阵营中更重一点,很多偏向Android的Geek认为用iOS的人都是被瞧不死牵着鼻子走的小白。
  2. 激进/保守情结(我偏向前者):某些人认为对软件或系统来说最重要的是稳定性,同时认为对开发环境来说也是如此,这样才能让开发人员有足够的时间嚼烂一个平台;而另一些人则认为正是前面那群人拖累了新技术的发展,使得硬件开发公司、系统开发公司都停滞不前,使PC的发展遭遇瓶颈。两边都是Geek,却互相不认同对方,认为对方是害群之马。
  3. TV/PC游戏机情结(我举手!我站在PC这边):这其实是前一种的变种。TV游戏机代表一个稳定的开发平台,而相对而言PC平台则更经常有新技术问世。

一个人因为自己的爱好或理念,或多或少会对某些东西有某些情结。但是在分析问题时,尤其是和别人讨论问题时,要千万留意抑制自己的这种情结。把喜好与好坏分离开,客观地去看待每一个产品、每一个功能、每一个特性,这才是一个专业人员应有的专业态度吧。