• 締切済み

プログラムの可読性が悪いです。対策は?

主にperlを使って、趣味で、プログラムを書いているのですが、処理を加える度、ifと行が増えて、気づけば、エディタ1ページ中に収まらず、非常に読みにくいプログラムになっています。 思いつきでも書きやすく、読みやすい、書き方or対策などはありますでしょうか? また、以前、プロのプログラマの方のPCスペックを見ると、弘法筆を選ばずと申しますか、ノートPCで解像度が低く、良く、あれだけの大きなプログラムが書けるなぁと感心したことがあります。 画面の大きさとプログラムの書き易さには差が無いのでしょうか? 私など、ゲームをするための24インチ(WUXGA)を使っていますが、1ページに表示できるプログラムの量が増えれば格段に作業しやすいのにと思っています。 何か、秘訣の様なものがあるのでしょうか? 以上、回答いただける点だけでも回答いただけると幸いです。 宜しくお願い致します。 #サンプル if($test = 1){  #300行くらい処理が続く  if($test1 = 1){   #300行くらい処理が続く  } }else{  #300行くらい処理が続く  if($test2 = 1){   #300行くらい処理が続く   if($test3 = 1){    #300行くらい処理が続く   }  } }

  • Perl
  • 回答数9
  • ありがとう数13

みんなの回答

回答No.9

1つのルーチンを20行程度にまとめられれば、小さな画面でも十分読む事が出来ると思います。 私も20インチのワイドディスプレイを縦型にして(90度傾けて)、高さ1650pxを確保していますが、 エディタのウインドウを分割すると800px以下になりますから、基本は小さな画面で読みやすい事ですね。 if($test == 1){   &do_test1(); # test1を実行する。というか、コメントが無くても「do test1」という言葉でわかるはず  if($test1 == 2){   &do_test2();  } } if($test == 1){   # test1を実行する   300行ぐらい続く   300行ぐらい続く   300行ぐらい続く  if($test1 == 2){   # test2を実行する   300行ぐらい続く   300行ぐらい続く   300行ぐらい続く  } } サンプルとは言え、ある程度きっちり書いておいた方が良いと思います。 クラス(パッケージ)化するのは、 人が見たときには「一定の処理をグループ化する」という意味では、サブルーチンと同じだと思います。 ローカル変数をグローバル変数の用に使える(サブルーチンに引数として渡す必要がない)、変数名の競合対策などとしてはかなり有効な手段だと思いますが、 見やすさという意味では、ほとんど変わらないと思います。

  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.8

そんな質問者氏には Damian Conway「Perl Best Practice」(オライリー) をお勧め. コードがきれいになってテクニックも身につくでしょう. Higher Order Perl もいいかもしれないけど, 日本語訳はありませんし,ちょっと難しいかも #最後の方の「パーサの作り方」とか「宣言的プログラム」とか #は圧巻なんだけどそれなりに難しい さて,分岐が増えてきて混乱するなら 「dispatch table」と呼ばれる連想配列の応用手法が 使えることがよくあります. 分岐先の処理内容そのものを隠蔽してしまうのです. %case={ 1 => sub{ }, # 1に応じた処理 2 => sub{ }, # 2に応じた処理 3 => sub{ }, # 3に応じた処理 } みたいに書いておいて,実際に処理する部分では $case{$test}->(引数) だけ. #これを発展させていくとPerlのオブジェクトで一般的な #「連想配列のbless」になったりする あとは「変数やサブルーチンの名前」を 意味を反映したわかりやすいものにすることも大事. 日本語のローマ字表記はあとで絶対に混乱する. 妙なスペルの省略はしない (省略するくらいなら,置換などを駆使して フルスペルで書く) 混乱しない程度にコメントを残しておくのも重要

回答No.7

サブルーチン化しても微妙だなーと思われるようであれば クラスにしてしまうという方法もあるようです。 詳しくは知らないんですが。 perlも今はオブジェクト指向なったんですよね? http://www.site-cooler.com/kwl/perl/10.htm クラスにしてしまえば プロパティを設定し、必要な場所で実行するだけという 実装部分を隠蔽したような書き方が出来ます。 通常の関数呼び出しでも引き数を与えて、動的な結果は得られるわけですけど、クラス化すると、より多彩な結果を返したり、継承を行うことで、重複するコードを書かずに、変更が必要な部分だけのコードを変更したり、追加したりできるわけです。 クラス内の実装部分では、自分が持つプロパティには自由にアクセスできるし、メソッド(関数)の呼び出しも自由に出来ます。 変数の初期化などは一箇所にまとめられ、実装部分は、提供する機能に集中した、的を絞ったコードを書けます。 よってシンプルになるはずなのです。 以下に良い例が載っているんですが http://www.site-cooler.com/kwl/perl/10.htm 実装部分に対して、実行部分は3行程度になっています。 参考までに。 継承 http://www.rfs.jp/sb/perl/04/03.html

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

「実際にどのように分割するか」は, もう本当に「処理を見てみないとわからない」世界です. でも, 基本的には「一言で説明できる範囲」で切っていくんじゃないかな. 「サブルーチン名」がたかだか数単語であることを考えると, それで説明できることが重要. 場合によっては「データの持ち方が適切でない」ということも考えられます. 余談ですが, if/unless/for (foreach)/while/until は式の後ろにつけて「その式だけが対象である」という意味にすることができます. if not = unless なので, return if not $a; と return unless $a; は同じ意味で, if (not $a) { return; } あるいは unless ($a) { return $a; } と同等です.

回答No.5

> 見たことが無い構文ですが、どういった意味になりますか? return if not $a は if (not $a) { return } と同じ意味です。 確かにググってもすぐに出てきませんね。おかしいな・・・ 自分は本で知ったんですが。 > VimやEmacsはまだ使ったことがありませんがお薦めでしょうか? VimやEmacsのいいところは拡張性じゃないでしょうか。 両方とも細かな挙動の設定や、欲しい機能を自由に追加・変更できたりします。 自分はVimを使っていますが、自分でプラグインを書いたりして機能を拡張しています。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

本当にこう書いたんだったら (ある意味) 尊敬するよ.... ふつうはサブルーチンを使うね. 300行もあったらその中には複数の機能ブロックがあるだろうから, それぞれをサブルーチンとして切り出す. 「1回しか実行しないものをサブルーチンにするのは変だ」というかもしれないけど, 個人的にはこの意見こそ変だと思う. 最近では「何らかの機能を持つコードブロックに名前を付けるのがサブルーチンの目的だ」というようにしてる. とはいえこの if文は明らかにおかしい. 以下余談: #3 の「視線の移動だけで見える範囲が広いか狭いかは、致命的な差がありますね」には同意するものの, 「15インチ QXGA」のノートPC を使ったりすると 24ドットではつらいのも事実. 36ドットだと, かなりいい感じ.

pevtone
質問者

補足

回答いただきありがとうございます。 全体のサイズが1MBくらいあるため、いつの間にかこんな風になっています。 また、よく使う機能と、時々使う機能は分けて、サブルーチンにしています。 サブルーチンかするという事は、こんな感じでしょうか? --------- #サンプル if($test = 1){  #300行くらい処理が続く  &suba();  if($test1 = 1){   #300行くらい処理が続く   &subb();  } }else{  #300行くらい処理が続く  &subc();  if($test2 = 1){   #300行くらい処理が続く   &subd();   if($test3 = 1){    #300行くらい処理が続く    &sube();   }  } } sub suba(){ 300行くらい処理が続く } sub subb(){ 300行くらい処理が続く } sub subc(){ 300行くらい処理が続く } sub subd(){ 300行くらい処理が続く } sub sube(){ 300行くらい処理が続く } --------- とした方が良いということでしょうか? ただ、この場合でも、1つのサブルーチンに、300行もしくは、それ以上あり、1ページ80行表示するディスプレイを使っているため、まだ、見づらく感じます。 かと言って、このサブルーチンを更に、分解すると、見づらくなりそうです。 どこまで分解して良いものか難しいです・・・ 何か、判断基準や、参考になる話などありますでしょうか?

  • zxcv0000
  • ベストアンサー率56% (111/196)
回答No.3

Perl は確かに 「Write only」とか言われます。 書く(プログラミングする)分には良いけど、過去に書いたものや他人が書いたものは読めたものじゃ無いと言う意味でしょう。 私も一理あるとは思います。 しかし、ご質問の件はそれとは別の問題の様ですね。 if の中身が長くなれば、else がでてきても何の if だったか判らないなんて事は、Perl に限らず多くのプログラミング言語に共通の問題です。 対策は、他の回答者さんと同じくサブルーチン化がお勧めです。 > 画面の大きさとプログラムの書き易さには差が無いのでしょうか? 人によって違うと思います。 私は質問者さんと同じで、画面中の文字数・行数は多ければ多い程良い派です。 視線の移動だけで見える範囲が広いか狭いかは、致命的な差がありますね。 一方で、表示文字数を犠牲にしても大きな文字が良いという人も実在します。 それはそれで、尊重しましょうね。

pevtone
質問者

補足

回答いただきありがとうございます。 よく使う機能と、時々使う機能は分けて、サブルーチンにしていますが、 サブルーチン化するという事は、こんな感じでしょうか? --------- #サンプル if($test = 1){  #300行くらい処理が続く  &suba();  if($test1 = 1){   #300行くらい処理が続く   &subb();  } }else{  #300行くらい処理が続く  &subc();  if($test2 = 1){   #300行くらい処理が続く   &subd();   if($test3 = 1){    #300行くらい処理が続く    &sube();   }  } } sub suba(){ 300行くらい処理が続く } sub subb(){ 300行くらい処理が続く } sub subc(){ 300行くらい処理が続く } sub subd(){ 300行くらい処理が続く } sub sube(){ 300行くらい処理が続く } --------- とした方が良いということでしょうか? ただ、この場合でも、1つのサブルーチンに、300行もしくは、それ以上あり、1ページ80行表示するディスプレイを使っているため、まだ、見づらく感じます。 かと言って、このサブルーチンを更に、分解すると、見づらくなりそうです。 どこまで分解して良いものか難しいです・・・ 何か、判断基準や、参考になる話などありますでしょうか? >大きなディスプレイは良いのですが、24インチより大きいものやディスプレイを縦にして使うと、視線の移動だけでもかなりの距離になり、ディスプレイ酔いしそうですし、細かい文字にするとかなり見づらくなります。 スキルの無さをハードで補っている感じ?ですが限界を感じているようなところがあります。 少ない情報量で書ける人は、プログラムの処理全体が頭の中に入っているんでしょうかね? 私も、できることなら、大きな文字で、見やすいプログラムを書きたいと思うのは山々なんですけどねぇ・・・

回答No.2

自分はif文のネストが多くなってきたなーと感じたら そこの処理をサブルーチン化して if ($a) { if ($b) { ... } } という文を return if not $a; return if not $b; ... という風に変えるとかしてますね。 でもだいたいネストしたif文の所の処理は 既にサブルーチン化してあるのでサブルーチンをわざわざ作ったりとか そういうことを気にすることは少ないような気がします。 ちなみにエディタはVimとかEmacsがおすすめじゃないでしょうか(Linuxでも使えるし 慣れるまで大変かもしれませんが...

pevtone
質問者

補足

回答いただきありがとうございます。 見たことが無い構文ですが、どういった意味になりますか? 少し、ググって見たのですが、いまいちよくわかりませんでした。 補足いただけると幸いです。 また、エディタについては、秀丸を使っています。 確かに、他のOSで使えるというのは良いですね。 VimやEmacsはまだ使ったことがありませんがお薦めでしょうか?

回答No.1

それぞれの処理をサブルーチンにすれば良いのではないですか。 http://www.kent-web.com/perl/chap8.html エディタも色々ありますよ。 ウィンドウを上下分割して、上と下で、同じファイルの別の場所を表示したり、同じファイルに対して、ウィンドウを複数出したり。

pevtone
質問者

補足

回答いただきありがとうございます。 よく使う機能と、時々使う機能は分けて、サブルーチンにしていますが、 サブルーチン化するという事は、こんな感じでしょうか? --------- #サンプル if($test = 1){  #300行くらい処理が続く  &suba();  if($test1 = 1){   #300行くらい処理が続く   &subb();  } }else{  #300行くらい処理が続く  &subc();  if($test2 = 1){   #300行くらい処理が続く   &subd();   if($test3 = 1){    #300行くらい処理が続く    &sube();   }  } } sub suba(){ 300行くらい処理が続く } sub subb(){ 300行くらい処理が続く } sub subc(){ 300行くらい処理が続く } sub subd(){ 300行くらい処理が続く } sub sube(){ 300行くらい処理が続く } --------- とした方が良いということでしょうか? ただ、この場合でも、1つのサブルーチンに、300行もしくは、それ以上あり、1ページ80行表示するディスプレイを使っているため、まだ、見づらく感じます。 かと言って、このサブルーチンを更に、分解すると、見づらくなりそうです。 どこまで分解して良いものか難しいです・・・ 何か、判断基準や、参考になる話などありますでしょうか?

関連するQ&A

  • プログラムの実行について

    os は windows php のバージョンは 5.2.11.11 です。 $logmax = file("test.txt"); $start = $logmax[count($logmax) - 1]; $start = trim($start); if ($start == "終了"){ $start = 1; } if (is_file("aaa.txt")){ $word = fopen("aaa.txt", "r"); for ($line = $start; !feof($word); $line++){ $lines = fgets($word); $lines = trim($lines); if ($lines){ 以下処理 } } } という感じの処理なのですが、三行目までは "test.txt" の最後の文字又は数字を抜き取る作業で 最初の if 関数はもし最後に "終了" ならば $start = 1 にするという感じです。 次の if 関数からが問題なのですが $start に 1 が入って "aaa.txt" の一行目からのスタートしてくれるのですが、 $start に 2 が入ってる場合は "aaa.txt" の二行目からスタートしたいのですが、 スタートしてくれず "aaa.txt" の一行目からスタートになってしまいます。 if 関数だとスタートが一行目からになってしまうのでしょうか?? それとも $lines = fgets($word); の所で "aaa.txt" の一行目からになっているのでしょうか?? 何が原因か分かる方がいましたらどうすればいいか教えてください。 宜しくお願いします

    • ベストアンサー
    • PHP
  • rubyの勉強をしていてプログラムを作っているのですがうまくいきません。

    rubyのプログラムを作っています。 指定したディレクトリの中の指定したファイルを検索します。 そしてファイルの有無を条件にして処理をしていくプログラムをつくっています。 イメージでは下記のような感じ if test.txtを検索(検索先のディレクトリは/../../tmp) #ファイル存在する なにもしない else #ファイルが存在しない test.txtを作成 処理1  test.txtを削除 end 日本語ばっかりで申し訳ないのですがこんな感じです。 今はifを使ったのですがそれ以外の方法でもかまいません。 できればサンプルのプログラムを載せていただけるとありがたいです。 ご教授をよろしくお願いします。 利用環境 Windows XP Home Edition cygwinをインストールしてrubyを実行しています

  • プログラムのイベント処理中断方法

    VB2008のイベンド中止処理についてお教え頂けませんでしょうか。 Formにボタンが1つあり、クリックするとCSVファイルが出力される処理をしたいです。 やりたい処理: 1. 「CSVファイル出力しますか?」というメッセージを出す。YESなら処理続行。Noなら処理中止。 2. CSVファイル出力処理。 3. 「CSVファイルを出力しました。」 (プログラム自体を終了したいわけではありません) VBAだと下記のようなコードを書きたいです。 Sub テスト() Dim ans As Integer ans = MsgBox("CSVファイル出力しますか?", vbYesNo, "テスト") If ans = vbNo Then end end if 'CSV出力処理~~~ end sub VBにendというステートメントがあれば、良いのですが無さそうです・・・ 何か上手な処理はあるでしょうか?VBAのコードになってしまいますが、下記のような処理方法しかないでしょうか? '''''''''''''''''1 Sub テスト() Dim ans As Integer ans = MsgBox("CSVファイル出力しますか?", vbYesNo, "テスト") If ans = vbNo Then end else 'CSV出力処理~~~ end if end sub ''''''''''''''''2 Sub テスト() Dim ans As Integer ans = MsgBox("CSVファイル出力しますか?", vbYesNo, "テスト") If ans = vbNo Then goto here end if 'CSV出力処理~~~ here: end sub

  • COBOLのプログラムで・・。

    現在COBOLプログラムを作ってまして以下のプログラムで表示結果が「EQUAL」となるようにしたいのですがどうやったらいいでしょうか?回答のほうよろしくお願いします、以下がプログラムです。 IDENTIFICATION DIVISION. PROGRAM-ID. TEST9. DATA DIVISION. * WORKING-STORAGE SECTION. * 01 GR01. 02 DATA1 PIC N(2). * 01 DATA2 PIC N(2). 02 SPACE TO DATA2 * PROCEDURE DIVISION. * MOVE SPACE TO GR01. * MOVE SPACE TO DATA2. IF DATA1 = DATA2 THEN DISPLAY "EQUAL" ELSE DISPLAY "NOT EQUAL" END-IF. * * STOP RUN. * END PROGRAM TEST9.

  • 良いプログラムを書くためには

    今回、プログラミングの上達方法に関してアドバイス頂きたく質問しました。 現在、ソフトウェア開発の仕事に就いていてCやJavaなどでプログラムを書いたりしています。主にCで書くことが多いです。与えられた課題に対して動くプログラムは作れるのですが、先輩などからプログラムが汚いとよく指摘されます。 指摘される事柄は色々ありますが、何点か挙げるとまずモジュール分割が上手く出来ていない。1000行位の動くプログラムを書き始められた頃は、共通の処理などの関数が分割されておらず、同じ処理がやたら多いなど、余計な処理が多くコードに無駄が多いと指摘されました。それを改善したところ、今度は無駄に関数の分割が多くなり、読みにくいなどの指摘を受けました。 その他にも、例えば関数の中で、for(条件式)の条件式を上手く工夫すれば、for()の中で、余計な条件分岐などが減るなどの、細かい記述に関しても指摘を受けます。 質問はプログラムを作成する上で、大きな観点からだと、どのようにすれば綺麗にモジュール化などが出来るのか、モジュール化だけではなく、ソフトウェアの設計全般に関してです。また細かいことで、いえば先ほどのfor()の様に、文法を上手く使いこなすためにはどうすればよいか。本などのサンプルコードでは、forならfor、ifならifの説明など、主に単独の説明が多いように思えます。関数の中で、各文法同士を上手く使いこなし、他人が見ても読みやすいコードなどを書きたいです。 先輩からは、他人のソースコードを見ることなどと言われますが、何か他人のソースコードを見る上でも、上で挙げた指摘を改善するための見方とか、他にも自分でプログラムを作る場合に、こういう事に注意しながら作るといいなど何か改善するアドバイスがあれば宜しくお願いします。また参考になる書籍やサイトなどもあったら教えて頂くと助かります。 長くなりましたが宜しくお願いします。

  • VBAのプログラムでうまく動かなくて困っています。

    VBA初心者です。 エクセルのVBAのプログラムでうまく動かなくて困っています。教えていただける方がいらしたら、ぜひ教えて下さい!よろしくお願いします。エクセルの内容は以下のとおりです。 (内容) セル    E H J L N P R・・・ 8行目100 200 50 40 30 80 9行目130 350 10 50 60 120 110 ・ ・ (1)列Hの値が列Eの値より大きい場合その下に行を追加します。 (2)セルJ+セルL+セルN+・・をしてセルEの値を超えたセル以降の値を追加した行のセルJ列から順にコピペする処理です。 上のセルの1行目の内容でいいますと、 (1)列Hの値「200」が列Eの値「100」より大きいのでその下に行追加 (2)セルJ、L、N「50」+「40」+「30」でセルEの値「100」より大きいので、追加した行のセルJ列にセルN、Pの値をコピペするです。 以下が私が書いたプログラムです。 Sub test() Dim x As Integer Dim s As Integer Dim t As Integer x = Range("B8").End(xlDown).Row r = Range("J8").End(xlToRight).Column '8行目から最終行までループ For i = x To 9 Step -1 If Cells(i, 5) < Cells(i, 8) Then ☆【For r = y To 11 Step -2 Cells(s, t).Value = Cells(i, r) + Cells(i, r + 2) If Cells(i, 5).Value < Cells(s, t).Value            Then Exit For Next】 Rows(i + 1).Insert Shift:=xlDown '超えたセルをコピーして、1行下の"J列以降"に代入 ★ x = x + 1 End If Next i End Sub 上記プログラムで★の部分がうまく書けません。☆の部分も間違っているような気がします。よろしくお願いします。

  • ファイルを読み込むプログラムについて

    下のプログラムで分からない所がありますので、教えて頂ければと思います。宜しくお願い致します。 text = fgets(buf,256,fp);はfpのファイルから一行を読み込んでbufに格納するという処理ということは分かります。でも、while文内なので次にこの処理をする時に今度は、2行目(下の段)を読み込むはずですが、プログラム中のどこに2行目に移動させる処理があるのか分かりません。 予想ですが、text = fgets(buf,256,fp);の中にそのような意味の処理が含まれているのでしょうか? どなたかご教授お願い致します。 #include <stdio.h> int main(void) { FILE *fp; char buf[256]; char *text; char flname[256]; printf("ファイル名:"); gets(flname); fp = fopen(flname,"r"); do{ text = fgets(buf,256,fp); if(text != NULL){ printf("%s",text); } }while(text != NULL); fclose(fp); return(0); }

  • バージョンの付け方

    プログラムには、Ver 1.0とか、バージョンが記されていますが、これは何か基準などあるのでしょうか? 例えば、○行以上追加したら0.1あげるとか、 プログラムが○%変わったら1上げるとか。 それとも、プログラマの自由なのでしょうか? 回答お願いします。

  • プログラム初心者に質問

     カテ違いはわざとです。ご容赦ください。  プロのプログラマーをやっております。  IT業界の社会人1年生、あるいは独学でプログラムを始めたばかりの人に質問です。  10月頃から一緒に仕事をしている、新人君ついてなのですが、当初彼は、プログラマーの募集に対して応募してきた人でした。  現在手がけている仕事がそう難しいものではないため、まぁよかろうと思って採用ということになったのですが……。  蓋を開けてみると……(笑) ・「変数」という言葉の意味が分からない。 ・「イフで分岐して」と言っても意味が直感的に理解できない。 ・ループ構造が書けない。 ・あげく出てくる質問は「デフォルトってなんですか?」(笑)  彼がなぜ「プログラマー募集」に応募しようと思ったのかはともかく(将来的にそうなりたいという希望だったのかもしれません)、プロとして仕事ができる状況ではなかったのです。  その中で彼がもっとも手こずったのが、「カウンター処理」です。  ループ処理の中でカウンター変数を+1していき、配列の中の値を1つずつ使っていく、という処理手法ですね。  彼は、これが2ヶ月たった今でも理解できないみたいなのです。  昔の自分がどうだったかを考えてみても、そう手こずった覚えもありません。  奥さん(プロではないが、腐女子向けゲーム作りのスクリプターをやっている)に教えたときも、言葉で言ってすぐ理解してくれました。  そう難しい問題ではないと思うのですが、一部の初心者にとって、これは難しいことなのでしょうか? という質問です。  イエスかノーで答えていただければけっこうです。  何か思うところがおありの方は、お話をお聞かせいただければと思います。

  • 方程式の解をだすプログラム

    今日の情報処理演習のテストで {正の整数(float型)aを入力させ、方程式x*x*x*-3*x+a=0の正の解のうち最も小さいxを小数点以下2桁の精度で求め、画面に表示するプログラム。ただし、a>2のときは、「解けません」というメッセージを表示するようにする。}  という問題がでたのですが、このプログラムがわかる人は教えてください。ちなみに、使うのはif構文とwhile構文(do~whileは使わない)でつくらなくてはなりません。  for構文とif構文の組み合わせを使えばできるとおもうのですが、whileだけでやるにはどうすればいいのでしょう。