PSR规范markdown

% **PSR规范**
% **肖士良**

# 为什么统一代码规范

1.提高可读性(isset、is_null、empty、false/true)

2.促进团队协作

3.减少名字冗余,降低维护成本

4.通过名称理解变量、方法含义,少挖坑少踩坑

5.提高程序员的个人能力

# 为什么选择PSR规范

1. 规范提出者:FIG是 Framework Interoperability Group(框架可互用性小组)缩写,目的是以最低程度的限制,来统一各个项目的编码规范,避免各家自行发展的风格阻碍了程序设计师开发的困扰。

2. PSR规范被CodeIgniter,Laravel,Yii, Zend2, CakePHP,Symfony2, AWS SDK等项目遵守,越来越多公司、团队、开发者遵守PSR规则。

# PSR规范

1. PSR-0 (Autoloading Standard) 自动加载标准

2. ** PSR-1 (Basic Coding Standard) 基础编码标准 **

3. ** PSR-2 (Coding Style Guide) 编码风格向导 **

4. PSR-3 (Logger Interface) 日志接口

5. PSR-4 (Autoloader) 自动加载改进

# PSR-0 & PSR-4:类命名与autoloader

1. 一个完全标准的`命名空间(namespace)`和`类(class)`的结构是这样的:`\<Vendor Name>\(<Namespace>\)*<Class Name>`

2. 每个`命名空间(namespace)`都必须有一个顶级的`空间名(namespace)`(“`组织名(Vendor Name)`”)。

3. 每个`命名空间(namespace)`中可以根据需要使用任意数量的`子命名空间(sub-namespace)`。

4. ~~从文件系统中加载源文件时,`空间名(namespace)`中的分隔符将被转换为 `DIRECTORY_SEPARATOR`。~~

5. ~~`类名(class name)`中的每个下划线`_`都将被转换为一个`DIRECTORY_SEPARATOR`。下划线`_`在`空间名(namespace)`中没有什么特殊的意义。~~

6. 完全标准的`命名空间(namespace)`和`类(class)`从文件系统加载源文件时将会加上`.php`后缀。

7. `组织名(vendor name)`,`空间名(namespace)`,`类名(class name)`都由大小写字母组合而成。

8. PSR-4中,在类名中使用下划线没有任何特殊含义。而PSR-0则规定类名中的下划线 _ 会被转化成目录分隔符。

***

示例:

`\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php`

`\Symfony\Core\Request` => `/path/to/project/lib/vendor/Symfony/Core/Request.php`

`\Zend\Acl` => `/path/to/project/lib/vendor/Zend/Acl.php`

`\Zend\Mail\Message` => `/path/to/project/lib/vendor/Zend/Mail/Message.php`

***

下面是一个怎样利用上述标准来实现自动加载的示例函数。

<?php

function autoload($className)
{
$className = ltrim($className, ‘\\’);
$fileName = ”;
$namespace = ”;
if ($lastNsPos = strrpos($className, ‘\\’)) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace(‘\\’, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace(‘_’, DIRECTORY_SEPARATOR, $className) . ‘.php’;

require $fileName;
}

# PSR-1 简单编码规范

– 源文件`必须`只使用 `<?php` 和 `<?=` 这两种标签。

– 源文件中php代码的编码格式`必须`只使用不带`字节顺序标记(BOM)`的`UTF-8`。

– 一个源文件`建议`只用来做声明(`类(class)`,`函数(function)`,`常量(constant)`等)或者只用来做一些引起副作用的操作(例如:输出信息,修改`.ini`配置等),但`不建议`同时做这两件事。

下面是一个既包含声明又有副作用的示例文件;即应避免的例子:

<?php
// 副作用:修改了ini配置
ini_set(‘error_reporting’, E_ALL);

// 副作用:载入了文件
include “file.php”;

// 副作用:产生了输出
echo “<html>\n”;

// 声明
function foo()
{
// 函数体
}

– `命名空间(namespace)`和`类(class)` `必须`遵守PSR-0标准。

– `类名(class name)` `必须`使用`骆驼式(StudlyCaps)`写法 (译者注:`驼峰式(cameCase)`的一种变种,后文将直接用`StudlyCaps`表示)。
`PHP5.3`之后的代码`必须`使用正式的`命名空间(namespace)`

<?php
// PHP 5.3 及之后:
namespace Vendor\Model;

class Foo
{
}

– `类(class)`中的常量`必须`只由大写字母和`下划线(_)`组成。

类常量`必须`只由大写字母和`下划线(_)`组成。

<?php
namespace Vendor\Model;

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

– `方法名(method name)` `必须`使用`驼峰式(cameCase)`写法(译者注:后文将直接用`camelCase`表示)。

# PSR-2 编码风格
– 代码`必须`遵守 PSR-1。

– 代码`必须`使用4个空格来进行缩进,而不是用制表符。

– 在`命名空间(namespace)`的声明下面`必须`有一行空行,并且在`导入(use)`的声明下面也`必须`有一行空行。

示例:

<?php
namespace Vendor\Package;

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

– `类(class)`的左花括号`必须`放到其声明下面自成一行,右花括号则`必须`放到类主体下面自成一行。

– `方法(method)`的左花括号`必须`放到其声明下面自成一行,右花括号则`必须`放到方法主体的下一行。

示例:

<?php
namespace Vendor\Package;

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

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
// 常量、属性、方法
public function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
// 方法主体部分
}
}

– 所有的`属性(property)`和`方法(method)` `必须`有可见性声明;`抽象(abstract)`和`终结(final)`声明`必须`在可见性声明之前;而`静态(static)`声明`必须`在可见性声明之后。

示例:

<?php
namespace Vendor\Package;

abstract class ClassName
{
protected static $foo;

abstract protected function zim();

final public static function bar()
{
// 方法主体部分
}
}

– 在控制结构关键字的后面`必须`有一个空格;而`方法(method)`和`函数(function)`的关键字的后面`不可`有空格。

– 控制结构的左花括号`必须`跟其放在同一行,右花括号`必须`放在该控制结构代码主体的下一行。

– 控制结构的左括号之后`不可`有空格,右括号之前也`不可`有空格。

示例:

<?php

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

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

# PSR-3 LoggerInterface

– PSR-3主要目标是让类库获得一个`Psr\Log\LoggerInterface`对象并能通过简单通用的方式来写日志。有自定义需求的框架和CMS`可以`根据情况扩展这个接口,但`推荐`保持和该文档的兼容性,以确保应用中使用到的第三方库能将日志集中写到应用日志里。
# 总结

– 规范不是义务的,当然你也可以选择自己的方式,但使用规范会让你的合作更轻松。

– 多读开源代码

– <a href=”https://github.com/hfcorriez/fig-standards” target=”_blank”>PSR规范中文翻译</a>

# Q&A

谢谢

PSR规范

 

为什么统一代码规范

1.提高可读性(isset、is_null、empty、false/true)

2.促进团队协作

3.减少名字冗余,降低维护成本

4.通过名称理解变量、方法含义,少挖坑少踩坑

5.提高程序员的个人能力

为什么选择PSR规范

  1. 规范提出者:FIG是 Framework Interoperability Group(框架可互用性小组)缩写,目的是以最低程度的限制,来统一各个项目的编码规范,避免各家自行发展的风格阻碍了程序设计师开发的困扰。
  2. PSR规范被CodeIgniter,Laravel,Yii, Zend2, CakePHP,Symfony2, AWS SDK等项目遵守,越来越多公司、团队、开发者遵守PSR规则。

PSR规范

  1. PSR-0 (Autoloading Standard) 自动加载标准
  2. ** PSR-1 (Basic Coding Standard) 基础编码标准 **
  3. ** PSR-2 (Coding Style Guide) 编码风格向导 **
  4. PSR-3 (Logger Interface) 日志接口
  5. PSR-4 (Autoloader) 自动加载改进

PSR-0 & PSR-4:类命名与autoloader

  1. 一个完全标准的命名空间(namespace)类(class)的结构是这样的:\<Vendor Name>\(<Namespace>\)*<Class Name>
  2. 每个命名空间(namespace)都必须有一个顶级的空间名(namespace)(“组织名(Vendor Name)“)。
  3. 每个命名空间(namespace)中可以根据需要使用任意数量的子命名空间(sub-namespace)
  4. ~~从文件系统中加载源文件时,空间名(namespace)中的分隔符将被转换为 DIRECTORY_SEPARATOR。~~
  5. ~~类名(class name)中的每个下划线_都将被转换为一个DIRECTORY_SEPARATOR。下划线_空间名(namespace)中没有什么特殊的意义。~~
  6. 完全标准的命名空间(namespace)类(class)从文件系统加载源文件时将会加上.php后缀。
  7. 组织名(vendor name)空间名(namespace)类名(class name)都由大小写字母组合而成。
  8. PSR-4中,在类名中使用下划线没有任何特殊含义。而PSR-0则规定类名中的下划线 _ 会被转化成目录分隔符。

示例:

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php

\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php

\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php

\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php


下面是一个怎样利用上述标准来实现自动加载的示例函数。

<?php

function autoload($className)
{
$className = ltrim($className, ‘\’);
$fileName = ”;
$namespace = ”;
if ($lastNsPos = strrpos($className, ‘\’)) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace(‘\’, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace(‘_’, DIRECTORY_SEPARATOR, $className) . ‘.php’;

  require $fileName;
 }

PSR-1 简单编码规范

  • 源文件必须只使用 &lt;?php&lt;?= 这两种标签。
  • 源文件中php代码的编码格式必须只使用不带字节顺序标记(BOM)UTF-8
  • 一个源文件建议只用来做声明(类(class)函数(function)常量(constant)等)或者只用来做一些引起副作用的操作(例如:输出信息,修改.ini配置等),但不建议同时做这两件事。下面是一个既包含声明又有副作用的示例文件;即应避免的例子:

    <?php
    // 副作用:修改了ini配置
    ini_set(‘error_reporting’, E_ALL);

    // 副作用:载入了文件
    include “file.php”;

    // 副作用:产生了输出
    echo “<html>\n”;

    // 声明
    function foo()
    {
    // 函数体
    }

  • 命名空间(namespace)类(class) 必须遵守PSR-0标准。
  • 类名(class name) 必须使用骆驼式(StudlyCaps)写法 (译者注:驼峰式(cameCase)的一种变种,后文将直接用StudlyCaps表示)。PHP5.3之后的代码必须使用正式的命名空间(namespace)

    <?php
    // PHP 5.3 及之后:
    namespace Vendor\Model;

    class Foo
    {
    }

  • 类(class)中的常量必须只由大写字母和下划线(_)组成。类常量必须只由大写字母和下划线(_)组成。

    <?php
    namespace Vendor\Model;

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

  • 方法名(method name) 必须使用驼峰式(cameCase)写法(译者注:后文将直接用camelCase表示)。

PSR-2 编码风格

  • 代码必须遵守 PSR-1。
  • 代码必须使用4个空格来进行缩进,而不是用制表符。
  • 命名空间(namespace)的声明下面必须有一行空行,并且在导入(use)的声明下面也必须有一行空行。示例:

    <?php
    namespace Vendor\Package;

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

  • 类(class)的左花括号必须放到其声明下面自成一行,右花括号则必须放到类主体下面自成一行。
  • 方法(method)的左花括号必须放到其声明下面自成一行,右花括号则必须放到方法主体的下一行。示例:

    <?php
    namespace Vendor\Package;

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

    class ClassName extends ParentClass implements \ArrayAccess, \Countable
    {
    // 常量、属性、方法
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
    // 方法主体部分
    }
    }

  • 所有的属性(property)方法(method) 必须有可见性声明;抽象(abstract)终结(final)声明必须在可见性声明之前;而静态(static)声明必须在可见性声明之后。示例:

    <?php
    namespace Vendor\Package;

    abstract class ClassName
    {
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
    // 方法主体部分
    }
    }

  • 在控制结构关键字的后面必须有一个空格;而方法(method)函数(function)的关键字的后面不可有空格。
  • 控制结构的左花括号必须跟其放在同一行,右花括号必须放在该控制结构代码主体的下一行。
  • 控制结构的左括号之后不可有空格,右括号之前也不可有空格。示例:

    <?php

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

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

PSR-3 LoggerInterface

  • PSR-3主要目标是让类库获得一个Psr\Log\LoggerInterface对象并能通过简单通用的方式来写日志。有自定义需求的框架和CMS可以根据情况扩展这个接口,但推荐保持和该文档的兼容性,以确保应用中使用到的第三方库能将日志集中写到应用日志里。

总结

  • 规范不是义务的,当然你也可以选择自己的方式,但使用规范会让你的合作更轻松。
  • 多读开源代码
  • PSR规范中文翻译

Lua基本语法

  • 关键字
and	break	do	else	elseif	
end	false	for	function	if	
in	local	nil	not	or	
repeat	return	then	true	until	while
  • 运算

1、数字预算

 

支持 +, -, *, /,^  比如2^3 结果为8, 2^4结果为16。
连接两个字符串,用".."运处符, php为".", JAVA、C#为"+"

2、赋值运算

  1. a,b,c,d=1,2,3,4   -- 多变量一起赋值
    a,b=b,a  --交换变量功能
    在默认情况下,变量总是认为是全局的。假如需要定义局部变量,则在第一次赋值的时候,需要用local说明。比如:
    local a,b,c = 1,2,3  -- a,b,c都是局部变量

3、逻辑运算

and, or, not
在Lua中,只有false和nil才计算为false,其它任何数据都计算为true,0也是true
and 和 or的运算结果不是true和false,而是和它的两个操作数相关。

a and b:如果a为false,则返回a;a true 返回b
a or b:如果 a 为true,则返回a;a false 返回b
  • 条件判断语句

if

if 条件 then 
      ... 
elseif 条件 then
      ... else ... 
end

repeat

repeat ... until 条件

while

while 条件 
do 
      ... 
end

for

for 变量=初值, 终点值, 步进 
do
      ... 
end
for 变量1, 变量2, ... 变量n in 表或枚举函数 
do 
       ... 
end
  • 常用结构

table

1. table 是 lua 中最重要的数据类型。
2. table 类似于 python 中的字典。
3. table 只能通过构造式来创建

tab = { a = 10, b = 20, c = 30, d = 40 }  
print(tab["a"])  
tab = { 10, m = 11, 20, 30, 40 }  

print(tab[1])  = 10
print(tab[2])  = 20
print(tab[3])  = 30
print(tab[4])  = 40

获取表长度:
print(table.getn(tab))  -> 4
print(#tab)             -> 4

遍历表:
for k, v in pairs(tab) do
	print(k, ":", v)
end

1	:	10
2	:	20
3	:	30
4	:	40
m	:	11

 

 

 

Nginx与Lua执行顺序

  • Nginx顺序

Nginx 处理每一个用户请求时,都是按照若干个不同阶段(phase)依次处理的,请求的过程一共划分为 11 个阶段,按照执行顺序依次是

post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.

post-read:
读取请求内容阶段
Nginx读取并解析完请求头之后就立即开始运行
例如模块 ngx_realip 就在 post-read 阶段注册了处理程序,它的功能是迫使 Nginx 认为当前请求的来源地址是指定的某一个请求头的值。
server-rewrite
Server请求地址重写阶段
当 ngx_rewrite 模块的set配置指令直接书写在 server 配置块中时,基本上都是运行在 server-rewrite 阶段
find-config
配置查找阶段
这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作。
rewrite
Location请求地址重写阶段
当 ngx_rewrite 模块的指令用于 location 块中时,便是运行在这个 rewrite 阶段。
另外,ngx_set_misc(设置md5、encode_base64等) 模块的指令,还有 ngx_lua 模块的 set_by_lua 指令和 rewrite_by_lua 指令也在此阶段。
post-rewrite
请求地址重写提交阶段
由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作,如果 rewrite 阶段有此要求的话。
preaccess
访问权限检查准备阶段
标准模块 ngx_limit_req 和 ngx_limit_zone 就运行在此阶段,前者可以控制请求的访问频度,而后者可以限制访问的并发度。
access
访问权限检查阶段
标准模块 ngx_access、第三方模块 ngx_auth_request 以及第三方模块 ngx_lua 的 access_by_lua 指令就运行在这个阶段。
配置指令多是执行访问控制性质的任务,比如检查用户的访问权限,检查用户的来源 IP 地址是否合法
post-access
访问权限检查提交阶段
主要用于配合 access 阶段实现标准 ngx_http_core 模块提供的配置指令 satisfy 的功能。
satisfy all(与关系)
satisfy any(或关系)
try-files
配置项try_files处理阶段
专门用于实现标准配置指令 try_files 的功能
如果前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会立即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.
content
内容产生阶段
Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个,因为运行在这个阶段的配置指令一般都肩负着生成“内容”
并输出 HTTP 响应的使命。
log
日志模块处理阶段
记录日志
  • Lua顺序

Nginx下Lua处理阶段与使用范围:

init_by_lua            http
set_by_lua             server, server if, location, location if
rewrite_by_lua         http, server, location, location if
access_by_lua          http, server, location, location if
content_by_lua         location, location if
header_filter_by_lua   http, server, location, location if
body_filter_by_lua     http, server, location, location if
log_by_lua             http, server, location, location if
timer
init_by_lua:
在nginx重新加载配置文件时,运行里面lua脚本,常用于全局变量的申请。
例如lua_shared_dict共享内存的申请,只有当nginx重起后,共享内存数据才清空,这常用于统计。

set_by_lua:
设置一个变量,常用与计算一个逻辑,然后返回结果
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

rewrite_by_lua:
在access阶段前运行,主要用于rewrite

access_by_lua:
主要用于访问控制,能收集到大部分变量,类似status需要在log阶段才有。
这条指令运行于nginx access阶段的末尾,因此总是在 allow 和 deny 这样的指令之后运行,虽然它们同属 access 阶段。

content_by_lua:
阶段是所有请求处理阶段中最为重要的一个,运行在这个阶段的配置指令一般都肩负着生成内容(content)并输出HTTP响应。

header_filter_by_lua:
一般只用于设置Cookie和Headers等
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

body_filter_by_lua:
一般会在一次请求中被调用多次, 因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的。
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

log_by_lua:
该阶段总是运行在请求结束的时候,用于请求的后续操作,如在共享内存中进行统计数据,如果要高精确的数据统计,应该使用body_filter_by_lua。
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

timer:

可参考官方文档:

http://wiki.nginx.org/HttpLuaModule

 

Nginx_Lua使用分享

  • 介绍

ngx_lua – 把lua语言嵌入nginx中,使其支持lua来快速开发基于nginx下的业务逻辑

添加lua支持后,开发复杂的模块,周期快,依然是100%异步非阻塞

该模块不在nginx源码包中,需自行下载编译安装。使用lua 5.1(目前不支持lua 5.2) 或 luajit 2.0 。

源码地址:https://github.com/chaoslawful/lua-nginx-module

  • 安装

安装nginx、lua-nginx-module模块…

  • 使用

在nginx.conf中的service添加一个location

location = /test {
       content_by_lua '
           ngx.say("Hello xiaosl")
	   ngx.log(ngx.ERR, "err err err")
       ';
}

访问http://localhost/test 打印Hello xiaosl

另外也可以调用外部脚本,如下:

location = /test2 {
       content_by_lua_file conf/lua/hello.lua;
}

hello.lua内容

ngx.say("Hello xiaosl")

代码重构markdown

% **代码重构**
% **肖士良**

# 程序开发做什么

1.开发新功能

2.重构

# 什么是重构

> 重构(名词):对软件内部结构的一种调整, 目的是在不改变”软件之可察行为”前提下,提高其可理解性,降低其修改成本.
>
> 重构(动词):使用一系列重构准则(手法),在不改变”软件之可察行为”前提下,调整其结构.

1. 不改变原有功能

2. 调整程序结构,提高程序维护性

# 重构目的

– 让代码易读易理解。(代码是写给人看的, 顺便能在计算机上运行)

– 改进程序设计,程序模块化,把代码放在合适的位置

– 找出隐藏BUG及缺陷

– 提高开发速度

– 提高程序性能

# 重构结果

– 可以更快更好的开发程序

– 良好的设计

– 代码清晰易读易理解

– 稳定健壮的程序

– 清晰高效的算法

– 提高对代码的控制能力

– 代码清晰易读,良好的代码风格

– 对常见BUG敏感,少出BUG

– 提高程序的设计能力,学会抽象和模块化

# 常用基本重构方法

– 重命名:对类,接口,方法,属性,参数等重命名,使代码更易理解( 统一编码统规范,PSR规范)

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040910155397.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040910195064.png)

– ![图3(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040910241779.png)

* * *

– 抽取代码:

1. 将复杂的处理过程分解成独立功能的小函数,函数名称解释函数功能(**不要复制代码**)

2. 将多处出现的代码段抽取封装为一个特定功能的方法,其他方法调用该方法(**不要复制代码**)

3. 将类的某些属性,方法抽取,组成新的类。原类继承或者使用(**不要复制代码**)

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012033109070595.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012033109110690.png)

* * *

– 抽取参数:提升方法内的局部变量为方法的参数

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040913581541.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040914012330.png)

* * *

– 删除参数:将方法的一个或多个参数删掉(对象作为参数传递)

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040916375073.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040916411265.png)

* * *

– 方法迁移:将函数放在它应该在的地方,降低耦合性

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012033116451424.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012033116464142.png)

* * *

– 对象替代数组:值域名称和函数名称清晰表达元素意义。

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040415335998.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040415384523.png)

* * *

– 合并条件语句:考虑合并理由

– ![图1(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040609222425.png)

– ![图2(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040609243679.png)

– ![图3(图片来自博客园)](http://pic002.cnblogs.com/images/2012/152332/2012040609304251.png)

* * *
## 其他方法
1. 隐藏属性、方法,控制权限。

2. 使用多态,替换switch

3. 避免硬编码

# 总结

1. 开发过程中注意抽象、模块化编程。

2. 不要只为实现功能而写代码,要保证代码质量。代码结构和维护性比实现功能更复杂更重要。

# Q&A

谢谢