My studying notes for Java,Ruby,Ajax and other any interesting things.

星期三, 十二月 24, 2014

doit.im体验小记

一直以来,使用Evernote作为GTD工具,大概做法是:
1、每天早上上班开始制作计划,格式模板如下,将当天需要完成的事情,按照时间四象限来进行归类整理,列出计划来;
2、每天中午和下午下班前进行记录,记录每天大概做的事情,以及时间消耗;
3、将当日重点事件进行回顾,并将备注信息记录下来,得到的每天总结大概如下:
使用这个流程已经将近有2年了,但是近期总结的时候发现有几个问题:
1、缺少按周、按月的回顾,因为任务和记录已经按照Note进行分日记录了,不便于回顾做了哪些事情;
2、长期任务的管理不好做,如果一个任务(比如读书)跨度比较长,就不容易安排到每日计划中来;
3、没有GTD的inbox过程,因此不方便快速添加和处理任务;当然,也可以通过Email的方式使用@#的title表示法来进行添加任务,但是终究不是专业GTD软件,这块儿不是很nice

于是开始调研新的GTD工具,看了一下有几个不错的,比如Omifoucs、GTD等,最后选择了doit.im,因为在Mac、Android、iOS三端都有很好地client,同步起来很方便,同时也支持中国和国际化的存储(虽然我最后选择了国外,不知道会不会有GFW的风险),做的也比较用心和精致。

下载地址:
http://doit.im mac retina和android的client都可以在其中下载并安装。

有一个tutorial,告诉怎么去使用这个软件,如激活邮箱,创建父子任务,Finish一个任务等。简单体验了一下,感觉还是不错的。
按照标准的GTD流程:
1、收集:inbox,可以通过邮件、手机快捷添加、mac下面的快捷键cmd+n快捷创建任务,其中最为称道的是在android的快捷添加,在任务栏中随时浮现,非常方便;
通过email添加inbox事项时候并没有很好地支持标记语法,比如:
这个在android下面可行,在mail的subject中输入则不可以;
在mac下面创建一个任务的详情:
都比较简单,project相对来说是一个分类,context是做这件事情的环境,比如公司,家里,路上等,优先级比较简单,tags估计主要用于分类和查找。repeat和reminder则相当于将日历的功能放进来,这个存疑,一般情况下mail和canlendar的集成会更加紧密。

2、计划:这个相对比较简单,对于inbox的任务可以快捷方便的拖入对应的项目和日程安排中

3.完成:只需要在手机或者mac app下面选中其中的checkbox,任务自动会标记为已完成。如果想要让doit.im帮你记录时间的话,则在任务详情页中输入花费的小时和分钟,最后系统会自动计算出来该任务的总时间。

快捷方式如下:

目前费用价格是100元/年,感觉还能够接受,刚注册使用可以免费使用1个月的收费权限,然后就变成免费了,免费有个致命缺点是每天只能同步1次。

GTD起来吧,附一张图:

Evernote,你的工作空间。下载Evernote

星期三, 十二月 17, 2014

关于PHP的匿名函数

在阅读一个PHP程序的时候,发现有很多地方都有重复的代码:
/* {{{ getXiaoquBaseInfoByCityPinyin 获取小区基本信息 */
    /**
     * 获取小区基本信息
     * @param  string $city    城市domain
     * @param  string $pinyin  小区拼音
     * @return array           小区信息数组
     */
    public function getXiaoquBaseInfoByCityPinyin($city, $pinyin) {
        try {
            //xiaoqu_xiaoqu
            $xiaoquModel = PlatformSingleton::getInstance('XiaoquXiaoquXiaoquModel');
            $result = $xiaoquModel->getXiaoquInfoByCityPinyin($city, $pinyin);

            $data = array(
                'errorno'  => ErrorConst::SUCCESS_CODE,
                'errormsg' => ErrorConst::SUCCESS_MSG,
                'data' => $result,
            );
        } catch (Exception $e) {
            $data = array(
                'errorno'  => $e->getCode(),
                'errormsg' => $e->getMessage(),
            );
        }
        return $data;
    } //}}}
    /* getXiaoquStatInfoByXiaoquId 获取小区统计信息 {{{ */
    /**
     * 获取小区统计信息
     * @param  int    $xiaoquId 小区id
     * @param  array  $fields   要查询的列
     * @return array
     */
    public function getXiaoquStatInfoByXiaoquId($xiaoquId, $fields=array()) {
        try {
            $model = PlatformSingleton::getInstance('XiaoquStatXiaoquModel');
            $xiaoquIds = array($xiaoquId);
            $result = $model->getXiaoquStatInfoByXiaoquId($xiaoquIds, $fields);
            $data = array(
                'errorno'  => ErrorConst::SUCCESS_CODE,
                'errormsg' => ErrorConst::SUCCESS_MSG,
                'data' => $result[0],
            );
        } catch (Exception $e) {
            $data = array(
                'errorno'  => $e->getCode(),
                'errormsg' => $e->getMessage(),
            );
        }
        return $data;
    } //}}}

一个类有740多行,大量相同的代码,如上面绿色部分都是重复的,感觉应该有办法改进。于是想了解PHP中是否有匿名类或者模板方法的做法。
在java中,一般可以这样来做:
public class A{
   public static void execute(B b){
       try{
            var xxx = b.dosth();
            fmt xxxx;
            return xxx;
       }catch(Exception e){
            deal exception;
       }
   }
}
public interface B {
   public abstract void dosth();
}
public class Test{
    public static void main(String[] argv){
         var xxx = A.execute(new B(){
            public void dosth(){ dosth reallly;}
         }
    }
}
上面代码,先定义了一个A的模板方法类,其execute方法中接受一个接口B的入参b,并在execute方法中调用了b的dosth方法来完成,execute方法本身提供了变量初始化xxx,和异常包装。在调用的时候(粉色代码)实际上使用了匿名内部类,动态的初始化了一个B的对象,并直在代码片段的时候完成了实现。

这个方法需要注意:
1、如果new B(){public void dosth()}里面要用到局部变量,需要将变量定义为final,不可修改,避免出现上下文依赖关系;
2、B的接口dosth的返回值将直接在excute方法中使用,而方法Test中处理的函数可能是个性的,有可能出现类型转换,通常做法是直接使用Object作为返回类型;

对PHP不熟悉,于是参照这个调查了一下php的匿名函数,发现匿名函数是在5.3以后才支持的,于是可以简单得到这样的代码:
[code]
<?php
class A
{
   public static function warpException($fun)
   {
        $astr = "string from warp Exception";
        return $fun($astr);
   }
}
class B
{
   public function methodB($bstr)
   {
        $fun = function($mystr) use($bstr)
        {
          return $mystr.':'.$bstr;
        };
        $bstr="str modified";
        $result = A::warpException($fun);
        return $result;
   }
}

class C
{
   public function methodC($bstr)
   {
        $bstr="str modified";
        $result = A::warpException(function($mystr) use($bstr)
        {
          return $mystr.':'.$bstr;
        });
        return $result;
   }
}

$b = new B();
$re = $b->methodB("this is just a test");
echo $re,"\n";
echo $b->methodB("new Test"),"\n";
$c = new C();
echo $c->methodC("this is just a test"),"\n";

[/code]
其中使用了PHP的匿名函数,如绿色部分。需要注意:
1、PHP5.3以后才支持匿名函数,尚未大规模推广,使用要注意坑;
2、实际上匿名函数就是闭包;
3、在使用的时候要注意use局部变量,避免出现变量变化以后内容不同;
4、在use的时候实际上已经对变量进行了一次值拷贝,后面如果有任何对变量的修改并不会发生变化。上述代码运行结果:
➜  php>  php AnyClassTest.class.php
string from warp Exception:this is just a test
string from warp Exception:new Test
string from warp Exception:str modified

此外,如果你使用的代码没有升级到5.3以后,可以使用__call进行封装,如:


Evernote,你的工作空间。下载Evernote