• 2016-06-18

    程序员眼中的无所不能与一无是处

    Views: 5076 | 3 Comments

    程序员常见的思维是提供"可扩展性", 这个可扩展性是程序员根据其职业生涯遇到的泪与汗得出的原则, 是一种保护罩. 可是, 这种思维导致其在做产品时, 会有一些不好的经典效果.

    例如, 程序员做的系统, 一般出发点就是做关系数据库表的增删改查. 不管做什么产品, 就是那几样 - 显示列表, 条件查询, 新增, 删除, 更改. 就这几招, 无所不能, 简直没有程序员做不了的系统. 如果你是程序员, 相信你有体会, 这种"无所不能"不会给你带来任何好处.

    我经常见到一些婴儿型程序员, 婴儿型程序员是我发明的一种人类标签, 主要是指那些像婴儿喜欢糖果一样喜欢某项技术的低级程序员, 这种喜爱完全是基于生物本能, 是生物的应激反应, 所以是低级的. 例如, 某些婴儿型程序员因为某语言用缩进方式来表示代码块, 突然就要认干爹了, 这种喜好让人反感.

    Continue reading »

    Posted by ideawu at 2016-06-18 13:47:44
  • 2016-06-17

    一个简单的聊天或者私信系统设计

    Views: 7106 | 1 Comment

    不少网站都会内置聊天或者私信系统, 为了方便更多人, 现将一个最简单的聊天系统的接口设计放在这里, 这是一个基于 HTTP 的聊天系统设计.

    首先是视图设计:

    # view:
    
    msg/unread
    	(全局)未读消息列表
    chat
    	一对一聊天窗口
    chat/history
    	我的聊天记录(按人组织)列表
    

    接着是数据接口设计:

    # ajax:
    
    msg/unread/get
    	获取(全局)未读消息列表
    	@last_msg_id: 获取比此消息更晚的未读消息, 不包含该条消息.
    chat/get
    	获取一对一聊天记录
    	@user_id: (msg_id, user_id 必须传一个)聊天者
    	@msg_id: (msg_id, user_id 必须传一个)根据此消息, 可得到聊天者, 并可在显示聊天记录时定位到对应的消息
    chat/get_new
    	@user_id: 聊天者
    	@last_msg_id: 获取比此消息更晚的消息, 不包含该条消息.
    chat/send
    	发送消息
    chat/history/get
    	我的聊天记录(按人组织)列表
    

    其中, 带有 last_msg_id 参数的接口, 可用于轮询获取新消息, 以便在缺少推送机制(PUSH)时提供一种替代方案. 大多数情况下, 10秒一次的刷新频率能达到"实时聊天"的效果.

    当有推送机制时, 如采用 iComet, 推送机制只推送通知(notify), 实际的消息内容仍然通过带 last_msg_id 的接口获取. 也就是说, 把固定刷新频率, 改为受通知时刷新(PUSH + PULL 结合).

    另外, 消息的持久化可以使用 MySQL 数据库, 但更推荐 SSDB NoSQL 数据库, 可以 SSDB 能存储超过十亿条的聊天历史记录并能快速查询.

    基于 SSDB + iComet 的聊天系统 demo: https://github.com/ideawu/icomet-demos

    Posted by ideawu at 2016-06-17 17:51:27
  • 2016-06-08

    Linux Shell mv 命令覆盖目标目录

    Views: 5057 | No Comments

    注意, 在Linux命令行下, mv是移动文件或者文件夹(目录), 如果目标路径是文件, 则会覆盖, 但如果目标是目录, 则被移动到目录里面. 有时, 我们需要替换到目标目录. 例如

    mv a tmp/a
    

    我们希望, 最终文件a(可能是文本文件)应该在tmp目录下. 但如果tmp目录已经有同名目录的话, a文件的路径会变成tmp/a/a, 这不是我们希望的.

    解决方法是加上-T参数:

    mv -T a tmp/a
    

    参数说明:

           -T, --no-target-directory
                  treat DEST as a normal file
    

    当然, Mac 不支持这个参数(估计BSD都不支持).

    Posted by ideawu at 2016-06-08 15:49:52
  • 2016-06-08

    iptables 封禁解封 IP

    Views: 4325 | No Comments

    iptables 封禁 IP:

    sudo iptables -I INPUT -s 1.2.3.4 -j DROP
    

    iptables 解封 IP:

    sudo iptables -D INPUT -s 1.2.3.4 -j DROP
    
    Posted by ideawu at 11:45:28
  • 2016-05-22

    到底是谁没有契约精神?

    Views: 3762 | No Comments

    前几天, 某个农产品网店做生意赔了几十万, 然后指责农民没有契约精神的事在知乎上讨论挺火. 但是, 约超过一半的人指责"农民没有契约精神", 当然, 也有不少人指出这个网店做生意赔钱的本质在于其不尊重市场规律而且没有现代商业所应有的品控体系导致的.

    不过, "农民没有契约精神"这样的字眼比较扎人, 而且, 我看到网络社交网站上不少莫名其妙的朋友也在附和, 基于完全没有道理的依据来附和, 这让我十分不爽.

    提到某个支持"农民没有契约精神"的言论, 这个言论漏洞百出, 但有些读过书的人竟然因为偏见而不认识其中的错误. 这个言论大致如下:

    某商家与农民群体签定合同, 不过, 合同细节没提, 从后来事情的发展来看, 应该是框架合同, 所以合同本身估计没有商定细节. 合同大体如言论中提到, 约定商家按2毛每斤的价格在第一年收购农民的蔬菜.

    第一年, 市场供给过剩, 价格大幅下跌至1毛每斤, 于是商家决定"慢慢地", "陆续地"履行合同, 价格仍按合同价. 很明显, 由于合同标的物是蔬菜, 具有严重的时间敏感性特点, 所以, 此商家已经毁约. 后来, 在农民的维权和当地部门强力之下, 商家不得不对自己的毁约行为进行补救, 按合同价格立即收购. 这个结果似乎给了商家错觉, 让他认为他已毁约这个行为并不存在, 并且他自己"很有契约精神", 事实上, 整个事情是商家先违约, 然后被惩罚, 后面的履约行为不过是对其违约行为的惩罚过程.

    基于某些考虑, 新合同继续. 条款和旧合同应该类似.

    第二年, 市场供给不足, 价格大幅上涨至3毛. 商家合理地要求农民按合同价格履约, 但农民故意违约.

    于是, 那个言论轻易地单方面指责农民"没有契约精神", 引得不少低级的知识分子赞同, 这是十分可笑的. 整个事情几年下来, 商家既没有契约精神, 农民也没有契约精神. 而且, 如果先后顺序对结论有决定性影响的话, 还是商家"先"不要脸单方毁约.

    有朋友提到, 这个事情其实反映的是市场不成熟, 这也是我的观点.

    一是当事双方不成熟. 商家只考虑价格, 不考虑供给数量, 这完全丧失了市场的基本要素. 农民没文化, 只能跟商家签定不成熟的合同, 最后导致合同违约. 从商业的角度, 这类合同根本就不应该出现, 哪有只定价格, 不定交易数量的远期交易合同? 这种合同严格意义上就是道德约定, 和古代社会的私下口头约定没有区别. 而且, 这个合同的标的是时间极度敏感的生鲜食品, 应当根据交易标的物的特点, 制定完善的交收步骤以及应对市场变化的措施等等, 但都没有.

    二是管理部门和法律不成熟. 商家违约被处罚要求继续履约, 而农民违约则无法被追究. 由于商家是一个, 而对应的农民成百上千, 每个农民的违约金额不过几百(原文如此), 显然, 追回损失的成本太高, 这也是农民违约而不被追究这种事实出现的客观原因.

    所以, 单方面指责"农民没有契约精神"是不科学的, 不符合事实的. 而且, 在面对没有契约精神的商家时, 农民出现了违约, 只单方面指责农民也是不道德的, 是滥用基本知识优势, 是非常虚伪的.

    Posted by ideawu at 2016-05-22 16:15:58
  • 2016-05-11

    有追求优秀之心的程序员

    Views: 6778 | 6 Comments

    前几天我发了条微博, 说目前程序员群体出现太多质量差的个体的情况:

    最近面了多个软件工程师,别看工作经验好几年,看起来好像能“干活”,但是竟然冒泡排序都不会写!这样的行业状况,一旦经济危机爆发,程序员群体估计要仆街。技术当然是成功的关键,但是经济状况出问题的话,行业的价值重估肯定让很多人痛苦不堪。

    这条微博发出来, 很多人表示认同我的观点, 也有不少人表示反对. 反对者的理由无非是"工作几年了, 不必考虑算法和数据结构了吧? 谁还记得这些基础的死记硬背的东西?..."等等.

    我之所以要在让面试者写冒泡排序, 是因为我有追求优秀之心, 同时, 我也根据实际, 不刻意难为面试者. 随着技术的发展, 程序员的门槛不断降低, 这是事物发展的正常规律, 我们也要与时俱进, 不能要求每一个程序员都要像早期程序员那样通过搭导线和打孔来编程. 但我们要随时保持优秀之心, 不能因为技术的发展导致许多连编程逻辑都不具备的人也进来做程序员就自惭形秽.

    在强大的互联网需求面前, 程序员群体供给相对紧缺, 必然导致大量分不清程序变量名和字符串中的单词这种级别的人也能进入行业供职, 而且不要感到惊讶, 这样不具备基础素质的人也能完成某些安排的工作, 也就是"能干活", 不要不解, 不要悲哀, 这就是技术发展的魔力.

    一个普通的程序员能按部就班地编程, 一步一步地完成业务逻辑. 一个优秀的程序员也能完成开发工作. 难道, 优秀和普通之间就没有区别了吗? 不是的!

    普通程序员开发了软件, 业务一跑起来, 怎么商品库存超卖了? 库存也做了判断, 应该不会超卖, 怎么会超卖? 优秀的程序员做出了系统, 无论怎么苛刻的运行条件, 系统都按照设想的那样运行, 数据准确, 业务正确. 为什么? 可能只是因为优秀的程序员做业务抽象, 应用了一项非常普通的技术来保证核心业务模型的准确.

    我的合伙人小张多次跟我说:"我们出来做懒投资, 还没做出产品来的时候就得到投资人的信任拿到千万投资, 没有几个人能做到, 我们认真做事, 出身高贵, 没有理由不感到优越!"

    如果你是一个优秀的程序员, 你理解程序内在逻辑, 你能对业务进行逻辑抽象, 你了解多项技术并合理应用, 你不把自己当做一个仅"能干活"的码农, 你就已经超越了百万甚至千万的同类, 你还有什么理由不认为自己出身高贵, 必将得到更好的回报呢?

    Posted by ideawu at 2016-05-11 12:05:36
|<<<123456789>>>| 5/121 Pages, 723 Results.