tuniutech

tuniutech 查看完整档案

南京编辑  |  填写毕业院校  |  填写所在公司/组织 www.tuniu.com 编辑
编辑

欢迎加入途牛,共同打造世界级的旅游平台。

个人动态

tuniutech 赞了回答 · 2016-06-10

解决感觉学PHP开发网站到瓶颈了,技术上不知如何突破,希望大神指点推荐几本书,谢谢!

你列的这个列表非常棒,知识面很完整,但我个人认为,你现在面临的这个瓶颈并不是书能够解决的。或者说光靠书很难解决。

想清楚学习的目的,避免为学而学

比如高并发,秒杀,架构,这些经常都是现有业务接触不到的东西,学习起来一般两种目的:要么为了应对面试,要么为了日后业务发展,需要的时候能够顶上(知识储备)。不同的目的有不同的学习手段和目标程度。比如如果为了面试,那么做到有一定了解,清楚场景、常见解决方案即可,面试的时候也不用瞎编,就说没机会接触但了解过如何如何,就是很好的回答了。如果是为了业务发展,如果当前公司很快就会发展到那个程度,那就得要到实战的地步,可以找老板沟通,老板说不定正发愁呢。

但如果你的公司离哪个场景很远,你又不打算跳槽,那就别浪费宝贵的时间,学点别的吧

实践,实践,实践!

无论你习惯看书,还是习惯视频,还是像我一样习惯面向google面向stackoverflow学习,学习唯一不变的终点永远是实践。无论你的学习目的是什么,开始之前永远都先给自己准备好实践的机会。公司需要就和老板沟通,公司不需要就自己业余开小项目,不方便的话,那就学到“了解问题点,了解常见解决方案”的程度停止

你已经具备很好的知识面,那么结合公司当下/未来的需求找到突破口应该不是难事,争取结合公司发展所需来学习是效率以及收益最高的,相信我,老板永远最喜欢那种公司需要什么技术就能跳起来说“以前我看过这个东西,有三种方案,我觉得B方案目前最适合我们公司的情况,我能带头把这个做出来”的员工

场景是王道

上面两点中我一直反复在聊场景,其实和英文很类似,英文的核心能力并不是几万的单词量,也不是多么高深的语法,而是“语感”,或者说,从场景联系到合适的表达方式,以及反过来从别人的表达中领会场景的能力。

书和视频,包括网上搜索,绝大多数都只能解决“how”的问题,但我始终认为"how"几乎是最不重要的事情,至少对于互联网技术来说,除了极端场景,99%的情况下,“how”都不是问题,不就是找最合适的那个类库看下文档,调用调试一下么。问题的关键永远是“when”和“what”,偶尔是“why”

  • how: 是怎么达成某件事情(比如怎么支撑大并发吧),这其实真的不太重要

  • when: 什么时候需要引入支撑并发的方案? 一台常见的单核8G服务器能支撑多少用户并发?怎么监视并发量从而确认是否需要扩容?常见的并发优化能有多少并发量的提升?这决定了业务成长到什么地步要考虑引入相应方案,过早优化是万恶之首

  • what: 并发问题的核心是解决什么问题? 比如一个方向是横向扩容/自动扩容,另一个方向是高并发下的数据一致性(事务和分布式事务),当然也还有单机并发优化。如果你理解了就会发现,单机优化确实重要而且是基础,但绝大多数时候远远不如前两个管用。如果你懵懵懂懂就奔着“高并发”这么个词,学了一堆单机优化的东西,可能最后派不上用

  • why: 为什么公司需要这个技术?业务和技术的结合点在哪里? 是你的公司的商业模式决定了需要靠支撑大量并发来盈利么?是公司的业务数据宝贵不容有失所以需要强大的异地容灾?还是因为公司业务无法接受当机时间过长,所以需要灾备,需要柔性高可用?当然,也不能排除“高层喜欢这个技术”这个稍稍令人丧气的理由。

合起来看,how之外的那些问题,简单地说就是场景问题,想通这个真的非常重要,只有想通这个,你的学习才是有目的,有条理,有计划,有最终成果的有效学习

最后,反感看书学习的我唯一推荐一本书,是一本最棒的学习list,有很多你没列出来却至关重要的需要学习/关注的点,《The Pragmatic Programmer》,译名《程序员修炼之道》有点俗,但错过实在可惜

附另一个回答《程序员怎样结合平时工作中的项目修炼自己的技能?》

关注 45 回答 11

tuniutech 发布了文章 · 2016-06-10

途牛原创|途牛无线权限系统的架构设计与实践

之前写过一篇大话权限中心的PHP架构之道,主要是从软件工程角度介绍,如何通过编码规范、依赖管理、数据源架构、事务处理、单元测试等技术,来保障权限系统的高可用,并未真正的涉及这套系统的架构。

今天准备从设计细节上分享一二。

望各位看官,心有“空杯”,带着“问题”一探究竟。

0. RBAC3

这里还是尤为的重要,因为他是整套系统设计的根基

所以残忍的从上一篇中复制了一遍。。。

RBAC认为权限授权实际上是Who、What、How的问题。在RBAC模型中,who、what、how构成了访问权限三元组,也就是“Who对What(Which)进行How的操作”。

  • Who:权限的拥用者或主体(如Principal、User、Group、Role、Actor等等)

  • What:权限针对的对象或资源(Resource、Class)。

  • How:具体的权限(Privilege,正向授权与负向授权)。

  • Operator:操作。表明对What的How操作。也就是Privilege+Resource

  • Role:角色,一定数量的权限的集合。权限分配的单位与载体,目的是隔离User与Privilege的逻辑关系.

RBAC3模型

权限系统的本质就是这个模型(个人观点勿喷)。我们在此核心思想上,抽象了两个新概念。

应用建模、权限自治

下面将从以下4个层面展开介绍。

  • 应用建模

  • 业务场景

  • 权限管理

  • 鉴权设计

1. 应用建模

系统架构上支撑权限系统灵活配置,不僵硬字段,不僵硬行为,基于各种业务权限管控的特征灵活设计。

公式一枚:应用=资源+行为+角色

1.1 字段定义

简单点说,就是要管控资源的属性和行为

比如要管控菜单,属性就包括菜单ID、菜单名称、菜单URL、菜单ICON、上级菜单ID等,行为就包括访问、授权等。(菜单权限)

比如要管控城市,属性就包括区域ID、区域名称、区域代码、所属区域ID等,行为就包括访问、授权等。(区域权限)

比如要管控CMS,字段就包含页面ID、页面名称等,行为就包括访问、授权、编辑、重置等。(CMS数据权限)

按照惯性的思维,这里就是3张资源表对应角色表,同时还有3张资源角色关系表,换而言之,就是有多少资源需要管控就有多少张表(又是个人观点,勿喷)。

惯性的思维,两个痛点

  1. 每一种资源都要独立存储。

  2. 每一种资源都要有一套Form排版&交互&存储实现。

为了解决这个问题,我们做了以下的设计。

字段建模

任意资源的字段,都可以抽象成如下几类。

  • 资源映射字段(mapField)

  • 资源节点字段(treeFiled)

  • 资源系统字段(systemFields)

  • 资源表单字段(columns)

  • 资源行为字段(privileges)

举个栗子:菜单资源。


class menu extends app
{
    public static $appMapField = 'url';
    public static $appTreeField = 'name';
    public static $columns = array(
        array(
            'id' => 'id',
            'label'  => '菜单ID',
            'type'  => 'input',
            'format' => 'int',
            'option' => array()
        ),
        array(
            'id' => 'name',
            'label'  => '菜单名称',
            'type'  => 'input',
            'format' => 'string',
            'option' => array()
        )
    );
    public static $privileges = array(
        array(
            'id'    => 'access',
            'name'  => '访问'
        )
    );
    public static $systemFields = array('id', 'parent_id');
}

动态表单

表单在网页中主要负责数据采集功能。一个表单有三个基本组成部分:

  1. 表单标签;

  2. 表单域,包含了文本框、密码框、隐藏域、多行文本框、复选框、单选框、下拉选择框和文件上传框等;

  3. 表单按钮。

常规工作是静态表单

设计动态表单模型,基本的思路应该是数据和表现显示的分离。抛开表现层,一个表单包含的若干个字段和填写的数据。所谓动态,就是这些字段名称可能改变,数量可能有增减。

  • 通过资源的columns字段控制表现层。

  • 通过资源的数据字段控制数据层。

通过这种模式,任意资源的Form排版&交互&存储都动态实现了。

1.2 数据存储

资源表对应的Schema如下:

字段名称字段备注
应用ID/
资源ID/
资源父ID/
资源DataJSON

通过反射API,获取当前应用的资源存储插件(资源Data字段)。


app::find($params['app_id'])->getResoucePlugin()->save($params['data']);

通过资源基类做数据存储的统一封装。


public function save()
{
    $this->beforeSave($this->attributes);
}

protected function beforeSave()
{
    //check attributes
}

很显然资源Data字段,不能很好的完成单资源行为鉴权的任务。

设计上引入了资源映射字段,每当资源变更时,触发addMap,会同步字段信息到资源映射关系表中(资源的语义化索引)。

举几个栗子,方便大家理解这个字段:

  • 比如菜单类应用,映射字段就是菜单链接。

  • 比如数据类应用,映射字段就是数据ID。


public function addMap()
{
    if ($this->map) {
        //sync map field
    } else {
        //create map field
    }
}

应用建模,相对来说是一个较技术的话题,换个方向,下面来和大家聊一聊系统的业务场景。

2. 业务场景

系统架构上支撑多种业务形态的权限管控。

2.1 菜单类业务

说到权限,大多数应用场景都会想到菜单权限,然而我们也不例外,菜单类的应用,就是生产的第一个实例。

举个栗子:A系统/菜单权限应用

  • 字段

    • 菜单ID、菜单名称、菜单链接、菜单上级ID

  • 行为

    • 访问、授权

2.2 数据类业务

数据类应用,相对于菜单类型来说,更关注的是,对某一行数据的行为控制,行为是多样的。

举个栗子:A数据/数据权限应用

  • 字段

    • 数据ID、数据名称

  • 行为

    • 访问、授权、编辑、删除、新增、重置、导出、导入

2.3 表单类业务

表单类应用,在2B的系统中,权限设计尤为重要。

举个栗子:A确认单/表单权限应用

  • 字段

    • 模块ID、模块名称(行程模块、供应商模块、订单模块、财务模块)

  • 行为

    • 访问、授权、只读、可写、隐藏

总结一下权限的业务场景:

  • 菜单类:单资源的单行为(能否”行为“当前“资源”)

  • 数据类:单资源的多行为

  • 表单类:多资源的多行为

小伙伴们,你们的业务场景能实现吗?(留言吧)

3 权限管理

接下来说说权限管理中的一些设计之道。

3.1 自治

设计上参考JIRA,当前应用的管理者主导当前应用的权限生态

  • 资源的增删改查

  • 角色的增删改查

  • 资源字段定义

  • 资源行为定义

  • 资源行为的角色赋予

3.2 自举

系统中给每一种资源都天生赋予一种系统行为叫做“授权”。

任意资源节点的角色行为赋予,都由拥有该资源节点授权行为的角色去分配。

3.3 双向授权

两个维度授权,方便检索,也方便配置。

基于角色+行为,选择资源。

基于资源+行为,选择角色。

^^^^^^^^

下一个阶段将会支持默认权限的配置,非应用内的角色,也同样可以享有应用内的部分资源的部分行为的权限。

4 鉴权设计

最后简单说下,鉴权接口的设计。

U、R、P、S分别表示用户集合、角色集合、许可权集合和会话集合。

PA P×R表示许可权与角色之间多对多的指派关系。

UA U×R表示用户与角色之间多对多的指派关系。

公式一枚:S=UA ∩ PA

4.1 单应用+单行为

统称为资源树接口。

举个栗子:R角色在A应用中拥有P行为的资源。

4.2 单应用+单资源+单行为

统称为行为鉴权接口。

举个栗子:R角色在A应用中是否拥有R资源的P行为。

结束语

权限系统一直以来是我们应用系统不可缺少的一个部分,若每个应用系统都重新对系统的权限进行设计,以满足不同系统用户的需求,将会浪费我们不少宝贵时间,所以花时间来设计一个相对通用的权限系统是很有意义的。

设计一个相对通用的系统是很有意义的。(不仅仅是权限)

多交流,多分享,书写更好的代码。

享受编程和技术所带来的快乐。

查看原文

赞 9 收藏 56 评论 5

tuniutech 赞了回答 · 2016-05-16

解决采用redis共享SESSION的时候,那么回话数据的key,是不是还是要基于COOKIE?

SESSION的存储和识别是互相独立的概念,主要的识别方式是Cookie式URL查询参数式,其中Cookie式效果最优,所以普遍都采用这种形式。而存储形式目前有很多种,有文件形式内存形式数据库形式等等。
只有存储和识别都存在,SESSION才能正常运行,二者缺一不可。也就是说不管选用哪种存储方式,都必须搭配一种识别形式才能实现SESSION,而常规的识别方式就是Cookie

关注 2 回答 2

tuniutech 赞了文章 · 2016-05-16

成为一名优秀的Developer的书单

这是一份关于如何Re-Practise的技术书籍推荐书单。

一直画/写一个推荐书单来供大家参考,无奈找不到一本合适的形式。有一天,想到了之前的技术树 https://github.com/phodal/sherlock,便开始落地了。

我深知自己的知识有限,所以写下本文以便和大家切磋交流。欢迎通过 GitHub 的Issues或者直接Pull Requests方式来分享你的经验。期待你的反馈。

基本阅读路线图:

BookTree

首先,你需要选择一门语言,然后学习之。这时有一些还不错,如JavaScript实战,JavaScript Cookbook,前者是一门实站手册,后者则是参考手册。再来一本某某语言,或者框架的实战,与权威指南,你就可以完成工作了。

然后呢?

说明: 完成工作是一件很容易的事,如何更好地完成工作就需要更多地学习。并且我坚信每一个有技术热情的人,都希望可以看到自己写的框架可以无处不在。

《技术的本质》 - W. Brain Arthur早已看穿了一切

这是一本关于『技术是什么,它是如何进化』的书。新的技术是根据于我们当前的目的、一个可实现的原理、一种新现象而发明的。并且,新的技术都是基于之前的技术发展出来的。

So,通过研究现有技术的一些发展,我们可以预料到一些新的技术的出现。尽管新的技术并没有解决一些根本性问题,如业务,但是它是为了业务而简化现有的技术。

如何写好代码——重构与设计模式

从编写可读的代码,到重构现有的代码,再到设计模式,是编码的必备法则。

如何写好代码——重构与设计模式

  • 《测试驱动开发》: 尽管在国内,我们很少听到开发人员写测试,就更少听人们谈论TDD。虽然我不是TDD的死忠,但是我觉得TDD还是很有好处的。特别是当你的函数特别长的时候,它可以驱使你写出更短的函数——更多的函数。红->绿->重构,就是这么简单。

  • 《重构: 改善既有代码的设计》: 红->绿->重构。如果重构之前没有测试,我相信你可能是想换个工作了。好的代码是重构出来的,而不是一开始就写出来的——除非你的代码不用于任何业务。反正,就是程序员必读,不想多说。

  • 《Head First设计模式》: GoF的《设计模式》一书很薄,所以也很抽象。第一次看《设计模式》的时候,硬着头皮看了几天,然后放弃了。。。不过,Head First系列可以将各种枯燥的设计生起起来,这是一本非常适合入门设计模式的书籍没有之一。

  • 《设计模式解析》: 比Head First更深入,但是比DP简单。作者选用了一些常用或者说用到的模式,讲述了为什么在这里适合用它。

  • 《易读代码的艺术/编写可读代码的艺术》: 纳尼!你居然不想买这本书?

  • 《代码整洁之道》: 书中给了很方法与规范,遵循它们可以写出整洁的代码。但是整洁并不意味着你应该让代码简单!

  • 《重构与模式》: 这本书的中文名字应该叫《重构到模式》!!!重构代码到设计模式就这么简单。

  • 《设计模式》: 必读,并且值得多读几遍。

  • 《元素模式》: 首先书名很扯!!!这本书更适合叫《设计模式要素》!这本书提取了设计模式中的一些基本元素,很具有启发性。

如何写前端框架——前端读书路线图

以JavaScript作为例子来解释如何去学习一门语言,从语法到最后的MVC。

如何写前端框架——前端读书路线图

机器学习读书路线

机器学习依赖于大量的数据和理论知识,而数据又可以创造出美妙的数据可视化图像。

机器学习读书路线

持续交付读书路线图

敏捷是过去,持续交付是现在,未来呢?

想要构建一个好的项目,构建系统、自动化测试、可配置缺一不可。

持续交付读书路线图

领域特定语言读书路线图

最好的语言就是可以表达你业务的语言。

如果你熟悉前端的知识的话,你会发现DSL无处不在。

领域特定语言读书路线图

架构与模式读书路线图——每个人都是架构师。

成为架构师最简单的方法就是学习别人的模式。

成为成功架构师便是创建模式。

架构与模式读书路线图

查看原文

赞 22 收藏 100 评论 3

tuniutech 赞了文章 · 2016-05-16

那些我希望在一开始使用 Zsh(oh-my-zsh) 时就知道的

其实我已经用了 fish shell 快半年了,因为被一些兼容性问题搞烦了,所以最近又用回了 zsh + oh-my-zsh。

zsh + oh-my-zsh 配合是真心好用,而且 oh-my-zsh 还偷偷干了很多人不知道的事,比如 rake task也能补全,第一次见到时真是有点惊讶。好吧,下面说一说我希望一开始就知道的。

自带的插件

其实我用了 oh-my-zsh 快三个月后才知道原来他自带了很多插件没有开启。。。

如何开启?找到 ~/.zshrc 有一行 plugins=(git),想加什么插件就把名字放里面就是了,比如plugins=(rails git ruby) 就开启了railsgitruby 三个插件。

更多插件请进入 ~/.oh-my-zsh/plugins文件夹探索,也可以看看 wiki 里的 Plugins Overview,每个人的需求不一样,里面有一些比较神奇的插件,比如敲两下esc 它会给你自动加上 sudo 的 sudo 插件,让复制显示进度条的cp插件,解压用的 extract 插件(有没有觉得在命令行下敲一大堆选项才能解压有点奇怪?),vi 粉的vi-mode 等等...

z

嗯,这也是个自带的但是没有开启的插件。为什么单独把它拿出来讲呢?因为太好用了,没有它我根本就不想用命令行。简直就是可以无脑跳跃,比如你经常进入~/Documents目录,按下 z doc 一般它就可以跳进去了(当然首先你得用一段时间让它积累一下数据才能用)。类似的插件还有好几个比如autojump,fasd,这类东西好像叫 FS Jumping,这里有个完整列表:https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins-Overview#fs-jumping

d

在 fish shell 里你可以按alt 加左右箭头随意穿梭于历史记录中,就像 GUI 文件浏览器的
前进,后退。zsh 没有这么好用,但是按一下 d 再回车你会看到最近的历史记录,然后你就可以通过数字比如 1, 2 之类的返回到某个历史记录中了。也是非常好用的。

zsh-autosuggestions

官方的介绍是Fish-like fast/unobtrusive autosuggestions for zsh,没错,这是模仿fish shell 的一个插件,作用基本上就是根据历史记录即时提示。没有这个东西让我感觉自己很盲目。没有用过 fish 的同学可能觉得它有点奇怪,但是一旦适应它以后就会发现它会大幅度的提高效率(按 ctrl+E 是正确姿势)。注意:它不是 oh-my-zsh 自带的,大家可以去 github 看它的安装说明。

自带的 Git Aliases

git 插件是默认开启的,大家可能注意到它能够自动补全以及显示所在 branch。对于一个 git 重度用户,一些 aliases 是不可缺少的。相信我,一旦习惯了 aliases,就会觉得原来敲那么一大堆命令真是不能忍了(即使它能够自动补全)。下面列一些我最常用的(当然也是 oh-my-zsh 自带的,更多请看 wiki):

AliasCommand
ggit
gstgit status
gagit add
gpgit push
gcgit commit -v
gc!git commit -v --amend

其他

  • zsh_stats 可以看到你的使用频率前 20 的命令是什么!

  • take 看看 which take 就知道它有什么用了

  • clipcopyclippaste,剪贴板和命令行的交互

官方的 wiki(重要!)

官方 wiki 上面给出了很多有用的功能介绍,比如一些 aliases,像..., ...., take 等等。

如果完整的看完了 wiki 的话我前面的介绍都是废话了。

结语

  • 推荐一个不相关的:trash-cli,就是命令行版的回收站,它的神奇之处在于不是简单的把文件移动到回收站,而且可以在回收站里恢复。所以它说自己是Command line interface to the freedesktop.org trashcan,我的 zshrc 里有一行:alias rt="trash"

  • 其他的一些非常有用的 tips 想到再补充。

  • 补上我的配置文件们:https://github.com/dd1994/dotfiles

查看原文

赞 30 收藏 81 评论 10

tuniutech 赞了文章 · 2016-05-16

JavaScript 就要统治世界了?

" JavaScript 可以……"
"嘛,不就是操作一下 DOM,可以让元素飞来飞去吗"
"JavaScript 是……"
"不就是用 jQuery 让网页动起来,顶多就是再用用 Ajax 和后端进行一下数据交换吗"
"JavaScript 是一门……"
"最讨厌和鄙视这种弱类型不需要编译的脚本语言了,你说 OOP? 扯淡的吧,JS 有对象吗"
"……"

0x00. 前言

早上起床惯例刷刷微博,突然看到 React Native 宣布支持 Android 的消息,一时感觉 Facebook 太给力了,不仅没有推迟发布 React Native For Android 而且还比之前公告的时间提前了一些。立马下床打开电脑赶紧上官网,心想着用 JS 写原生安卓的日子终于要来了。乐乐呵呵地打开文档,然后瞬间就傻眼了。好吧,尽欺负我们这些买不起 Mac 的穷学生。

React Native Requirements

虽然暂且还是用不了 React Native,但是突然就感觉到了 JS 的强大,细细一想,还真是暗暗作喜,这么恶劣的语言也居然能做出这么多有趣的事情,也真是苦了那些 JS 工程师啊。于是有了这篇稍稍对 JavaScript 畅想的文章。第一次写这类文章,还只是一名在校学生,固然没有大神们的那种境界,有错误和不妥之处还请指出,我定虚心学习。

0x01. 浏览器中的 JavaScript

曾经很单纯地认为能够熟练地使用 jQuery/JavaScript 操作 DOM,能够将一些高复用的组件注册为插件就是掌握 JS 的标志。然而随着自己接触更多的人,接触更多的技术才发现自己的无知和渺小,浏览器其实只是 JavaScript 的一个宿主环境,提供 JavaScript 引擎来解释 JavaScript,浏览器环境下的 JavaScript 和 JavaScript 本身还是有很大区别的,浏览器下的 JavaScript 在 JavaScript 整个体系中其实也只是很小(但很重要)的一部分而已。

JavaScript In Console

0x02. JavaScript 能做什么

1. Web 前端

很早以前各大公司对于 Web 标准的恶战让 JS 的环境异常恶劣,加之语言其本身的不成熟让其功能仅限于一些简单的前端交互。Ajax 技术的出现让前端可以在不刷新页面的情况下和后端进行数据交换,jQuery/zepto 等库的盛行让 JS 变得异常简单,Bootstrap/Amaze UI 等 UI 框架更是让前端的成本无限降低,RequireJS/SeaJs 让 JavaScript 也可以进行依赖管理,MVVM(Model-View-ViewModel 的出现让前后端的分离做到了极致,JavaScript 在前端领域前景明朗。

 // jQuery 进行 Ajax 请求
 $.ajax({
   async: true,
   type: 'POST',
   url: "api.php/CustomerLogin/login",
   data: {
     username: 'PuYart',
     password: 'jianshu', 
     uuid: 'web_jianshu'
   }, 
   success: function (data) {
       // 登录成功
   }
 });

阮一峰如是说

2. 后端之旅

2009年5月,Ryan Dah 发布了 Node 的最初版本。Node 是一个基于 Chrome JavaScript 运行时建立的平台,它对 Google V8 引擎进行了封装,使 JavaScript 第一次走出前端运行在了服务器上。这对 JavaScript 来说是一种质的突破,这使得 Web 编程可以只用一门语言便可完成。It's Amazing! Web 的大一统时代仿佛就要来了。同时 Node 也诞生了 npm,从此 JavaScript 也有了强大的包管理机制。

// 使用 Express 的 Hello world
var express = require('express');
var app = express();

app.get('/', function (req, res) {
 res.send('Hello World!');
});

var server = app.listen(3000, function () {
 var host = server.address().address;
 var port = server.address().port;

 console.log('Example app listening at http://%s:%s', host, port);
});

3. Hybrid App

传统上 JavaScript 只能在浏览器中运行,Node 的出现让 JavaScript 运行在了服务端,然而只是这样的话,好像还是少点什么。人们总是希望用一种方式去做所有的事情,于是聪明的工程师们就发明了 Hybrid App 这种形式,让 JavaScript 在一定意义上运行在了移动设备上。然而当前 Hybrid App 虽然让 JavaScript 也可以写出 JAVA/Objective-C 才能实现的 APP,但是这种方式仍然没有抛弃浏览器运行环境,对 WebView 有很强的依赖性,性能和原生应用还有很大差距。

APICloud 云端一体平台介绍

4. 桌面应用

至此 JavaScript 除了可以被浏览器解析,也可以作为后端语言使用,还可以用来构建移动端 APP。仿佛已经够强大了吧,然而这还不够,JavaScript 还可以用来构建桌面应用!

Node-webkit

Node-webkit 是一个 Web 应用程序运行时环境,它可以让你以 Web 的方式来写桌面应用程序,你可以用任何流行的 Web 技术来编写一个跨平台(Windows,Linux,MacOS)的桌面程序,并且性能和交互也是良好的,Teambition 桌面客户端便是使用 Node-webkit 编写的。目前在 GitHub 上有 24463 Star。

heX

heX 是有道公司开发的采用前端技术(HTML,CSS,JavaScript)开发桌面应用软件的跨平台解决方案,意在解决传统桌面应用开发中繁琐的 UI 和交互开发工作,使其变的简单而高效。特别适合重 UI,重交互的桌面应用软件。新版有道词典 beta 版的首页便是使用 heX 开发完成的。

Electron

Electron(以前叫做 Atom Shell) 是 GitHub 开源的使用 Web 技术开发桌面应用的技术平台。它允许你使用 HTML, CSS 和 JavaScript 编写跨平台的桌面应用。它是 io.js 运行时的衍生,专注于桌面应用而不是 web 服务端。Electron 不仅仅是一个支持打包 web 应用成为桌面应用的原生 web view。它现在包含 app 的自动升级、安装包、崩溃报告、通知和一些其它原生桌面应用的功能——所有的这些都通过 JavaScript API 调用的。

5. 神作 React

React

React(React.js) 是由 FaceBook 开发和维护的前端框架,目前在 GitHub 得到了 27900+ star。它摒弃了 MVC/MVVM 的模式,仅仅是做 UI,开创性地采用了 Virtual DOM(虚拟 DOM)避免了 DOM 操作消耗性能的问题,将 UI 拆分成不同的可组合、可复用、可维护的组件,组件和组件之间耦合度极低,开发效率大幅度增加。在前端 UI 组件化的趋势下,这很值得去尝试。instagram.com 全站都采用 React 进行开发。

React 架构 - 来自 @鬼道 (http://www.zhihu.com/people/luics) 的知乎回答

上图来自 @鬼道 的知乎回答如何评价 React Native?

   // 简单的官方示例
   var HelloMessage = React.createClass({
       render: function() {
           return <div>Hello {this.props.name}</div>;
       }
   });

   React.render(<HelloMessage name="John" />, mountNode);

React Native

React Native 既拥有 Native 的用户体验,又保留 React 的开发效率。开源不到1周 GitHub Star 破万,这简直是逆天的成绩啊!上线之初仅支持 iOS,React 也在9月14号对 Android 提供了支持服务,这几天意味着你可以使用同一套逻辑和架构、同一门语言实现 Web、iOS、Android 的开发。由于各大平台 API 和交互逻辑的不同,React Native 的理念是 “Learn once, write anywhere”,而不是曾经跨平台流行的 “Write once, run anywhere” 。实际上 React Native 和 React 有很大的差别,但是逻辑和架构还是保持一致的。React Native 和 Hybrid 最大的区别是前者摒弃了饱受性能诟病的 WebView,通过 HTML 标签和移动平台的组件进行映射,仿佛是将 JS “编译”成了原生语言一样,性能和交互体验会比 Hybrid 好上不少。目前在 GitHub 上有 18551 Star。

 // 简单的官方示例
 // iOS
 var React = require('react-native');
 var { TabBarIOS, NavigatorIOS } = React;
 var App = React.createClass({ 
    render: function() { 
       return ( 
         <TabBarIOS> 
           <TabBarIOS.Item title="React Native" selected={true}>
           <NavigatorIOS initialRoute={{ title: 'React Native' }} />
         </TabBarIOS.Item> </TabBarIOS>
       ); 
     },
 });

 // Android
 var React = require('react-native');
 var { DrawerLayoutAndroid, ProgressBarAndroid } = React;
 var App = React.createClass({
     render: function() {
       return (
         <DrawerLayoutAndroid
           renderNavigationView={() => <Text>React Native</Text>}>        
           <ProgressBarAndroid />
         </DrawerLayoutAndroid>
       );
     },
 });

6. 游戏

世界上最流行的 2D 游戏引擎之一 Cocos2d 和最流行的 3D 游戏引擎之一 Unity3D 均支持 JS 开发游戏。

Cocos2d-js

Cocos2d-JS 是 Cocos2d-x 的 JavaScript 版本,融合了 Cocos2d-html5 和Cocos2d-x JavaScript Bindings。它支持 Cocos2d-x 的所有核心特性并提供更简单易用的 JavaScript 风格 API,并且天然支持原生、浏览器跨平台应用。

在3.0版中,Cocos2d-JS 完成了不同平台工作流的彻底整合,为不同平台提供了统一的开发体验。无论开发 Web 应用还是原生应用,都可以便捷地采用 Cocos2d-JS 实现“一次开发,全平台运行”。采用 Cocos2d-JS 开发的同一套 JavaScript 游戏代码,可以同时运行在 Mac OS X, Windows, iOS, Android等原生平台、以及所有现代浏览器上,这将使得我们的开发者轻松覆盖几乎所有发行渠道,带来前所未有的机遇。另一方面,若开发者只想开发一款 Web 轻度休闲游戏,Cocos2d-JS 也专门为此类游戏定制了 Lite Version,直接将 Cocos2d-JS Lite Version 集成到页面中即可使用。

Cocos2d-JS v3.0 框架

Unity3D

Unity3D 是一个跨平台的 3D 游戏引擎,与 Cocos2d 最大的区别在于前者主要面对 2D 游戏开发者,后者主要进行大型 3D 游戏的开发。

Pomelo

pomelo 是一个网易开发的基于 Node.js 的开源游戏服务器框架,与以往单进程的游戏框架不同, 它是高性能、高可伸缩、分布式多进程的游戏服务器框架,并且使用很简单。它包括基础开发框架和一系列相关工具和库,可以帮助开发者省去游戏开发中枯燥的重复劳动和底层逻辑工作,免除开发者的重造轮子,让开发者可以更多地去关注游戏的具体逻辑,大大提高开发效率。pomelo 强大的可伸缩性和灵活性使得 pomelo 也可以作为通用的分布式实时应用开发框架,用于一些高实时应用的开发,而且 pomelo 在很多方面的表现甚至超越了现有的开源实时应用框架。pomelo 支持所有主流平台的客户端,并提供了客户端的开发库,使得客户端的开发变得很友好。

Bearcat

Bearcat 是网易 pomelo 项目团队开发的一个基于 POJOs(Plain Old JavaScript Objects) 进行开发的应用层框架,Bearcat 提供了一个轻量级的容器来编写简单、可维护的 Node.js。Bearcat 提供了一个基础的底层来管理应用逻辑对象,使得开发者就可以把精力放在应用层的逻辑编写上。Bearcat 使开发者编写“简单纯粹的 JavaScript 对象”(POJO),并且不会侵入这些 POJO,你完全可以在不使用 Bearcat 的环境下部署应用这些 POJO。

7. 其它

FUSE

Fuse 是一个为开发者和设计者而设计的用户体验(UX)工具集,用于创建原生的、跨平台的 iOS 和 Android 移动应用。在 Fuse 中,开发者使用标记定义用户界面,使用 JavaScript 编写应用程序逻辑,同时所有的渲染都会被编译成原生代码以获得最佳性能。通过 Fuse,用户能够快速地创建漂亮的、具有流畅动画体验的原生移动应用。

Cylon

Cylon

Cylon.js 是一个开源 JavaScript 框架,使用 Node.js 来进行机器人开发和物理计算。Cylon.js 提供一个简单强大的方法来解决同一时间合并不同设备的问题。目前支持多达 43 种平台的硬件设备,其中包括 Arduino、AT&T M2X、Intel Edison、Leap Motion、Nest、OpenCV 等众多热门的硬件平台。

浏览器插件和扩展

现代浏览器大都支持扩展程序的开发,我们常用的慧慧购物助手、有道翻译、浏览器截图等等这些浏览器插件都是使用 JavaScript 开发完成的。浏览器会暴露一些方法给扩展程序使用,比如 js 注入、窗口管理、页面通讯等。正是这些插件的存在让浏览器的可用性大大增强。

0x03. JavaScript 语言是坨屎?

  • 兼容性

  • 性能

  • 面向对象

  • 深拷贝

  • 单线程

  • ···

这些都是 JavaScript 的语言缺陷,拿面向对象举例,JavaScript 没有严格意义的类和对象,只能用函数这种奇奇怪怪的方式实现 OOP。这些缺陷也情有可原,因为事实上 JavaScript 在几天(据说为10天)的时间内就被 Brendan Eich 设计出来了。很多人都感叹 JavaScript 在这么恶劣的语言和环境中竟能得到这样的成功。正是因为 JavaScript 开发周期短、早期规范缺失、浏览器厂商竞争这些原因导致一些问题迟迟不能解决。

// 工厂模式 常用
function Person(name, gender, age) {
 var obj = Object();
 obj.name = name;
 obj.gender = gender;
 obj.age = age;
 obj.tellAge = function () {
   console.log(this.age);
 };
 return obj;
}

var puya = new Person('PuYart', 'male', '21');
puya.tellAge();
// 构造函数模式
function Person(name, gender, age) {
  this.name = name;
  this.gender = gender;
  this.age = age;
  this.tellAge = function () {
    console.log(this.age);
  };
}

var puya = new Person('PuYart', 'male', '21');
puya.tellAge();
// 原型链(+构造函数)模式 很常用
function Person(name, gender, age) {
  this.name = name;
  this.gender = gender;
  this.age = age;
}

Person.prototype.tellAge = function () {
    console.log(this.age);
};

var puya = new Person('PuYart', 'male', '21');
puya.tellAge();

这里举出了常用的三种构造对象的方法,你也会感觉到恶心得要死吧。为了改善 JavaScript 语言本身的不足,微软在2012年推出了 TypeScript 语言,TypeScript 是 JavaScript 的超集,支持强类型和 OOP,最终编译为 JavaScript。当然了 CoffeeScript 也是一种解决方案。

ECMAScript 经过4个版本的迭代之后,终于迎来了第5个版本(因为 ES4 流产了)—— ES6。ES6 标准的发布可谓是 JavaScript 历史上最重要的里程碑,它给 JavaScript 带来了诸多语言特性,箭头操作符、类的支持、字符串模板、函数参数默认值、迭代器、for-of 遍历、生成器、Symbols 基本类型等等,这就意味着你可以这样写 JavaScript 了:

// ES6 中启用了关键字 class
class Person {
  constructor(name, gender, age) {
    this.name = name;
    this.gender = gender;
    this.age = age;
  }
  tellAge() {
    console.log(this.age);
  }
}

var puya = new Person('PuYart', 'male', '21');
puya.tellAge();

虽然 ES6 带来了很多美妙的特性,让 JavaScript 也可以像其他语言那样优雅地写出健壮的代码,但是 ES5 还会独占市场很久,各浏览器厂商跟进也需要一段时间。然而我们有理由相信,在不久的将来,JavaScript 的另一片美好的天空定会到来。毕竟 JavaScript 是一门年轻但是充满活力、不断进化的语言。

0x04. JavaScript 统治世界?

JavaScript 固然可以做很多事情,从前端到后端,从桌面到移动,从应用到游戏,仿佛干了所有的事情一样。然而,也正是 JavaScript 固有的语言特性,使其在很多场景并不适用,调用硬件(经 @zhangyang 提醒 nodebots 可以控制硬件)、大数据、高强度计算等等这些考验性能和执行效率的事情 JavaScript 是万万做不到的不太擅长的;尽管 JavaScript 可以移动开发,然而真正采用 JavaScript 来开发移动端是一个很需要魄力的选择,没有生态支持、没有历史可借鉴,究竟有多少人愿意这样做也是一个问题。细细一想,JavaScript 成熟的应用空间也只剩下了前端、轻量级后端和游戏了吧。然而当 ES6 大量部署的时候,这个世界会是什么样,谁又知道呢?

JavaScript 统治世界,任重而道远啊!

查看原文

赞 51 收藏 269 评论 26

tuniutech 发布了文章 · 2016-05-16

途牛原创|使用 lombok 简化 Java 代码

一个典型的 Java 类

public class A {

  private int a;

  private String b;

  public int getA() {
    return a;
  }

  public String getB() {
    return b;
  }

  public void setA(int a) {
    this.a = a;
  }

  public void setB(String b) {
    this.b = b;
  }

}

对于这样一个简单的 Java 类,我们通常需要给每个属性写gettersetter,而这种实际上没有什么太大的意义。当然,如果有的公司或团队使用代码行数评估工作量,还是多写几行吧;同时,可以考虑一下我们团队。

使用 lombok,简化代码

为了简化gettersetter,lombok 提供了一种机制,帮助我们自动生成这些样板代码。以上的代码,如果使用lombok的话,将变得很简单:

@lombok.Getter
@lombok.Setter
public class A {

    private int a;

    private String b;

}

顾名思义,lombok.Getter就是生成getterlombok.Setter就是生成setter。但是,这样真的就可以了么?编译下,让我们看看生成的二进制代码。(请自行下载lombok.jar)

命令行> javac -cp lombok.jar A.java
命令行> javap -c A.class

输出结果略。可以看到完全一样。

更进一步,如果在编译的时候,加入-g:none选项,甚至可以看到生成的文件完全一样。

简单使用

虽然我们可以在编译的时候,加入classpath,但是,一般来说,在各类IDE中使用,还是需要特殊处理一下。

Maven

加上依赖就好。同时,由于lombok只在编译期才处理,所以并不需要在运行时有这个依赖,可以把scope定义为provided

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.8</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

值得注意的是,mavenmaven-compiler-plugin低版本和lombok高版本不兼容,目前已知maven-compiler-plugin2.3.Xlombok1.6.X不兼容。这个需要了解lombok的原理才能进一步说明。

Eclipse

由于eclipse的默认编译器并不是javac,所以,需要额外安装,基本就是改下引导参数,可以直接运行jar包,或者手动在eclipse.ini里加上参数-Xbootclasspath/a:lombok.jar -javaagent:lombok.jar

IDEA IntelliJ

虽然IDEA IntelliJ默认使用javac作为编译器,理论上可以不装插件。可是,跳转等特性也随之没了。所以,还是安装个插件吧,直接去仓库里搜索lombok就成。

如果项目中使用高级配置,需要额外注意一下。虽然在编译的时候,lombok配置文件可以在任何能找到的目录,但是,lombok-intellij插件默认并不支持在任何目录,如果有配置文件,建议放在java的源代码根目录中。

更多 lombok 注解

lombok 目前最新版本为 1.16.8,个人觉得比较常用的有以下几种,更多请查看官网。

  • @val

如果你要定义一个final的变量,并且不想写类型,这个可以帮到你。但是,在实际项目中,完全没有使用到。

  • @NonNull

这个在参数中使用,如果调用时传了null,就直接抛空指针。

  • @Data

@ToString@EqualsAndHashCode@Getter@Setter@RequiredArgsConstructor注解的集合。

  • @Getter@Setter

作用于属性和类上,自动生成属性的getXXX()setXXX()方法。若在类上,则对所有属性有效。并可通过AccessLevel参数控制方法的访问级别。

  • @ToString

作用于类,自动重写类的ToString()方法。常用的参数有exclude(指定方法中不包含的属性)、callSuper(方法中是否包含父类ToString()方法返回的值)

  • @EqualsAndHashCode

作用于类,自动重写类的equals()hashCode()方法。常用的参数有exclude(指定方法中不包含的属性)、callSuper(方法中是否包含父类ToString()方法返回的值)

  • @NoArgsConstructor, @RequiredArgsConstructor@AllArgsConstructor

作用于类,@NoArgsConstructor自动生成不带参数的构造方法;@RequiredArgsConstructor自动生成带参数的构造方法,主要针对一些需要特殊处理的属性,比如未初始化的final属性;@AllArgsConstructor自动生成包含所有属性的构造方法。

  • @Synchronized

作用于方法,可锁定指定的对象,如果不指定,则默认创建创建一个对象锁定。

  • @Log,或者直接@Slf4j

作用于类,具体包含@CommonsLog@Log@Log4j@Log4j2@Slf4j@XSlf4j,分别对用不同的日志系统。利用此类注解,可为类创建一个log属性。

sonar源码审查

sonar是一个源码审查工具。最新版5.X已经支持lombok的全部注解,不再认为是没有使用的变量。但是,旧的4.X还是认为没有使用这些变量。可以后向移植这些包,或者应用单独的补丁。

原理

呃,真的有人想看原理么?如果想,请留言,以后再发。

参考文献

  1. lombok, lombok 官网,但是,目前没有发现哪里可以捐赠

  2. sonar, sonar 官网,对代码规范有一些建议

  3. sonar-java, sonar-java 低版本插件,支持lombok

查看原文

赞 1 收藏 16 评论 3

tuniutech 发布了文章 · 2016-05-16

途牛原创|如何使用 hexo+github 搭建个人博客

如何使用 hexo+github 搭建个人博客

前段时间,在一次分享会上发现,很多人不知道 github 的一个强大功能 —— GitHub Pages,今天就介绍下。如果你不想要像新浪、csdn 这类样式丑、页面内容杂的博客网站,或者不想在移植、迁移上浪费精力,又或者不想付出多余的银子买VPS,那么 GitHub Pages 是不错的选择。

GitHub Pages 有以下几个优点:

  • 轻量级的博客系统,没有麻烦的配置

  • 免费空间,享受 Git 版本管理功能

  • 使用标记语言,比如 Markdown

  • 无需自己搭建服务器

  • 可以绑定自己的域名

当然他也有缺点:

  • 搭配模板系统,相当于静态页发布,每运行生成一次都必须遍历全部的文本文件,网站越大,生成时间越长

  • 动态程序的部分相当局限,比如没有评论,不过有解决方案

  • 基于 Git,很多东西需要定制,不像 Wordpress 有强大的后台

要想搭建漂亮的 blog,还需要模板系统,官方推荐的是 jekyll,但是配置稍复杂,今天推荐另一个选择 —— hexo,一个简单地、轻量地、基于 Node 的一个静态博客框架。

下面介绍下如何使用 hexo 和 github pages 搭建个人博客。

准备工作

注意: 本文针对 Windows 平台和 Hexo 3.1.1

安装 github windows

主要使用 git bash,如果对 git 命令不熟悉的也可以使用 git 客户端进行某些操作

github windows

安装 node.js

因为要使用 npm,比较简单的方法就是安装 node.js

node.js

安装完成后添加 Path 环境变量,使 npm 命令生效

;C:\Program Files\nodejs\node_modules\npm

创建 Github Pages

没有 github 账号的话,需要注册一个,不赘述

然后创建一个仓库,名字是[yourGithubAccount].github.io

配置 ssh key

使用 git bash 生成 public ssh key,以下是最简单的方法

$ ssh-keygen -t rsa

C/Documents and Settings/username/.ssh 目录下会生成 id_rsa.pub

将 id_rsa.pub 的内容完全复制到 github Account Setting 里的 ssh key 里即可

测试

$ ssh -T git@github.com

然后会看到

Hi [yourGithubAccount]! You've successfully authenticated, but GitHub does not provide shell access.

设置用户信息

$ git config --global user.name "[yourName]"//用户名
$ git config --global user.email  "[yourEmail]"//填写自己的邮箱

经过以上步骤,本机已成功连接到 github,为部署打下基础。

配置 hexo

本地 clone

创建本地目录,然后使用 git bash 或者客户端 clone 之前创建的仓库([yourGithubAccount].github.io)

安装、配置 hexo

进入仓库目录,使用 git bash 安装配置 hexo

$ npm install -g hexo-cli
$ npm install hexo --save
$ hexo init

安装 hexo 插件

npm install hexo-generator-index --save
npm install hexo-generator-archive --save
npm install hexo-generator-category --save
npm install hexo-generator-tag --save
npm install hexo-server --save
npm install hexo-deployer-git --save
npm install hexo-deployer-heroku --save
npm install hexo-deployer-rsync --save
npm install hexo-deployer-openshift --save
npm install hexo-renderer-marked@0.2 --save
npm install hexo-renderer-stylus@0.2 --save
npm install hexo-generator-feed@1 --save
npm install hexo-generator-sitemap@1 --save

安装 ejs,否则无法解析模板

$ npm install

生成 public 文件夹

$ hexo g

浏览器输入 localhost:4000 本地查看效果

$ hexo s

主题

hexo 有很多主题可选,我选了 Jacman,默认支持多说评论、网站统计、分享等功能,只要稍微配置即可使用。可以根据自己需求进行选择。

使用 hexo

部署

配置 _config.yml

deploy:
  type: git
  repository: git@github.com:[yourGithubAccount]/[yourGithubAccount].github.io.git
  branch: master
$ hexo d

即可将 hexo 部署到 github 上

提示找不到 git 时

需执行(虽然之前已经执行过)

npm install hexo-deployer-git --save

然后

$ hexo d

即可通过 http://[yourGithubAccount].github.io/ 查看了

发表新文章

$ hexo new "title"

然后在 source/_post 下会生成该md文件,即可使用编辑器编写了

编写过程中,可以在本地实时查看效果,很是方便

支持 markdown,不了解的自行 google 吧

编写完成后,部署还是一样的

$ hexo g
$ hexo d

如果部署过程中报错,可执行以下命令重新部署

$ hexo clean
$ hexo generate
$ hexo deploy

添加自定义页面

$ hexo new page "about"

该命令会生成 source/about/index.md,编辑即可

插件的升级与卸载

$ npm update
$ npm uninstall <plugin-name>

更新 hexo

npm update -g hexo

绑定自定义域名

在/source/ 目录下新建内容为自定义域名的 CNAME 文件,部署即可(域名设置略)

备注:

Hexo简写命令

hexo n #new
hexo g #generate
hexo s #server
hexo d #deploy

以上是基本操作,质量高的 blog 所带来的好处是不言而喻的,感兴趣的可以行动起来了。

参考资料

查看原文

赞 8 收藏 29 评论 0

tuniutech 回答了问题 · 2016-05-16

codeigniter3如何集成phpunit

可以看看这个日本大神的:https://github.com/kenjis/ci-phpunit-test

关注 2 回答 1

tuniutech 回答了问题 · 2016-05-15

restful api开发网站的要怎样架构?

关于RESTful:链接
关于API设计:链接

关注 17 回答 7

认证与成就

  • 获得 44 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • soft-tech

    分享&传阅知识,理解技术,合理运用,造福人类。

注册于 2016-05-13
个人主页被 1.5k 人浏览