if

基本上所有的程序语言,程序结构都分为:顺序结构、选择结构、循环结构这三种类型。顺序结构:代码从上自下执行,注意一下每行语句的依赖关系。(有的时候,可以适当的调整位置,提前某个变量的定义、某条语句的位置,然后后面代码可以共用这个代码的福利)。选择结构,便是本文的重点对象,进行分支选择。正是因为它的存在,让代码有了可变,让每次的执行,都不太一样。循环结构,然某个重复单元重复执行。

选择结构:常用的有if,swith,也有一些利用and or进行短路处理。或者用字典来做选择。

程序出口。一定要注意,每个分支都要有一个出口。如果相同的处理,可以利用技巧共用。

if

最简单的结构

$age = 1;
if($a){
    $age = 2;
}

或者

if($a){
    $age = 2;
}else{
	$age = 1;
}

多分支结构

if($a>90){
    echo '优秀!';
}else if($a>80){
    echo '还不错';
}else if($a > 60){
    echo '及格';
}else{
    echo '成绩不合格,需加油啊!';
}

现实中上上面这样简单的判断(没有什么好讲,关键在于里面的条件都不同。)。

嵌套分支。

if($a > 0 ){
    if($b){
        return ''; // 第1个return 
    }else{
        //not return
    }
}else{
    //do somethin and contuine;
}
// do something common
return  '';//第2个return

堆叠

if($a==90){
    echo '优秀!';
} 
if($a==80){
    echo '还不错';
}
if($a == 60){
    echo '及格';
}

上面的堆叠,虽然,只能进入其中一个入口。但是用上多分支,只有其中一个执行,可能更好。

一些常用的思想,如例子:

function getData($b){
    if($自己并没有使例化){
        //好吧,先实例化
    }
    return $实例话的变量。
}

swith

and、or

重复判断

代码大全里讲,通过重复判断,能降低嵌套层次。

下面的原本是,这样

if( $target_prot){
    $urls['step4'] = "http://localhost:$target_prot/";
	if($top_url){
		$urls['step4'] = "http://localhost:$target_prot". self::getUri($top_url);
	}
}

改为扁平的结构:

if($top_url && $target_prot){
    $urls['step4'] = "http://localhost:$target_prot". self::getUri($top_url);
}else if( $target_prot ){
    $urls['step4'] = "http://localhost:$target_prot/";
}

卫语句

if虽然非常好用,但是滥用,会造成代码非常难理解。

逻辑转换与有优化

示例1

需求是:倒计时,如果超过60秒,则,每60秒提醒一次。1分钟内,则希望60、30、20、10,这几个时间点进行提醒。对于这种对于同一个切面的分类,按顺序处理:超过60秒,则intval为60,针对60、30这个点,则intval为30,少于30,则为10。所以便有如下代码。

Sub sleep(n)
    Dim intv = 60 ' 每隔一段时间提醒一次
    Dim left
    For i = 1 To n
        Delay 1000
        left = n - i
        If left > 60 Then
            intv = 60
        Else If left > 30 Then
            int = 30
        Else
            int = 10
        End If
        If i Mod intv = 0 Then 
            TracePrint "等待"&(n-i)& "秒"
        End If		
    Next
End Sub

' 上面的代码,看起来很复杂。由于intv默认值已经给了,所以第1个分支,其实是多余的。所以,我们考虑反序。
' 反序后,我们发现,第3个分支,包含了第2个分支,所以,intval实际上取两个值就行。10跟60。
' 所以代码如下:代码一下见解了很多。

Sub sleep(n)
    Dim intv = 60 ' 每隔一段时间提醒一次
    Dim left
    For i = 1 To n
        Delay 1000
        left = n - i
        If left <= 30 Then
            int = 10
        End If
        If i Mod intv = 0 Then 
            TracePrint "等待"&(n-i)& "秒"
        End If		
    Next
End Sub

' 如果只是合并2跟3分支,则如下
Sub sleep(n)
    Dim intv = 60 ' 每隔一段时间提醒一次
    Dim left
    For i = 1 To n
        Delay 1000
        left = n - i
        If left >= 60 Then
            intv = 60
        Else If left <= 30 Then
            int = 10
        End If
        If i Mod intv = 0 Then 
            TracePrint "等待"&(n-i)& "秒"
        End If		
    Next
End Sub

总结:针对上面类似的优化,对于同一个逻辑切面,而又有默认的值,那么我们考虑,两种顺序的逻辑如何写。另外,能减少分支,尽量减少分支的处理。比如,intv只有10跟60两种情况,已经满足我们的需求,那么,我们就没有必要10、30、60这3种情况了。

切分

示例

示例1

if(strpos($msg,$error)!==false){ 
    //直接使用 shell 完成编码纠正。
    exec("iconv -f UTF-8 -t UTF-8 -c -o {$newfile} {$filename};");
    //再次尝试导入修正后的文件
    safe_import($newfile,$try_times+1);
}elseif($table ==='th_gpsdata' && (strpos($msg,$error2)!==false || strpos($msg,$error3) !==false ) ){  //csv gps中demical格式错误 ,高度超高,只针对th_gpsdata 表
    check_num($filename,$newfile);
    safe_import($newfile,$try_times+1);
}else{
    throw new Exception($msg, 1);
}

第2个条件非常复杂。拆分的话:

if($table ==='th_gpsdata'  ){  //csv gps中demical格式错误 ,高度超高,只针对th_gpsdata 表
    if(strpos($msg,$error2)!==false || strpos($msg,$error3) !==false){
        check_num($filename,$newfile);
        safe_import($newfile,$try_times+1);
    }
    // else 分支,没有办法交给后续的分支
}

怎么理解上面这种情况呢?

示例2

场景:从首页到签到页,再到娱乐中心页。不确定当前是哪一页。比如,如果当前是首页,则需要经过2个页面的操作,才能到达第3页。

所以,下面简单的叠加场景,正适合不确定当前是哪一页的判断。如果下面的If判断,反过来,则不成立。

'判断当前页面
If is_index() Then
    TracePrint "应该不会到主页"
    TracePrint "进入主界面,等待10秒"
    Touch 380,75,500
    Delay 10000
End If
If findText("签到") Then
    TracePrint "选择领取3g流量,等待10秒"
    Touch 96,508,200
    Delay 10000
End If
If findText("娱乐中心") Then
    If get_top() > -1 Then 
        TracePrint "找到了顶部"
        adjust_top
    End If
    ' 水平滑动几次
    For page-1 
        TracePrint "水平滑动"
        huadong (4)
        Delay 2000
    Next 
End If

示例3

锁结构代码、标识代码。

$flag = false

if (!$flag) {
    //当前没有其他人操作,则先操作,再释放锁。
    //todo  操作
    $flag = false
}

c语言防止头文件重复加载,原理是类似的:

#ifndef _STDIO_H
#define _STDIO_H
/* 声明部分 */
#endif