FALLHUNTER

Web & Mobile, Design & Code

小心浏览器的重定向缓存 redirect cache

这几天开发中遇到一个怪事,一个按钮(超链接)不知道怎么回事就不能用了,跟了代码,发现超链接中的参数没有传到server上来,百思不得其解,想尽了各种方法,都没解决。你说你感到万分沮丧,甚至开始怀疑server。

后来用抓包工具查看了浏览器发出的请求,发现发出请求时就没有了连接中的get参数,看来还是浏览器的问题,尝试不同浏览器,chrome和safari都不行,firefox居然没问题。为什么不尝试ie?我才不在乎ie行不行呢!

再仔细深入重现问题的操作序列,发现了其中有一个重定向!忽然想起了当年peter同学在技术交流上介绍301和302的区别,这真如一道黎明的曙光闪现!没错,w3c标准,301为永久重定向,应该被缓存。查看代码,Django的redict函数,默认发出的是301!这样,看似“见鬼”的问题解决了。其实是因为重定向到了不带参数的url,使得问题看起来好像是参数丢失了,让我们误入歧途。

总结,重定向分为301永久重定向和302临时重定向,对于301来说,浏览器可以缓存重定向的结果,当下次请求未定向的连接时,改为直接请求重定向后的结果。这也是为什么在浏览器状态栏眼睁睁的看着一个连接,点进去却是另外一个。那我们的问题在firefox中没有发生?从这点上,看来firefox还不够“标准”哈。


添加评论(3)

史上最好的邮件退订体验——从细处看Groupon缘何成功

Groupon 大家都已非常熟悉了,它是国内各种团购网站模仿的对象。然而一个偶然的操作,让我更加深刻的理解到Groupon为什么如此伟大。

出于对Groupon研究的目的,才订阅了Groupon的邮件,每天一封,然而我并不是团购用户,对远在美国的团购内容也不感冒,没过多久,我就点击了邮件中的“unsubscribe“ 退订了邮件。

点击”unsubscribe“后,打开了一个页面,直接显示了一行字:已经退订。我心想,这个不错,直接就退订了,不像有的网站,点开页面之后还要点一下才能退订。更有甚者,还需要你填一些为什么退订的理由才能退订。然而仅仅如此设计,当然算不上伟大,很多网站都是这么做的,让我震惊的,是马上显示出来的视频。不多说,大家可以自己看一下:

http://www.groupon.com/unsubscribed/

天啊,下面居然还有一个按钮可以操作。

我虽然退订了Groupon的邮件,但退订的体验让我印象如此深刻,即使没有去使用Groupon的业务,我也知道这是一个非常棒的产品,我一定会主动推荐给我的朋友。我虽然退订了邮件,但我却成了Groupon的传道者,显然,这是史上最好的邮件退订设计。

我想起《加州旅馆》里的一句歌词:

“You can check out anytime you like, but you can never leave”

套用在Groupon上非常合适:

“You can unsubscribe anytime you like, but you can never leave”

一个产品能做到这点,不留住用户的人,而留住了用户的心,不可谓不伟大。


添加评论

iPhone开发/ObjectiveC 面试题目

在做iPhone开发过程中,收集了一些常见到问题,可以用作面试题目,供大家参考,如果这些问题对你来说完全没有难度,可以发一份简历到 join@mapiz.com

  1. ObjC中,与alloc语义相反的方法是dealloc还是release?与retain语义相反的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?
  2. 在一个对象的方法里面:
    self.name = “object”;

    name =”object”
    有什么不同吗?
  3. 这段代码有什么问题吗:
    @implementation Person
    - (void)setAge:(int)newAge {
    self.age = newAge;
    }
    @end
  4. 什么是retain count?
  5. 以下每行代码执行后,person对象的retain count分别是多少
    Person *person = [[Person alloc] init];
    [person retain];
    [person release];
    [person release];
  6. 为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?
  7. 定义属性时,什么情况使用copy,assign,和retain
  8. autorelease的对象是在什么时候被release的?
  9. 这段代码有什么问题,如何修改
    for (int i = 0; i < someLargeNumber; i++)
    {
    NSString *string = @”Abc”;
    string = [string lowercaseString];
    string = [string stringByAppendingString:@"xyz"];
    NSLog(@“%@”, string);
    }
  10. autorelease和垃圾回收机制(gc)有什么关系?
  11. IPhone OS有没有垃圾回收(gc)?
  12. 什么是Notification?
  13. 什么时候用delegate,什么时候用Notification?
  14. 什么是KVC和KVO?
  15. Notification和KVO有什么不同?
  16. KVO在ObjC中是怎么实现的?
  17. ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?
  18. ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?默认的操作是什么?
  19. 未完待续…


添加评论

地铁里弹唱的男孩

北京的地铁,经常会遇到各种形式的乞讨者。有年迈的老奶奶,有失去双腿的大叔,有失去双臂的儿童,有背着扩音器唱歌的盲人,有拿着残疾证放到每个人面前的聋哑少年,还有各式各样悲惨的形态。有一点比较奇怪的是,我感觉乞讨者的形态似乎符合一定的流行规律,比如,残疾证的方式前几年经常见到,最近则不常见了。最近经常见到的形态是两人结伴,一人乞讨,一人背着扩音器唱歌,唱歌者往往是双目失明或其他残疾,由乞讨者带领前行。最近半年中,我遇到过不少于十次这种形态的乞讨,唱歌者大爷居多,声音听起来让你撕心裂肺,无限凄惨。而他们使用的麦克风和音箱,在我看起来却是如此的相似。

说实话,这些各种形态的乞讨,我从来没有施舍过一分钱,一分也没有。

今天晚上,我在地铁里遇到一个弹吉他的男孩,只有他一个人,衣着很整洁,看起来就是普通的大学生的样子。他在车厢里弹唱,吉他下面挂着一个开口的书包。弹唱期间,还拿出手机接了个电话。我听着他的旋律,不知道是不是他自己的原创歌曲,反正我没有听过,我觉得很好听,一曲终了,我伸出手为他鼓掌,有两个乘客也跟着鼓掌了,在拥挤的车厢里显得稀稀落落,他轻轻说了声谢。当他走过我身边,我拿出钱包,把零钱全都放到了他的书包里。

如今的社会让我不敢去判断什么真真假假,我们永远不知道背后的真相是什么,很多时候,我们只是听从我们的感觉。

这就是我一直说的,形式很重要。

任何事物,并不在于它是什么,而在于人们认为它是什么。

对于软件产品,形式就是UI,就是交互,就是用户体验。


添加评论

创业周年记

/*

我真的不希望,这篇日志的题目变成 《创业周年祭》

*/

一年多,过得如此之快,关于创业经历,早就该写点什么。

的确很忙。然而,写东西其实是一种心情,我问很多朋友怎么不写日志了,大家都说没时间,而实际上,我想应该是没有心情。而这种心情,似乎只会在某种特定的状态下才会出现,是我们的疲惫,搅乱了内心的平静,远离了这种心情。

一年以来,似乎什么也没有做出来,没有稳定的产品,没有稳定的用户,没有稳定的收入,什么都没有。我甚至不知道自己在做什么,或许,我们还不懂所谓的”创业“。

而这一切却渐渐变成了我新的生活方式,思考,不停的思考,直到感觉到大脑快速运转而发出的热量,直到听到神经元噼噼啪啪传达信号的声音,直到眼睛肿胀成植物大战僵尸里面的红眼巨人,直到身体发轻飘飘欲仙,直到东方渐白,楼下甲亢的看门人开始不耐烦的训斥过往的车辆……

对于产品,这是一个新的方向,是块未开垦的土地,我想我们会是这片土地上最弱小的掠食者,跟数不清的各路神仙一起混战,试图找到一块能够占据的领地。

对于团队,我们是一群年轻的孩子们,初出茅庐,不经风雨,在一个美好的愿望中摸索属于自己的道路。

没有任何胜算,我却痴迷于这种单纯。

我知道真正的战场是我们内心那些未开垦的土地,除非我们自己放任荒芜,没有人能抢走。在这里,我们每走一步,都是进步,我们每到一处,都是胜利。我想,这就是创业的魅力,让我无法拒绝。

多年以来,我常用来描述自己的一句话是:“编码是一种生活方式,游戏是一种人生态度。” 这是因为我曾经想做一名快乐的程序员,编写各种游戏软件。几年前,我从windows转向linux,发现了一个全新的世界,感慨以前的无知;现在,由程序员出来创业,我发现了一个广阔的宇宙,感慨昨日的狭隘。我希望那句话能改成这样:

“创业是一种生活方式,游戏是一种人生态度。”


添加评论(6)

Meet Mapiz Users At PIER 39

Mapiz 技术交流

 

Mapiz 技术交流是Mapiz组织的一个半公开的系列技术交流活动,其主题主要涵盖Web开发、LAMP(P指Python)技术、移动开发(IPhone、Andriod)等,主要面在职的技术人员和开发人员,主旨是为大家提供一个轻松的交流机会。

所谓半公开,其主要目的是为了控制参与者的数量和质量。控制数量是因为我们没有足够大的场地来容纳更多的观众,控制质量是因为我们希望参与者对各种技术有一定的认知能力,有自己见解可以发表,有自己的心得可以共享,或提出自己的问题大家一起讨论。我们不希望构建一个Web1.0式的讲座,而是希望构建一个Web2.0式的活动,大家充分参与进来进行讨论和学习,我们希望让这些离开大学的大孩子们找到大学宿舍里讨论问题的感觉。而半公开采用的邀请方法,也是为了基本保持参与人的固定,大家彼此更熟悉,也就更容易发表见解。同时,为了扩大我们的视野,我们也希望不断有新的朋友加入,让这些不善言谈的技术人员们结识更多志同道合的朋友。

 

本周的主题是 Android Application Framework,由来自 Motorola 的一位技术大牛主讲,机会难得,感兴趣的抓紧联系我呀!


添加评论

几个不错的图标搜索引擎和图标资源站

 

伟大的互联网,给我们提供了太多,创意将越来越容易的变成现实。

最近使用过的一些图标搜索引擎和图标资源站点:

 

另外一些不错的图片搜索和资源站点,参见:


添加评论(1)

网站维护日一周年

去年的今天,是中国首届网站维护日,VeryCD、饭否等大批网站停机维护,有些,甚至维护至今…… 于是,中国互联网首个全国节假日,中国网站维护日 诞生了!

正如刚刚过去国际六一儿童节的由来一样,网站维护日也来自悲剧和惨案。国际六一儿童节来自1942年法西斯在捷克的血腥屠杀,为纪念死难儿童,保障儿童权利,在1949年将6月1日定义为国际儿童节。而不同的是,网站维护日却是为了“保障网民的上网权利”,而抹杀一段历史,掩盖一个事实。

互联网的事情,按下葫芦起来瓢,我们不清楚,某些人物在这种类似“打地鼠”的游戏中是不亦乐乎还是焦头烂额。“民可使由之,不可使知之”的理念已经被发扬光大成“民不可使知之,亦不可使由之”,国内的互联网从业者们,老实躲在地鼠洞里做一些和谐的网游呀、团购呀,一样可以闷声发财,干啥老想伸出头来看看,别忘了游戏规则是谁设计的。

所以请不要再抱怨中国的互联网没有创新,是我们创新的伤口还没有痊愈;请不要再感慨中国的创业者缺乏创意,是他们还在掩埋战友的尸体。

我们可爱的追求真理的创业者们,总是不怕牺牲而前仆后继,LBS大哥 foursquare 已经被挡在门外,我们们又有十几位勇士走向了这条路,看看这里(需翻墙) http://foursquare.com/venue/2689874,这是大家不能绕开的问题。

戈壁的神兽啊,请指引我们前进的方向——


添加评论

将django的models放到多个文件中

 

随着django程序越来越大,一个application里的model也越来越多,而django有个非常不好的约定就是所有的model都写在一个models.py 文件中, 而对于喜欢追求“优雅”的程序员来说,这的确很难忍受。

由python的特性,自然会想到将models.py 用一个目录代替,在__init__.py 中,import整个目录里的文件,这样python是认可了,django却不认! ./manager.py syncdb 的时候并不会发现目录下面的model。

搜了半天,发现解决方法比较简单,只要在每个model类中加上Meta的app_label 属性就可以了。

from django.db import models

class Test(models.Model):
    class Meta:
        app_label = 'myapp'
但还是觉得这个地方有点别扭,总是要记着加上这个,显得不那么自然。
这种做法是没有在Django官方文档里说明的,之前还用过另外一个Undocumented Technique,是在Django Single注册的时候,

models.signals.post_save.connect(flaggedentry_post_save, sender=FlaggedEntry, dispatch_uid=’mofin.store.models’)

其中 dispatch_uid 是一个undocumented 参数,指定这个参数后,则对应的single 处理函数不会被重复注册,出现这种问题的情况是,当上面的注册语句被直接写在文件里,而这个文件又被import了多次,则上面的语句会被多次执行,如果没有指定 dispatch_uid 的话,处理函数就会被多次注册,而Single发生时就被执行多次了。

参考资料


添加评论(1)

© 2009 FALLHUNTER. All Rights Reserved.

This blog is powered by Wordpress and Magatheme by Bryan Helmig.