diff --git a/chapters/11-milestone.md b/chapters/11-milestone.md new file mode 100644 index 0000000..e9e0362 --- /dev/null +++ b/chapters/11-milestone.md @@ -0,0 +1,62 @@ +GitHub 里程碑 +=== + +写在GitHub 的第 19999 个 star 时 +--- + +> Star 虽好,可不要贪杯哦。 +> 两年前在做 Annual Review 订下一年的目标时,想着写一个开源框架。去年订下今年的目标时,仍然继续着这样的想法。今年又要制定下一年的目标,2333~~。 + +不久前,在 GitHub Ranking 上看到自己的 star 数(star 不是设计用于做“点赞”的,而是用来收藏的)时,发现已经快 20000 了。然后把自己的项目过了一遍,发现没有一个比较好的**代表性框架,**要么是应用,要么是电子书。 + +前 8 个项目里,除了 Growth 应用以外,其他的都是电子书内容——六本电子书加起来的 star 数有 **10619**,果然是骗 star 的。我只能尽力地去想想:为什么事情会变成这样了? + +### 从创建开源框架说起 + +创建开源框架和创建创建开源项目是不一样的,前者你服务于开发者,后者你服务于用户。 + +两年前在做 Annual Review 的时候,想着未来的一年里可以做一个开源框架试试。那时刚毕业不久,对开源世界的各种游戏规则不是很了解:**开源并不是将代码提交上去,然后就会一下子火起来**。虽然我们可以在短期内赚上一些眼球,但是真正要将它采用到项目上的人不多。 + +当时,我遇到的最主要的问题是:**想参与到项目的人并没有遇到足够的能力**。你还需要花费大量的时间去教他们,鼓励 GitHub 新手并不是一件容易的事。有时我需要在接受他的 PR 后,再修改他的代码。并且人们提交 PR 可能是出于不同的原因。 + +然后,知道了开源世界还有一个游戏规则是:**谁的影响力大,谁就能产生更广泛的影响**。如 Virtual Dom 并不是 Facebook 首创的,但是却因为 FB 火的; 松本行弘在写下 mruby 的 README 时(印象中是这个项目),star 数就已经过 1k 了。这种例子数不胜数,要么是在推广上花了力气,要么个人、公司有着更大的影响力。 + +一年前,稍微改变了下策略:暂时以**培养人为主**,同时想着做一个合适的开源框架——只是在今年看来,前端领域已经没有合适的地方可以造轮子了。 + +在 GitHub 上有一个很常见的问题是,**大多部分项目的维护者就是发起人**——如果这个发起人发生意外了,那么这个项目怎么办。如果这是一个很火的项目,它就存在着巨大的风险;同时这可能也说明了,缺乏一套合理的机制。 + +你的开源项目不仅仅需要一个使用文档,还需要一个相关设计思想的文档、路线图、未来计划等等。 + +去年年底写总结的时候,想到可以 RePractise 文章为基础来培养人,于是就有了 Growth 的三个项目: + + - 应用:[Growth](https://github.com/phodal/growth) + - 电子书:《[Growth:全栈增长工程师指南](https://github.com/phodal/growth-ebook)》 + - 电子书:《[Growth:全栈增长工程师实战](https://github.com/phodal/growth-in-action)》 + +如今 Growth 已经有了过万的用户,每天活跃的用户数也接近 300 了。第一步看上去很成功,但是下一步怎么走呢? + +### 下一个开源项目 + +后来我开始在思索一个问题,创建一个开源框架是必须的吗? + +在编写 Growth 电子书的时候,我发现一个好的软件工程实践远远比一个易上手的框架重要多了。框架本身是易变的东西,过去你在用 Backbone,现在你在用 React.js;过去你在用 Angular.js,现在你在用 Vue。会不会使用某个框架,并不是区分你是不是一个有经验的开发者的标准。 + +一直将焦点关注于**学习不同的框架的使用**是有问题的,一个在校生可以轻松地比你了解某个框架的原理——你白天在工作,而他整天在学习。这时你很容易就失去竞争力了,你需要从框架之外了解更深层次的东西。**一个好的框架并不能让你写出一段好的代码**。 + +> 如果中国人的思想不觉悟,即使治好了他们的病,也只是做毫无意义。 + +这算是我为自己在 GitHub 下的 Markdown 的自辩吧——谁让我一直有写作的冲动呢。 + +不过我仍然还有一些想法,只是还没有抽出足够的时间去思考这样的事。 + +**GNU/Linux 的桌面**。这是几年前的一个想法了,当时 GNU/Linux 的那些操作系统上都没有一个好玩的桌面,不过感觉这个坑太深了,就没有进行了。 + +**家居智能中心**。我仍然对于大学学的知识有点念念不忘,虽然已经写了一本书,但是硬件还是相当的刺激。唯一的问题是:连房子都没有,怎么做智能家居。 + +**图形框架**。这是我之前在做一个图形界面的时候,发生没有一个合适的框架可以满足我的要求。然后我就在想,还是自己做一个吧。 + +不过,最好的开源项目就是自己平时用的。于是,我开始将写各种工作来提自己使用——如现在在用的这篇微信编辑工具:[mdpub](https://github.com/phodal/mdpub)。 + +最后,我做了一个简单的 HTML 5 动画来记录这一时刻,作为这一个里程碑的记念: + +[https://phodal.github.io/20k/](https://phodal.github.io/20k/) diff --git a/github-roam.md b/github-roam.md index 00508b2..897b946 100644 --- a/github-roam.md +++ b/github-roam.md @@ -2931,3 +2931,66 @@ OnMap项目是为了让我用Nokia Lumia 920拍照的照片,可以在地图上 如果你也想提高自己,不妨从创建你的 ideas 项目开始,如我的[Ideas](https://github.com/phodal/ideas)项目一样,上面已经有了大量的 Idea。然后,我们还可以依据这一个个的项目,创建出一本电子书,即 [ideabook](https://github.com/phodal/ideabook)。 + +GitHub 里程碑 +=== + +写在GitHub 的第 19999 个 star 时 +--- + +> Star 虽好,可不要贪杯哦。 +> 两年前在做 Annual Review 订下一年的目标时,想着写一个开源框架。去年订下今年的目标时,仍然继续着这样的想法。今年又要制定下一年的目标,2333~~。 + +不久前,在 GitHub Ranking 上看到自己的 star 数(star 不是设计用于做“点赞”的,而是用来收藏的)时,发现已经快 20000 了。然后把自己的项目过了一遍,发现没有一个比较好的**代表性框架,**要么是应用,要么是电子书。 + +前 8 个项目里,除了 Growth 应用以外,其他的都是电子书内容——六本电子书加起来的 star 数有 **10619**,果然是骗 star 的。我只能尽力地去想想:为什么事情会变成这样了? + +### 从创建开源框架说起 + +创建开源框架和创建创建开源项目是不一样的,前者你服务于开发者,后者你服务于用户。 + +两年前在做 Annual Review 的时候,想着未来的一年里可以做一个开源框架试试。那时刚毕业不久,对开源世界的各种游戏规则不是很了解:**开源并不是将代码提交上去,然后就会一下子火起来**。虽然我们可以在短期内赚上一些眼球,但是真正要将它采用到项目上的人不多。 + +当时,我遇到的最主要的问题是:**想参与到项目的人并没有遇到足够的能力**。你还需要花费大量的时间去教他们,鼓励 GitHub 新手并不是一件容易的事。有时我需要在接受他的 PR 后,再修改他的代码。并且人们提交 PR 可能是出于不同的原因。 + +然后,知道了开源世界还有一个游戏规则是:**谁的影响力大,谁就能产生更广泛的影响**。如 Virtual Dom 并不是 Facebook 首创的,但是却因为 FB 火的; 松本行弘在写下 mruby 的 README 时(印象中是这个项目),star 数就已经过 1k 了。这种例子数不胜数,要么是在推广上花了力气,要么个人、公司有着更大的影响力。 + +一年前,稍微改变了下策略:暂时以**培养人为主**,同时想着做一个合适的开源框架——只是在今年看来,前端领域已经没有合适的地方可以造轮子了。 + +在 GitHub 上有一个很常见的问题是,**大多部分项目的维护者就是发起人**——如果这个发起人发生意外了,那么这个项目怎么办。如果这是一个很火的项目,它就存在着巨大的风险;同时这可能也说明了,缺乏一套合理的机制。 + +你的开源项目不仅仅需要一个使用文档,还需要一个相关设计思想的文档、路线图、未来计划等等。 + +去年年底写总结的时候,想到可以 RePractise 文章为基础来培养人,于是就有了 Growth 的三个项目: + + - 应用:[Growth](https://github.com/phodal/growth) + - 电子书:《[Growth:全栈增长工程师指南](https://github.com/phodal/growth-ebook)》 + - 电子书:《[Growth:全栈增长工程师实战](https://github.com/phodal/growth-in-action)》 + +如今 Growth 已经有了过万的用户,每天活跃的用户数也接近 300 了。第一步看上去很成功,但是下一步怎么走呢? + +### 下一个开源项目 + +后来我开始在思索一个问题,创建一个开源框架是必须的吗? + +在编写 Growth 电子书的时候,我发现一个好的软件工程实践远远比一个易上手的框架重要多了。框架本身是易变的东西,过去你在用 Backbone,现在你在用 React.js;过去你在用 Angular.js,现在你在用 Vue。会不会使用某个框架,并不是区分你是不是一个有经验的开发者的标准。 + +一直将焦点关注于**学习不同的框架的使用**是有问题的,一个在校生可以轻松地比你了解某个框架的原理——你白天在工作,而他整天在学习。这时你很容易就失去竞争力了,你需要从框架之外了解更深层次的东西。**一个好的框架并不能让你写出一段好的代码**。 + +> 如果中国人的思想不觉悟,即使治好了他们的病,也只是做毫无意义。 + +这算是我为自己在 GitHub 下的 Markdown 的自辩吧——谁让我一直有写作的冲动呢。 + +不过我仍然还有一些想法,只是还没有抽出足够的时间去思考这样的事。 + +**GNU/Linux 的桌面**。这是几年前的一个想法了,当时 GNU/Linux 的那些操作系统上都没有一个好玩的桌面,不过感觉这个坑太深了,就没有进行了。 + +**家居智能中心**。我仍然对于大学学的知识有点念念不忘,虽然已经写了一本书,但是硬件还是相当的刺激。唯一的问题是:连房子都没有,怎么做智能家居。 + +**图形框架**。这是我之前在做一个图形界面的时候,发生没有一个合适的框架可以满足我的要求。然后我就在想,还是自己做一个吧。 + +不过,最好的开源项目就是自己平时用的。于是,我开始将写各种工作来提自己使用——如现在在用的这篇微信编辑工具:[mdpub](https://github.com/phodal/mdpub)。 + +最后,我做了一个简单的 HTML 5 动画来记录这一时刻,作为这一个里程碑的记念: + +[https://phodal.github.io/20k/](https://phodal.github.io/20k/) diff --git a/index.html b/index.html index e017097..3b883d6 100644 --- a/index.html +++ b/index.html @@ -199,6 +199,12 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
可是除了HTTP协议,还有MQTT和CoAP。对于MQTT协议来说,那还算好,毕竟自带授权,如:
-mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message."mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message."便可以让我们简单地完成这个功能,然而有的协议是没有这样的功能如CoAP协议中是用Option来进行授权的。现在的工具如libcoap只能有如下的简单功能
-coap-client -m get coap://127.0.0.1:5683/topics/zero -Tcoap-client -m get coap://127.0.0.1:5683/topics/zero -T于是,先写了个测试脚本来验证功能。
var coap = require('coap');
var request = coap.request;
@@ -1375,16 +1381,16 @@ str = tableHandler(str编写测试->功能代码->修改测试->重构
上次在和buddy聊天的时候,才知道测试在功能简单的时候是后行的,在功能复杂不知道怎么下手的时候是先行的。
开始之前请原谅我对于Java语言的一些无知,然后,看一下我写的Main函数:
-package com.phodal.learing;
+package com.phodal.learing;
public class Main {
- public static void main(String[] args) {
+ 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);
+ System.out.println("Hello,s");
+ System.out.println(c);
+ System.out.println(d);
}
}
代码写得还好(自我感觉),先不管Cal和Cal2两个类。大部分都能看懂,除了c,d不知道他们表达的是什么意思,于是。
@@ -1396,16 +1402,16 @@ str = tableHandler(str把光标移到int d中的d,按下shift+f6,输入result_sub
于是就有
-package com.phodal.learing;
+package com.phodal.learing;
public class Main {
- public static void main(String[] args) {
+ 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);
+ System.out.println("Hello,s");
+ System.out.println(result_add);
+ System.out.println(result_sub);
}
}
Extract Method
@@ -1417,16 +1423,16 @@ str = tableHandler(str在弹出的窗口中输入mprint
于是有了
-public static void main(String[] args) {
+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("Hello,s");
mprint(result_add);
mprint(result_sub);
}
private static void mprint(int result_sub) {
- System.out.println(result_sub);
+ System.out.println(result_sub);
}
似乎我们不应该这样对待System.out.println,那么让我们内联回去
Inline Method
@@ -1438,12 +1444,12 @@ str = tableHandler(str选中Inline all invocations and remove the method(2 occurrences) 点确定
然后我们等于什么也没有做了~~:
-public static void main(String[] args) {
+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);
+ System.out.println("Hello,s");
+ System.out.println(result_add);
+ System.out.println(result_sub);
}
似乎这个例子不是很好,但是够用来说明了。
Pull Members Up
@@ -1483,7 +1489,7 @@ str = tableHandler(str重构之前
过多的临时变量会让我们写出更长的函数,函数不应该太多,以便使功能单一。这也是重构的另外的目的所在,只有函数专注于其功能,才会更容易读懂。
以书中的代码为例
-import java.lang.System;
+import java.lang.System;
public class replaceTemp {
public void count() {
@@ -1501,7 +1507,7 @@ str = tableHandler(strReplace Temp With Query
便会返回
-import java.lang.System;
+import java.lang.System;
public class replaceTemp {
public void count() {
@@ -1528,9 +1534,9 @@ str = tableHandler(strpublic class replaceTemp {
public void method() {
- String str = "str";
- String aString = returnString().concat(str);
- System.out.println(aString);
+ String str = "str";
+ String aString = returnString().concat(str);
+ System.out.println(aString);
}
}
@@ -1714,7 +1720,7 @@ public class replaceTemp {
2014年1月1日零时到一时,用户在github上的操作,这里的用户指的是很多。。一共有4814条数据,从commit、create到issues都有。
数据解析
import json
-for line in open(jsonfile):
+for line in open(jsonfile):
line = f.readline()
然后再解析json
import dateutil.parser
@@ -1727,23 +1733,23 @@ date = dateutil.parser.parse(lin["
dataarray = []
datacount = 0
- for line in open(jsonfile):
+ 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)]
+ minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
f.close()
return minuteswithcount
下面这句代码就是将上面的解析为
-minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
这样的数组以便于解析
[(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
-sudo pip install matplotlib
+sudo pip install matplotlib
然后引入这个库
import matplotlib.pyplot as plt
如上面的那个结果,只需要
@@ -1769,14 +1775,14 @@ date = dateutil.parser.parse(lin["
dataarray = []
datacount = 0
- for line in open(jsonfile):
+ 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)]
+ minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
f.close()
return minuteswithcount
@@ -1785,7 +1791,7 @@ date = dateutil.parser.parse(lin["
x = []
y = []
mwcs = parse_data(files)
- for mwc in mwcs:
+ for mwc in mwcs:
x.append(mwc[0])
y.append(mwc[1])
@@ -1839,7 +1845,7 @@ draw_date("data/2014-01-01-0.json")重写了一个新的方法用于计算提交数,直至后面才意识到其实我们可以算行数就够了,但是方法上有点hack
def get_minutes_counts_with_id(jsonfile):
datacount, dataarray = handle_json(jsonfile)
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+ minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
return minuteswithcount
@@ -1848,7 +1854,7 @@ draw_date("data/2014-01-01-0.json")= []
datacount = 0
- for line in open(jsonfile):
+ for line in open(jsonfile):
line = f.readline()
lin = json.loads(line)
date = dateutil.parser.parse(lin["created_at"])
@@ -1870,7 +1876,7 @@ draw_date("data/2014-01-01-0.json") :rtype : object
"""
monthdaycount = []
- for i in range(1, 20):
+ for i in range(1, 20):
if i < 10:
filename = 'data/2014-02-0' + i.__str__() + '-0.json'
else:
@@ -1905,43 +1911,43 @@ draw_date("data/2014-01-01-0.json")= 0
userinfo = []
condition = 'select * from userinfo where owener = \'' + str(username) + '\''
- for zero in c.execute(condition):
+ for zero in c.execute(condition):
count += 1
userinfo.append(zero)
return count, userinfo
当我查询gmszone的时候,也就是我自己就会有如下的结果
-(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
+(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了。
值得注意的是。
--rw-r--r-- 1 fdhuang staff 905M Apr 12 14:59 userdata.db
+-rw-r--r-- 1 fdhuang staff 905M Apr 12 14:59 userdata.db
这个数据库文件有905M,不过查询结果相当让人满意,至少相对于原来的结果来说。
Python自带了对SQLite3的支持,然而我们还需要安装SQLite3
-brew install sqlite3
+brew install sqlite3
或者是
-sudo port install sqlite3
+sudo port install sqlite3
或者是Ubuntu的
-sudo apt-get install sqlite3
+sudo apt-get install sqlite3
openSUSE自然就是
-sudo zypper install sqlite3
+sudo zypper install sqlite3
不过,用yast2也很不错,不是么。。
数据导入
需要注意的是这里是需要python2.7,起源于对gzip的上下文管理器的支持问题
def handle_gzip_file(filename):
userinfo = []
with gzip.GzipFile(filename) as f:
- events = [line.decode("utf-8", errors="ignore") for line in f]
+ events = [line.decode("utf-8", errors="ignore") for line in f]
- for n, line in enumerate(events):
+ for n, line in enumerate(events):
try:
event = json.loads(line)
except:
@@ -1950,7 +1956,7 @@ draw_date("data/2014-01-01-0.json")= event["actor"]
attrs = event.get("actor_attributes", {})
- if actor is None or attrs.get("type") != "User":
+ if actor is None or attrs.get("type") != "User":
continue
key = actor.lower()
@@ -1970,7 +1976,7 @@ draw_date("data/2014-01-01-0.json")= 2014
month = 3
- for day in range(1,31):
+ 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",
@@ -1978,7 +1984,7 @@ draw_date("data/2014-01-01-0.json")= {"year": year, "month": month, "day": day, "n": "*"}
filenames = glob.glob(fn_template.format(**kwargs))
- for filename in filenames:
+ for filename in filenames:
c.executemany('INSERT INTO userinfo VALUES (?,?,?,?,?)', handle_gzip_file(filename))
conn.commit()
@@ -2004,11 +2010,11 @@ pipe = pipe = r.pipeline()
pipe.zscore('osrc:user',"gmszone")
pipe.execute()
系统返回了227.0,试试别人。
->>> pipe.zscore('osrc:user',"dfm")
-<redis.client.StrictPipeline object at 0x104fa7f50>
->>> pipe.execute()
-[425.0]
->>>
+>>> pipe.zscore('osrc:user',"dfm")
+<redis.client.StrictPipeline object at 0x104fa7f50>
+>>> pipe.execute()
+[425.0]
+>>>
看看主要是在哪一天提交的
>>> pipe.hgetall('osrc:user:gmszone:day')
<redis.client.StrictPipeline object at 0x104fa7f50>
@@ -2035,7 +2041,7 @@ pipe.execute()
r = redis.StrictRedis(host='localhost', port=6379, db=0)
no_pipe = False
- if pipe is None:
+ if pipe is None:
pipe = pipe = r.pipeline()
no_pipe = True
@@ -2091,12 +2097,12 @@ pipe.execute()
points[0] = 1.0 / (total + 1)
# Week means.
- for k, v in results[1].iteritems():
+ for k, v in results[1].iteritems():
points[1 + int(k)] = float(v) / total
# Event types.
n = 8
- for k, v in results[2]:
+ for k, v in results[2]:
points[n + evttypes.index(k)] = float(v) / total
# Number of contributions, connections and languages.
@@ -2108,8 +2114,8 @@ pipe.execute()
# Top languages.
n += 4
- for k, v in results[7]:
- if k in langs:
+ for k, v in results[7]:
+ if k in langs:
points[n + langs.index(k)] = float(v) / total
else:
# Unknown language.
@@ -2590,5 +2596,42 @@ pipe.execute()
See you Again
停止这次连击,只是为了有一个更好的开始。
如果你也想提高自己,不妨从创建你的 ideas 项目开始,如我的Ideas项目一样,上面已经有了大量的 Idea。然后,我们还可以依据这一个个的项目,创建出一本电子书,即 ideabook。
+GitHub 里程碑
+写在GitHub 的第 19999 个 star 时
+
+Star 虽好,可不要贪杯哦。 两年前在做 Annual Review 订下一年的目标时,想着写一个开源框架。去年订下今年的目标时,仍然继续着这样的想法。今年又要制定下一年的目标,2333~~。
+
+不久前,在 GitHub Ranking 上看到自己的 star 数(star 不是设计用于做“点赞”的,而是用来收藏的)时,发现已经快 20000 了。然后把自己的项目过了一遍,发现没有一个比较好的代表性框架,要么是应用,要么是电子书。
+前 8 个项目里,除了 Growth 应用以外,其他的都是电子书内容——六本电子书加起来的 star 数有 10619,果然是骗 star 的。我只能尽力地去想想:为什么事情会变成这样了?
+从创建开源框架说起
+创建开源框架和创建创建开源项目是不一样的,前者你服务于开发者,后者你服务于用户。
+两年前在做 Annual Review 的时候,想着未来的一年里可以做一个开源框架试试。那时刚毕业不久,对开源世界的各种游戏规则不是很了解:开源并不是将代码提交上去,然后就会一下子火起来。虽然我们可以在短期内赚上一些眼球,但是真正要将它采用到项目上的人不多。
+当时,我遇到的最主要的问题是:想参与到项目的人并没有遇到足够的能力。你还需要花费大量的时间去教他们,鼓励 GitHub 新手并不是一件容易的事。有时我需要在接受他的 PR 后,再修改他的代码。并且人们提交 PR 可能是出于不同的原因。
+然后,知道了开源世界还有一个游戏规则是:谁的影响力大,谁就能产生更广泛的影响。如 Virtual Dom 并不是 Facebook 首创的,但是却因为 FB 火的; 松本行弘在写下 mruby 的 README 时(印象中是这个项目),star 数就已经过 1k 了。这种例子数不胜数,要么是在推广上花了力气,要么个人、公司有着更大的影响力。
+一年前,稍微改变了下策略:暂时以培养人为主,同时想着做一个合适的开源框架——只是在今年看来,前端领域已经没有合适的地方可以造轮子了。
+在 GitHub 上有一个很常见的问题是,大多部分项目的维护者就是发起人——如果这个发起人发生意外了,那么这个项目怎么办。如果这是一个很火的项目,它就存在着巨大的风险;同时这可能也说明了,缺乏一套合理的机制。
+你的开源项目不仅仅需要一个使用文档,还需要一个相关设计思想的文档、路线图、未来计划等等。
+去年年底写总结的时候,想到可以 RePractise 文章为基础来培养人,于是就有了 Growth 的三个项目:
+
+- 应用:Growth
+- 电子书:《Growth:全栈增长工程师指南》
+- 电子书:《Growth:全栈增长工程师实战》
+
+如今 Growth 已经有了过万的用户,每天活跃的用户数也接近 300 了。第一步看上去很成功,但是下一步怎么走呢?
+下一个开源项目
+后来我开始在思索一个问题,创建一个开源框架是必须的吗?
+在编写 Growth 电子书的时候,我发现一个好的软件工程实践远远比一个易上手的框架重要多了。框架本身是易变的东西,过去你在用 Backbone,现在你在用 React.js;过去你在用 Angular.js,现在你在用 Vue。会不会使用某个框架,并不是区分你是不是一个有经验的开发者的标准。
+一直将焦点关注于学习不同的框架的使用是有问题的,一个在校生可以轻松地比你了解某个框架的原理——你白天在工作,而他整天在学习。这时你很容易就失去竞争力了,你需要从框架之外了解更深层次的东西。一个好的框架并不能让你写出一段好的代码。
+
+如果中国人的思想不觉悟,即使治好了他们的病,也只是做毫无意义。
+
+这算是我为自己在 GitHub 下的 Markdown 的自辩吧——谁让我一直有写作的冲动呢。
+不过我仍然还有一些想法,只是还没有抽出足够的时间去思考这样的事。
+GNU/Linux 的桌面。这是几年前的一个想法了,当时 GNU/Linux 的那些操作系统上都没有一个好玩的桌面,不过感觉这个坑太深了,就没有进行了。
+家居智能中心。我仍然对于大学学的知识有点念念不忘,虽然已经写了一本书,但是硬件还是相当的刺激。唯一的问题是:连房子都没有,怎么做智能家居。
+图形框架。这是我之前在做一个图形界面的时候,发生没有一个合适的框架可以满足我的要求。然后我就在想,还是自己做一个吧。
+不过,最好的开源项目就是自己平时用的。于是,我开始将写各种工作来提自己使用——如现在在用的这篇微信编辑工具:mdpub。
+最后,我做了一个简单的 HTML 5 动画来记录这一时刻,作为这一个里程碑的记念:
+