偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

設(shè)計(jì)原則:KISS、DRY、LOD 原則

開(kāi)發(fā)
除了了人盡皆知的 SOLID 原則之外,其實(shí)還有其他一些有用且很受大家認(rèn)可的設(shè)計(jì)原則,本節(jié)課就來(lái)介紹這些設(shè)計(jì)原則。

除了了人盡皆知的 SOLID 原則之外,其實(shí)還有其他一些有用且很受大家認(rèn)可的設(shè)計(jì)原則。本節(jié)課就來(lái)介紹這些設(shè)計(jì)原則。主要包括以下三種設(shè)計(jì)原則:

  • KISS 原則;
  • DRY 原則;
  • LOD 原則。

一、KISS 原則

KISS 原則(Keep It Simple, Stupid)是軟件開(kāi)發(fā)中的重要原則,強(qiáng)調(diào)在設(shè)計(jì)和實(shí)現(xiàn)軟件系統(tǒng)時(shí)應(yīng)該保持簡(jiǎn)單和直觀,避免過(guò)度復(fù)雜和不必要的設(shè)計(jì)。

KISS 原則的英文描述有好幾個(gè)版本,比如下面這幾個(gè)。

  • Keep It Simple and Stupid;
  • Keep It Short and Simple;
  • Keep It Simple and Straightforward。

不過(guò),仔細(xì)看你就會(huì)發(fā)現(xiàn),它們要表達(dá)的意思其實(shí)差不多,翻譯成中文就是:盡量保持簡(jiǎn)單。

KISS 原則是保證代碼可讀性和可維護(hù)性的重要手段。KISS 原則中的“簡(jiǎn)單”并不是以代碼行數(shù)來(lái)考量的。代碼行數(shù)越少并不代表代碼越簡(jiǎn)單,我們還要考慮邏輯復(fù)雜度、實(shí)現(xiàn)難度、代碼的可讀性等。而且,本身就復(fù)雜的問(wèn)題,用復(fù)雜的方法解決,并不違背 KISS 原則。除此之外,同樣的代碼,在某個(gè)業(yè)務(wù)場(chǎng)景下滿足 KISS 原則,換一個(gè)應(yīng)用場(chǎng)景可能就不滿足了。

對(duì)于如何寫出滿足 KISS 原則的代碼,有下面幾條指導(dǎo)原則:

  • 不要使用同事可能不懂的技術(shù)來(lái)實(shí)現(xiàn)代碼
  • 不要重復(fù)造輪子,要善于使用已經(jīng)有的工具類庫(kù)
  • 不要過(guò)度優(yōu)化

下面是一個(gè)使用 KISS 原則設(shè)計(jì)的簡(jiǎn)單計(jì)算器程序的示例:

package main

import"fmt"

// Calculator 定義簡(jiǎn)單的計(jì)算器結(jié)構(gòu)
type Calculator struct{}

// Add 方法用于相加兩個(gè)數(shù)
func (c Calculator) Add(a, b int) int {
    return a + b
}

// Subtract 方法用于相減兩個(gè)數(shù)
func (c Calculator) Subtract(a, b int) int {
    return a - b
}

func main() {
    calculator := Calculator{}

    // 計(jì)算 5 + 3
    result1 := calculator.Add(5, 3)
    fmt.Println("5 + 3 =", result1)

    // 計(jì)算 8 - 2
    result2 := calculator.Subtract(8, 2)
    fmt.Println("8 - 2 =", result2)
}

在上述示例中,我們定義了一個(gè)簡(jiǎn)單的計(jì)算器結(jié)構(gòu) Calculator,包含 Add 和 Subtract 方法用于實(shí)現(xiàn)加法和減法操作。通過(guò)簡(jiǎn)單的設(shè)計(jì)和實(shí)現(xiàn),這個(gè)計(jì)算器程序清晰、易懂,符合 KISS 原則的要求。

二、DRY 原則

DRY 原則,全稱為“Don’t Repeat Yourself”,是軟件開(kāi)發(fā)中的重要原則之一,強(qiáng)調(diào)避免重復(fù)代碼和功能,盡量減少系統(tǒng)中的冗余。DRY 原則的核心思想是任何信息在系統(tǒng)中應(yīng)該有且僅有一個(gè)明確的表達(dá)形式,避免多處重復(fù)定義相同的信息或邏輯。

你可能會(huì)覺(jué)得 DRY 原則非常簡(jiǎn)單、非常容易應(yīng)用。只要兩段代碼長(zhǎng)得一樣,那就是違反 DRY 原則了。真的是這樣嗎?答案是否定的。這是很多人對(duì)這條原則存在的誤解。實(shí)際上,重復(fù)的代碼不一定違反 DRY 原則,而且有些看似不重復(fù)的代碼也有可能違反 DRY 原則。

通常存在三種典型的代碼重復(fù)情況,它們分別是:實(shí)現(xiàn)邏輯重復(fù)、功能語(yǔ)義重復(fù)和代碼執(zhí)行重復(fù)。這三種代碼重復(fù),有的看似違反 DRY,實(shí)際上并不違反;有的看似不違反,實(shí)際上卻違反了。

1. 實(shí)現(xiàn)邏輯重復(fù):

type UserAuthenticator struct{}

func (ua *UserAuthenticator) authenticate(username, password string) {
    if !ua.isValidUsername(username) {
        // ... code block 1
    }

    if !ua.isValidPassword(username) {
        // ... code block 1
    }
    // ...省略其他代碼...
}

func (ua *UserAuthenticator) isValidUsername(username string) bool {}

func (ua *UserAuthenticator) isValidPassword(password string) bool {}

假設(shè) isValidUserName() 函數(shù)和 isValidPassword() 函數(shù)代碼重復(fù),看起來(lái)明顯違反 DRY 原則。為了移除重復(fù)的代碼,我們對(duì)上面的代碼做下重構(gòu),將 isValidUserName() 函數(shù)和 isValidPassword() 函數(shù),合并為一個(gè)更通用的函數(shù) isValidUserNameOrPassword()。

經(jīng)過(guò)重構(gòu)之后,代碼行數(shù)減少了,也沒(méi)有重復(fù)的代碼了,是不是更好了呢?答案是否定的。單從名字上看,我們就能發(fā)現(xiàn),合并之后的 isValidUserNameOrPassword() 函數(shù),負(fù)責(zé)兩件事情:驗(yàn)證用戶名和驗(yàn)證密碼,違反了“單一職責(zé)原則”和“接口隔離原則”。

實(shí)際上,即便將兩個(gè)函數(shù)合并成 isValidUserNameOrPassword(),代碼仍然存在問(wèn)題。因?yàn)?nbsp;isValidUserName() 和 isValidPassword() 兩個(gè)函數(shù),雖然從代碼實(shí)現(xiàn)邏輯上看起來(lái)是重復(fù)的,但是從語(yǔ)義上并不重復(fù)。所謂“語(yǔ)義不重復(fù)”指的是:從功能上來(lái)看,這兩個(gè)函數(shù)干的是完全不重復(fù)的兩件事情,一個(gè)是校驗(yàn)用戶名,另一個(gè)是校驗(yàn)密碼。盡管在目前的設(shè)計(jì)中,兩個(gè)校驗(yàn)邏輯是完全一樣的,但如果按照第二種寫法,將兩個(gè)函數(shù)的合并,那就會(huì)存在潛在的問(wèn)題。在未來(lái)的某一天,如果我們修改了密碼的校驗(yàn)邏輯,那這個(gè)時(shí)候,isValidUserName() 和 isValidPassword() 的實(shí)現(xiàn)邏輯就會(huì)不相同。我們就要把合并后的函數(shù),重新拆成合并前的那兩個(gè)函數(shù)。

對(duì)于包含重復(fù)代碼的問(wèn)題,我們可以通過(guò)抽象成更細(xì)粒度函數(shù)的方式來(lái)解決。

2. 功能語(yǔ)義重復(fù):

在同一個(gè)項(xiàng)目代碼中有下面兩個(gè)函數(shù):isValidIp() 和 checkIfIpValid()。盡管兩個(gè)函數(shù)的命名不同,實(shí)現(xiàn)邏輯不同,但功能是相同的,都是用來(lái)判定 IP 地址是否合法的。

func isValidIp(ipAddress string) bool {
    // ... 正則表達(dá)式判斷
}

func checkIfIpValid(ipAddress string) bool {
    // ... 字符串方式判斷
}

在這個(gè)例子中,盡管兩段代碼的實(shí)現(xiàn)邏輯不重復(fù),但語(yǔ)義重復(fù),也就是功能重復(fù),我們認(rèn)為它違反了 DRY 原則。我們應(yīng)該在項(xiàng)目中,統(tǒng)一一種實(shí)現(xiàn)思路,所有用到判斷 IP 地址是否合法的地方,都統(tǒng)一調(diào)用同一個(gè)函數(shù)。

3. 代碼執(zhí)行重復(fù):

type UserService struct {
    userRepo UserRepo
}

func (us *UserService) login(email, password string) {
    existed := us.userRepo.checkIfUserExisted(email, password)
    if !existed {
        // ...
    }
    user := us.userRepo.getUserByEmail(email)
}

type UserRepo struct{}

func (ur *UserRepo) checkIfUserExisted(email, password string) bool {
    if !ur.isValidEmail(email) {
        // ...
    }
}

func (ur *UserRepo) getUserByEmail(email string) User {
    if !ur.isValidEmail(email) {
        // ...
    }
}

上面這段代碼,既沒(méi)有邏輯重復(fù),也沒(méi)有語(yǔ)義重復(fù),但仍然違反了 DRY 原則。這是因?yàn)榇a中存在“執(zhí)行重復(fù)”。這個(gè)問(wèn)題解決起來(lái)比較簡(jiǎn)單,我們只需要將校驗(yàn)邏輯從 UserRepo 中移除,統(tǒng)一放到 UserService 中就可以了。

4. 如何提高代碼復(fù)用性?

  • 減少代碼耦合;
  • 滿足單一職責(zé)原則;
  • 模塊化業(yè)務(wù)與非業(yè)務(wù)邏輯分離;
  • 通用代碼下沉;
  • 繼承、多態(tài)、抽象、封裝;
  • 應(yīng)用模板等設(shè)計(jì)模式。

下面是一個(gè)簡(jiǎn)單的人員管理系統(tǒng)示例,使用 DRY 原則來(lái)確保代碼的清晰和重用性:

package main

import"fmt"

// Person 結(jié)構(gòu)體表示人員信息
type Person struct {
    Name string
    Age  int
}

// PrintPersonInfo 打印人員信息
func PrintPersonInfo(p Person) {
    fmt.Printf("Name: %s, Age: %d\n", p.Name, p.Age)
}

func main() {
    // 創(chuàng)建兩個(gè)人員信息
    person1 := Person{Name: "Alice", Age: 30}
    person2 := Person{Name: "Bob", Age: 25}

    // 打印人員信息
    PrintPersonInfo(person1)
    PrintPersonInfo(person2)
}

在上述示例中,我們定義了一個(gè) Person 結(jié)構(gòu)體表示人員信息,以及一個(gè) PrintPersonInfo 函數(shù)用于打印人員信息。通過(guò)將打印人員信息的邏輯封裝在 PrintPersonInfo 函數(shù)中,遵循DRY原則,避免重復(fù)編寫打印邏輯,提高了代碼的復(fù)用性和可維護(hù)性。

三、LOD 原則

LOD原則(Law of Demeter),又稱為最少知識(shí)原則,旨在降低對(duì)象之間的耦合度,減少系統(tǒng)中各部分之間的依賴關(guān)系。LOD原則強(qiáng)調(diào)一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象了解得越少越好,不應(yīng)直接與陌生對(duì)象通信,而通過(guò)自己的成員進(jìn)行操作。

迪米特法則法則強(qiáng)調(diào)不該有直接依賴關(guān)系的類之間,不要有依賴;有依賴關(guān)系的類之間,盡量只依賴必要的接口。迪米特法則是希望減少類之間的耦合,讓類越獨(dú)立越好。每個(gè)類都應(yīng)該少了解系統(tǒng)的其他部分。一旦發(fā)生變化,需要了解這一變化的類就會(huì)比較少。

下面是一個(gè)使用LOD原則設(shè)計(jì)的簡(jiǎn)單用戶管理系統(tǒng)示例:

package main

import"fmt"

// UserService 用戶服務(wù),負(fù)責(zé)用戶管理
type UserService struct{}

// GetUserByID 根據(jù)用戶ID獲取用戶信息
func (us UserService) GetUserByID(id int) User {
    userRepo := UserRepository{}
    return userRepo.FindByID(id)
}

// UserRepository 用戶倉(cāng)庫(kù),負(fù)責(zé)用戶數(shù)據(jù)維護(hù)
type UserRepository struct{}

// FindByID 根據(jù)用戶ID查詢用戶信息
func (ur UserRepository) FindByID(id int) User {
    // 模擬從數(shù)據(jù)庫(kù)中查詢用戶信息
    return User{id, "Alice"}
}

// User 用戶結(jié)構(gòu)
type User struct {
    ID   int
    Name string
}

func main() {
    userService := UserService{}

    user := userService.GetUserByID(1)
    fmt.Printf("User ID: %d, Name: %s\n", user.ID, user.Name)
}

在上述示例中,我們?cè)O(shè)計(jì)了一個(gè)簡(jiǎn)單的用戶管理系統(tǒng),包括 UserService 用戶服務(wù)和 UserRepository 用戶倉(cāng)庫(kù)兩個(gè)部分。UserService 通過(guò)調(diào)用 UserRepository 來(lái)查詢用戶信息,遵循了LOD原則中只與直接的朋友通信的要求。

責(zé)任編輯:趙寧寧 來(lái)源: 令飛編程
相關(guān)推薦

2022-12-30 08:16:34

2020-02-05 09:13:43

編程開(kāi)發(fā)編碼

2024-10-30 15:42:39

2009-03-05 13:47:59

2023-05-26 08:19:04

2016-03-29 09:59:11

JavaScriptAPI設(shè)計(jì)

2012-03-15 11:15:13

Java設(shè)計(jì)模式

2013-04-17 10:46:54

面向?qū)ο?/a>

2012-05-08 10:14:45

設(shè)計(jì)原則

2012-03-05 13:58:34

設(shè)計(jì)模式里氏置換

2012-03-07 10:40:19

Java設(shè)計(jì)模式

2012-03-07 11:03:13

Java設(shè)計(jì)模式

2010-10-11 11:25:26

MySQL主鍵

2012-06-07 10:11:01

面向?qū)ο?/a>設(shè)計(jì)原則Java

2017-06-19 14:21:01

JavaScriptAPI設(shè)計(jì)原則

2011-06-01 10:58:57

2012-03-08 10:57:00

Java設(shè)計(jì)模式

2013-06-09 11:04:07

設(shè)計(jì)扁平化設(shè)計(jì)平面化設(shè)計(jì)

2009-07-17 17:25:31

敏捷開(kāi)發(fā)

2014-05-04 11:06:41

移動(dòng)網(wǎng)站移動(dòng)設(shè)計(jì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)