[三流君] −−> [プログラマー業務の愚痴] −−> [バックナンバー一覧]
−−> No.167 Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ

Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ


本文(発行内容)


<Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ>

こんにちは、三流プログラマーのKen3です。 どちらかと言えば、芸術的プログラムとは無縁の三流プログラマーです。 えっ、そんなのわかってるって? そんな前フリは置いといて、 今回は、 Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ コピーして編集するプログラムは工夫できる率が高いよ って話です。 まぁ、いつもの独り言だけど、聞いてください。

/* * 1.今回のキッカケ */

VBA系のメルマガで、And演算子、Not演算子の解説を行ってました。 自己レスじゃないけど、フトお馬鹿なことに気がつく。 ※いつになったら、手前味噌的な自慢系のメルマガに成長できるのだろう(笑)  オレ様のプログラムってキレイだろ、芸術品だよ、、と  いつか自信を持って、言って見たいよね。。。 おっと、挨拶はこれくらいにして、

/* * 2.コピー -->貼り付け で作るプログラムの罠(笑) */

No.76 Access レポート Me.NextRecord = Falseで移動を止める http://www.ken3.org/backno/backno_vba16.html#76 左端ならラベルを表示、レコード移動を止め次に実データを印刷する そんなテストプログラムなのですが、 初めは下記のように、普通に作成してました。
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    If (Me![cntA] Mod 3) = 1 Then  '左端なら
        If pFLG = False Then 'まだラベルエリアを印刷してなかったら
            Me.NextRecord = False      'レコードの移動をまず止める
            pFLG = True  '印刷フラグを立てる
               'ここにラベルのOn/Off処理を入れる
            Me![lab01].Visible = True
            Me![lab02].Visible = True
               '実データをOff  <−−−注目(笑)
            Me![ID].Visible = False
            Me![WrietTime].Visible = False
            Me![F_TITLE].Visible = False
            Me![F_MEMO].Visible = False
        Else
               'ここにラベルのOn/Off処理を入れる
            Me![lab01].Visible = False
            Me![lab02].Visible = False
               '実データをOff  <−−−注目(笑)
            Me![ID].Visible = True
            Me![WrietTime].Visible = True
            Me![F_TITLE].Visible = True
            Me![F_MEMO].Visible = True
        End If
    Else
        pFLG = False  'その他の時
    End If

End Sub
よく見ると、同じような処理があって、 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'ここにラベルのOn/Off処理を入れる Me![lab01].Visible = True と Else 'ここにラベルのOn/Off処理を入れる Me![lab01].Visible = False みたいな感じでOn/Offが逆なだけでした。 まぁ、処理が 左端ならラベルを表示、実データは非表示、 その他はラベル非表示、実データを表示だから、 True/Falseが違うだけで同じなんですよね。 そっか、それで、キーボードでCtrl+C,Ctrl+Vでコピーして、 True/Falseを逆に書いたんだ。 えっ、なんでCtrl+C,Ctrl+Vでコピーしたってわかったの? だってさ、コメントが直ってないんだよ、アンタのコメントが? えっ、どこどこ? よく見ろよ、 If pFLG = False Then 'まだラベルエリアを印刷してなかったら Me.NextRecord = False 'レコードの移動をまず止める pFLG = True '印刷フラグを立てる 'ここにラベルのOn/Off処理を入れる Me![lab01].Visible = True Me![lab02].Visible = True '実データをOff <−−−注目(笑) Me![ID].Visible = False Me![WrietTime].Visible = False Me![F_TITLE].Visible = False Me![F_MEMO].Visible = False と Else 'ここにラベルのOn/Off処理を入れる Me![lab01].Visible = False Me![lab02].Visible = False '実データをOff <−−−注目(笑) Me![ID].Visible = True Me![WrietTime].Visible = True Me![F_TITLE].Visible = True Me![F_MEMO].Visible = True End If を良く見ると、 '実データをOff ^^^^^^^^^^^^^^^^^ ってコメントが一緒だよ。 Elseの部分のコメントは、実データをon、可視にする ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ が正しいんじゃないの? コピーして作るのもいいけど、直してね、 コメントだから、まだ実害なかったけど、 もし、TrueとFalseを逆にするのを直し忘れてたら? ゾッとするよね。 最近の開発スタイルって、エディターに直打ち、即実行確認、 なんて環境だから、 一呼吸置いて、考えないでコピー、貼り付けって多いと思う。 で、コピーした一部(部分的範囲)を変更する。 修正中にメールや携帯が鳴って、割り込みが入り作業中断、 そしたら、修正忘れがあったり、、なんて変なストーリーあったりしてね。 たまたま、今回は、 VBA系の No.77 Not演算子で細工する、プログラムはパズルのように... http://www.ken3.org/backno/backno_vba16.html#77 で、 Not演算子を使用して下記のようにまとめてみたけど、 何も考えないと、私のように同じ処理が氾濫してたりするよ(笑) 手前味噌、芸術的、ナルシスト的プログラムって言われてもたまには作ってみようよ。
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    If (Me![cntA] Mod 3) = 1 Then  '左端なら
        'フラグを使用して可視/不可視をセットする
        Me![lab01].Visible = Not pFLG  'ラベルはフラグの逆をセット
        Me![lab02].Visible = Not pFLG
        '実データ
        Me![ID].Visible = pFLG         '実データにはフラグそのままセット
        Me![WrietTime].Visible = pFLG
        Me![F_TITLE].Visible = pFLG
        Me![F_MEMO].Visible = pFLG
        
        If pFLG = False Then 'まだラベルエリアを印刷してなかったら
            Me.NextRecord = False      'レコードの移動をまず止める
            pFLG = True  '印刷フラグを立てる
        End If
    Else
        pFLG = False  'その他の時
    End If

End Sub
と、Not演算子を使用して、まとめました。 これなら、項目の1つだけTrue/Falseの修正忘れの単純ミスもないし、 項目が増えても、2ヶ所に処理を入れなくてOKです。

/* * 3.プログラムには、ループや配列を使った処理が存在するんだよ(笑) */

画面に1回目、2回目、、4回目とMsgboxで表示してよと言われたら、 簡単なプログラムは、
Sub AAA()
   Msgbox "1回目"
End Sub
って書いてから、いつものCtrl+CでコピーCtrl+Vを3回押してと
Sub AAA()
   Msgbox "1回目"
   Msgbox "1回目"
   Msgbox "1回目"
   Msgbox "1回目"
End Sub
してから、
Sub AAA()
   Msgbox "1回目"
   Msgbox "2回目"
   Msgbox "3回目"
   Msgbox "4回目"
End Sub
と直します(笑) そんなことしないよFor文使うよ ~~~~~~~~~~~~~~~~~~ って、みなさん、心の中で言ったと思います (私が勝手にアナタの心の中を予想しました) ですよね、まぁ、コピー、一部変更プログラム極論でした。 では、チエちゃん好き、ミキちゃん好き、アキちゃん好き、マイちゃん好き と名前を出すときは?
Sub AAA()
   Msgbox "チエちゃん好き"
   Msgbox "ミキちゃん好き"
   Msgbox "アキちゃん好き"
   Msgbox "マイちゃん好き"
End Sub
じゃなくって、
Sub BBB()

    Dim strNAME As Variant
    Dim n As Integer
    '配列を代入
    strNAME = Array("チエ", "ミキ", "アキ", "マイ")
    'データを表示
    For n = 0 To 3
        MsgBox strNAME(n) & "ちゃん好きです"
    Next n

End Sub
と、ループとArrayで配列を作成の知識のある人は作るかな。

/* * 4.配列の要素数を返すUBound関数を使ったりする */

表示させたい、好きな子が増えたら? コピー君は、
Sub AAA()
   Msgbox "チエちゃん好き"
   Msgbox "ミキちゃん好き"
   Msgbox "アキちゃん好き"
   Msgbox "マイちゃん好き"
   Msgbox "アヤちゃん好き"  '午後の紅茶のアヤちゃんは好きじゃないけど(笑)
End Sub
とコピーで作成するのかな。 For君は、
Sub BBB()
    Dim strNAME As Variant
    Dim n As Integer
    '配列を代入
    strNAME = Array("チエ", "ミキ", "アキ", "マイ", "アヤ")
    'データを表示
    For n = 0 To 4 'カウンタも忘れずに増やす
        MsgBox strNAME(n) & "ちゃん好きです"
    Next n
End Sub
とデータとカウンタを増やすのかな。 まぁ、忘れそうなのが、データ増やしてカウンタを増やすことを忘れるパターン。 それを防止する方法?があって、 昔からの古典的手法は データの最後に"END""STOP","99"など、 ストップワードを入れて判断する方法もある。
Sub CCC()
    Dim strNAME As Variant
    Dim n As Integer
    '配列を代入
    strNAME = Array("チエ", "ミキ", "アキ", "マイ", "アヤ", "STOP")
    'stopまでデータを表示
    n = 0 'カウンタ初期化
    While strNAME(n) <> "STOP"  'STOP以外の間ループする
        MsgBox strNAME(n) & "ちゃん好きです"
        n = n + 1  'カウントアップ次の子にする
    Wend
End Sub
これだと、ループの回数は指定しないで、"STOP"までループ可能。 まぁ、今風の書き方だと、配列の最大要素数を求めるUBoundって関数があって、
Sub DDD()
    Dim strNAME As Variant
    Dim n As Integer
    '配列を代入
    strNAME = Array("チエ", "ミキ", "アキ", "マイ", "アヤ")
    'データを表示
    For n = 0 To UBound(strNAME) '配列の最大要素までループ
        MsgBox strNAME(n) & "ちゃん好きです"
    Next n
End Sub
ASPで作った例だけど、Split関数とUBound関数のサンプル http://www.ken3.org/cgi-bin/test/test024-2.asp こっちも参考にしてみてね。

/* * 5.コントロールをループさせる For Each IN を使って */

この流れの解説だと、(話の流れだと) 読者の心の声をまたまた勝手に代弁すると、 ^^^^^^^^^^^^^^ データをプログラム内に持たないで、ファイルなど外部に持つ方法だろ、、 と 普通は来るのですが、疲れたので、今日は辞めます(笑) オイオイ、そりゃないでしょ。 えっと、このメルマガのタイトルに戻って、 タイトル?なんだっけ? 三流君、手前味噌的にプログラムを語る?だったっけ・・・ 違うでしょ、 Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ってタイトルです。 下記のプログラムに戻ってと、 実は、ここでもCtrl+C Ctrl+Vでプログラム書いてるんですよね。 Me![ID].Visible = pFLG をコピーして、 Me![F_TITLE].Visible = pFLG Me![F_MEMO].Visible = pFLG なんて、作ってるんですね。
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    If (Me![cntA] Mod 3) = 1 Then  '左端なら
        'フラグを使用して可視/不可視をセットする
        Me![lab01].Visible = Not pFLG  'ラベルはフラグの逆をセット
        Me![lab02].Visible = Not pFLG
        '実データ
        Me![ID].Visible = pFLG         '実データにはフラグそのままセット
        Me![WrietTime].Visible = pFLG
        Me![F_TITLE].Visible = pFLG
        Me![F_MEMO].Visible = pFLG
        
        If pFLG = False Then 'まだラベルエリアを印刷してなかったら
            Me.NextRecord = False      'レコードの移動をまず止める
            pFLG = True  '印刷フラグを立てる
        End If
    Else
        pFLG = False  'その他の時
    End If

End Sub
このプログラムでもいいんだけど、 実データの印刷フィールドが追加になったら、(F_TAKOフィールド) Me![F_TAKO].Visible = pFLG と、プログラムの追加が発生します。 フィールドが追加になったから、ショウガナイヨネ、これは。 まぁ、そうなんですが、よく見ると、 Me![lab01]とMe![lab02]のラベル関係 と 実データのMe![F_XXXXX]の実データ関係 そんな2つのグループ分けができてます(IDとwriteなど例外あるけど(笑)) コントロールの名前付けで、 規則性があるなら、ループでまわせよってことで、 ↑~~~~~~~~~~~~~~~~(コントロール名を規則正しく作って) Controlsコレクションでまわしてみます。 Controls?コレクション? コントロールにアクセスする方法は、 Me.Controls!新規データ Me.Controls![新規データ] Me.Controls("新規データ") なんて、名前を指定する方法と、 インデックスでコントロールを参照することもできます。 Me(0) ' コレクションの最初の項目を参照します。 Me.Controls(0) これを利用して、
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    Dim n As Integer
    If (Me![cntA] Mod 3) = 1 Then  '左端なら
        For n = 0 To Me.Controls.Count - 1 'コントロールの数ループする
            If Left(Me.Controls(n).Name, 3) = "lab" Then '名前はラベル
                Me.Controls(n).Visible = Not pFLG
            Else
                Me.Controls(n).Visible = pFLG
            End If
        Next n
        If pFLG = False Then 'まだラベルエリアを印刷してなかったら
            Me.NextRecord = False      'レコードの移動をまず止める
            pFLG = True  '印刷フラグを立てる
        End If
    Else
        pFLG = False  'その他の時
    End If
End Sub
と書いて、 コントロールの名前付けの規則でTrue/False を 切り替える方法も1つの手です。 Me.Controls(n).Visible あっ、これが三流君のうわさのクセね。 ループのカウンタでまわしたがるってヤツね。 VBA系の No.73 オブジェクトのループはFor Each In でループさせる http://www.ken3.org/backno/backno_vba15.html#73 で、 偉そうなこと語ってて、これかよ。 ~~~~~~~~~~~~~~~~~~~~ わかったよ、一般向けにFor Each版に修正するよ。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    Dim objITEM As Object  'コントロールのオブジェクトを入れる変数
    If (Me![cntA] Mod 3) = 1 Then  '左端なら
        For Each objITEM In Me.Controls 'コントロールを取り出しループする
            If Left(objITEM.Name, 3) = "lab" Then '名前はラベル
                objITEM.Visible = Not pFLG
            Else
                objITEM.Visible = pFLG
            End If
        Next

        If pFLG = False Then 'まだラベルエリアを印刷してなかったら
            Me.NextRecord = False      'レコードの移動をまず止める
            pFLG = True  '印刷フラグを立てる
        End If
    Else
        pFLG = False  'その他の時
    End If

End Sub
これなら、ラベルと実データの切り替えも、 コントロール名の規則にしたがって作成すれば、 変更の少ないプログラムで済みますね。

/* * 6.終わりの挨拶(次回はアルのか?(爆)) */

よくわからなかったけど、何が今日は言いたかったの? えっと、 Ctrl+C , Ctrl+V でサクサク?コーディングするんだけど、 ちょっと待てよ、 コピー、貼り付け、一部変更、 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ なんてプログラムには、一工夫する余地があるのでは? って話でした。 まぁ、キーボード打つのが早い、エディター使うのが早い そんな若いプログラマーにトータル的に勝つには、 変更が来たとき、キーボード打量を減らす(もしくは打たなくていい) そんなプログラム作りたいよね、 30代のキーボード打ち込み遅いおっさんプログラマーとしては(爆) 何か読者の心に残れば、うれしいです。 *私の独り言をうまく消化してくださいね。 手前味噌プログラム発表したいよねのKen3でした。 ~~~~~~~(↑オイオイ)


ページフッター

ここまで、読んでいただきどうもです。ここから下は、三流君のホームページの紹介・案内です
目的の情報が見つかったか?少々心配しつつ、、、

リンクや広告など

項目別に本音?それとも建て前?的な記事をまとめました。

気になったジャンル↓を選択してください。
[ルーキー rookies]・・・ 新人さん達 初心者さんへ
[学ぶ study]・・・学習、技術の取得
[仕様書 doc]・・・仕様書・設計書関係の話
[共同作業 team]・・・チーム、グループ作業
[プログラムは心? spirit]・・・プログラマー 心・気質・魂

[掲示板デビューしようぜ bbs]・・・掲示板関係の話、質問者・回答者の気持ちほか
[昔はできた seo]・・・三流式の効果無しSEOとアフィリエイト
[仕事や作業、転職 job]・・・仕事や転職、評価、作業など
[その他 etc]・・・その他 分類外の記事

※↑文章の味付けが変わっていて、お口に合うかわかりませんが。。。
※※読んで、気分を悪くされたらスミマセン。

Blogとリンク:[三流君の作業日記]/ [愚痴(Bookmark)]/ [広告Blog(Bookmark)]



[三流君(TOP ken3.org へ戻る)] / [プログラマー業務の愚痴] / [バックナンバー 一覧]