diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..8034480 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +github.phodal.com diff --git a/README.md b/README.md index 017740d..58eb811 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#Github 漫游指南 +# Github 漫游指南 2014年,写了一个《[一步步搭建物联网系统](https://github.com/phodal/designiot)》。 @@ -8,11 +8,11 @@ 但是过了很久都没有动静,今天是2015.10.24,我想是时候完成这个目标了。 -##其他 +## 其他 我的微信公众号: - + ## License @@ -20,5 +20,4 @@ 本作品采用[知识共享署名-非商业性使用 4.0 国际许可协议](http://creativecommons.org/licenses/by-nc/4.0/)进行许可。 -© 2015 [Phodal Huang](http://www.phodal.com)。[待我代码编成,娶你为妻可好](http://www.xuntayizhan.com/person/ji-ke-ai-qing-zhi-er-shi-dai-wo-dai-ma-bian-cheng-qu-ni-wei-qi-ke-hao-wan/)。 - +© 2015 [Phodal Huang](http://www.phodal.com)。[待我代码编成,娶你为妻可好](http://www.xuntayizhan.com/person/ji-ke-ai-qing-zhi-er-shi-dai-wo-dai-ma-bian-cheng-qu-ni-wei-qi-ke-hao-wan/)。 \ No newline at end of file diff --git a/build/author.html b/build/author.html deleted file mode 100644 index 57319dd..0000000 --- a/build/author.html +++ /dev/null @@ -1,5 +0,0 @@ - -
-
\n' + micromarkdown.htmlEncode(stra[1]).replace(/\n/gm, '
').replace(/\ /gm, ' ') + '
\n');
-}
-
-/* headlines */
-while ((stra = micromarkdown.regexobject.headline.exec(str)) !== null) {
- count = stra[1].length;
- str = str.replace(stra[0], '\n' + micromarkdown.htmlEncode(stra[1]).replace(/\n/gm, '
').replace(/\ /gm, ' ') + '
\n');
-}
-```
-
-提取方法成
-
-```javascript
-codeFilter: function (str, stra) {
- return str.replace(stra[0], '\n' + micromarkdown.htmlEncode(stra[1]).replace(/\n/gm, '
').replace(/\ /gm, ' ') + '
\n');
- },
-```
-
-while语句就成了
-
-```javascript
-while ((stra = regexobject.code.exec(str)) !== null) {
- str = this.codeFilter(str, stra);
-}
-```
-
-然后,运行所有的测试。
-
-```
-grunt test
-```
-
-同理我们就可以``mail``、``headline``等方法进行重构。接着就会变成类似于下面的代码,
-
-```javascript
-/* code */
-while ((execStr = regExpObject.code.exec(str)) !== null) {
-str = codeHandler(str, execStr);
-}
-
-/* headlines */
-while ((execStr = regExpObject.headline.exec(str)) !== null) {
-str = headlineHandler(str, execStr);
-}
-
-/* lists */
-while ((execStr = regExpObject.lists.exec(str)) !== null) {
-str = listHandler(str, execStr);
-}
-
-/* tables */
-while ((execStr = regExpObject.tables.exec(str)) !== null) {
-str = tableHandler(str, execStr, strict);
-}
-```
-
-然后你也看到了,上面有一堆重复的代码,接着让我们用JavaScript的``奇技浮巧``,即apply方法,把上面的重复代码变成。
-
-```javascript
-['code', 'headline', 'lists', 'tables', 'links', 'mail', 'url', 'smlinks', 'hr'].forEach(function (type) {
- while ((stra = regexobject[type].exec(str)) !== null) {
- str = that[(type + 'Handler')].apply(that, [stra, str, strict]);
- }
-});
-```
-
-进行测试,blabla,都是过的。
-
-```javascript
- Markdown
- ✓ should parse h1~h3
- ✓ should parse link
- ✓ should special link
- ✓ should parse font style
- ✓ should parse code
- ✓ should parse ul list
- ✓ should parse ul table
- ✓ should return correctly class name
-```
-
-快来试试吧, [https://github.com/artisanstack/js-refactor](https://github.com/artisanstack/js-refactor)
-
-是时候讨论这个Refactor利器了,最初看到这个重构的过程是从ThoughtWorks郑大晔校开始的,只是之前对于Java的另外一个编辑器Eclipse的坏感。。这些在目前已经不是很重要了,试试这个公司里面应用广泛的编辑器。
-
-##Interllij Idea重构
-
-开发的流程大致就是这样子的,测试先行算是推荐的。
-
- 编写测试->功能代码->修改测试->重构
-
-上次在和buddy聊天的时候,才知道测试在功能简单的时候是后行的,在功能复杂不知道怎么手手的时候是先行的。
-
-
-开始之前请原谅我对于Java语言的一些无知,然后,看一下我写的Main函数:
-
-```java
-package com.phodal.learing;
-
-public class Main {
-
- public static void main(String[] args) {
- int c=new Cal().add(1,2);
- int d=new Cal2().sub(2,1);
- System.out.println("Hello,s");
- System.out.println(c);
- System.out.println(d);
- }
-}
-```
-
-代码写得还好(自我感觉),先不管Cal和Cal2两个类。大部分都能看懂,除了c,d不知道他们表达的是什么意思,于是。
-
-###Rename
-
-**快捷键:Shift+F6**
-
-**作用:重命名**
-
- - 把光标丢到int c中的c,按下shift+f6,输入result_add
- - 把光标移到int d中的d,按下shift+f6,输入result_sub
-
-于是就有
-
-```java
-package com.phodal.learing;
-
-public class Main {
-
- public static void main(String[] args) {
- int result_add=new Cal().add(1,2);
- int result_sub=new Cal2().sub(2,1);
- System.out.println("Hello,s");
- System.out.println(result_add);
- System.out.println(result_sub);
- }
-}
-```
-
-###Extract Method
-
-**快捷键:alt+command+m**
-
-**作用:扩展方法**
-
-- 选中System.out.println(result_add);
-- 按下alt+command+m
-- 在弹出的窗口中输入mprint
-
-于是有了
-
-```java
-public static void main(String[] args) {
- int result_add=new Cal().add(1,2);
- int result_sub=new Cal2().sub(2,1);
- System.out.println("Hello,s");
- mprint(result_add);
- mprint(result_sub);
-}
-
-private static void mprint(int result_sub) {
- System.out.println(result_sub);
-}
-```
-
-似乎我们不应该这样对待System.out.println,那么让我们内联回去
-
-###Inline Method
-
-**快捷键:alt+command+n**
-
-**作用:内联方法**
-
-- 选中main中的mprint
-- alt+command+n
-- 选中Inline all invocations and remove the method(2 occurrences) 点确定
-
-然后我们等于什么也没有做了~~:
-
-```java
-public static void main(String[] args) {
- int result_add=new Cal().add(1,2);
- int result_sub=new Cal2().sub(2,1);
- System.out.println("Hello,s");
- System.out.println(result_add);
- System.out.println(result_sub);
-}
-```
-
-似乎这个例子不是很好,但是够用来说明了。
-
-###Pull Members Up
-
-开始之前让我们先看看Cal2类:
-
-```java
-public class Cal2 extends Cal {
-
- public int sub(int a,int b){
- return a-b;
- }
-}
-```
-
-以及Cal2的父类Cal
-
-```java
-public class Cal {
-
- public int add(int a,int b){
- return a+b;
- }
-
-}
-```
-
-最后的结果,就是将Cal2类中的sub方法,提到父类:
-
-```java
-public class Cal {
-
- public int add(int a,int b){
- return a+b;
- }
-
- public int sub(int a,int b){
- return a-b;
- }
-}
-```
-
-而我们所要做的就是鼠标右键
-
-###重构之以查询取代临时变量
-
-快捷键
-
-Mac: 木有
-
-Windows/Linux: 木有
-
-或者: ``Shift``+``alt``+``command``+``T`` 再选择 ``Replace Temp with Query``
-
-鼠标: **Refactor** | ``Replace Temp with Query``
-
-####重构之前
-
-过多的临时变量会让我们写出更长的函数,函数不应该太多,以便使功能单一。这也是重构的另外的目的所在,只有函数专注于其功能,才会更容易读懂。
-
-以书中的代码为例
-
-```java
-import java.lang.System;
-
-public class replaceTemp {
- public void count() {
- double basePrice = _quantity * _itemPrice;
- if (basePrice > 1000) {
- return basePrice * 0.95;
- } else {
- return basePrice * 0.98;
- }
- }
-}
-```
-
-####重构
-
-选中``basePrice``很愉快地拿鼠标点上面的重构
-
-
-
-便会返回
-
-```java
-import java.lang.System;
-
-public class replaceTemp {
- public void count() {
- if (basePrice() > 1000) {
- return basePrice() * 0.95;
- } else {
- return basePrice() * 0.98;
- }
- }
-
- private double basePrice() {
- return _quantity * _itemPrice;
- }
-}
-```
-
-而实际上我们也可以
-
-1. 选中
-
- _quantity * _itemPrice
-
-2. 对其进行``Extrace Method``
-
-3. 选择``basePrice``再``Inline Method``
-
-####Intellij IDEA重构
-
-在Intellij IDEA的文档中对此是这样的例子
-
-```java
-public class replaceTemp {
-
- public void method() {
- String str = "str";
- String aString = returnString().concat(str);
- System.out.println(aString);
- }
-
-}
-```
-
-接着我们选中``aString``,再打开重构菜单,或者
-
-``Command``+``Alt``+``Shift``+``T`` 再选中Replace Temp with Query
-
-便会有下面的结果:
-
-
-```javas
-import java.lang.String;
-
-public class replaceTemp {
-
- public void method() {
- String str = "str";
- System.out.println(aString(str));
- }
-
- private String aString(String str) {
- return returnString().concat(str);
- }
-
-}
-```
\ No newline at end of file
diff --git a/chapters/10-streak-your-github.md b/chapters/10-streak-your-github.md
deleted file mode 100644
index 30174c7..0000000
--- a/chapters/10-streak-your-github.md
+++ /dev/null
@@ -1,322 +0,0 @@
-#Github连击
-
-##100天
-
-我也是蛮拼的,虽然我想的只是在Github上连击100~200天,然而到了今天也算不错。
-
-
-
-``在停地造轮子的过程中,也不停地造车子。``
-
-在那篇连续冲击365天的文章出现之前,我们公司的大大([https://github.com/dreamhead](https://github.com/dreamhead))也曾经在公司内部说过,天天commit什么的。当然这不是我的动力,在连击140天之前
-
-- 给过google的``ngx_speed``、``node-coap``等项目创建过pull request
-- 也有``free-programming-books``、``free-programming-books-zh_CN``这样的项目。
-- 当然还有一个连击20天。
-
-对比了一下365天连击的commit,我发现我在total上整整多了近0.5倍。
-
-
-
-同时这似乎也意味着,我每天的commit数与之相比多了很多。
-
-在连击20的时候,有这样的问题: *为了commit而commit代码*,最后就放弃了。
-
-而现在是``为了填坑而commit``,为自己挖了太多的想法。
-
-###40天的提升
-
-当时我需要去印度接受毕业生培训,大概有5周左右,想着总不能空手而归。于是在国庆结束后有了第一次commit,当时旅游归来,想着自己在不同的地方有不同的照片,于是这个repo的名字是 [onmap](https://github.com/phodal/onmap)——将自己的照片显示在地图上的拍摄地点(手机是Lumia 920)。然而,中间因为修改账号的原因,丢失了commit。
-
-再从印度说起,当时主要维护三个repo:
-
-- 物联网的CoAP协议
-- [一步步设计物联网系统](https://github.com/phodal/designiot)的电子书
-- 一个Node.js + JS的网站
-
-说说最后一个,最后一个是练习的项目。因为当时培训比较无聊,业余时间比较多,英语不好,加上听不懂印度人的话。晚上基本上是在住的地方默默地写代码,所以当时的目标有这么几个:
-
-- TDD
-- 测试覆盖率
-- 代码整洁
-
-这也就是为什么那个repo有这样的一行:
-
-
-
-做到98%的覆盖率也算蛮拼的,当然还有Code Climate也达到了4.0,也有了112个commits。因此也带来了一些提高:
-
-- 提高了代码的质量(code climate比jslint更注重重复代码等等一些bad smell)。
-- 对于Mock、Stub、FakesServer等用法有更好的掌握
-- 可以持续地交付软件(版本管理、自动测试、CI、部署等等)
-
-###100天的挑战
-
-(ps:从印度回来之后,由于女朋友在泰国实习,有了更多的时间可以看书、写代码)
-
-有意思的是越到中间的一些时间,commits的次数上去了,除了一些简单的pull request,还有一些新的轮子出现了。
-
-
-
-这是上一星期的commits,这也就意味着,在一星期里面,我需要在8个repo里切换。而现在我又有了一个新的idea,这时就发现了一堆的问题:
-
- - 今天工作在这个repo上,突然发现那个repo上有issue,需要去修复,于是就放下了当前的代码。
- - 在不同的repo间切换容易分散精力
- - 很容易就发现有太多的功能可以实现,但是时间是有限的。
- - 没有足够的空闲时间,除了周末。
- - 希望去寻找那些有兴趣的人,然而却发现原来没有那么多时间去找人。
-
-###140天的希冀
-
-在经历了100天之后,似乎整个人都轻松了,毕竟目标是100~200天。似乎到现在,也不会有什么特殊的情怀,除了一些希冀。
-
-当然,对于一个开源项目的作者来说,最好有下面的情况:
-
-- 很多人知道了这个项目
-- 很多人用它的项目。
-- 在某些可以用这个项目快速解决问题的地方提到了这个项目
-- 提了bug、issue、问题。
-- 提了bug,并解决了。(ps:这是最理想的情况)
-
-
-##200天的Showcase
-
-今天是我连续泡在Github上的第200天,也是蛮高兴的,终于到达了:
-
-
-
-故事的背影是: 去年国庆完后要去印度接受毕业生培训——就是那个神奇的国度。但是在去之前已经在项目待了九个多月,项目上的挑战越来越少,在印度的时间又算是比较多。便给自己设定了一个长期的goal,即100~200天的longest streak。
-
-或许之前你看到过一篇文章[让我们连击](https://github.com/phodal/github-roam/blob/master/chapters/12-streak-your-github.md),那时已然140天,只是还是浑浑噩噩。到了今天,渐渐有了一个更清晰地思路。
-
-先让我们来一下ShowCase,然后再然后,下一篇我们再继续。
-
-###一些项目简述
-
-上面说到的培训一开始是用Java写的一个网站,有自动测试、CI、CD等等。由于是内部组队培训,代码不能公开等等因素,加之做得无聊。顺手,拿Node.js +RESTify 做了Server,Backbone + RequireJS + jQuery 做了前台的逻辑。于是在那个日子里,也在维护一些旧的repo,如[iot-coap](https://github.com/phodal/iot-coap)、[iot](https://github.com/phodal/iot),前者是我拿到WebStorm开源License的Repo,后者则是毕业设计。
-
-对于这样一个项目也需要有测试、自动化测试、CI等等。CI用的是Travics-CI。总体的技术构架如下:
-
-####技术栈
-
-前台:
-
-- Backbone
-- RequireJS
-- Underscore
-- Mustache
-- Pure CSS
-
-后台:
-
-- RESTify
-
-测试:
-
-- Jasmine
-- Chai
-- Sinon
-- Mocha
-- Jasmine-jQuery
-
-一直写到五星期的培训结束, 只是没有自动部署。想想就觉得可以用github-page的项目多好~~。
-
-过程中还有一些有意思的小项目,如:
-
-###google map solr polygon 搜索
-
-[google map solr polygon 搜索](http://www.phodal.com/blog/google-map-width-solr-use-polygon-search/)
-
-
-
-代码: [https://github.com/phodal/gmap-solr](https://github.com/phodal/gmap-solr)
-
-###技能树
-
-这个可以从两部分说起:
-
-####重构Skill Tree
-
-原来的是
-
-- Knockout
-- RequireJS
-- jQuery
-- Gulp
-
-
-
-代码: [https://github.com/phodal/skillock](https://github.com/phodal/skillock)
-
-####技能树Sherlock
-
-- D3.js
-- Dagre-D3.js
-- jquery.tooltipster.js
-- jQuery
-- Lettuce
-- Knockout.js
-- Require.js
-
-
-
-代码: [https://github.com/phodal/sherlock](https://github.com/phodal/sherlock)
-
-####Django Ionic ElasticSearch 地图搜索
-
-
-
-- ElasticSearch
-- Django
-- Ionic
-- OpenLayers 3
-
-代码: [https://github.com/phodal/django-elasticsearch](https://github.com/phodal/django-elasticsearch)
-
-####简历生成器
-
-
-
-- React
-- jsPDF
-- jQuery
-- RequireJS
-- Showdown
-
-代码: [https://github.com/phodal/resume](https://github.com/phodal/resume)
-
-
-####Nginx 大数据学习
-
-
-
-- ElasticSearch
-- Hadoop
-- Pig
-
-代码: [https://github.com/phodal/learning-data/tree/master/nginx](https://github.com/phodal/learning-data/tree/master/nginx)
-
-####其他
-
-虽然技术栈上主要集中在Python、JavaScript,当然还有一些Ruby、Pig、Shell、Java的代码,只是我还是习惯用Python和JavaScript。一些用到觉得不错的框架:
-
-- Ionic: 开始Hybird移动应用。
-- Django: Python Web开发利器。
-- Flask: Python Web开发小刀。
-- RequireJS: 管理js依赖。
-- Backbone: Model + View + Router。
-- Angluar: ...。
-- Knockout: MVV*。
-- React: 据说会火。
-- Cordova: Hybird应用基础。
-
-还应该有:
-
-- ElasticSearch
-- Solr
-- Hadoop
-- Pig
-- MongoDB
-- Redis
-
-##365天
-
- 给你一年的时间,你会怎样去提高你的水平???
-
-
-
-正值这难得的sick leave(万恶的空气),码文一篇来记念一个过去的366天里。尽管想的是在今年里写一个可持续的开源框架,但是到底这依赖于一个好的idea。在我的[Github 孵化器](http://github.com/phodal/ideas) 页面上似乎也没有一个特别让我满意的想法,虽然上面有各种不样有意思的ideas。多数都是在过去的一年是完成的,然而有一些也是还没有做到的。
-
-尽管一直在Github上连击看上去似乎是没有多大必要的,但是人总得有点追求。如果正是漫无目的,却又想着提高技术的同时,为什么不去试试?毕竟技术非常好、不需要太多练习的人只是少数,似乎这样的人是不存在的。大多数的人都是经过练习之后,才会达到别人口中的“技术好”。
-
-这让我想起了充斥着各种气味的知乎上的一些问题,在一些智商被完虐的话题里,无一不是因为那些人学得比别人早——哪来的天才?所谓的天才,应该是未来的智能生命一般,一出生什么都知道。如果并非如此,那只是说明他练习到位了。
-
-练习不到位便意味着,即使你练习的时候是一万小时的两倍,那也是无济于事的。如果你学得比别人晚,在**很长的一段时间里**(可能直到进棺材)输给别人是必然的——落后就要挨打。就好像我等毕业于一所二本垫底的学校里,如果在过去我一直保持着和别人(各种重点)一样的学习速度,那么我只能一直是Loser。
-
-需要注意的是,对你来说考上二本很难,并不是因为你比别人笨。教育资源分配不均的问题,在某种程度上导致了新的阶级制度的出现。如[我的首页](https://www.phodal.com/)说的那样: **THE ONLY FAIR IS NOT FAIR**——唯一公平的是它是不公平的。我们可以做的还有很多——**CREATE & SHARE**。真正的不幸是,因为营养不良导致的教育问题。
-
-于是在想明白了很多事的时候起,便有了Re-Practise这样的计划,而365天只是中间的一个产物。
-
-###编程的基础能力
-
-虽说算法很重要,但是编码才是基础能力。算法与编程在某种程度上是不同的领域,算法编程是在编程上面的一级。算法写得再好,如果别人很难直接拿来复用,在别人眼里就是shit。想出能work的代码一件简单的事,学会对其重构,使之变得更易读就是一件有意义的事。
-
-于是,在某一时刻在Github上创建了一个组织,叫[Artisan Stack](https://github.com/artisanstack)。当时想的是在Github寻找一些JavaScript项目,对其代码进行重构。但是到底是影响力不够哈,参与的人数比较少。
-
-####重构
-
-如果你懂得如何写出高可读的代码,那么我想你是不需要这个的,但是这意味着你花了更多的时候在思考上了。当谈论重构的时候,让我想起了TDD(测试驱动开发)。即使不是TDD,那么如果你写着测试,那也是可以重构的。(之前写过一些利用Intellij IDEA重构的文章:[提炼函数](https://www.phodal.com/blog/intellij-idea-refactor-extract-method/)、[以查询取代临时变量](https://www.phodal.com/blog/intellij-idea-refactor-replace-temp-with-query/)、[重构与Intellij Idea初探](https://www.phodal.com/blog/thoughtworks-refactor-and-intellij-idea/)、[内联函数](https://www.phodal.com/blog/intellij-idea-refactor-inline-method/))
-
-在各种各样的文章里,我们看到过一些相关的内容,最好的参考莫过于《重构》一书。最基础不过的原则便是函数名,取名字很难,取别人能读懂的名字更难。其他的便有诸如长函数、过大的类、重复代码等等。在我有限的面试别人的经历里,这些问题都是最常见的。
-
-####测试
-
-而如果没有测试,其他都是扯淡。写好测试很难,写个测试算是一件容易的事。只是有些容易我们会为了测试而测试。
-
-在我写[EchoesWorks](https://github.com/echoesworks/echoesworks)和[Lan](https://github.com/phodal/lan)的过程中,我尽量去保证足够高的测试覆盖率。
-
-
-
-
-
-从测试开始的TDD,会保证方法是可测的。从功能到测试则可以提供工作次效率,但是只会让测试成为测试,而不是代码的一部分。
-
-测试是代码的最后一公里。所以,尽可能的为你的Github上的项目添加测试。
-
-####编码的过程
-
-初到TW时,Pair时候总会有人教我如何开始编码,这应该也是一项基础的能力。结合日常,重新演绎一下这个过程:
-
-1. 有一个可衡量、可实现、过程可测的目标
-2. Tasking (即对要实现的目标过程进行分解)
-3. 一步步实现 (如TDD)
-4. 实现目标
-
-放到当前的场景就是:
-
-1. 我想在Github上连击365天。对应于每一个时候段的目标都应该是可以衡量、测试的——即每天都会有Contributions。
-2. 分解就是一个痛苦的过程。理想情况下,我们应该会有每天提交,但是这取决于你的repo的数量,如果没有新的idea出现,那么这个就变成为了Contributions而Commit。
-3. 一步步实现
-
-在我们实际工作中也是如此,接到一个任务,然后分解,一步步完成。不过实现会稍微复杂一些,因为事务总会有抢占和优先级的。
-
-###技术与框架设计
-
-在上上一篇博客中《[After 500: 写了第500篇博客,然后呢?](https://www.phodal.com/blog/after-500-blogposts-analytics-after-tech/)》也深刻地讨论了下这个问题,技术向来都是后发者优势。对于技术人员来说,也是如此,后发者占据很大的优势。
-
-如果我们只是单纯地把我们的关注点仅仅放置于技术上,那么我们就不具有任何的优势。而依赖于我们的编程经验,我们可以在特定的时候创造一些框架。而架构的设计本身就是一件有意思的事,大抵是因为程序员都喜欢创造。(ps:之前曾经写过这样一篇文章,《[对不起,我并不热爱编程,我只喜欢创造](https://www.phodal.com/blog/sorry-i-don't-like-programming/)》)
-
-**创造是一种知识的再掌握过程。**
-
-回顾一下写echoesworks的过程,一开始我需要的是一个网页版的PPT,当然这类的东西已经有很多了,如impress.js、bespoke.js等等。分析一下所需要的功能:markdown解析器、键盘事件处理、Ajax、进度条显示、图片处理、Slide。我们可以在Github上找到各式各样的模块,我们所要做的就是将之结合在一样。在那之前,我试着用类似的原理写(组合)了[Lettuce](https://github.com/phodal/lettuce)。
-
-组合相比于创造过程是一个更有挑战性的过程,我们需要在这过程去设计胶水来粘合这些代码,并在最终可以让他工作。这好比是我们在平时接触到的任务划分,每个人负责相应的模块,最后整合。
-
-想似的我在写[lan](https://github.com/phodal/lan)的时候,也是类似的,但是不同的是我已经设计了一个清晰的架构图。
-
-
-
-而在我们实现的编码过程也是如此,使用不同的框架,并且让他们能工作。如早期玩的[moqi.mobi](https://github.com/echoesworks/moqi.mobi),基于Backbone、RequireJS、Underscore、Mustache、Pure CSS。在随后的时间里,用React替换了View层,就有了[backbone-react](https://github.com/phodal/backbone-react)的练习。
-
-技术同人一样,需要不断地往高一级前进。我们只需要不断地Re-Practise。
-
-###领域与练习
-
-说业务好像不太适合程序员的口味,那就领域吧。不同行业的人,如百度、阿里、腾讯,他们的领域核心是不一样的。
-
-而领域本身也是相似的,这可以解释为什么互联网公司都喜欢互相挖人,而一般都不会去华为、中兴等非互联网领域挖人。出了这个领域,你可能连个毕业生都不如。领域、业务同技术一样是不断强化知识的一个过程。Ritchie先实现了BCPL语言,而后设计了C语言,而BCPL语言一开始是基于CPL语言。
-
-领域本身也在不断进化。
-
-这也是下一个值得提高的地方。
-
-###其他
-
-是时候写这个小结了。从不会写代码,到写代码是从0到1的过程,但是要从1到60都不是一件容易的事。无论是刷Github也好(不要是自动提交),或者是换工作也好,我们都在不断地练习。
-
-而练习是要分成不同的几个步骤,不仅仅局限于技术:
-
-1. 编码
-2. 架构
-3. 设计
-4. 。。。
\ No newline at end of file
diff --git a/chapters/11-find-github-project.md b/chapters/11-find-github-project.md
deleted file mode 100644
index d945ac8..0000000
--- a/chapters/11-find-github-project.md
+++ /dev/null
@@ -1,172 +0,0 @@
-#如何在Github"寻找灵感(fork)"
-
-> 重造轮子是重新创造一个已有的或是已被其他人优化的基本方法。
-
-最近萌发了一个想法写游戏引擎,之前想着做一个JavaScript前端框架。看看,这个思路是怎么来的。
-
-##[Lettuce](https://github.com/phodal/lettuce)构建过程
-
-> Lettuce是一个简约的移动开发框架。
-
-故事的出发点是这样的:``写了很多代码,用的都是框架,最后不知道收获什么了``?事实也是如此,当自己做了一些项目之后,发现最后什么也没有收获到。于是,就想着做一个框架。
-
-###需求
-
-有这样的几个前提
-
- - 为什么我只需要jQuery里的选择器、Ajax要引入那么重的库呢?
- - 为什么我只需要一个Template,却想着用Mustache
- - 为什么我需要一个Router,却要用Backbone呢?
- - 为什么我需要的是一个isObject函数,却要用到整个Underscore?
-
-我想要的只是一个简单的功能,而我不想引入一个庞大的库。换句话说,我只需要不同库里面的一小部分功能,而不是一个库。
-
-实际上想要的是:
-
-> 构建一个库,里面从不同的库里面抽取出不同的函数。
-
-###计划
-
-这时候我参考了一本电子书《Build JavaScript FrameWork》,加上一些平时的需求,于是很快的就知道自己需要什么样的功能:
-
- - Promise 支持
- - Class类(ps:没有一个好的类使用的方式)
- - Template 一个简单的模板引擎
- - Router 用来控制页面的路由
- - Ajax 基本的Ajax Get/Post请求
-
-在做一些实际的项目中,还遇到了这样的一些功能支持:
-
- - Effect 简单的一些页面效果
- - AMD支持
-
-而我们有一个前提是要保持这个库尽可能的小、同时我们还需要有测试。
-
-###实现第一个需求
-
-简单说说是如何实现一个简单的需求。
-
-####生成框架
-
-因为Yeoman可以生成一个简单的轮廓,所以我们可以用它来生成这个项目的骨架。
-
- - Gulp
- - Jasmine
-
-####寻找
-
-在Github上搜索了一个看到了下面的几个结果:
-
-- [https://github.com/then/promise](https://github.com/then/promise)
-- [https://github.com/reactphp/promise](https://github.com/reactphp/promise)
-- [https://github.com/kriskowal/q](https://github.com/kriskowal/q)
-- [https://github.com/petkaantonov/bluebird](https://github.com/petkaantonov/bluebird)
-- [https://github.com/cujojs/when](https://github.com/cujojs/when)
-
-但是显然,他们都太重了。事实上,对于一个库来说,80%的人只需要其中20%的代码。于是,找到了[https://github.com/stackp/promisejs](https://github.com/stackp/promisejs),看了看用法,这就是我们需要的功能:
-
-```javascript
-function late(n) {
- var p = new promise.Promise();
- setTimeout(function() {
- p.done(null, n);
- }, n);
- return p;
-}
-
-late(100).then(
- function(err, n) {
- return late(n + 200);
- }
-).then(
- function(err, n) {
- return late(n + 300);
- }
-).then(
- function(err, n) {
- return late(n + 400);
- }
-).then(
- function(err, n) {
- alert(n);
- }
-);
-```
-
-接着打开看看Promise对象,有我们需要的功能,但是又有一些功能超出我的需求。接着把自己不需要的需求去掉,这里函数最后就变成了
-
-```javascript
-function Promise() {
- this._callbacks = [];
-}
-
-Promise.prototype.then = function(func, context) {
- var p;
- if (this._isdone) {
- p = func.apply(context, this.result);
- } else {
- p = new Promise();
- this._callbacks.push(function () {
- var res = func.apply(context, arguments);
- if (res && typeof res.then === 'function') {
- res.then(p.done, p);
- }
- });
- }
- return p;
-};
-
-Promise.prototype.done = function() {
- this.result = arguments;
- this._isdone = true;
- for (var i = 0; i < this._callbacks.length; i++) {
- this._callbacks[i].apply(null, arguments);
- }
- this._callbacks = [];
-};
-
-var promise = {
- Promise: Promise
-};
-```
-
-需要注意的是: ``License``,不同的软件有不同的License,如MIT、GPL等等。最好能在遵循协议的情况下,使用别人的代码。
-
-###实现第二个需求
-
-由于,现有的一些Ajax库都比较,最后只好参照着别人的代码自己实现。
-
-```javascript
-Lettuce.get = function (url, callback) {
- Lettuce.send(url, 'GET', callback);
-};
-
-Lettuce.load = function (url, callback) {
- Lettuce.send(url, 'GET', callback);
-};
-
-Lettuce.post = function (url, data, callback) {
- Lettuce.send(url, 'POST', callback, data);
-};
-
-Lettuce.send = function (url, method, callback, data) {
- data = data || null;
- var request = new XMLHttpRequest();
- if (callback instanceof Function) {
- request.onreadystatechange = function () {
- if (request.readyState === 4 && (request.status === 200 || request.status === 0)) {
- callback(request.responseText);
- }
- };
- }
- request.open(method, url, true);
- if (data instanceof Object) {
- data = JSON.stringify(data);
- request.setRequestHeader('Content-Type', 'application/json');
- }
- request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
- request.send(data);
-};
-```
-
-
diff --git a/chapters/12-analytics-01.md b/chapters/12-analytics-01.md
deleted file mode 100644
index 7b4ffbe..0000000
--- a/chapters/12-analytics-01.md
+++ /dev/null
@@ -1,256 +0,0 @@
-#Github项目分析一
-
-##生成图表
-
-如何分析用户的数据是一个有趣的问题,特别是当我们有大量的数据的时候。除了``matlab``,我们还可以用``numpy``+``matplotlib``
-
-数据可以在这边寻找到
-
-[https://github.com/gmszone/ml](https://github.com/gmszone/ml)
-
-最后效果图
-
-
-
-要解析的json文件位于``data/2014-01-01-0.json``,大小6.6M,显然我们可能需要用每次只读一行的策略,这足以解释为什么诸如sublime打开的时候很慢,而现在我们只需要里面的json数据中的创建时间。。
-
-==,这个文件代表什么?
-
-**2014年1月1日零时到一时,用户在github上的操作,这里的用户指的是很多。。一共有4814条数据,从commit、create到issues都有。**
-
-###数据解析
-
-```python
-import json
-for line in open(jsonfile):
- line = f.readline()
-```
-
-然后再解析json
-
-```python
-import dateutil.parser
-
-lin = json.loads(line)
-date = dateutil.parser.parse(lin["created_at"])
-```
-
-这里用到了``dateutil``,因为新鲜出炉的数据是string需要转换为``dateutil``,再到数据放到数组里头。最后有就有了``parse_data``
-
-```python
-def parse_data(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- f.close()
- return minuteswithcount
-```
-
-下面这句代码就是将上面的解析为
-
-```python
-minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
-```
-
-这样的数组以便于解析
-
-```python
-[(0, 92), (1, 67), (2, 86), (3, 73), (4, 76), (5, 67), (6, 61), (7, 71), (8, 62), (9, 71), (10, 70), (11, 79), (12, 62), (13, 67), (14, 76), (15, 67), (16, 74), (17, 48), (18, 78), (19, 73), (20, 89), (21, 62), (22, 74), (23, 61), (24, 71), (25, 49), (26, 59), (27, 59), (28, 58), (29, 74), (30, 69), (31, 59), (32, 89), (33, 67), (34, 66), (35, 77), (36, 64), (37, 71), (38, 75), (39, 66), (40, 62), (41, 77), (42, 82), (43, 95), (44, 77), (45, 65), (46, 59), (47, 60), (48, 54), (49, 66), (50, 74), (51, 61), (52, 71), (53, 90), (54, 64), (55, 67), (56, 67), (57, 55), (58, 68), (59, 91)]
-```
-
-###Matplotlib
-
-开始之前需要安装``matplotlib
-
-```bash
-sudo pip install matplotlib
-```
-然后引入这个库
-
- import matplotlib.pyplot as plt
-
-如上面的那个结果,只需要
-
-
- plt.figure(figsize=(8,4))
- plt.plot(x, y,label = files)
- plt.legend()
- plt.show()
-
-
-最后代码可见
-
-
-```python
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import json
-import dateutil.parser
-import numpy as np
-import matplotlib.mlab as mlab
-import matplotlib.pyplot as plt
-
-
-def parse_data(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- f.close()
- return minuteswithcount
-
-
-def draw_date(files):
- x = []
- y = []
- mwcs = parse_data(files)
- for mwc in mwcs:
- x.append(mwc[0])
- y.append(mwc[1])
-
- plt.figure(figsize=(8,4))
- plt.plot(x, y,label = files)
- plt.legend()
- plt.show()
-
-draw_date("data/2014-01-01-0.json")
-```
-
-##每周分析
-
-继上篇之后,我们就可以分析用户的每周提交情况,以得出用户的真正的工具效率,每个程序员的工作时间可能是不一样的,如
-
-
-
-这是我的每周情况,显然如果把星期六移到前面的话,随着工作时间的增长,在github上的使用在下降,作为一个
-
- a fulltime hacker who works best in the evening (around 8 pm).
-
-不过这个是osrc的分析结果。
-
-###python github 每周情况分析
-
-看一张分析后的结果
-
-
-
-结果正好与我的情况相反?似乎图上是这么说的,但是数据上是这样的情况。
-
- data
- ├── 2014-01-01-0.json
- ├── 2014-02-01-0.json
- ├── 2014-02-02-0.json
- ├── 2014-02-03-0.json
- ├── 2014-02-04-0.json
- ├── 2014-02-05-0.json
- ├── 2014-02-06-0.json
- ├── 2014-02-07-0.json
- ├── 2014-02-08-0.json
- ├── 2014-02-09-0.json
- ├── 2014-02-10-0.json
- ├── 2014-02-11-0.json
- ├── 2014-02-12-0.json
- ├── 2014-02-13-0.json
- ├── 2014-02-14-0.json
- ├── 2014-02-15-0.json
- ├── 2014-02-16-0.json
- ├── 2014-02-17-0.json
- ├── 2014-02-18-0.json
- ├── 2014-02-19-0.json
- └── 2014-02-20-0.json
-
-我们获取是每天晚上0点时的情况,至于为什么是0点,我想这里的数据量可能会比较少。除去1月1号的情况,就是上面的结果,在只有一周的情况时,总会以为因为在国内那时是假期,但是总觉得不是很靠谱,国内的程序员虽然很多,会在github上活跃的可能没有那么多,直至列出每一周的数据时。
-
- 6570, 7420, 11274, 12073, 12160, 12378, 12897,
- 8474, 7984, 12933, 13504, 13763, 13544, 12940,
- 7119, 7346, 13412, 14008, 12555
-
-###Python 数据分析
-
-重写了一个新的方法用于计算提交数,直至后面才意识到其实我们可以算行数就够了,但是方法上有点hack
-
-```python
-def get_minutes_counts_with_id(jsonfile):
- datacount, dataarray = handle_json(jsonfile)
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- return minuteswithcount
-
-
-def handle_json(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- f.close()
- return datacount, dataarray
-
-
-def get_minutes_count_num(jsonfile):
- datacount, dataarray = handle_json(jsonfile)
- return datacount
-
-
-def get_month_total():
- """
-
- :rtype : object
- """
- monthdaycount = []
- for i in range(1, 20):
- if i < 10:
- filename = 'data/2014-02-0' + i.__str__() + '-0.json'
- else:
- filename = 'data/2014-02-' + i.__str__() + '-0.json'
- monthdaycount.append(get_minutes_count_num(filename))
- return monthdaycount
-```
-
-接着我们需要去遍历每个结果,后面的后面会发现这个效率真的是太低了,为什么木有多线程?
-
-###Python Matplotlib图表
-
-让我们的matplotlib来做这些图表的工作
-
-```python
-if __name__ == '__main__':
- results = pd.get_month_total()
- print results
-
- plt.figure(figsize=(8, 4))
- plt.plot(results.__getslice__(0, 7), label="first week")
- plt.plot(results.__getslice__(7, 14), label="second week")
- plt.plot(results.__getslice__(14, 21), label="third week")
- plt.legend()
- plt.show()
-```
-
-蓝色的是第一周,绿色的是第二周,蓝色的是第三周就有了上面的结果。
-
-我们还需要优化方法,以及多线程的支持。
-
-
diff --git a/chapters/13-analytics-02.md b/chapters/13-analytics-02.md
deleted file mode 100644
index 52fb618..0000000
--- a/chapters/13-analytics-02.md
+++ /dev/null
@@ -1,519 +0,0 @@
-#Github项目分析二
-
-
-让我们分析之前的程序,然后再想办法做出优化。网上看到一篇文章[http://www.huyng.com/posts/python-performance-analysis/](http://www.huyng.com/posts/python-performance-analysis/)讲的就是分析这部分内容的。
-
-##Time Python分析
-
-分析程序的运行时间
-
-```bash
-$time python handle.py
-```
-
-结果便是,但是对于我们的分析没有一点意义
-
-```
- real 0m43.411s
- user 0m39.226s
- sys 0m0.618s
-```
-
-###line_profiler python
-
-```bash
-sudo ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" easy_install line_profiler
-```
-
-然后在我们的``parse_data.py``的``handle_json``前面加上``@profile``
-
-```python
-@profile
-def handle_json(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- f.close()
- return datacount, dataarray
-```
-
-Line_profiler带了一个分析脚本``kernprof.py``,so
-
-```bash
-kernprof.py -l -v handle.py
-```
-
-我们便会得到下面的结果
-
-```
-Wrote profile results to handle.py.lprof
-Timer unit: 1e-06 s
-
-File: parse_data.py
-Function: handle_json at line 15
-Total time: 127.332 s
-
-Line # Hits Time Per Hit % Time Line Contents
-==============================================================
- 15 @profile
- 16 def handle_json(jsonfile):
- 17 19 636 33.5 0.0 f = open(jsonfile, "r")
- 18 19 21 1.1 0.0 dataarray = []
- 19 19 16 0.8 0.0 datacount = 0
- 20
- 21 212373 730344 3.4 0.6 for line in open(jsonfile):
- 22 212354 2826826 13.3 2.2 line = f.readline()
- 23 212354 13848171 65.2 10.9 lin = json.loads(line)
- 24 212354 109427317 515.3 85.9 date = dateutil.parser.parse(lin["created_at"])
- 25 212354 238112 1.1 0.2 datacount += 1
- 26 212354 260227 1.2 0.2 dataarray.append(date.minute)
- 27
- 28 19 349 18.4 0.0 f.close()
- 29 19 20 1.1 0.0 return datacount, dataarray
-```
-
-于是我们就发现我们的瓶颈就是从读取``created_at``,即创建时间。。。以及解析json,反而不是我们关心的IO,果然``readline``很强大。
-
-###memory_profiler
-
-首先我们需要install memory_profiler:
-
-```bash
-$ pip install -U memory_profiler
-$ pip install psutil
-```
-
-如上,我们只需要在``handle_json``前面加上``@profile``
-
-```bash
-python -m memory_profiler handle.py
-```
-
-于是
-
-```
-Filename: parse_data.py
-
-Line # Mem usage Increment Line Contents
-================================================
- 13 39.930 MiB 0.000 MiB @profile
- 14 def handle_json(jsonfile):
- 15 39.930 MiB 0.000 MiB f = open(jsonfile, "r")
- 16 39.930 MiB 0.000 MiB dataarray = []
- 17 39.930 MiB 0.000 MiB datacount = 0
- 18
- 19 40.055 MiB 0.125 MiB for line in open(jsonfile):
- 20 40.055 MiB 0.000 MiB line = f.readline()
- 21 40.066 MiB 0.012 MiB lin = json.loads(line)
- 22 40.055 MiB -0.012 MiB date = dateutil.parser.parse(lin["created_at"])
- 23 40.055 MiB 0.000 MiB datacount += 1
- 24 40.055 MiB 0.000 MiB dataarray.append(date.minute)
- 25
- 26 f.close()
- 27 return datacount, dataarray
-```
-
-###objgraph python
-
-安装objgraph
-
-```bash
-pip install objgraph
-```
-
-我们需要调用他
-
-```python
-import pdb;
-```
-
-以及在需要调度的地方加上
-
-```python
-pdb.set_trace()
-```
-
-接着会进入``command``模式
-
-```python
-(pdb) import objgraph
-(pdb) objgraph.show_most_common_types()
-```
-
-然后我们可以找到。。
-
-```
-function 8259
-dict 2137
-tuple 1949
-wrapper_descriptor 1625
-list 1586
-weakref 1145
-builtin_function_or_method 1117
-method_descriptor 948
-getset_descriptor 708
-type 705
-```
-
-也可以用他生成图形,貌似这里是用``dot``生成的,加上``python-xdot``
-
-很明显的我们需要一个数据库。
-
-如果我们每次都要花同样的时间去做一件事,去扫那些数据的话,那么这是最好的打发时间的方法。
-
-##python SQLite3 查询数据
-
-我们创建了一个名为``userdata.db``的数据库文件,然后创建了一个表,里面有owner,language,eventtype,name url
-
-```python
-def init_db():
- conn = sqlite3.connect('userdata.db')
- c = conn.cursor()
- c.execute('''CREATE TABLE userinfo (owner text, language text, eventtype text, name text, url text)''')
-```
-
-接着我们就可以查询数据,这里从结果讲起。
-
-```python
-def get_count(username):
- count = 0
- userinfo = []
- condition = 'select * from userinfo where owener = \'' + str(username) + '\''
- for zero in c.execute(condition):
- count += 1
- userinfo.append(zero)
-
- return count, userinfo
-```
-
-当我查询``gmszone``的时候,也就是我自己就会有如下的结果
-
-```bash
-(u'gmszone', u'ForkEvent', u'RESUME', u'TeX', u'https://github.com/gmszone/RESUME')
-(u'gmszone', u'WatchEvent', u'iot-dashboard', u'JavaScript', u'https://github.com/gmszone/iot-dashboard')
-(u'gmszone', u'PushEvent', u'wechat-wordpress', u'Ruby', u'https://github.com/gmszone/wechat-wordpress')
-(u'gmszone', u'WatchEvent', u'iot', u'JavaScript', u'https://github.com/gmszone/iot')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-109
-````
-
-一共有109个事件,有``Watch``,``Create``,``Push``,``Fork``还有其他的,
-项目主要有``iot``,``RESUME``,``iot-dashboard``,``wechat-wordpress``,
-接着就是语言了,``Tex``,``Javascript``,``Ruby``,接着就是项目的url了。
-
-值得注意的是。
-
-```bash
--rw-r--r-- 1 fdhuang staff 905M Apr 12 14:59 userdata.db
-```
-
-这个数据库文件有**905M**,不过查询结果相当让人满意,至少相对于原来的结果来说。
-
-Python自带了对SQLite3的支持,然而我们还需要安装SQLite3
-
-```bash
-brew install sqlite3
-```
-
-或者是
-
-```bash
-sudo port install sqlite3
-```
-
-或者是Ubuntu的
-
-```bash
-sudo apt-get install sqlite3
-```
-
-openSUSE自然就是
-
-```bash
-sudo zypper install sqlite3
-```
-
-不过,用yast2也很不错,不是么。。
-
-###数据导入
-
-需要注意的是这里是需要python2.7,起源于对gzip的上下文管理器的支持问题
-
-```python
-def handle_gzip_file(filename):
- userinfo = []
- with gzip.GzipFile(filename) as f:
- events = [line.decode("utf-8", errors="ignore") for line in f]
-
- for n, line in enumerate(events):
- try:
- event = json.loads(line)
- except:
-
- continue
-
- actor = event["actor"]
- attrs = event.get("actor_attributes", {})
- if actor is None or attrs.get("type") != "User":
- continue
-
- key = actor.lower()
-
- repo = event.get("repository", {})
- info = str(repo.get("owner")), str(repo.get("language")), str(event["type"]), str(repo.get("name")), str(
- repo.get("url"))
- userinfo.append(info)
-
- return userinfo
-
-def build_db_with_gzip():
- init_db()
- conn = sqlite3.connect('userdata.db')
- c = conn.cursor()
-
- year = 2014
- month = 3
-
- for day in range(1,31):
- date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
-
- fn_template = os.path.join("march",
- "{year}-{month:02d}-{day:02d}-{n}.json.gz")
- kwargs = {"year": year, "month": month, "day": day, "n": "*"}
- filenames = glob.glob(fn_template.format(**kwargs))
-
- for filename in filenames:
- c.executemany('INSERT INTO userinfo VALUES (?,?,?,?,?)', handle_gzip_file(filename))
-
- conn.commit()
- c.close()
-```
-
-``executemany``可以插入多条数据,对于我们的数据来说,一小时的文件大概有五六千个会符合我们上面的安装,也就是有``actor``又有``type``才是我们需要记录的数据,我们只需要统计用户的那些事件,而非全部的事件。
-
-我们需要去遍历文件,然后找到合适的部分,这里只是要找``2014-03-01``到``2014-03-31``的全部事件,而光这些数据的gz文件就有1.26G,同上面那些解压为json文件显得不合适,只能用遍历来处理。
-
-这里参考了osrc项目中的写法,或者说直接复制过来。
-
-首先是正规匹配
-
-```python
-date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
-```
-
-不过主要的还是在于``glob.glob``
-
-> glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索,支持通配符操作。
-
-这里也就用上了``gzip.GzipFile``又一个不错的东西。
-
-最后代码可以见
-
-[github.com/gmszone/ml](http://github.com/gmszone/ml)
-
-更好的方案?
-
-##Redis
-
-查询用户事件总数
-
-```python
-import redis
-r = redis.StrictRedis(host='localhost', port=6379, db=0)
-pipe = pipe = r.pipeline()
-pipe.zscore('osrc:user',"gmszone")
-pipe.execute()
-```
-
-系统返回了``227.0``,试试别人。
-
-```bash
->>> pipe.zscore('osrc:user',"dfm")
-