iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 26
1
Modern Web

從無到有,使用 Go 開發應用程式系列 第 26

Refactoring Name Provider

前面 25 天,我們已經成功寫出了一個 CLI App 以及 Web App ,包括交付與佈署都有實作,這次鐵人賽主題的基本要求已經算達標了。

剩下五天的目標將會是改善這個程式,無論是功能上的改進或是重構

首先有一個問題非常明顯:台灣人的名通常都是兩個字,我們必須保留一點彈性在字數調整上。

分析

這個問題一直拖著沒改,其實是因為要先重構原本的程式碼,才會好動工。

原本的 provider/name.go 的程式碼片段如下:

func (generator *Generator) LastName() string {
	length := len(generator.Resource.LastNames)
	randomIndex := generator.rand.Intn(length)

	return generator.Resource.LastNames[randomIndex]
}

func (generator *Generator) FirstName() string {
	merge := append(generator.Resource.CharacterMale, generator.Resource.CharacterFemale...)
	length := len(merge)
	randomIndex := generator.rand.Intn(length)

	return merge[randomIndex]
}

我們可以發現, LastNameFirstName 有一個模式是一樣的:在某個 collection 裡面隨便取一筆資料。

因此第一步可以先把這個行為抽出,寫成另一個函式 pickCharacter

func (generator *Generator) LastName() string {
	return generator.pickCharacter(generator.Resource.LastNames)
}

func (generator *Generator) FirstName() string {
	merge := append(generator.Resource.CharacterMale, generator.Resource.CharacterFemale...)

	return generator.pickCharacter(merge)
}

func (generator *Generator) pickCharacter(collection []string) string {
	length := len(collection)
	randomIndex := generator.rand.Intn(length)

	return collection[randomIndex]
}

再來,台灣人的名大部分是兩個字,但姓和單名會是一個字。或許 pickCharacter 多一個參數來決定要取幾個字會是個好選擇。先把參數加進去試看看:

func (generator *Generator) LastName() string {
	return generator.pickCharacter(generator.Resource.LastNames, 1)
}

func (generator *Generator) FirstName() string {
	merge := append(generator.Resource.CharacterMale, generator.Resource.CharacterFemale...)

	return generator.pickCharacter(merge, 2)
}

func (generator *Generator) pickCharacter(collection []string, count int) (chars string) {
	length := len(collection)

	for i := 0; i < count; i++ {
		randomIndex := generator.rand.Intn(length)
		chars = chars + collection[randomIndex]
	}

	return chars
}

接著要開放這個數字讓外界可以呼叫,才會有實際的價值,這裡的做法是先把原本的 FirstName 改名為 firstName 並加入 count 參數,接著開出三個接口 FirstNameFirstNameSingleFirstNameDouble

func (generator *Generator) FirstName() string {
	return generator.firstName(generator.rand.Intn(2) + 1)
}

func (generator *Generator) FirstNameSingle() string {
	return generator.firstName(1)
}

func (generator *Generator) FirstNameDouble() string {
	return generator.firstName(2)
}

func (generator *Generator) firstName(count int) string {
	merge := append(generator.Resource.CharacterMale, generator.Resource.CharacterFemale...)

	return generator.pickCharacter(merge, count)
}

原本的 Name 函式行為改成會亂數取單名與複名。如果要指定單名或複名的話,我們必須再加開兩個函式 NameSingleNameDouble

func (generator *Generator) NameSingle() string {
	return generator.LastName() + generator.FirstNameSingle()
}

func (generator *Generator) NameDouble() string {
	return generator.LastName() + generator.FirstNameDouble()
}

指令也需要重構,明天再針對指令做調整。

展示

$ go run main.go generate
Generate 10
楊志雅
劉明志
張家豪
趙春
趙志婷
王春春
劉志
趙嬌家
李志
王婷

程式碼可以參考 PR Day 26

參考資料


上一篇
Docker
下一篇
Refactoring Command
系列文
從無到有,使用 Go 開發應用程式30

尚未有邦友留言

立即登入留言