Mac点滴-三指拖拽窗口

之前一直以为三指拖拽窗口是触摸板设置的功能,其实是在辅助功能里设置,官方教程如下:

“三指拖移”是 OS X 中的一种 Multi-Touch 手势。通过这个手势,您能使用三个手指移动屏幕上的活跃窗口。

本文介绍了在您的 Mac 配备了 Force Touch 触控板的情况下,该如何开启“三指拖移”。

  1. 从 Apple 菜单中,选取“系统偏好设置”。
  2. 点按“辅助功能”图标。
  3. 从左侧的选项中选取“鼠标与触控板”。
  4. 点按“触控板选项”。
  5. 在“启用拖移”旁边勾选。
  6. 从相关的弹出式菜单中,选取“三指拖移”,这样该项旁边会显示一个勾号。
  7. 点按“好”。

learn-kylin解析

learn-kylin是Apache Kylin自带的一个示例,展示了数据组织、模型构建以及Cube构建的过程等。本文通过深入解析learn-kylin,希望能帮助大家学习Kylin的使用。

安装完Kylin后可通过./bin/sample.sh来初始化示例。该脚本主要完成创建hive数据库以及表、将数据导入到hive中、准备必要的目录、初始化模型以及cube等。

下边我们将详细学习一下数据以及kylin的工作过程。

1、关于数据

1.1、原始数据

原始数据包括如下5张表,用于记录销售信息。其中KYLIN_SALES为销售订单明细,为实体表,其他表为维度表,分表为KYLIN_CAL_DT(时间扩展表)、KYLIN_CATEGORY_GROUPINGS(商品类别表)、KYLIN_ACCOUNT(账户表)、KYLIN_COUNTRY(国家地理位置表)。

1.2、原始数据之间的关系


SELECT
KYLIN_SALES.TRANS_ID
,KYLIN_SALES.PART_DT
,KYLIN_SALES.LEAF_CATEG_ID
,KYLIN_SALES.LSTG_SITE_ID
,KYLIN_CATEGORY_GROUPINGS.META_CATEG_NAME
,KYLIN_CATEGORY_GROUPINGS.CATEG_LVL2_NAME
,KYLIN_CATEGORY_GROUPINGS.CATEG_LVL3_NAME
,KYLIN_SALES.LSTG_FORMAT_NAME
,KYLIN_SALES.SELLER_ID
,KYLIN_SALES.BUYER_ID
,BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL
,SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL
,BUYER_ACCOUNT.ACCOUNT_COUNTRY
,SELLER_ACCOUNT.ACCOUNT_COUNTRY
,BUYER_COUNTRY.NAME
,SELLER_COUNTRY.NAME
,KYLIN_SALES.OPS_USER_ID
,KYLIN_SALES.OPS_REGION
,KYLIN_SALES.PRICE
FROM DEFAULT.KYLIN_SALES as KYLIN_SALES
INNER JOIN DEFAULT.KYLIN_CAL_DT as KYLIN_CAL_DT
ON KYLIN_SALES.PART_DT = KYLIN_CAL_DT.CAL_DT
INNER JOIN DEFAULT.KYLIN_CATEGORY_GROUPINGS as KYLIN_CATEGORY_GROUPINGS
ON KYLIN_SALES.LEAF_CATEG_ID = KYLIN_CATEGORY_GROUPINGS.LEAF_CATEG_ID AND KYLIN_SALES.LSTG_SITE_ID = KYLIN_CATEGORY_GROUPINGS.SITE_ID
INNER JOIN DEFAULT.KYLIN_ACCOUNT as BUYER_ACCOUNT
ON KYLIN_SALES.BUYER_ID = BUYER_ACCOUNT.ACCOUNT_ID
INNER JOIN DEFAULT.KYLIN_ACCOUNT as SELLER_ACCOUNT
ON KYLIN_SALES.SELLER_ID = SELLER_ACCOUNT.ACCOUNT_ID
INNER JOIN DEFAULT.KYLIN_COUNTRY as BUYER_COUNTRY
ON BUYER_ACCOUNT.ACCOUNT_COUNTRY = BUYER_COUNTRY.COUNTRY
INNER JOIN DEFAULT.KYLIN_COUNTRY as SELLER_COUNTRY
ON SELLER_ACCOUNT.ACCOUNT_COUNTRY = SELLER_COUNTRY.COUNTRY

这里需要注意,KYLIN_ACCOUNT既是BUYER_ACCOUNT又是SELLER_COUNTRY,也就是说账户表里即存了购买者与销售者的账户信息。

ER图简介以及举例

ER图即实体关系模型,可以辅助进行数据库表设计。通过如下图标来描述实体关系之间的关系,然后通过ER图来转换为数据库的表结构。其中:

  • 长方形: 实体,对应一张实体,最终转化为一张数据库表。
  • 菱形:关系,一般用动词描述,在多对多关系中可以转换为一张表。
  • 椭圆: 属性,实体或者关系包含的属性,最终将对应表中的一列。

实体和属性比较简单,我们不多说,下边来看一下关系:

小技巧:对于确定关系的时候,请从左向右来描述一遍,然后再从右到左描述一遍来看一下。

  • 1对1

1对1关系比较简单,比如学生以及学生身份证号就是一对一的关系,那么只需要简历一张表即可。

  • 1对n

请看如下关系,学生和来源城市之间的关系。使用上述小技巧,来试一下,“学生来源于一个城市,一个城市可以为多个学生的来源”,所以学生对一个城市,一个城市对应多个学生,如图所示。

1对多关系可以转换为两张表,通过在“多”这侧添加“1”侧的唯一键来关联起来,即在学生表添加城市ID(city_id)来关联。上图转换为下边两张表“学生表”和“城市表”。

学生表:

城市表:

  • n对n

请看如下关系,学生和课程之间的关系。“一个学生需要学习多门课程,一门课程有许多学生学习”,所以一个学生对多个课程,一个课程对应多个学生,如下图所示。

多对多关系需要转化为至少三张表,两个实体表和一个关系表,关系表存储两个实体的对应关系,存储两个实体表的键即可。转化后的表为:学生表、课程表、学生课程表。

学生表:

课程表:

有了上边两张表,那么我们的关系表就咋办呢?比如我们让张三学习一下这两门课程。学生课程表如下:

OK,到此E-R图基本上就是这样了,按照标准来说,我们需要给实体加上属性,但是如果把属性都画上图会很乱,所以一般不会画出属性。对于属性还有个主键的问题,就是在属性加下划线即可,不再演示。关于其他问题以后再跟新这篇文章。

 

TOP 20 REST API面试题及解答(测试人员版本)【翻译】

RESTful API作为目前比较流行的API设计架构,是每个所有技术人员需要掌握的。本文虽然是写给测试人员的,但是可以作为所有同学的入门来看。

正文:

亲爱的读者,这是写给测试工程师的前20 REST API面试问题和答案列表。作为一个QA工程师,我们也应该了解rest API概念。

Q-1. 简述 REST?

Ans. REST 代表Representational State Transfer(表述性状态转移). REST是一种开发网络服务的架构风格,它利用了HTTP协议的普遍性并且使用HTTP方法来定义动作。它围绕资源展开,一切组件都是可以通过使用HTTP标准方法统一接口被访问的资源。

在REST架构中,REST服务端提供资源访问和REST客户端访问和描述资源。每个资源通过URI或者全局ID区分。REST使用不同的方式来描述资源,比如text、JSON和XML。现在XML和JSON是最为流行的资源描述方式。

Q-2. 描述 RESTFul Web Service?

Ans. 通常,有两种比较流行的Web服务。

1. 简单对象访问协议SOAP (Simple Object Access Protocol) 是一种基于XML的方式提供网络服务。

2. 使用REST风格开发的网络服务被称作RESTful web service。这种服务使用HTTP方法来实现REST架构的概念。RESTful web 服务通常定义一个URI,统一资源标识符服务、提供资源描述比如JSON并且一系列HTTP方法。

Q-3. 简述在REST中什么是一个“资源(Resource)”?

Ans. REST架构将每一个内容作为资源。资源可以使文本文件、HTML页面、图片、视频或者动态的商业数据。

REST服务提供资源访问,REST客户端访问和修改这些资源。此处每个资源通过URI或者全局ID来区分。

Q-4.在REST中最流行的资源表述方式是什么?

Ans. REST使用不同描述方式来定义一个资源比如text、JSON和XML。

XML和JSON是最流行的资源描述方式。

Q-5.  RESTful Web Services使用哪种协议?

Ans. RESTful网络服务使用HTTP协议作为客户端和服务器通信的媒介。

Q-6. RESTful Web Services的消息是什么?

Ans. RESTful网络服务使用HTTP协议作为客户端和服务器通信的媒介。客户端以HTTP请求方式的发送消息。

作为响应,服务器端传递HTTP响应。这项技术叫做消息(Message)。此消息包含消息数据和元数据等其他关于消息本身的信息。

Q-7. 描述一个HTTP请求的核心组成?

Ans. 每个HTTP请求包含5个关键元素。

1. 谓词- 描述HTTP方法的动词,比如GET, PUT, POST, DELETE。
2. URI – URI 代表 Uniform Resource Identifier (URI) 统一资源定位。它是服务器上资源的标识。
3. 版本 – 描述HTTP版本的HTTP Version,例如HTTP v1.1.
4. 请求头 – 携带了HTTP请求信息元数据(键值对)的请求头。元数据可以是客户端(或者浏览器)类型,客户端支持的类型,消息体格式和缓存设置等。
5. 请求体 – 描述消息内容或者资源描述的消息体。

Q-8. 描述一个HTTP响应的核心组成?

Ans. 每个HTTP响应包含四个核心元素。

1. 状态/响应码 – 表述HTTP请求的资源服务器状态。 例如,404表示资源未找到的意思,200代表返回成功的意思。
2. HTTP版本 – 表述 HTTP版本, 例如HTTP v1.1.
3. 响应头 – 包含了以键值对形式存储的HTTP响应消息的元信息。例如,内容长度,内容类型,响应日期以及服务器类型等。
4. 响应体 – 表述响应消息或者资源描述。

Q-9. 指出几个最常用的REST 支持的HTTP方法?

Ans. 有几个HTTP方法在REST中经常使用。

1. GET – 通过URL请求一个资源。请求不应包含请求体, 因为请求体会被丢弃。请求可能会在本地或者服务器端缓存。
2. POST – 提交需要服务器端处理的信息;典型地,应该返回一个修改后的或者新的资源。
3. PUT – 通过URL更新资源。
4. DELETE – 通过URL删除资源。
5. OPTIONS – 描述可支持的技术。
6. HEAD – 返回请求URL的元数据信息。

Q-10. 简述, 是否可以使用GET请求代替PUT来创建一个资源?

Ans. 不可以,应该使用PUT或者POST方法。相反,使用GET操作是只读操作。

Q-11. PUT和POST操作有什么不同?请简述。

Ans. PUT 和 POST 操作几乎相同。唯一的不同是关于他们产生的结果。

PUT 操作是幂等的,而POST操作可以得到不同的结果。

举一个例子:

1. PUT 通过一个特定的URI请求一个文件或者资源。如果资源已经存在,那么PUT更新它。如果是首次请求,那么PUT创建它。
2. POST发送数据到一个特定的URI并且期望那个URI的资源处理请求。在这种情况下,服务器可以根据特定资源的内容来决定采取什么动作处理数据。

Q-12. 在RESTful Web Services中,OPTIONS操作的目的是什么?

Ans. 这个方法列出所有网络服务支持的操作。发送只读的请求到服务器。

Q-13. URI是什么?解释基于REST的网络服务中它的意义? 它的形式是怎样的?

Ans. URI 代表 Uniform Resource Identifier统一资源定位符. URI是资源的标识符,在REST架构中。

URI的意义是用于在提供网络服务的服务器上定位资源。 URI 形式如下:

<protocol>://<service-name>/<ResourceType>/<ResourceID>

Q-14. 在RESTful Web Service中,关于负载(Payload)你是如何理解的?

Ans. 每个HTTP消息的消息体包含的请求数据叫做负载。这部分是接收者感兴趣的消息。

我们可以说用POST方法发送了负载,但是不能使用GET和DELETE方法。

Q-15. 在POST方法中传递负载的上限是多少?

Ans. <GET> 附加数据到服务的URL上。但是,它的长度不应该超过最大URL长度限制。然而,<POST>并没有这种限制。

因此,理论上,用户可以传递无限数据作为POST方法的负载。但是,如果我们考虑现实情况,发送POST携带大量负载需要考虑带宽消耗。将会对服务器造成大量耗时和性能挑战。因此用户应该根据情况来定。

Q-16. 解释缓存机制?

Ans. 缓存是在客户端存储服务器相应的处理。它可以从一次次请求相同资源节省客观的时间。

服务器响应返回使客户端执行缓存的信息。以帮助客户端确定存档时长或者不再存储。

Q-17. 列举SOAP和REST之间的不同?

                        SOAP                       REST

1. SOAP 是一个两台电脑通过共享XML文档通信的协议。

1. Rest是一种服务架构,为基于网络软件架构而设计。

2. SOAP 只支持XML格式。

2.  支持多种不同数据类型。

3. SOAP不支持缓存。

3. 支持缓存。

4. SOAP 类似于桌面应用,紧密链接服务器。

4.  REST客户端就像浏览器并且使用标准的方法。应用内在兼容。

5. SOAP 比 REST慢.

5. 比SOAP快

6. 使用 HTTP,但独立封装信息。

6. 使用HTTP头部传递元信息。

Q-18.测试网络服务可以使用的工具有哪些?

Ans. 如下工具可以帮助测试SOAP和RESTful网络服务。

1.  SOAP UI 工具.
2.  Firefox浏览器的Poster.
3. Chrome扩展Postman.

Q-19.  解释哪些因素可以帮助决定网络服务使用哪种类型? SOAP或者REST?

Ans. 通常,使用基于REST的网络服务是首选,由于其简单、高性能、可扩展和支持多种数据格式。

但是,在需要高级别安全性以及事务可靠性的场景下SOAP最常被采用。

但是你可以阅读如下因素在你选择任何形式前。

1. 服务是暴露数据还是业务逻辑?暴露数据REST是更好的选择,SOAP对逻辑更好。
2. 如果消费者或者服务提供者需要标准契约,那么SOAP可以通过WSDL提供这种契约。
3. 需要支持多种数据格式。REST可以支持。
4. 支持AJAX调用。REST可以使用XMLHttpRequest。
5. 异步和同步调用 – SOAP同时支持同步/异步操作,然而REST内建支持同步调用。
6. 无状态或者有状态调用 – REST适合于无状态操作。

你也可以考虑如下一些高级的因素。

1. 安全要求 – SOAP提供高级别的安全等级。
2. 事务支持 – SOAP支持更好的事务管理。
3. 带宽限制 –  SOAP由于基于XML,请求SOAP头部时候,在发送/接受包时有更多的额外开支 。但是,REST发送请求到服务器需要更少的带宽。几乎所有消息都采用JSON格式。
4. 易用性 – 基于REST的应用,容易实现、测试和维护。

Q-20. 哪个Java API 可以帮助开发RESTful Web Service?

Ans. 在Java用,有大量的可用的框架和类库来给程序员来创建RESTful网络服务。例如,JAX-RS类库是一个标准的方式来开发REST网络服务。

同时,Jersey是另一个JAX-RS的流行的实现,它提供了更多。还有其他的像RESTEasy、RESTlet和Apache CFX。

如果你喜欢Scala,那么你应该使用Play框架来开发RESTful网络服务。

 

Top 20 REST API Interview Questions and Answers for Software Testers

 

PSR-2:PHP编码规范

本规范继承并扩展自PSR-1,基本编码规范。

本文档中的关键词”必须(MUST)”,”禁止(MUST NOT)”,”必须(REQUIRED)”,”必须(SHALL)”,”禁止(SHALL NOT)”,”SHOULD(应该)”,“不应该(SHOULD NOT)”, “建议(RECOMMENDED)”, “可能(MAY)”和 “可选(OPTIONAL)” 遵循RFC2119约定。

1、概览

  • 代码必须遵守代码规范PSR[PSR-1]。
  • 代码必须使用四个空格缩进,不能使用tabs。
  • 禁止硬性限制行长度;必须限制在120个字符;应该在80个字符以内。
  • namespace声明后必须有一个空行,并且use声明块后必须有一个空行。
  • 类的开始花括号({) 必须 写在函数声明后自成一行,结束花括号(})也 必须 写在函数主体后自成一行。
  • 方法的开始花括号({) 必须 写在函数声明后自成一行,结束花括号(})也 必须 写在函数主体后自成一行。
  • 的属性和方法 必须 添加访问修饰符(privateprotected 以及 public),abstract 以及 final 必须 声明在访问修饰符之前,而 static 必须 声明在访问修饰符之后。
  • 控制结构的关键字后 必须 要有一个空格符,而调用方法或函数时则 一定不可 有。
  • 控制结构的开始花括号({) 必须 写在声明的同一行,而结束花括号(}) 必须 写在主体后自成一行。
  • 控制结构的开始左括号后和结束右括号前,都 禁止 有空格符。

1.1、例子

<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
    public function sampleMethod($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}

2、通则

2.1、基础编码规范

代码必须遵循所有PSR-1概述的规范。

2.2、文件

  • 所有PHP文件必须使用Unix LF(换行)作为行结尾。
  • 所有PHP文件必须以一个空行作为结尾。
  • 只包含PHP的文件中必须删除结束标签?>。

2.3、行

  • 行字符长处禁止有硬性限制。
  • 行字符必须在120字符内;自动样式检查必须提醒但禁止抛错。
  • 不应该超过80个字符;超过长度应该分为不超过80个字符的多行。
  • 非空行末禁止有空格。
  • 为了提高可读性以及标识代码块应该添加空行。
  • 每行禁止超过一个声明。

2.4、缩进

  • 代码必须使用4个空格作为缩进,禁止使用tab缩进。

注:仅仅使用空格,而不是空格和tab混合,以帮助避免在对比,补丁,历史和注释问题。使用空格可以使行内对齐更简单。

2.5、关键词和True/False/Null

PHP关键词必须小写。

PHP常量 truefalse和 null 必须小写。

3、namespace和use声明

  • 当遇到时,在 namespace 声明后必须有一个空行。
  • 当遇到时,所有 use 声明必须在 namespace 声明后。
  • 每个声明必须一个 use 关键词。
  •  在 use 代码块后必须有一个空格。
<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

// ... additional PHP code ...

4、类、属性和方法

此 “class” 泛指所有 classes, interfaces 和 traits。

4.1、Extends 和 Implements

  •  extends 和 implements 关键词必须和class名称在同一行声明。
  • 类的开始花括号({) 必须 写在函数声明后自成一行,结束花括号(})也 必须 写在函数主体后自成一行。
<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // constants, properties, methods
}

多个implements应该拆分到多行, 每行添加一个缩进。当这么做时,第一个必须在下一行,并且每个接口必须占一行。

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}

4.2、属性

  • 所有属性必须声明可见性。
  •  var 关键字禁止用于声明属性。
  • 每个声明禁止超过一个属性。
  • 属性名不应该以一个下划线开头来说明为protected或private可见性。

声明一个属性看起来如下。

<?php
namespace Vendor\Package;

class ClassName
{
    public $foo = null;
}

4.3、方法

  • 所有方法必须声明可见性。
  • 方法名不应该使用单个下划线来说明为protected或private可见性。
  • 方法名后禁止有空格。方法的开始花括号({) 必须 写在函数声明后自成一行,结束花括号(})也 必须 写在函数主体后自成一行。方法的开始花括号后禁止有空格,并且方法的结束花括号前禁止有空格。
 声明一个方法看起来如下。注意括号,逗号,空格和大括号的位置:
<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}

4.4、方法参数

  • 在参数列表中, 在逗号前禁止有空格,在逗号后边必须有一个空格。
  • 有默认值的参数必须在参数列表的后边。
<?php
namespace Vendor\Package;

class ClassName
{
    public function foo($arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}

参数列表可能拆分为多行,每行缩进一个。当这么做的时候,列表中的第一个参数必须在下一行,并且必须每行只能有一个参数。

当参数拆分为多行,结束括号和开始大括号之前必须有一个空格并且放在同一行。

<?php
namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // method body
    }
}

4.5、abstract、final和static

当遇到时, abstract 和 final 声明必须优先于可见性声明。

当遇到时, static 声明必须在可见性声明之后。

<?php
namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // method body
    }
}

4.6、方法调用

当进行方法调用时候,在方法名和开始括号间禁止有空格,在开始括号后禁止有空格,在结束括号后禁止有空格,在结束括号前禁止有空格。在参数列表中,在每个逗号前禁止有空格,逗号后必须有空格。

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

参数列表可能拆分到多行中,每行缩进一个。当这么做时,列表中的第一项必须在下一行,并且必须每行一个参数。

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

5、控制结构

对控制结构的一般规则如下:

  • 控制结构关键字后必须有一个空格。
  • 开始括号后禁止有空格。
  • 结束括号前禁止有空格。
  • 在结束括号和开始大括号之间必须有一个空格。
  • 控制结构体必须缩进一个。
  • 结束大括号必须自成一行。

每个结构体必须在花括号中。这样标准化可以跟好看,并且在添加新行的话可以减少出错。

5.1、 if、elseif、else

if 结构如下。注意括号、空格和大括号的位置;并且 else 以及 elseif 和之前的结束大括号在同一行。

<?php
if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}

关键词 elseif应该代替 else if 来使用,以此让所有控制关键词看起来都是一个词。

5.2、switch、case

switch 结构如下。注意括号、空格和大括号的位置。 case 声明相对switch必须有一个缩进, 并且 break 关键字 (或者其他结束关键字) 必须和 case 体有相同缩进. 当有意通过一个非空的 case 体,必须有一个注释像// no break 。

<?php
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}

5.3.、while, do while

while 结构如下。注意括号、空格和大括号的位置。

<?php
while ($expr) {
    // structure body
}

相似的, do while 结构如下。注意括号、空格和大括号的位置。

<?php
do {
    // structure body;
} while ($expr);

5.4、for

for 结构如下。注意括号、空格和大括号的位置。

<?php
for ($i = 0; $i < 10; $i++) {
    // for body
}

5.5、foreach

foreach 结构如下。注意括号、空格和大括号的位置。

<?php
foreach ($iterable as $key => $value) {
    // foreach body
}

5.6、try, catch

try catch 结构如下。注意括号、空格和大括号的位置。

<?php
try {
    // try body
} catch (FirstExceptionType $e) {
    // catch body
} catch (OtherExceptionType $e) {
    // catch body
}

6、闭包(Closures)

闭包声明在 function 关键词后必须有一个空格, 并且在 use 关键词前后必须各有一个空格。

开始大括号必须在同一行,并且结束大括号必须自成一行。

在参数或者变量列表的开头括号后禁止有空格,并且在结束括号前禁止有空格。

在参数和变量变量列表中,在每个空格前禁止有空格,在每个空格后必须有一个空格。

闭包带默认值的参数必须在参数列表的后端。

闭包声明如下。注意括号、逗号、空格和大括号的位置:

<?php
$closureWithArgs = function ($arg1, $arg2) {
    // body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // body
};

参数和变量列表可能拆分为多行,每行缩进一个。当这么做时,在里表中第一项必须在下一行,并且每行必须一个参数或者变量。

当结束的那个列表(无论是参数或者变量)分布于多行,结束括号和开始大括号必须用空格隔开并自称一行。

如下是带参数列表和不带参数列表以及参数列表分布于多行的闭包的例子。

<?php
$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
    // body
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
    // body
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

注意在闭包被作为参数直接传给方法的时候,也采用本样式规范。

<?php
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);

7、总结(Conclusion)

以上规范难免有疏忽,其中包括但不仅限于:

  • 全局变量和常量的定义
  • 函数的定义
  • 操作符和赋值
  • 行内对齐
  • 注释和文档描述块
  • 类名的前缀及后缀
  • 最佳实践

本规范之后的修订与扩展将弥补以上不足。

 

本文参考:

PSR-1:PHP基本编码规范

本规范制定了代码基本元素的相关标准,以确保共享的PHP代码间具有较高程度的技术互通性。

本文档中的关键词”必须(MUST)”,”禁止(MUST NOT)”,”必须(REQUIRED)”,”必须(SHALL)”,”禁止(SHALL NOT)”,”SHOULD(应该)”,“不应该(SHOULD NOT)”, “建议(RECOMMENDED)”, “可能(MAY)”和 “可选(OPTIONAL)” 遵循RFC2119约定。

1、概览

  • 文件 必须 只能用<?php和<?=标签。
  • 文件 必须 只能使用UTF-8(无BOM)编码格式。
  • PHP代码中 应该 只定义类、函数、常量等声明,或其他会产生 副作用 的操作(如:生成文件输出以及修改 .ini 配置文件等),二者只能选其一;
  • 命名空间以及类 必须 符合 PSR 的自动加载规范:PSR-0,PSR-4 中一个;
  • 类名称必须使用大驼峰(StudlyCaps)。
  • 类常量必须全部大写,用下划线分割。
  • 方法名必须使用小驼峰(camelCase)。

2. 文件

2.1、 PHP标签

PHP代码必须使用<?php ?>或者<?= ?>标签;禁止使用其他变形标签。

2.2、编码格式

PHP代码必须使用UTF-8(无BOM)编码格式。

2.3、副作用(Side Effects)

一个文件应该 只定义类、函数、常量等声明并且不会引起其他副作用,或者应该执行逻辑,但是只能二选一。
“副作用(Side Effects)”这个词指可执行的逻辑,而非直接声明类、函数、常量等,只是在include file的情况下。
“副作用(Side Effects)”包括但不限于:产生输出,显式使用requiredinclude,链接外部服务,修改ini配置,触发错误或异常,修改全局或者静态变量,读取或写入文件等等。
下来是一个既包含声明又包含副作用的实例;例如,一个反例:

<?php
// side effect: change ini settings
ini_set('error_reporting', E_ALL);

// side effect: loads a file
include "file.php";

// side effect: generates output
echo "\n";

// declaration
function foo()
{
    // function body
}

下边的例子仅包含声明无副作用;一个仿真示例:

<?php
// declaration
function foo()
{
    // function body
}

// conditional declaration is *not* a side effect
if (! function_exists('bar')) {
    function bar()
    {
        // function body
    }
}

3、命名空间和类名称

命名空间以及类 必须 符合 PSR 的自动加载规范:PSR-0,PSR-4 中的一个。

这意味着每个类独立一个文件,并且必须处在一个命名空间下:一个顶层vendor下。

类名称必须使用大驼峰(StudlyCaps)。

PHP5.3之后版本书写的代码必须使用标准命名空间。

例如:

<?php
// PHP 5.3 and later:
namespace Vendor\Model;

class Foo
{
}

5.2.x之前的版本书写的代码应该使用在类名中用下划线的伪命名约定Vendor_

<?php
// PHP 5.2.x and earlier:
class Vendor_Model_Foo
{
}

4、类常量、属性以及方法

此处“类”(class)反之所有的classes, interfaces和traits。

4.1、类常量

类常量必须全部大写并使用下划线分开。例如:

<?php 
namespace Vendor\Model;

class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}

4.2、属性

本规范对使用$StudlyCaps,$camelCase或者$under_score作为属性名故意不做任何建议。
使用任何命名约定在一个合理范围内应该保持一致。范围应该是vendor级别,package级别,class级别或者method级别。

4.3、方法

方法名必须使用小驼峰(camelCase)。

职位要求: 
具备良好的编程习惯,熟练掌握OOP编程和常见设计模式;
良好的编程风格和项目文档编写习惯

web开发中各类缓存设计

1、缓存

缓存即指一种存储着数据的硬件或者软件组件,可加速数据请求;缓存中的数据可以是之前的运算结果,或者是其他地方存储的数据的备份。

In computing, a cache /ˈkæʃ/ KASH,[1] is a hardware or software component that stores data so future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere.

其实说白了缓存就是一个临时放数据地方。你可以放到本地缓存中、可以放到memcache、redis、tair等缓存系统中,也可以放到MySQL中等等。

缓存主要解决一个问题就是加速数据请求速度。每次从网络接口请求数据,改成在本地缓存一份,这个在APP开发中经常用到,从而可以减少网络请求耗时,还能节省用户流量,体验更好。每次从数据库通过SQL查数据,如果每次请求的结果是固定的,那就可以考虑将查询结果缓存到redis等缓存里,减少数据库压力。

2、缓存设计

2.1 考虑的问题

  • 数据量
  • 响应时间
  • 扩展性
  • 数据一致性
  • 更新策略

 

<未完待续>

Apache Kylin 安装教程

Kylin安装非常简单,可以认为它就是一个web应用,还是单机版本的,解压即可使用。

根据情况下载: http://kylin.apache.org/cn/download/

修改kylin配置:

kylin.job.jar=/opt/test/kylin/lib/kylin-job-2.0.0.jar
kylin.coprocessor.local.jar=/opt/test/kylin/lib/kylin-coprocessor-2.0.0.jar
kylin.job.yarn.app.rest.check.status.url=http://hadoop-30:8088/ws/v1/cluster/apps/${job_id}?anonymous=true
kylin.job.mr.lib.dir=/opt/cloudera/parcels/CDH/lib/sentry/lib

需要注意kylin.job.yarn.app.rest.check.status.url,这个url可以通过手动访问来查看mr状态。

配置环境变量:

export JAVA_HOME=/usr/local/java
export KYLIN_HOME=/opt/test/kylin
export HBASE_HOME=/opt/cloudera/parcels/CDH-5.10.1-1.cdh5.10.1.p0.10/lib/hbase
export HADOOP_HOME=/opt/cloudera/parcels/CDH-5.10.1-1.cdh5.10.1.p0.10/
export HIVE_HOME=/opt/cloudera/parcels/CDH-5.10.1-1.cdh5.10.1.p0.10/lib/hive
export HADOOP_CMD=/opt/cloudera/parcels/CDH-5.10.1-1.cdh5.10.1.p0.10/lib/hadoop/bin/hadoop
export HCAT_HOME=/opt/cloudera/parcels/CDH-5.10.1-1.cdh5.10.1.p0.10/lib/hive-hcatalog

启动Kylin:

./bin/kylin.sh start

访问页面: http://domain:7070/kylin
默认用户名:admin;密码: KYLIN

Kotlin简明教程

Kotlin精简教程,包含基本数据类型、控制语句以及函数,并且包含面向对象的相关类、继承和接口的定义以及实现等。本文旨在帮助想快速体验Kotlin的同学快读上手,在最短的时间内掌握更多的知识。Kotlin成为Android的官方语言后,毕竟带来一场新的变革,让我们拭目以待吧,当然手来还是要有东西的,赶紧安装一个Kotlin,顺着本手册快速过一遍吧。

1 基础篇


1.1  数据类型

Kotlin基本数据类型: 数值、字符、布尔和数组。

1.1.1 数字类型

Type Bit width
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

1.1.2 字符类型

字符类型用Char声明。例如 ‘1’。

1.1.3 布尔类型

Boolean声明布尔类型,布尔类型有两个值:true 和 false。内置运算符布包括 ||(或)、&&(与)、!(非)。

1.1.4 数组

在Kotlin中的数组通过Array类声明,并且具有getset方法,以及size属性。我们可以通过arrayOf(1, 2, 3)来创建一个数组。

1.1.5 字符串

字符串使用String来声明,字符串是不可变的。数组中的元素就是字符,可以通过s[i]访问。

var a : Int = 1000
var b : Char = 'b'
var c : IntArray = intArrayOf(1, 2, 3, 5)
var d : String = "Hello world!"
var e : Boolean = true

1.2 控制语句

1.2.1 IF表达式

在kotlin中,if是一个表达式,带返回值。

if (a < b) max = b 

if (a > b) {
    max = a
} else {
    max = b
}
 
val max = if (a > b) a else b

1.2.2 WHEN表达式

WHEN代替了SWITCH。

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // Note the block
        print("x is neither 1 nor 2")
    }
}

1.2.3 FOR循环

for (i in array.indices) {
    print(array[i])
}

1.2.4 WHILE循环

Kotlin支持while和do…while

while (x > 0) {
    x--
}

do {
    val y = retrieveData()
} while (y != null) // y is visible here!

1.3 函数

1.3.1 函数声明

在Kotlin中使用fun声明函数。这真是一件有趣的事情。

fun double(x: Int): Int {
}

1.3.2 函数调用

val result = double(2)

1.3.3 参数

函数的参数采用Pasical风格name:type。参数之间用逗号隔开。参数必须指定类型。参数可以指定默认值。

fun read(b: Array, off: Int = 0, len: Int = b.size()) {
...
}

可变参数可以通过vararg声明

fun read(vararg ts:Int) {
...
}

如果参数较多,可以通过命名参数来调用函数

fun reformat(str: String,
             normalizeCase: Boolean = true,
             upperCaseFirstLetter: Boolean = true,
             divideByCamelHumps: Boolean = false,
             wordSeparator: Char = ' ') {
...
}
//命名调用
reformat(str, wordSeparator = '_')

1.3.4 单行函数

如果函数只是返回一个表达式,那就可以直接用等号

fun double(x: Int): Int = x * 2

1.3.5 返回值

函数可返回Unit(即什么都不返回)或者准确数据类型。

fun printHello(name: String?): Unit {
    if (name != null)
        println("Hello ${name}")
    else
        println("Hi there!")
    // `return Unit` or `return` is optional
}

//等价于
fun printHello(name: String?) {

}

 

2、面向对象


2.1 类与继承

2.1.1 类

在Kotlin中类通过class来声明

class Invoice {
}
2.1.1.1 类的构造方法

Kotlin的构造方法有主构造方法和多个副构造方法。在类名后边的为主构造方法,此处可以省略constructor关键字,类中的constructor为副构造方法。

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
2.1.1.2 类的实例化

Kotlin没有new关键字,所以如下实例化。

val customer = Customer("Joe Smith")

2.1.2 继承

Kotlin的所有类都有一个公共的超类Any

class Example // 隐式继承自Any

继承一个类,只需要将父类放到子类的后边即可,有点类似于定义方法的返回值。

open class Base(p: Int)

class Derived(p: Int) : Base(p)

如果父类有主构造方法,需要正确的初始化;如果父类有副构造方法,需要使用super关键字初始化。

class MyView : View {
    constructor(ctx: Context) : super(ctx)

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}

open关键字和java中的final关键字相反,它允许其他类继承此类。在Kotlin中所有的类默认均为final类型。

2.1.2.1 重写方法

重写方法时,子类类的方法必须是通过open关键字限定的,并且子类的相应方法也默认被继承为open类型,如果需要禁止,可以通过final关键字来限定。重写方法使用关键字overwrite。

open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    override fun v() {} //此处可以在开始加上final,来禁止次方法被重写
}
2.1.2.2 重写属性

重写属性和重写方法类似。

open class Foo {
    open val x: Int get { ... }
}

class Bar1 : Foo() {
    override val x: Int = ...
}
2.1.2.3 重写规则

Kotlin,实现继承的规则是: 如果类继承自多个相同成员的实现,子类必须重写这些成员并提供自己的实现(或者是继承其中一个)。此处可以使用super关键字,例如super<Base>

open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } // interface members are 'open' by default
    fun b() { print("b") }
}

class C() : A(), B {
    // The compiler requires f() to be overridden:
    override fun f() {
        super<A>.f() // call to A.f()
        super<B>.f() // call to B.f()
    }
}

2.1.3 抽象类

抽象类用abstract声明。由于抽象类不涉及到具体实现,所以抽象类及其方法不需要用open限定就可以重写。此外我们也可以将一个非抽象类中的open成员写成抽象的。

open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

2.2 接口

可以使用interface定义接口

interface MyInterface {
    fun bar()
    fun foo() {
      // optional body
    }
}

2.2.1 接口实现

类或者对象都可以显示类。

class Child : MyInterface {
    override fun bar() {
        // body
    }
}

更多内容请参考手册

MySQL Query时间都去哪儿了

MySQL作为被广泛应用的关系型数据库,帮助大家完成数据存储、数据处理以及数据分析等相关工作。在使用MySQL过程中最常遇到的问题大约就是慢查询或者运算时间很长的问题,那么时间都去哪儿了呢?

使用SHOW PROFILE

MySQL提供的SHOW PROFILE语法,可以帮助我们分析查询执行的每个步骤极其花费的时间。我们可以通过执行set profiling=1来开启此功能。先让我们看个例子

select count(*) from user;
show profile;


通过show profile命令我们可以查看时间主要消耗在了Sending data阶段,Sending data状态描述的是读和处理SELECT涉及的行以及发送数据到客户端:

The thread is reading and processing rows for a SELECT statement, and sending data to the client. Because operations occurring during this state tend to perform large amounts of disk access (reads), it is often the longest-running state over the lifetime of a given query.

其他状态的解释请参考手册。通过分析查询每个步骤消耗的时间,我们可以有针对性的进行优化。让我们来查看另一个例子。

select * from user order by email desc limit 1000, 10;

show profiles;

show profile for query 2;


通过上边的例子,我们可以发现时间主要花到了排序上。

使用 EXPLAIN

我们可以使用EXPLAIN来获取关于查询执行计划的信息, EXPLAIN命令等价于DESCRIBE/DESC。EXPLAIN命令是查看查询优化器如何决定执行查询的主要方法。

EXPLAIN命令可以帮助我们查看查询我们的SQL语句可能用到的索引(possible_keys)以及影响的行数(rows),可以帮我们更好的定位慢的原因。每列值得具体解释请参考手册。此外EXPLAIN也可以看表结构。

目前MySQL提供的工具在分析查询性能定位上还是比较弱的,但是造成查询性能底下的原因还是比较明确的:就是访问的数据太多。那么通过调整索引结构、调整检索语句的条件以及重构查询等均能收到不错的优化效果。

通过上述两个工具我们基本上能够确定我们的SQL在干什么以及消耗了多少时间,也能够了解查询优化器为我们做的一些工作,更具它们为我们提供的信息,我们可以调整我的查询方式来提高我们的查询效率。