
できるだけ同じ処理は関数化したほうが良いと言いますが、間に非共通のソースがある場合も関数化しますか?
例えば下記のような場合は2つ共通の部分のみ関数化して2つの関数を呼ばないといけないですよね。
共通
非共通
共通
非共通
共通
逆にややこしくて管理しにくいように感じるのですが、これでも無理に関数化すべきなのでしょうか?
また、そうだったとしても共通のソースが5行以上であればまだわかるのですが、3行以内の場合はどうでしょうか?
それくらいなら全く同じ処理でもさすがにコピペしますか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答5件
0
ぶっちゃけTPOです。
コードは、機械が逐次処理をしていく命令文の羅列であると同時に、人間が読んで修正するべき文章です。
この後者の部分は意識してください。
質問文の共通、非共通と並んでいる箇所ですが、
文章として読んだ時にそれが最も自然でシンプルなあるべき姿なのでしょうか?
もしYesと言い切れるのなら変える必要はありません。
ですが……そのコードは自然でシンプルなのですか?本当に?何を根拠に言ってるの?
こういう風に詰められるとだんだん不安になってきますね。
どうすれば良いかの勘所はリーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニックという書籍を読めば身につきます。
どんなにロジカル人のコードでもこれを読んでない人のコードは品質がバラツキます。
この書籍を読んだ人のコードはとても読みやすく、共通部品を取り出すとはなんなのかが分かりますので、長いエンジニア人生で一番役に立つ書籍となるだろうと言っても過言ではありません。
ただし序盤はともかく終盤は難解ですので、まずは読める範囲までで良いので繰り返し読んでくださいね。
さて、上記前提を元に今回の質問文を更に掘り下げていきます。
質問文を見返すと、「共通・非共通・共通・非共通・共通」となってますね。
1行1行の処理に着目しすぎのように思えます。
オブジェクト指向プログラミングで解決出来そうなので、
少しチュートリアル的なモノを次の章で記載します。
まず、オブジェクト指向に限らず、プログラミングに於いては以下の流れを守ってください。
- 入力(必要な情報の収集) + 加工(入力値を処理しやすくする)
- 処理
- 出力(結果を画面なりファイルなりへ書き出す)
この一連の流れは全てが終わるまで、絶対に次へ行かないでください。
質問文のコードが「共通・非共通・共通・非共通・共通」の流れになってしまうのは、
殆どのケースに於いて1→3の流れを守れずに小出しにしているからです。
また「少しの情報を受け取って処理することを繰り返す」のも、
「全ての情報を受け取ってまとめて処理する」のも全体的な処理時間は変わりません。
例外が出たらその時はその時で悩んでください。
次にコードに対して大まかな名前を付けてください。
まずゴール(あるべき姿)はなんですか?そのまま名称にして、クラス名や関数名として利用できます。
達成条件も箇条書きにしてください。
これらの達成条件も個別に関数名やクラスのメソッド名等に使えます。
また、達成条件は「どんなケースでも達成しなければならないのでしょうか?」
「スイッチをONにした時だけ達成出来れば良いのですか?」なども予め考えて置くと捗ります。
ここでやってオブジェクト指向プログラミングのターンです。
情報の収集・加工が済んだら処理に必要なデータを、クラスに投げ込んでインスタンスを作ってください。
別の処理を挟みたいなら、オプショナルな条件のメソッドを用意してONにするようにしてください。
全てのデータを投げ込み終わったら、作ったインスタンスのstartメソッドを叩いて結果を待ちましょう。
この流れで統一するようにすれば、
何をまとめられそうか、何をまとめるのが無理そうかが一目で区別出来るようになってきます。
最初は何千行もの神クラスを作り込んだりして酷いコードになると思います。
オブジェクト指向プログラミングの腕が上がってくれば、比例して読みやすく抽象化された素晴らしいコードが書けるようになるはずです。
例えばDIコンテナという、ある程度の情報を格納しておいたインスタンスをプロパティとして保存するテクニックがあります。
これ使えればかっこいいプログラミングが出来るようになりますよ。
ファイルの出力先を覚えこませたロガーとか、MySQLのサーバーに接続済みのコネクションとか…
DIコンテナを駆使すれば移譲するという手が使えるようになるので、
計算を実行するクラスがMySQLサーバーに接続しにいって、ログファイルを決め打ちのパスに書き出し始めるといった
「私って○○の目的で作られたなのに、別のおまじないばかり…なにやってんだろ?」というケースを回避出来るようになります。
オブジェクト指向で良い本は思いつきませんでした。
色んなサイトを見たりコードを書いた後にオブジェクト指向と10年戦ってわかったこと - Qiitaの記事を読んでください。
記事のカプセル化の項目に「正しい名前をつけることが大切」と語られていますが、オブジェクト指向プログラミングをする上で、リーダブルコードの知識は確実に活きます。
少し長くなりましたが以上です。何かしら役に立てば幸いです。
投稿2018/02/18 04:50
編集2018/02/18 05:20総合スコア21400
0
文脈的に少し外れた内容かもしれませんが・・・
DRY(Don't Repeat Yourself)でヒットするいくつかのページを眺めてみることも有用な気がしました。例えば
など、「どんなとき良くて、どんなとき良くないか」について考えさせられます。
前者の記事は「コードの重複じゃなく設計の重複を避けるのが本質」とか「共通化により結合度が不当に高くなる危険がある」という点が有用と感じました。後者の記事は「共通化によるコストと共通化しないことによるコストを天秤にかけて選択しよう」みたいなことが書いてありますが
- その判断をなるべく的確にしたいところだがそれは単純ではなさそう
- でもそういう点を意識しておくことは有用なはず
みたいなことを思いました。きっと経験あるプログラマーの方は「より明確な自分自信のポリシー」をお持ちではないかと思います。
残念ながらナンチャッテアマチュアプログラマーの自分は普段から間違った判断をしまくりな気がします。ともすれば共通化をやりすぎてしまうのです。その是非は設計中は気づけないことが多いのですが時間が経ってから見直すと気づくことがままあります。変に共通化しすぎて全然わかりやすくない(変更がやりにくい)と感じることもあれば、適度に分かり易くなっていると感じることもあります。
投稿2018/02/18 03:40
編集2018/02/18 03:41総合スコア18404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。


0
ベストアンサー
具体的なソースを見て判断すべき問題ですがほとんどの場合は、
分離できスッキリ書くことができます。
とは言え処理が同じ場合よりも、意味合いが同じ場合に共通化をする必要があります。(意味合いが同じ場合おのずと同じ処理になることが多い程度に考えた方が良いです。)逆に意味合いが遠いので、共通化する必要がない場合もあります。
場合によっては関数を引数に持たせることで対応は可能ですが、何らかのクラスの導入をすれば解決できる場合がほどんどです。
非共通の処理は共通の処理の前処理か後処理の場合がほどんどです。(”処理”多すぎ・・・)
その場合は、非共通の処理をしているのは、サブクラスとして定義した方が良いかもしれません。
もし、前処理でも後処理でもない場合は、移動か可能か別のメソッドで処理すべきものである可能性が高いです。
投稿2018/02/18 11:49
総合スコア2884
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2018/02/19 02:48

退会済みユーザー
2018/02/19 04:13

0
具体的にどうするのかは場合によって違うと思いますが、ラムダ式でうまくいくかもしれません。
投稿2018/02/18 02:48
総合スコア28673
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2018/02/18 09:15

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/02/18 09:18
2018/02/18 09:39
2018/02/18 09:47
退会済みユーザー
2018/02/18 12:19