Skip to content

Commit 8f18db0

Browse files
massongitclaudeGoryudyuma
authored
lib/ameshのリファクタリング: 循環的複雑度とコード重複の削減 (#227)
* lib/ameshのリファクタリング: 循環的複雑度とコード重複の削減 ParseLocationWithClient関数の循環的複雑度削減のため関数分割: - parseCoordinates: 座標文字列の直接解析 - geocodePlace: ジオコーディングAPI呼び出し - parseGeocodeResponse: ジオコーディングレスポンス解析 HTTPリクエスト処理の重複コード削減: - executeAndReadResponse関数を新規追加 - geocodePlaceとmakeHTTPRequestで共通利用 - jscpdエラーを解消(重複率0.37% → 0%) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * 公開メソッドを公開メソッドエリアに移動 ParseLocation関数とGenerateFileName関数を非公開メソッドエリアから 公開メソッドエリアに移動し、ファイル構成を整理 * 関数の並び順を依存関係に基づいて整理 geocodePlace関数を、それが呼び出すヘルパー関数 (executeAndReadResponse、parseGeocodeResponse)の後に移動し、 関数の依存関係を明確化 * 元のerrも保持した上でWrapする Co-authored-by: Goryudyuma(Kei.Matsumoto) <6211370+Goryudyuma@users.noreply.github.com> * parseCoordinates関数のエラー変数名を統一 レビューコメントに対応し、err1、err2をerrに統一することで 意味のない変数名を排除し、可読性を向上させた。 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Goryudyuma(Kei.Matsumoto) <6211370+Goryudyuma@users.noreply.github.com>
1 parent 9d9807f commit 8f18db0

File tree

1 file changed

+82
-45
lines changed

1 file changed

+82
-45
lines changed

lib/amesh/amesh.go

Lines changed: 82 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -253,36 +253,66 @@ func ParseLocationWithClient(ctx context.Context, req *ParseLocationWithClientPa
253253
return nil, lib.ErrParamsNil
254254
}
255255
// 座標が直接提供されているかチェック
256-
parts := strings.Fields(req.GeocodeRequest.Place)
257-
if len(parts) == 2 {
258-
if parsedLat, err1 := parseFloat64(parts[0]); err1 == nil {
259-
if parsedLng, err2 := parseFloat64(parts[1]); err2 == nil {
260-
return &Location{
261-
Lat: parsedLat,
262-
Lng: parsedLng,
263-
PlaceName: fmt.Sprintf("%.2f,%.2f", parsedLat, parsedLng),
264-
}, nil
265-
}
256+
location, err := parseCoordinates(req.GeocodeRequest.Place)
257+
if err != nil {
258+
// 地名をジオコーディング
259+
var err2 error
260+
location, err2 = geocodePlace(ctx, req)
261+
if err2 != nil {
262+
return nil, errors.Wrap(errors.Join(err, err2), "Failed to geocodePlace")
266263
}
267264
}
268265

269-
// 地名をジオコーディング
270-
place := req.GeocodeRequest.Place
271-
if place == "" {
272-
place = "東京"
273-
}
266+
return location, nil
267+
}
274268

275-
requestURL := fmt.Sprintf(
276-
"https://map.yahooapis.jp/geocode/V1/geoCoder?appid=%s&query=%s&output=json",
277-
req.GeocodeRequest.APIKey,
278-
url.QueryEscape(place),
269+
// ParseLocation 地名文字列から位置を解析し、Location構造体とエラーを返す
270+
func ParseLocation(ctx context.Context, place, apiKey string) (*Location, error) {
271+
return ParseLocationWithClient(ctx, &ParseLocationWithClientParams{
272+
Client: http.DefaultClient,
273+
GeocodeRequest: GeocodeRequest{
274+
Place: place,
275+
APIKey: apiKey,
276+
},
277+
})
278+
}
279+
280+
// GenerateFileName 位置情報からamesh画像のファイル名を生成する
281+
func GenerateFileName(location *Location) string {
282+
return fmt.Sprintf(
283+
"amesh_%s_%d.png",
284+
strings.ReplaceAll(location.PlaceName, " ", "_"),
285+
time.Now().Unix(),
279286
)
287+
}
280288

281-
httpReq, err := http.NewRequestWithContext(ctx, "GET", requestURL, nil)
289+
// parseCoordinates 文字列から座標を直接解析する
290+
func parseCoordinates(place string) (*Location, error) {
291+
parts := strings.Fields(place)
292+
if len(parts) != 2 {
293+
return nil, errors.New("not a coordinate pair")
294+
}
295+
296+
parsedLat, err := parseFloat64(parts[0])
282297
if err != nil {
283-
return nil, errors.Wrap(err, "Failed to http.NewRequestWithContext")
298+
return nil, errors.Wrap(err, "Failed to parseFloat64")
284299
}
285-
resp, err := httpclient.ExecuteHTTPRequest(req.Client, httpReq)
300+
301+
parsedLng, err := parseFloat64(parts[1])
302+
if err != nil {
303+
return nil, errors.Wrap(err, "Failed to parseFloat64")
304+
}
305+
306+
return &Location{
307+
Lat: parsedLat,
308+
Lng: parsedLng,
309+
PlaceName: fmt.Sprintf("%.2f,%.2f", parsedLat, parsedLng),
310+
}, nil
311+
}
312+
313+
// executeAndReadResponse HTTPリクエストを実行してレスポンスボディを読み込む
314+
func executeAndReadResponse(client *http.Client, req *http.Request) ([]byte, error) {
315+
resp, err := httpclient.ExecuteHTTPRequest(client, req)
286316
if err != nil {
287317
return nil, errors.Wrap(err, "Failed to httpclient.ExecuteHTTPRequest")
288318
}
@@ -292,6 +322,11 @@ func ParseLocationWithClient(ctx context.Context, req *ParseLocationWithClientPa
292322
return nil, errors.Wrap(err, "Failed to handleHTTPResponse")
293323
}
294324

325+
return body, nil
326+
}
327+
328+
// parseGeocodeResponse ジオコーディングAPIのレスポンスを解析する
329+
func parseGeocodeResponse(body []byte, place string) (*Location, error) {
295330
var result struct {
296331
Feature []struct {
297332
Name string `json:"Name"`
@@ -332,24 +367,30 @@ func ParseLocationWithClient(ctx context.Context, req *ParseLocationWithClientPa
332367
}, nil
333368
}
334369

335-
// ParseLocation 地名文字列から位置を解析し、Location構造体とエラーを返す
336-
func ParseLocation(ctx context.Context, place, apiKey string) (*Location, error) {
337-
return ParseLocationWithClient(ctx, &ParseLocationWithClientParams{
338-
Client: http.DefaultClient,
339-
GeocodeRequest: GeocodeRequest{
340-
Place: place,
341-
APIKey: apiKey,
342-
},
343-
})
344-
}
370+
// geocodePlace 地名をジオコーディングして位置情報を取得する
371+
func geocodePlace(ctx context.Context, req *ParseLocationWithClientParams) (*Location, error) {
372+
place := req.GeocodeRequest.Place
373+
if place == "" {
374+
place = "東京"
375+
}
345376

346-
// GenerateFileName 位置情報からamesh画像のファイル名を生成する
347-
func GenerateFileName(location *Location) string {
348-
return fmt.Sprintf(
349-
"amesh_%s_%d.png",
350-
strings.ReplaceAll(location.PlaceName, " ", "_"),
351-
time.Now().Unix(),
377+
requestURL := fmt.Sprintf(
378+
"https://map.yahooapis.jp/geocode/V1/geoCoder?appid=%s&query=%s&output=json",
379+
req.GeocodeRequest.APIKey,
380+
url.QueryEscape(place),
352381
)
382+
383+
httpReq, err := http.NewRequestWithContext(ctx, "GET", requestURL, nil)
384+
if err != nil {
385+
return nil, errors.Wrap(err, "Failed to http.NewRequestWithContext")
386+
}
387+
388+
body, err := executeAndReadResponse(req.Client, httpReq)
389+
if err != nil {
390+
return nil, errors.Wrap(err, "Failed to executeAndReadResponse")
391+
}
392+
393+
return parseGeocodeResponse(body, place)
353394
}
354395

355396
// deg2rad 度数をラジアンに変換する
@@ -536,18 +577,14 @@ func makeHTTPRequest(ctx context.Context, client *http.Client, url string) (*htt
536577
if err != nil {
537578
return nil, errors.Wrap(err, "Failed to http.NewRequestWithContext")
538579
}
539-
resp, err := httpclient.ExecuteHTTPRequest(client, req)
580+
581+
body, err := executeAndReadResponse(client, req)
540582
if err != nil {
541583
if errors.Is(err, httpclient.ErrHTTPRequestError) {
542584
return &httpRequestResult{Body: nil, IsEmpty: true}, nil
543585
}
544586

545-
return nil, errors.Wrap(err, "Failed to httpclient.ExecuteHTTPRequest")
546-
}
547-
548-
body, err := handleHTTPResponse(resp)
549-
if err != nil {
550-
return nil, errors.Wrap(err, "Failed to handleHTTPResponse")
587+
return nil, errors.Wrap(err, "Failed to executeAndReadResponse")
551588
}
552589

553590
return &httpRequestResult{Body: body, IsEmpty: false}, nil

0 commit comments

Comments
 (0)