7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

あなたの名付けた冗長な関数名について

Posted at

スーパー忙しい人向け

use config::config_file_path;

let path = config_file_path();

より

use config;

let path = config::file_path();

の方がいいよね

はじめに

タイトルは強い言葉を使っただけです。
刺さった人はぜひこの先をどうぞ。

どんな冗長であるコードが生まれたか

// ファイル分割をmodule blockで表現
// 実際は非推奨
mod paths {
    use std::path::PathBuf;

    // appそのものが配置されるディレクトリのパスを返す
    fn app_local_dir_path() -> Option<PathBuf> {
        ...
    }

    // appのconfigが配置されるディレクトリのパスを返す
    fn app_config_dir_path() -> Option<PathBuf> {
        ...
    }
}

mod main {
    use crate::paths::app_local_dir_path;
    use crate::paths::app_config_dir_path;
    use crate::config::config_init;
    use crate::app::launch_app_from_local;

    fn main() {
        // 細かい部分は省略

        // 冗長なコード!
        let config_dir = app_config_dir_path().unwrap();

        // appのコンフィグを初期化する関数のつもり
        config_init(config_dir);

        // 冗長なコード!
        let dir_path = app_local_dir_path().unwrap();

        // appをlocalから起動する関数のつもり
        launch_app_from_local(dir_path);
    }
}

私が過去に見てあまりの酷さに頭を抱えたコードです。(一般化済み & コメントは後付け)
このコードは当時動いてこそいましたが文字量で全体的にコードが読みにくくなっていた印象を受けました。

そうなった理由を挙げると、

  • use句の多さ
  • 関数の目的と処理を明確にしたいがあまり長い名前になっている

等があります。

pathsのみを例として提示しましたが、appconfigの中身も同様であったと記憶しています。


理由として挙げた二つのうち、前者は規模が大きくなるにつれて避けられないリスクではあります。
ですが、避けられないリスクであるならば出来る限り軽減するべきだと私は思っています。

理由として挙げた際は"多さ"とだけ表現しましたが、もう少し正確に表現するならばそれはuseする対象が関数であること、そしてその関数名が冗長なものでありファイルの上部を圧迫していることが理由であると言えます。
use句自体はファイルの上部に固めて記述するのがスタンダードであり、それが圧迫されるのはファイルの可視性に問題が生じているということでしょう。

では、どうやって軽減するか。
それは単純に不要なuse句を削除してファイル上部をコンパクトにすることです。

単純に削除とは言ってもその結果コンパイルが通らなくなっても問題なので、適宜修正する必要もあります。

修正後
use crate::{paths, config, app};

fn main() {
    // 細かい部分は省略

    // まだもう少し冗長なコード
    let config_dir = paths::app_config_dir_path().unwrap();

    // 冗長なコード
    config::config_init(config_dir);

    // まだもう少し冗長なコード
    let dir_path = paths::app_local_dir_path().unwrap();

    // 冗長なコード
    app::launch_app_from_local(dir_path);
}

どうでしょうか。
関数の呼び出しをmodule::funcの形式にすることでuse句を大幅に削減することが出来ました。
そして、形式を変更したことで新たに冗長な部分が見えてきたと思います。


冗長な理由として挙げたことの後者、

関数の目的と処理を明確にしたいがあまり長い名前になっている

です。

例を挙げると、config::config_initapp::launch_app_from_local同じ語句が二度使われていて冗長に感じることでしょう。
そして、形式を変更した以上その部分を削ることが出来ます。

修正後その2
use crate::{paths, config, app};

fn main() {
    // 細かい部分は省略

    // まだもう少し冗長なコード
    let config_dir = paths::app_config_dir_path().unwrap();

    // config_initから名称を変更
    config::init(config_dir);

    // まだもう少し冗長なコード
    let dir_path = paths::app_local_dir_path().unwrap();

    // launch_app_from_localから名称を変更
    app::launch_from_local(dir_path);
}

ですが、この修正例ではpathsに存在する関数を修正していません。
何故ならpathsそれそのものが冗長であるからです。


pathsそのものが冗長とはどういうことでしょうか。

そのことについて説明するためにはファイルの分割方法について多少知っておく必要があります。
上記の例ではmainconfigapppathsと四つにファイルが分割されています。
このうち、mainconfigappはそれぞれ単一の存在に対して作成され、関係しているファイルであると捉えることが出来ます。

ですが、pathsは各ファイルパスを返すという共通点がある関数の集合でしかなく、端的に表現するとこれは直接的な関係の無いものを似ているからというだけの理由で集めたものになります。
決してこの形態のファイルが悪であると断ずることは出来ませんが、その場合はmiscなどの名称として関係の無いものを集めたと明言した方がより正しいとは言えるであろうと考えています。

そして、そのような名称に変更せずとも大抵の場合はより良い位置に配置し直すことで解決すると共に冗長さも解決することが出来ます。

この場合、app_config_dir_pathconfigに、app_local_dir_pathappに再配置することでpaths自体を削除し、名称もそれに合わせて変更することで冗長さを排除することが出来ます。

修正後その3
use crate::{config, app};

fn main() {
    // 細かい部分は省略

    // app_config_dir_pathから名称を変更
    let config_dir = config::dir_path().unwrap();

    config::init(config_dir);

    // app_local_dir_pathから名称を変更
    let dir_path = app::local_dir_path().unwrap();

    app::launch_from_local(dir_path);
}
7
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?