国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

談?wù)劥a——如何避免寫出糟糕if...else語句

huhud / 2429人閱讀

摘要:源碼剖析之設(shè)計(jì)模式鑒賞策略模式小結(jié)在這篇文章中筆者和大家分享幾個(gè)減少的小由于這些都會(huì)有一定的限制因此還向大家介紹了幾個(gè)能夠避免寫出糟糕的的設(shè)計(jì)模式并使用觀察者模式簡(jiǎn)單的改進(jìn)了仲裁者模式的例子

本文首發(fā)于數(shù)據(jù)浮云:https://mp.weixin.qq.com/s?__...

在寫代碼的日常中,if...else語句是極為常見的.正因其常見性,很多同學(xué)在寫代碼的時(shí)候并不會(huì)去思考其在目前代碼中的用法是否妥當(dāng).而隨著項(xiàng)目的日漸發(fā)展,糟糕的if...else語句將會(huì)充斥在各處,讓項(xiàng)目的可維護(hù)性急劇下降.故在這篇文章中,筆者想和大家談?wù)勅绾伪苊鈱懗鲈愀?b>if...else語句.

由于脫密等原因.文章中的示例代碼將會(huì)用一些開源軟件的代碼或者抽象過的生產(chǎn)代碼作為示范.
問題代碼

當(dāng)我們看到一組if...else時(shí),一般是不會(huì)有什么閱讀負(fù)擔(dān)的.但當(dāng)我們看到這樣的代碼時(shí):

    private void validate(APICreateSchedulerMessage msg) {
        if (msg.getType().equals("simple")) {
            if (msg.getInterval() == null) {
                if (msg.getRepeatCount() != null) {
                    if (msg.getRepeatCount() != 1) {
                        throw new ApiMessageInterceptionException(argerr("interval must be set when use simple scheduler when repeat more than once"));
                    }
                } else {
                    throw new ApiMessageInterceptionException(argerr("interval must be set when use simple scheduler when repeat forever"));
                }
            } else if (msg.getInterval() != null) {
                if (msg.getRepeatCount() != null) {
                    if (msg.getInterval() <= 0) {
                        throw new ApiMessageInterceptionException(argerr("interval must be positive integer"));
                    } else if ((long) msg.getInterval() * (long) msg.getRepeatCount() * 1000L + msg.getStartTime() < 0 ) {
                        throw new ApiMessageInterceptionException(argerr("duration time out of range"));
                    } else if ((long) msg.getInterval() * (long) msg.getRepeatCount() * 1000L + msg.getStartTime() > 2147454847000L) {
                        throw new ApiMessageInterceptionException(argerr("stopTime out of mysql timestamp range"));
                    }
                }
            }

            if (msg.getStartTime() == null) {
                throw new ApiMessageInterceptionException(argerr("startTime must be set when use simple scheduler"));
            } else if (msg.getStartTime() != null && msg.getStartTime() < 0) {
                throw new ApiMessageInterceptionException(argerr("startTime must be positive integer or 0"));
            } else if (msg.getStartTime() != null && msg.getStartTime() > 2147454847 ){
                //  mysql timestamp range is "1970-01-01 00:00:01" UTC to "2038-01-19 03:14:07" UTC.
                //  we accept 0 as startDate means start from current time
                throw new ApiMessageInterceptionException(argerr("startTime out of range"));
            }

            if (msg.getRepeatCount() != null && msg.getRepeatCount() <= 0) {
                throw new ApiMessageInterceptionException(argerr("repeatCount must be positive integer"));
            }
        }

        if (msg.getType().equals("cron")) {
            if (msg.getCron() == null || ( msg.getCron() != null && msg.getCron().isEmpty())) {
                throw new ApiMessageInterceptionException(argerr("cron must be set when use cron scheduler"));
            }
            if ( (! msg.getCron().contains("?")) || msg.getCron().split(" ").length != 6) {
                throw new ApiMessageInterceptionException(argerr("cron task must follow format like this : "0 0/3 17-23 * * ?" "));
            }
            if (msg.getInterval() != null || msg.getRepeatCount() != null || msg.getStartTime() != null) {
                throw new ApiMessageInterceptionException(argerr("cron scheduler only need to specify cron task"));
            }
        }
    }

亦或是這樣的代碼:

try {
   for (int j = myConfig.getContentStartNum(); j <= rowNum; j++) {
        row = sheet.getRow(j);
        T obj = target.newInstance();
        for (int i = 0; i < colNum; i++) {

            Field colField = ExcelUtil.getOneByTitle(metaList, titleList[i]);
            colField.setAccessible(true);
            String fieldType = colField.getType().getSimpleName();
            HSSFCell cell = row.getCell(i);
            int cellType = cell.getCellType();
            System.out.println(colField.getName()+"|"+fieldType+" | "+cellType);

            if(HSSFCell.CELL_TYPE_STRING == cellType){
                if("Date".equals(fieldType)){
                    colField.set(obj, DateUtil.parse(cell.getStringCellValue()));
                }else {
                    colField.set(obj, cell.getStringCellValue());
                }
            }else if(HSSFCell.CELL_TYPE_BLANK == cellType){
                System.out.println("fieldName"+colField.getName());
                if("Boolean".equals(fieldType)){
                    colField.set(obj, cell.getBooleanCellValue());
                }else{
                    colField.set(obj, "");
                }
            }else if(HSSFCell.CELL_TYPE_NUMERIC == cellType){
                if("Integer".equals(fieldType) || "int".equals(fieldType)){
                    colField.set(obj, (int)cell.getNumericCellValue());
                }else {
                    colField.set(obj, cell.getNumericCellValue());
                }
            }else if(HSSFCell.CELL_TYPE_BOOLEAN == cellType){
                colField.set(obj, cell.getBooleanCellValue());
            }
        }
        result.add(obj);
    }
} catch (InstantiationException | IllegalAccessException | ParseException e) {
    e.printStackTrace();
}

看完這兩段代碼,相信大家和我的心情是一樣的:

閱讀它們的負(fù)擔(dān)實(shí)在是太大了——我們要記住好幾個(gè)邏輯判斷分支,才能知道到底什么情況下才能得到那個(gè)結(jié)果.更別說維護(hù)的成本有多高了,每次維護(hù)時(shí)都要讀一遍,然后再基于此來改.長(zhǎng)此以往,我們的代碼就變成"箭頭式代碼"了.

    //...............
        //...............
             //...............
                 //...............
                     //...............
                     //...............
                 //...............
             //...............
       //...............
 //...............
目標(biāo)和關(guān)鍵指標(biāo)

前面說過,我們的目標(biāo)減少糟糕的if...else代碼.那么什么是糟糕的if...else代碼呢?我們可以簡(jiǎn)單的總結(jié)一下:

兩重以上的嵌套

一個(gè)邏輯分支的判斷條件有多個(gè),如:A && B || C這種.其實(shí)這也可以看作變種的嵌套

這樣就可以看出來,我們的關(guān)鍵指標(biāo)就是減少嵌套.

常見Tips 1. 三元表達(dá)式

三元表達(dá)式在代碼中也是較為常見的,它可以簡(jiǎn)化一些if...else,如:

    public Object getFromOpaque(String key) {
        return opaque == null ? null : opaque.get(key);
    }

為什么說是一些呢?因此三元表達(dá)式必須要有一個(gè)返回值.

這種情況下就沒法使用三元表達(dá)式

    public void putToOpaque(String key, Object value) {
        if (opaque == null) {
            opaque = new LinkedHashMap();
        }
        opaque.put(key, value);
    }
2. switch case

在Java中,switch可以關(guān)注一個(gè)變量( byte short int 或者 char,從Java7開始支持String),然后在每個(gè)case中比對(duì)是否匹配,是的話則進(jìn)入這個(gè)分支.

在通常情況下,switch case的可讀性比起if...else會(huì)好一點(diǎn).因?yàn)閕f中可以放復(fù)雜的表達(dá)式,而switch則不行.話雖如此,嵌套起來還是會(huì)很惡心.

因此,如果僅僅是對(duì) byte,short,int和char以String簡(jiǎn)單的值判斷,可以考慮優(yōu)先使用switch.

3. 及時(shí)回頭
   /* 查找年齡大于18歲且為男性的學(xué)生列表 */
    public ArrayList getStudents(int uid){
        ArrayList result = new ArrayList();
        Student stu = getStudentByUid(uid);
        if (stu != null) {
            Teacher teacher = stu.getTeacher();
            if(teacher != null){
                ArrayList students = teacher.getStudents();
                if(students != null){
                    for(Student student : students){
                        if(student.getAge() > = 18 && student.getGender() == MALE){
                            result.add(student);
                        }
                    }
                }else {
                    throw new MyException("獲取學(xué)生列表失敗");
                }
            }else {
                throw new MyException("獲取老師信息失敗");
            }
        } else {
            throw new MyException("獲取學(xué)生信息失敗");
        }
        return result;
    }

針對(duì)這種情況,我們應(yīng)該及時(shí)拋出異常(或者說return),保證正常流程在外層,如:

   /* 查找年齡大于18歲且為男性的學(xué)生列表 */
    public ArrayList getStudents(int uid){
        ArrayList result = new ArrayList();
        Student stu = getStudentByUid(uid);
        if (stu == null) {
             throw new MyException("獲取學(xué)生信息失敗");
        }
 
        Teacher teacher = stu.getTeacher();
        if(teacher == null){
             throw new MyException("獲取老師信息失敗");
        }
 
        ArrayList students = teacher.getStudents();
        if(students == null){
            throw new MyException("獲取學(xué)生列表失敗");
        }
 
        for(Student student : students){
            if(student.getAge() > 18 && student.getGender() == MALE){
                result.add(student);
            }
        }
        return result;
    }
使用設(shè)計(jì)模式

除了上面的幾個(gè)tips,我們還可以通過設(shè)計(jì)模式來避免寫出糟糕的if...else語句.在這一節(jié),我們將會(huì)提到下面幾個(gè)設(shè)計(jì)模式:

State模式

Mediator模式

Observer模式

Strategy模式

1. State模式

在代碼中,我們經(jīng)常會(huì)判斷一些業(yè)務(wù)對(duì)象的狀態(tài)來決定在當(dāng)前的調(diào)用下它該怎么做.我們舉個(gè)例子,現(xiàn)在我們有一個(gè)銀行的接口:

public interface Bank {
    /**
     * 銀行上鎖
     * */
    void lock();
    /**
     * 銀行解鎖
     * */
    void unlock();
    /**
     * 報(bào)警
     * */
    void doAlarm();
}

讓我們來看一下它的實(shí)現(xiàn)類

public class BankImpl implements Bank {
    @Override
    public void lock() {
        //保存這條記錄
    }

    @Override
    public void unlock() {
        if ((BankState.Day == getCurrentState())) {
            //白天解鎖正常
            //僅僅保存這條記錄
        } else if (BankState.Night == getCurrentState()) {
            //晚上解鎖,可能有問題
            //保存這條記錄,并報(bào)警
            doAlarm();
        }
    }

    @Override
    public void doAlarm() {
        if ((BankState.Day == getCurrentState())) {
            //白天報(bào)警,聯(lián)系當(dāng)?shù)鼐?,并保留這條記錄
        } else if (BankState.Night == getCurrentState()) {
            //晚上報(bào)警,可能有事故,不僅聯(lián)系當(dāng)?shù)鼐?,還需要協(xié)調(diào)附近的安保人員,并保留這條記錄
        }
    }


    private BankState getCurrentState() {
        return BankState.Day;
    }
}

顯然,我們涉及到了一個(gè)狀態(tài):

public enum BankState {
    Day,
    Night
}

在不同的狀態(tài)下,同一件事銀行可能會(huì)作出不同的反應(yīng).這樣顯然很挫,因?yàn)樵谡鎸?shí)業(yè)務(wù)場(chǎng)景下,業(yè)務(wù)的狀態(tài)可能不僅僅只有兩種.每多一種,就要多寫一個(gè)if...else.所以,如果按照狀態(tài)模式,可以這樣來重構(gòu):

public class BankDayImpl implements Bank {
    @Override
    public void lock() {
        //保存這條記錄
    }

    @Override
    public void unlock() {
        //白天解鎖正常
        //僅僅保存這條記錄

    }

    @Override
    public void doAlarm() {
        //白天報(bào)警,聯(lián)系當(dāng)?shù)鼐?,并保留這條記錄
    }
}
public class BankNightImpl implements Bank {
    @Override
    public void lock() {
        //保存這條記錄
    }

    @Override
    public void unlock() {
        //晚上解鎖,可能有問題
        //保存這條記錄,并報(bào)警
        doAlarm();
    }

    @Override
    public void doAlarm() {
        //晚上報(bào)警,可能有事故,不僅聯(lián)系當(dāng)?shù)鼐?,還需要協(xié)調(diào)附近的安保人員,并保留這條記錄
    }
}
2. Mediator模式

在本文的第一段的代碼中,其實(shí)是ZStack 2.0.5版本中某處的代碼,它用來防止用戶使用Cli時(shí)傳入不當(dāng)?shù)膮?shù),導(dǎo)致后面的邏輯運(yùn)行不正常.為了方便理解,我們可以對(duì)其規(guī)則做一個(gè)簡(jiǎn)化,并畫成圖的樣子來供大家理解.

假設(shè)這是一個(gè)提交定時(shí)重啟VM計(jì)劃任務(wù)的“上古級(jí)”界面(因?yàn)楹玫慕换ピO(shè)計(jì)師一定不會(huì)把界面設(shè)計(jì)成這樣吧...).規(guī)則大概如下:

2.1 Simple類型的Scheduler

Simple類型的Scheduler,可以根據(jù)Interval,RepeatCount,StartTime來定制一個(gè)任務(wù).

2.1.1 當(dāng)選擇Simple類型的任務(wù)時(shí),Interval,StartTime這兩個(gè)參數(shù)必填

2.1.2 當(dāng)填好Interval,和StartTime,這個(gè)時(shí)候已經(jīng)可以提交定時(shí)任務(wù)了

2.1.3 RepeatCount是個(gè)可選參數(shù)

2.2 Cron類型的Scheduler

Cron類型的Scheduler,可以根據(jù)cron表達(dá)式來提交任務(wù).

2.2.1 當(dāng)填入cron表達(dá)式后,這個(gè)時(shí)候已經(jīng)可以提交定時(shí)任務(wù)了

在這里請(qǐng)大家思考一個(gè)問題,如果要寫這樣的一個(gè)界面,該怎么寫?——在一個(gè)windows類里,先判斷上面的可選欄是哪種類型,然后根據(jù)文本框里的值是否被填好決定提交按鈕屬否亮起...這算是基本邏輯.上面還沒有提到邊界值的校驗(yàn)——這些邊界值的校驗(yàn)往往會(huì)散落在各個(gè)組件的實(shí)例里,并通過互相通信的方式來判斷自己應(yīng)該做出什么樣的變化,相信大家已經(jīng)意識(shí)到了直接無腦堆if...else代碼的恐怖之處了吧.

2.3 使用仲裁者改善它

接下來,我們將會(huì)貼上來一些偽代碼,方便讀者更好的理解這個(gè)設(shè)計(jì)模式

/**
 * 仲裁者的成員接口
 * */
public interface Colleague {
    /**
     * 設(shè)置成員的仲裁者
     * */
    void setMediator(Mediator mediator);

    /**
     * 設(shè)置成員是否被啟用
     * */
    void setColleagueEnabled(boolean enabled);
}
/**
 * 仲裁者接口
 * */
public interface Mediator {
    /**
     * 當(dāng)一個(gè)組員發(fā)生狀態(tài)變化時(shí),調(diào)用此方法
     * */
    void colllectValueChanged(String value);
}
/**
 * 含有textField的組件應(yīng)當(dāng)實(shí)現(xiàn)接口
 */
public interface TextField {
    String getText();
}
/**
 * 當(dāng)一個(gè)組件的值發(fā)生變化時(shí),ValueListener會(huì)收到相應(yīng)通知
 * */
public interface ValueListener {
    /**
     * 當(dāng)組員的值變化時(shí),這個(gè)接口會(huì)被調(diào)用
     * */
    void valueChanged(String str);
}

定義了幾個(gè)接口之后,我們開始編寫具體的類:

用于表示SimpleCron的checkBox

public class CheckBox {
    private boolean state;

    public boolean isState() {
        return state;
    }

    public void setState(boolean state) {
        this.state = state;
    }
}

Button

public class ColleagueButtonField implements Colleague, ValueListener {
    private Mediator mediator;

    @Override
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    @Override
    public void setColleagueEnabled(boolean enabled) {
        setEnable(enabled);
    }

    private void setEnable(boolean enable) {
        //當(dāng)true時(shí)去掉下劃線,并允許被按下
    }

    @Override
    public void valueChanged(String str) {
        mediator.colllectValueChanged(str);
    }
}

以及幾個(gè)Text

public class ColleagueTextField implements Colleague, ValueListener, TextField {
    private Mediator mediator;
    private String text;

    @Override
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    @Override
    public void setColleagueEnabled(boolean enabled) {
        setEnable(enabled);
    }

    private void setEnable(boolean enable) {
        //當(dāng)true時(shí)去掉下劃線,并允許值輸入
    }

    @Override
    public void valueChanged(String str) {
        mediator.colllectValueChanged(str);
    }

    @Override
    public String getText() {
        return text;
    }
}

SchedulerValidator的具體實(shí)現(xiàn)SchedulerValidatorImpl就不貼上來了,里面僅僅是一些校驗(yàn)邏輯.

接著是我們的主類,也就是知道全局狀態(tài)的窗口類

public class MainWindows implements Mediator {
    private SchedulerValidator validator = new SchedulerValidatorImpl();
    ColleagueButtonField submitButton, cancelButton;
    ColleagueTextField intervalText, repeatCountText, startTimeText, cronText;
    CheckBox simpleCheckBox, cronCheckBox;


    public void main() {
        createColleagues();
    }

    /**
     * 當(dāng)一個(gè)組員發(fā)生狀態(tài)變化時(shí),調(diào)用此方法
     * 組件初始化時(shí)都為true
     */
    @Override
    public void colllectValueChanged(String str) {
        if (simpleCheckBox.isState()) {
            cronText.setColleagueEnabled(false);
            simpleChanged();
        } else if (cronCheckBox.isState()) {
            intervalText.setColleagueEnabled(false);
            repeatCountText.setColleagueEnabled(false);
            startTimeText.setColleagueEnabled(false);
            cronChanged();
        } else {
            submitButton.setColleagueEnabled(false);
            intervalText.setColleagueEnabled(false);
            repeatCountText.setColleagueEnabled(false);
            startTimeText.setColleagueEnabled(false);
            cronText.setColleagueEnabled(false);
        }
    }


    private void cronChanged() {
        if (!validator.validateCronExpress(cronText.getText())) {
            submitButton.setColleagueEnabled(false);
        }
    }

    private void simpleChanged() {
        if (!validator.validateIntervalBoundary(intervalText.getText())
                || !validator.validateRepeatCountBoundary(repeatCountText.getText())
                || !validator.validateStartTime(startTimeText.getText())) {
            submitButton.setColleagueEnabled(false);
        }
    }

    private void createColleagues() {
        submitButton = new ColleagueButtonField();
        submitButton.setMediator(this);
        cancelButton = new ColleagueButtonField();
        cancelButton.setMediator(this);

        intervalText = new ColleagueTextField();
        intervalText.setMediator(this);
        repeatCountText = new ColleagueTextField();
        repeatCountText.setMediator(this);
        startTimeText = new ColleagueTextField();
        startTimeText.setMediator(this);
        cronText = new ColleagueTextField();
        cronText.setMediator(this);

        simpleCheckBox = new CheckBox();
        cronCheckBox = new CheckBox();
    }
}


在這個(gè)設(shè)計(jì)模式中,所有實(shí)例狀態(tài)的判斷全部都交給了仲裁者這個(gè)實(shí)例來判斷,而不是互相去通信.在目前的場(chǎng)景來看,其實(shí)涉及的實(shí)例還不是特別多,但在一個(gè)復(fù)雜的系統(tǒng)中,涉及的實(shí)例將會(huì)變得非常多.假設(shè)現(xiàn)在有A,B兩個(gè)實(shí)例,那么會(huì)有兩條通信線路:

而有A,B,C時(shí),則有6條線路

當(dāng)有4個(gè)實(shí)例時(shí),將會(huì)有12個(gè)通信線路

當(dāng)有5個(gè)實(shí)例時(shí),會(huì)有20個(gè)通信線路

以此類推...

這個(gè)時(shí)候,仲裁者模式的優(yōu)點(diǎn)就發(fā)揮出來了——這些邏輯如果分散在各個(gè)角色中,代碼將會(huì)變得難以維護(hù).

3. Observer模式
ZStack源碼剖析之設(shè)計(jì)模式鑒賞——三駕馬車

結(jié)合本文的主題,其實(shí)觀察者模式做的更多的是將if...else拆分到屬于其自己的模塊中.以ZStack的為例,當(dāng)主存儲(chǔ)重連時(shí),主存儲(chǔ)模塊可能要讓模塊A和模塊B去做一些事,如果不使用觀察者模式,那么代碼就會(huì)都耦合在主存儲(chǔ)模塊下,拆開if...else也就不太可能了.

改進(jìn)之前的仲裁者例子

觀察者模式一般是通過事件驅(qū)動(dòng)的方式來通信的,因此Observer和Subject一般都是松耦合的——Subject發(fā)出通知時(shí)并不會(huì)指定消費(fèi)者.而在之前仲裁者模式的例子中,仲裁者和成員之間緊耦合的(即他們必須互相感知),因此可以考慮通過觀察者模式來改進(jìn)它.

4. Strategy模式

通常在編程時(shí),算法(策略)會(huì)被寫在具體方法中,這樣會(huì)導(dǎo)致具體方法中充斥著條件判斷語句。但是Strategy卻特意將算法與其他部分剝離開來,僅僅定義了接口,然后再以委托的方式來使用算法。然而這種做法正是讓程序更加的松耦合(因?yàn)槭褂梦锌梢苑奖愕恼w替換算法),使得整個(gè)項(xiàng)目更加茁壯。

ZStack源碼剖析之設(shè)計(jì)模式鑒賞——策略模式
小結(jié)

在這篇文章中,筆者和大家分享幾個(gè)減少if...else的小tips,由于這些tips都會(huì)有一定的限制,因此還向大家介紹了幾個(gè)能夠避免寫出糟糕的if...else的設(shè)計(jì)模式,并使用觀察者模式簡(jiǎn)單的改進(jìn)了仲裁者模式的例子.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73065.html

相關(guān)文章

  • Python 工匠:編寫條件分支代碼的技巧

    摘要:系列文章工匠善用變量改善代碼質(zhì)量序言編寫條件分支代碼是編碼過程中不可或缺的一部分。而進(jìn)行條件分支判斷時(shí)用到的也是這個(gè)值重點(diǎn)來了,雖然所有用戶類實(shí)例的布爾值都是真。 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由鵝廠優(yōu)文發(fā)表于云+社區(qū)專欄 作者:朱雷 | 騰訊IEG高級(jí)工程師 『Python 工匠』是什么? 我一直覺得編程某種意義是一門『手藝』,因?yàn)閮?yōu)雅而高效的代碼...

    KaltZK 評(píng)論0 收藏0
  • 論 CSS 中的邏輯

    摘要:天生缺乏邏輯性的問題導(dǎo)致了預(yù)處理器的出現(xiàn)。這會(huì)導(dǎo)致圈復(fù)雜度問題。圈復(fù)雜度對(duì)于來說可能是一種比較高階的原則,但如果我們通過它來考量那些蘊(yùn)含在我們寫的選擇器中的邏輯性,那我們也許就能寫出更加優(yōu)秀的代碼。 本文在征得原作者 @csswizardry 同意的情況下,翻譯自他博客中的文章:Cyclomatic Complexity: Logic in CSS。最初發(fā)布于我的個(gè)人博客:咀嚼之...

    PiscesYE 評(píng)論0 收藏0
  • 代碼整潔之道》讀書筆記

    摘要:看完代碼整潔之道之后我受益匪淺,但等到自己實(shí)踐時(shí)卻很難按照書中給的建議編寫出整潔的代碼。意味著新人除了了解代碼邏輯之外,還需要學(xué)習(xí)這種編碼語言。代碼在演化,注釋卻不總是隨之變動(dòng)。區(qū)隔與靠近空格強(qiáng)調(diào)左右兩邊的分割。 看完《代碼整潔之道》之后我受益匪淺,但等到自己實(shí)踐時(shí)卻很難按照書中給的建議編寫出整潔的代碼。一方面是規(guī)則太多,記不住,另一方面書上引用了大量示例代碼對(duì)這些規(guī)則進(jìn)行佐證,在我記...

    liangzai_cool 評(píng)論0 收藏0
  • 十個(gè)你需要在 PHP 7 中避免的坑

    摘要:不要使用類函數(shù)終于,你不用再看到建議不要使用函數(shù)的提示了。因?yàn)閺暮诵纳贤耆瞥怂鼈?,這意味著請(qǐng)你移步至更好的類函數(shù),或者更靈活的層。將從數(shù)據(jù)庫獲取一個(gè)元數(shù)據(jù),如果您正在循環(huán)訪問特定文章的元數(shù)據(jù),則可以在循環(huán)中使用它。 showImg(https://segmentfault.com/img/bV75FM?w=1024&h=534); 1. 不要使用 mysql_ 類函數(shù) 終于,你不用...

    leanote 評(píng)論0 收藏0
  • 談?wù)?/em>JavaScript異步代碼優(yōu)化

    摘要:異步問題回調(diào)地獄首先,我們來看下異步編程中最常見的一種問題,便是回調(diào)地獄。同時(shí)使用也是異步編程最基礎(chǔ)和核心的一種解決思路?;冢壳耙脖粡V泛運(yùn)用,其是異步編程的一種解決方案,比傳統(tǒng)的回調(diào)函數(shù)解決方案更合理和強(qiáng)大。 關(guān)于 微信公眾號(hào):前端呼啦圈(Love-FED) 我的博客:勞卜的博客 知乎專欄:前端呼啦圈 前言 在實(shí)際編碼中,我們經(jīng)常會(huì)遇到Javascript代碼異步執(zhí)行的場(chǎng)景...

    chnmagnus 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<