今さらリーダブルコード

今さらながら、改めてリーダブルコードを読んだ。

https://www.amazon.co.jp/%E3%83%AA%E3%83%BC%E3%83%80%E3%83%96%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89-%E2%80%95%E3%82%88%E3%82%8A%E8%89%AF%E3%81%84%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AE%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%A7%E5%AE%9F%E8%B7%B5%E7%9A%84%E3%81%AA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-Theory-practice-Boswell/dp/4873115655

## 特に改めて意識したいと思ったこと

- 変数名
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/5571c141-e359-45cf-b55e-61f4e832d70d.png)

- 制御フロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/27add307-fbbf-4256-be2d-d2fb72eaf1b9.png)

- 無関係の下位問題の抽出
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/49c2c939-4bcf-4e51-8f17-f50f5b0117b6.png)

- きれいなインターフェース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/028a2483-54f8-4830-92f8-83f1ccb2224b.png)

- コードをより明確にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/62aec768-651f-4718-aecb-c9eb06807be6.png)



## 実践
少しだが、自分のアプリのコード(Flutter)を直してみた。

### 無関係の下位問題の抽出
- 一箇所目：リストの中の特定の項目の入れ替えは、アイテムの更新とは無関係な下位問題なので、別メソッドに切り出した。
AndroidStudioでは右クリックでrefactor > extractでできるので楽ちん。
before
```flutter
Future<void> updateItem(ListItemModel item) async {
    state = state.copyWith(
      items: [
        for (int i = 0; i < state.items!.length; i++)
          if (i == state.items!.indexOf(item)) item else state.items![i],
      ],
    );
    await state.update(item);
  }
```
after
```flutter
///アイテムの更新
  Future<void> updateItem(ListItemModel item) async {
    updateStateOfItem(item);
    await state.update(item);
  }

  ///アイテムの状態を更新
  void updateStateOfItem(ListItemModel item) {
    state = state.copyWith(
      items: [
        for (int i = 0; i < state.items!.length; i++)
          if (i == state.items!.indexOf(item)) item else state.items![i],
      ],
    );
  }

```


- 2箇所目
DBへ接続している部分と、リストの並べ替えを別メソッドにした。

before
```
///買い物リストを取得して返す
  Future<List<ListItemModel>> findShopList(String? listId) async {
    ///db接続設定
    FirebaseFirestore db = FirebaseFirestore.instance;
    final shoppingRef = db.collection(EnvSettings.xxx);

    List<ListItemModel> result = [];
    final QuerySnapshot snapshot =
        await shoppingRef.where('xxx', isEqualTo: xxx).get();

    final List<ListItemModel> items =
        snapshot.docs.map((DocumentSnapshot document) {
      ///jsonからオブジェクトに変換
      Map<String, dynamic> data = document.data() as Map<String, dynamic>;
      ListItemModel result =
          ListItemModel.fromJson(docId: document.id, json: data);
      return result;
    }).toList();

    ///お店・カテゴリ・名前順に並び替え
    if (AppUtils.isNotEmptyArray(items)) {
      items.sort((a, b) {
        int shopResult =
            Enum.compareByIndex(a.shop.getShop(), b.shop.getShop());
        if (shopResult != 0) return shopResult;
        int catResult = Enum.compareByIndex(a.category, b.category);
        if (catResult != 0) return catResult;
        return a.itemName.compareTo(b.itemName);
      });
    }
    result = items;
    return result;
  }
  ```
  after
  何をしているかぱっと見でわかりやすくなった、気がする。
  ```
/// 買い物リストを取得して返す
  Future<List<ListItemModel>> findShopList(String? listId) async {
    /// DBから買い物リストを取得
    ShoppingListRepository shoppingListRepository = ShoppingListRepository();
    List<ListItemModel> items =
        await shoppingListRepository.getItemList(listId: listId);

    /// お店・カテゴリ・名前順に並び替え
    List<ListItemModel> sortedItems = sortByShopCategoryName(items);

    return sortedItems;
  }
  ```

## おわり
改めて読むことで、以前よりも当たり前と思えていることが増えていてよかった。一方、上に記載したような、改めて意識したいと思えることもあったので今後に活かしたい。
それと、久しぶりにFlutterを触ったらやはり開発体験がよいと思った。