Streamlit中級者に提案したいディレクトリ構成

# はじめに
みなさんの開発現場でもアジャイル開発が採用されていますか？</br>
AIを活用したアプリのプロトを迅速に開発するシーンにおいて、大規模開発を伴わない場合　**streamlit**の採用は多いのかと思われます。</br>

一方、streamlitを用いることで**単一的なデザイン**のアプリになってしまう悩みを持たれていないでしょうか。</br>
また、中規模で開発する場合、**保守性を考慮した設計**にしたいとお考えではないでしょうか。

https://streamlit.io/

# 対象読者
- streamlitのデザインに飽きが来ているエンジニア
- 人とは違うstreamlitのアプリを作りたいエンジニア
- 保守性を考慮したディレクトリ構成を考えたいエンジニア

# 成果物
追記: このテンプレートを活用した株価分析アプリを "share.streamlit.io"にデプロイしています。
https://stockprice-imaima.streamlit.app/


↓イメージ
![output-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/892674/0b0d0bb1-fbc2-9655-e0ea-76ac89235ba9.png)

https://github.com/akihiko-ima/streamlit-sidebar-template

# ディレクトリ戦略
React(Next.js)の開発経験を元にstreamlitにおいても関数コンポーネントと関数(services)を分離する構成を選択しました。気になる点がありましたら、コメントでお知らせください:grinning:

- (\*) 要変更

```bash
    streamlit-sidebar-template/
    ├── .streamlit/                  # streamlit標準config
    │   └── config.toml
    ├── components/                  # (*) UIコンポーネント (サイドコンポーネント以外に追加も可能)
    │   └── sidebar_component.py
    ├── router/                      # ルーティング
    │   ├── __init__
    │   └── router.py
    ├── services/                    # (*) 横断的な汎用関数
    │   └── get_data.py
    ├── views/　　　                  # (*) 関数コンポーネント (React / Nextjsで採用されている構成)
    │   ├── __init__.py
    │   ├── first_page.py
    │   ├── second_page.py
    │   └── third_page.py
    ├── app.py                        # エントリポイント
    ├── config.py　　　　　　　　　　　 # (*) ルーティング設定
    └── global.css                    # サイドコンポーネント
```
## components/
- streamlit-on-Hover-tabsのサイドバーコンポーネントを配備

## services/ 
- 横断的な汎用関数を格納します
- DBアクセス、authなどの機能に応じて、配下にディレクトリを追加する選択もありかと思います。
```
    services/              # (*) 横断的な汎用関数
    ├── database/
    │   ├── database.py
    │   └── models.py
    └── auth/
        ├── sign_in.py
        └── sign_up.py
```
## views/
- ページごとに一つの.pyファイルを構成して配備

## config.py　
:::note info
このディレクトリ構成の中で最も重要なファイルとなります。
:::
```config.py
    from dataclasses import dataclass
    from typing import Dict, Callable
    
    # import your streamlit page
    from views import first_page, second_page, third_page
    
    
    @dataclass
    class RouterMapping:
        routing_name: str
        icon: str
        streamlit_page: Callable[[], None]
    
    
    # router mapping
    """
    ・If you have any pages you would like to route, please add them here.
    ・The icons in the sidebar use "Google Fonts."
     [https://fonts.google.com/icons](https://fonts.google.com/icons)
    """
    routers: Dict[str, RouterMapping] = {
        "router_1": RouterMapping(routing_name="first", icon="home", streamlit_page=first_page),
        "router_2": RouterMapping(routing_name="second", icon="rocket_launch", streamlit_page=second_page),
        "router_3": RouterMapping(routing_name="third", icon="login", streamlit_page=third_page),
    }
```
- routers: 辞書型 (Dict[str, RouterMapping]) となります。キーとなる"router_1"、routing_nameは**ユニークな値**にしてください。
- icon: Google Fonts / iconsから使用したいアイコンを選択してください。</br>
[https://fonts.google.com/icons](https://fonts.google.com/icons)
- streamlit_page: **views/** ディレクトリに保存した関数を呼び出すようにしてください。

## 思い
streamlitの採用事例が増え、よりstreamlitの開発が進展することを期待しています。

# 参考
https://github.com/Socvest/streamlit-on-Hover-tabs