パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

美しくなくても十分に機能するコードで良い?」記事へのコメント

  • どの言語でも (スコア:3, 参考になる)

    by take0m (4948) on 2002年09月18日 17時19分 (#168125) 日記
    パフォーマンスを重視すると、
    ある程度汚く読みにくくなるのは、
    仕方がないと思われますが。

    うちの仕事ものんびりした仕事は少ないので、
    とりあえず動くものということだと、
    金余分に貰ってそれをOSとDBにつぎ込んで
    VBできる人を集めて、ASPで作っちゃいます。

    Javaの「使える」エンジニアは常に不足気味ですから、
    なかなか現場の要求に迅速に対応できないんですよね。
    SunとJava陣営はそこんとこなんとかしないとね。

    .netによって、これまでの大量のVBプログラマが
    VB.Net経由でC#に徐々に慣れてくれれば、
    あとでJavaに移植しやすくなるので
    ありがたいと思うんですけど。
    • Re:どの言語でも (スコア:5, 参考になる)

      by SteppingWind (2654) on 2002年09月18日 18時03分 (#168154)

      > パフォーマンスを重視すると、
      > ある程度汚く読みにくくなるのは、
      > 仕方がないと思われますが。

      これって昔から言われることですが, 本当にこれが当てはまるケースって今ではごく稀になっているのではないかと. おそらくは

      • 直接アセンブラを使ってディレイスロット等を入れる場合
      • パイプラインの長さを生かすためにループアンローリング等の技法を使う場合

      程度か, その類似の場合だけで, 多くの場合はむしろコンパイラが最適化しやすいように明瞭なプログラムの流れにした方が良いでしょう. それに手による最適化が必要な局面って, プログラム全体の高々数%未満ですから, 最適化を理由に汚いコードを書く人は, 単にきれいなコードを書くスキルが無いと思った方が良いでしょう. 経験的には, スキルの有る人が汚いコードを書かざるを得ない場合には, なぜそのようになったかがコメントに明記されているので, 十分に分かりやすくなっています.

      で, いわゆる自称VBプログラマが問題になるのは, 実際のプログラミングに入る前段階での実装設計能力に欠けているからです. これは言語環境にはほとんど依存しませんから, RAD技法で対応可能な規模を超える物件では, どれだけプログラマが増えようと保種困難なクズプログラムが増えるだけで, 保守を前提としない使い捨てプログラムにしか適応不可能です.

      親コメント
      • by take0m (4948) on 2002年09月18日 18時37分 (#168179) 日記
        どの業界でもそうなんだと思いますが、HRに関しては、その業界の市場が大きくなるに連れて、一定のクォリティを維持するのがどんどん難しくなるのではないかと思います。
        ソフトウェアの開発も十二分に大きな市場ですから、優秀な人材を探したり育成したりすることに投資するよりも、優秀とはいえない人材をいかに活用するかへ金が流れるようになるのでしょう。

        とくにWeb系に関しては、開発スパンがweek単位~長くて1年ですから、満足な設計すらもままならないことになり、プログラマにその辺のしわ寄せがやってくるケースが多々あるのではないでしょうか。
        それに加えて、サーバサイドアプリケーションの場合は成果物を配布しませんから、設計や仕様変更に関して柔軟に対応できる分、コードのクォリティが必然的に低下していきます。

        ある意味で、顧客満足度を高めるために、コードが犠牲になっているとも言えますが・・・
        親コメント
        • >それに加えて、サーバサイドアプリケーションの場合は成果物を配布しませんから、設計や
          >仕様変更に関して柔軟に対応できる分、コードのクォリティが必然的に低下していきます。

          これは、逆じゃないですか?
          設計や仕様変更に関して柔軟に対応する必要があるのなら、読みやすく、
          メンテナンスしやすいコードほど、修正が短時間で行えるのだから、
          コードのクオリティを高める必要が出てくるのでは?

          使い捨てのプログラムなら(つまり、再利用や保守の必要が無いなら)、コードの
          クオリティは低くて構わないのかもしれませんが。
          親コメント
          • Re:どの言語でも (スコア:2, 参考になる)

            by take0m (4948) on 2002年09月18日 22時14分 (#168291) 日記
            > これは、逆じゃないですか?
            > 設計や仕様変更に関して柔軟に対応する必要があるのなら、読みやすく、
            > メンテナンスしやすいコードほど、修正が短時間で行えるのだから、
            > コードのクオリティを高める必要が出てくるのでは?

            柔軟に対応する必要があるというよりは、
            柔軟に対応を迫られる、
            という表現が近いのでしょうね。

            で、修正を短時間で行えるのは理想なのですが、設計と実装も短時間で行わなければなりませんから・・・なかなか理想的には行きません。

            先日も、あるJava信仰者のSEの人が保守性を主張しまくって、大変な目にあいました。
            保守性に固執しすぎてコーディングのアップが遅れると、テストのスケジュールを圧迫し、それによって成果物のクォリティが低下するという悲惨な結果を招く場合もあります。
            大切なのはバランスだと思いますが、それがなかなか難しいんですよね。
            親コメント
            • つまり、

              > 設計や仕様変更に関して柔軟に対応できる分、コードのクォリティが必然的に低下していきます。

              ではなく、

              > 設計や仕様変更に関して柔軟に対応させられる為、コードのクオリティが必然的に低下していく。

              ということでよろしいでしょうか。それなら納得です。

              ----

              <オフトピック>

              > 大切なのはバランスだと思いますが、それがなかなか難しいんですよね。

              ああ、もう、本当その通りですよね。御託ばっかり並べても、上手くやる奴は上手く
              やるし、上手く出来ない奴は出来ない。で、何が違うのかというと、バランス感覚
              というものを知っているか、ということなんやろなー、とよく思います。とは言え、
              うまくバランスを取るのは難しい。要領よくやりたいもんですけどねー。
              </オフトピック>
              親コメント
      • > 経験的には, スキルの有る人が汚いコードを書かざるを得ない場合には, なぜそのようになったかがコメントに明記されているので, 十分に分かりやすくなっています.

        そういう人と一緒に仕事がしたいっっっっ。

        #そんなこと言う前に自分がそういう人になる事が先決>俺
        親コメント
      • > 本当にこれが当てはまるケースって今ではごく稀になっているのではないかと.

        そうかな?コンパイラによる最適化が効くような、
        抽象度の低い層の話だけでもないだろう。

        外部には公開していない、
        オブジェクト内部でだけ保持しているような中間状態を利用して
        高速化を行うことって多いんでないかな。特に OOP だと。
        もちろん、そういう書き方をすると「公開用インターフェース」と
        「内部向けインターフェース」の2つが混在するから、
        「公開用インターフェース」のみに絞った場合に比べて
        読みにくくなる。

        後半の部分については同意。
        --
        # mishimaは本田透先生を熱烈に応援しています
        親コメント
        • by DrSaider (9448) on 2002年09月18日 19時06分 (#168196) 日記
          そうそう、privateだとかはコメントレスも良くある話 :D
          (って言うか、ちょっとしたのならやっちゃうし。

          public:はキレイキレイに書くんだけどなぁ。

          愚痴
           コメントレスなソースとか時々見かけたりして
           ソース見ただけで判るからコメント要らないなんて言ってる人とは
           一緒に仕事したくありません(タダの愚痴だよ (/_;)
          親コメント
          • by Anonymous Coward
            むはー。MT-Safe だとかイロイロ考え始めると、private メンバたりともおろそかに扱って欲しくないけどなぁ!

            Java 文化の場合、

            ・クラス名、メソッド名、メンバ変数名は省略せずに書く
            ・1ファイル1クラス
            ・(特にシステムパッケージ以外の) import はクラス単位で書く
      • by Anonymous Coward on 2002年09月18日 19時19分 (#168204)
        >どれだけプログラマが増えようと保種困難なクズプログラムが増えるだけで, 保守を前提としない使い捨てプログラムにしか適応不可能です.

        悲しいかな私の廻りでは時代は変わり、今や「使い捨てプログラム」を作る時代になってしまいました。
        使い捨てなプログラムになってしまうのではなく、初めから使い捨てにするつもりのプログラムなのです。take0m さんの書いてらっしゃるような、Web 系の開発スパンの短いものはほとんどがそういうものです。

        いわゆる職人の出番は無い、悲しい時代です。
        親コメント
        • Re:どの言語でも (スコア:2, おもしろおかしい)

          by Dentom (9064) on 2002年09月18日 22時43分 (#168305)
          >今や「使い捨てプログラム」を作る時代

          一瞬、「使い捨てプログラマ」って読んでしまいそうになった(笑)。

          いや、笑い事じゃないな…。
          親コメント
        • by Quo Vadis (10810) on 2002年09月18日 21時30分 (#168270)
          いわゆる職人の出番は無い、悲しい時代です。
          いや、使い捨て、だけど、それなりに使えるプログラムをちゃっちゃと書き上げるってのも、これまた職人の仕事ですよ。
          やってて虚しいのは確かですがね。
          親コメント
        • シェルプログラムなんかは、昔からよく使い捨てますよ。
          大体 5 分ぐらいで「ちゃちゃ」っと書き上げて、
          20 分ぐらい実行して、処理後のデータを見ることが多いですね。
          その空いている時間は、調べものや息抜きタイムです。

          > いわゆる職人の出番は無い、悲しい時代です。
          こんな時代だからこそ、職人の時代です。
          親コメント
      • 今もファームを書いているんですけど
        この前もコンパイラの最適化では追いつかなくて ループ内のポインタ演算をアセンブラで最適化したり、
        割り込み処理ルーチンでコンパイラがレジスタ退避などに使っていた部分を 処理内容にあわせて削ったりしました。
        このためにグローバル変数を専用に作ったりして、ある程度美しくないソースになってしまいました。
        この仕事では、全体の30%くらいはこのような状況でした。
        というわけで、今でも状況によってはコンパイラに頼れない場面もかなりあります。
        #んで愚痴になるんですが、
        #その仕事で使うC処理系がかなり腐ってまして、
        #単純二重ループを入れるだけでコンパイルが通らなくなる…
        #結局ループを別関数に逃がさないといけないのでそのオーバーヘッド分遅くなる…
        #それにCPUの「仕様」で特定の命令でダミーの信号が出てしまい、それを回避するためにインラインアセンブラの嵐
        #しかもインラインアセンブラを使うとバグなのかAUTO変数がたまに化ける…
        #それの回避にスタティック変数を大量に使わざるを得ない…
        #美しいソースがどうこう言えるような状態では無い(;-;)
        #バージョンアップは無いのかっ!
        親コメント
        • by G7 (3009) on 2002年09月18日 21時56分 (#168281)
          それ、コンパイラ(とついでにCPU)を作り直すのに、一度思い切ってしかるべき量の工数を裂いたほうが、
          最終的に幸せになるのでは?…とか、一瞬思ってしまいました。
          まぁそう簡単にもいかないでしょうけどね。ご愁傷様ですm(__)m

          ところでそういうコンパイラって、もしや売り物なのですか?
          なんかとてもじゃないが売り物水準じゃないDQNな物に思えるのですが。
          親コメント
          • 一応開発ツールとしては売り物のようです…
            そこの社内でも使って居るものなんですけど、何で修正されないのか不思議です。
            親コメント

          1. へぼい CPU の情報

          2. 腐っているという C コンパイラの情報


          これらの情報が無いので判断ができませんが、
          チューニングでスペック叩き出すより、
          アルゴリズムやデータ構造を変えた方が良くないですか ?

          30% が特殊なコーディングなら
          60% 以上は性能が上がってないと割りに合わないかなと。

          ま、
          やっている事がどんだけ複雑か知らないで言っていますが。
          親コメント
          • 全体のパフォーマンス向上のためではなく、
            ハードウェアが要求する仕様を満たすためのものです。
            そのためチューニングにより性能は0(動作しない)から1(動作する)へと
            無限大%(?)向上しています。
            ちなみにアルゴリズムがどうこう言うレベルのものではなく
            単にバッファにデータを送るだけのものだったりします。
            そのタイミングの条件が厳しいのがチューニングをする理由です。

            ハードウェアのスペックがぎりぎりなのは、少量ですが数が出るので
            部品代と部品点数を削るのが理由です。
            親コメント
            • by G7 (3009) on 2002年09月19日 16時06分 (#168687)
              >そのタイミングの条件が厳しいのがチューニングをする理由です。

              そういう0%から100%にするための修正(だよね)は、
              「チューニング」とは、あんまり呼ばないのでは?
              親コメント
              • by Quo Vadis (10810) on 2002年09月19日 16時35分 (#168702)
                元コメントがいまいち(失礼)なのがよくない気がしますが、
                ハードウェアのタイミング要件を満たすために、ソフトウェアをチューニングして間に合わせる、ってのはありますね。
                こういうのは、ハードとソフトを組み合わせた製品として見れば「チューニング」じゃないんでしょうが、ソフト部分のみ取り出して見れば、「チューニング」以外の何ものでもないでしょう。
                親コメント
      • 主旨には賛成ですが、いちおう突っこんでおきます。

        > 直接アセンブラを使ってディレイスロット等を入れる場合

        delay slot を手で埋めて最適化というのは、ちょっと古い気がします。
        命令スケジューラを完備した最適化コンパイラの場合、コンパイラに埋めさせた方が高速だと思います。

        p.s.

        delay slot に似たような話だと、プレディケイト命令があります。
        プレディケイト命令は使い所が難しくて静的なコンパイラだけでは痛し痒しなコードを出力しますが、
        (C言語の)処理系によっては、条件分岐を 3項演算子で書くと積極的にプレディケイト命令を使ってくれてハッピーな場合があります。

        特に EPIC の Itanium になると同時実行される命令スロットを埋めるために、
        プレディケイト命令を積極的に使う必要がありますから、高速化のために
        コーディングスタイルの変更を求められるかもしれません。

        p.p.s.

        コンパイラが最適化しやすいコードって、プログラマにとって明瞭な流れになるかなぁ?
        例えば「A と B の 2 つの処理を定数回繰り返す返すループ。ただし、cond1 が成立する場合には初回の A 処理を省略する」というルーチンの場合、どれが読みやすいですか?
        # コンパイラが最適化しやすいのは例 3。

        ● 例1
        if( cond1 )
            goto label;

        for( i=0 ; i<N ; i++ ){
            // A
        lable:
            // B
        }

        ● 例2
        if( !cond1 ){
            // A
        }
        // B
        for( i=1 ; i<N ; i++){
            // A -> B
        }

        ● 例3
        if( cond1 ){
            // B
            for( i=1 ; i<N ; i++){
                // A -> B
            }
        } else {
            for( i=0 ; i<N ; i++ ){
                // A → B
            }
        }

        ● 例4
        tmp = cond1;
        for( i=0 ; i<N ; i++ ){
            if( tmp )
                tmp = 0;
            else{
                // A
            }
            // B
        }
        --
        コンタミは発見の母
        親コメント
        • すいません。訂正させてください。

          ● 例1
          i=0;
          if( cond1 )
              goto label;

          for( ; i<N ; i++ ){
              // A
          lable:
              // B
          }
          --
          コンタミは発見の母
          親コメント
        • by albireo (7374) on 2002年09月19日 6時35分 (#168500) 日記
          ● 例5
          i=0;
          if( cond1 ){
              // B
              i++;
          }
          for( ; i<N ; i++ ){
              // A -> B
          }

          はどうでしょう?例2よりはちょっぴりましになるかも。

          保守性を考えると例1が好きですね。
          同じ処理を複数箇所に書くと、片方だけ修正して気づかないことがよくあるので。
          --
          うじゃうじゃ
          親コメント
          • > 保守性を考えると例1が好きですね。
            > 同じ処理を複数箇所に書くと、片方だけ修正して気づかないことがよくあるので。

            ですね。私も普通に書くときは例1のように書くと思います。
            goto はスパゲッティーコードの素と言われますが、使い方によってはプログラムを読みやすくしてくれます。

            p.s.
            例1は goto の代わりに switch を使うこともできます。
            --
            コンタミは発見の母
            親コメント
            • by boo (899) on 2002年09月19日 20時24分 (#168791) 日記
              > 例1は goto の代わりに switch を使うこともできます。

              switch (!cond) {
                  case 0: for (i=0; i<N; i++) {
                      // A
                  default:
                      // B
                  }
              }

              # 先生! 合ってますか?
              --
              あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
              親コメント
              • by boo (899) on 2002年09月19日 20時37分 (#168797) 日記
                自己採点したら間違ってた (^^;

                i=0;
                switch (cond) {
                    case 0: for (; i<N; i++) {
                        // A
                    default:
                        // B
                    }
                }
                ですね。

                # 薀蓄をたれると Duff's device といいます。
                --
                あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
                親コメント
              • ですね。

                でも、この手の怪しい記述のコードは薀蓄を語る時か、コンパイラ
                のデバッグをするときにしか使いませんよね。

                実際のプログラムでこういうコーディングをする人がいて、
                その人の書いたコードをデバッグすることになったら嫌だろうなぁ。
                --
                コンタミは発見の母
                親コメント
        • by boo (899) on 2002年09月19日 9時18分 (#168526) 日記
          例1と例4が最適化しにくいのは分かります。(1はループが強連結じゃない。4はループ内に分岐がある。)
          例3が例2より最適化しやすい理由がわかりません。よろしかったら教えてください。

          # 個人的には私なら2を選ぶだろうなと思います。
          --
          あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
          親コメント
          • 例1のループはコンパイラの世界では簡略化不能なループ(irreducible loop)とか不自然なループ(unnatural loop)とか呼びます。ループ本体への入口が複数あるループですね。
            このままではほとんどの最適化手法が使えないので、最適化コンパイラはコードを複製して例3 に近い形に変形します。
            # irreducible loop が多段に入ると、びっくりするほど大きなオブジェクトコードが生成される
            # ことがあります。

            例3 はループ本体をコピーしているため、例2 よりループを周る回数を判断しやすいです。ループ系の最適化が効き易くなります。
            --
            コンタミは発見の母
            親コメント
            • > 例3 はループ本体をコピーしているため、例2 よりループを周る回数を判断しやすいです。
              この説明は嘘ですね。例2、3ともループの回数を判断できますから。
              ただ、ループに入る前の変数の状態の曖昧さ 例3 の方が少ないので、最適化は効き易いです。
              A が S++、B が空だとすると、以下のように最適化される可能性があります。

              ● 例2
              if(!cond1){
                  S++;
              }
              S += N-1;

              ● 例3
              if(cond1){
                  S += N-1;
              } else {
                  S += N;
              }

              # 例のコードの外側にさらにループがある場合には、例2 の方が有利かもしれません。
              --
              コンタミは発見の母
              親コメント
              • by boo (899) on 2002年09月19日 14時45分 (#168655) 日記
                > > 例3 はループ本体をコピーしているため、例2 よりループを周る回数を判断しやすいです。
                > この説明は嘘ですね。例2、3ともループの回数を判断できますから。

                ああ、そうでしたか。Nがcondに依存する変数のつもりで書かれたのかと思いました。

                > ただ、ループに入る前の変数の状態の曖昧さ 例3 の方が少ないので、最適化は効き易いです。

                なるほど、そのとおりですね。ご説明ありがとうございました。
                --
                あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
                親コメント
    • by Dentom (9064) on 2002年09月18日 18時27分 (#168173)
      >.netによって、これまでの大量のVBプログラマが
      >VB.Net経由でC#に徐々に慣れてくれれば、

      私の知っているVBプログラマって、たいていは
      VB“しかできない”プログラマ
      だったりするので、彼らに限って言えば無理っすね。
      親コメント
      • Re:どの言語でも (スコア:3, すばらしい洞察)

        by Quo Vadis (10810) on 2002年09月18日 21時27分 (#168269)
        私の知っているVBプログラマって、たいていは
        VB“しかできない”プログラマ
        だったりするので、彼らに限って言えば無理っすね。
        そりゃいいっすね。
        私の知っているVBプログラマって、大抵はVBもできないプログラマだったりします。

        で、そいつらの書いたコードと思しきものをメンテすることになる罠。
        親コメント
      • Basic という名前で、ビギナーを取り込むが、
        そもそも Basic ですらない VB.

        しかも、どういうわけか依存性が強く、
        他の言語に移(らない|れない)人が多い気がします。

        オブジェクト指向っぽい言語ですが、
        「っぽい」所がコードらしき文字の羅列を
        作らせるのではないでしょうか。

        罪を憎んで人を憎まず。
        親コメント

あつくて寝られない時はhackしろ! 386BSD(98)はそうやってつくられましたよ? -- あるハッカー

処理中...