コードを短く書く努力をすると、テストが省ける

まぁ、がしがしとタイピングするのも楽しいけど、私は作業量を考えて短くするのが好きです。
行数にするとアウトプットの量が減るんですけどねw、気にせず。

こんな風な画面で、マウスをポイントしたとき(MouseEnter と MouseLeaveイベント)の時にステータスバーにメッセージを表示します。
あと、チェックボックスを切り替えた時に、各ボタンの有効/無効が変えられます。

ざっと、ソースコード。何故か VB で(笑)

Public Class Form1

	Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		' 有効/無効を設定
		InitEnableMode()
		' 動的にイベントを追加
		AddHandler RadioButton1.CheckedChanged, AddressOf RadioButton1_CheckedChanged
		AddHandler RadioButton2.CheckedChanged, AddressOf RadioButton1_CheckedChanged
		AddHandler RadioButton3.CheckedChanged, AddressOf RadioButton1_CheckedChanged

		' ステータスバーの設定
		InitStatusBar()
		' イベントを追加
		Dim items As New List(Of Control)
		items.Add(Button1)
		items.Add(Button2)
		items.Add(Button3)
		items.Add(ComboBox1)
		items.Add(TextBox1)
		items.Add(TextBox2)
		items.Add(TextBox3)
		For Each c In items
			AddHandler c.MouseEnter, AddressOf Button1_MouseEnter
			AddHandler c.MouseLeave, AddressOf Button1_MouseLeave
		Next
	End Sub

	''' <summary>
	''' 有効/無効を設定
	''' </summary>
	''' <remarks></remarks>
	Public Sub InitEnableMode()
		Dim o As Boolean = True
		Dim x As Boolean = False

		'' Mode 1, 2, 3, コントロールの順で指定
		SETMODE(o, o, o, Button1)
		SETMODE(o, o, x, Button2)
		SETMODE(o, x, x, Button3)
		SETMODE(o, x, x, ComboBox1)
		SETMODE(o, x, x, TextBox1)
		SETMODE(x, o, o, TextBox2)
		SETMODE(x, o, o, TextBox3)

	End Sub

	Private _modes As New List(Of List(Of Object))
	Public Sub SETMODE(ByVal ParamArray params As Object())
		Dim max As Integer = params.Length
		Dim items As New List(Of Object)
		items.Add(params(max - 1))
		For i As Integer = 0 To max - 2
			items.Add(params(i))
		Next
		_modes.Add(items)
	End Sub

	Public Sub ChangeMode(ByVal mode As Integer)
		For Each items As List(Of Object) In _modes
			Dim c As Control = CType(items(0), Control)
			c.Enabled = CType(items(mode + 1), Boolean)
		Next
	End Sub
	Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
		If sender Is RadioButton1 Then
			ChangeMode(0)
		ElseIf sender Is RadioButton2 Then
			ChangeMode(1)
		ElseIf sender Is RadioButton3 Then
			ChangeMode(2)
		End If
	End Sub


	Class STATMSG
		Public cont As Control
		Public msg As String
	End Class
	Private _status As New List(Of STATMSG)
	''' <summary>
	''' フォーカス時のメッセージを設定
	''' </summary>
	''' <param name="c"></param>
	''' <param name="msg"></param>
	''' <remarks></remarks>
	Public Sub SETSTATUS(ByVal c As Control, ByVal msg As String)
		Dim sm As New STATMSG() With {.cont = c, .msg = msg}
		_status.Add(sm)
	End Sub

	Public Sub InitStatusBar()
		SETSTATUS(Button1, "先頭のボタンです")
		SETSTATUS(Button2, "真ん中のボタンです")
		SETSTATUS(Button3, "一番舌のボタンです")
		SETSTATUS(ComboBox1, "項目を選択します")
		SETSTATUS(TextBox1, "名前を入力します")
		SETSTATUS(TextBox2, "年齢を入力します")
		SETSTATUS(TextBox3, "住所を入力します")
	End Sub

	Public Sub ChangeFocus(ByVal sender As Object, ByVal b As Boolean)
		If b = False Then
			ToolStripStatusLabel1.Text = ""
		Else
			For Each cm In _status
				If cm.cont Is sender Then
					ToolStripStatusLabel1.Text = cm.msg
				End If
			Next
		End If
	End Sub

	Private Sub Button1_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs)
		ChangeFocus(sender, True)
	End Sub
	Private Sub Button1_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs)
		ChangeFocus(sender, False)
	End Sub
End Class

眠たいので、詳しい解説は後ほどやる…かもしれず。

メモ的に書いておくと、モードの設定のフォーマットがミソです。

	''' <summary>
	''' 有効/無効を設定
	''' </summary>
	''' <remarks></remarks>
	Public Sub InitEnableMode()
		Dim o As Boolean = True
		Dim x As Boolean = False

		'' Mode 1, 2, 3, コントロールの順で指定
		SETMODE(o, o, o, Button1)
		SETMODE(o, o, x, Button2)
		SETMODE(o, x, x, Button3)
		SETMODE(o, x, x, ComboBox1)
		SETMODE(o, x, x, TextBox1)
		SETMODE(x, o, o, TextBox2)
		SETMODE(x, o, o, TextBox3)

	End Sub

bool 値を「o」と「x」に割り当てているのは、こんな風に表形式で設定したいからです。かつて、VC++ の時に作ったノウハウです。その時には、define を使ったり外部ファイルを include したりしたのですが、vb ではできません。ture, false を使ってもいいのですが、visual studio が勝手にフォーマットしてしまうから、桁がずれるんです。なので、こんな風に「o」と「x」を使うわけです。
なんとなく分かり易いですね。
モードが増えた場合は、行を増やせばいい訳です。

同じようにステータスバーの切り替えの設定も書けます。

	Public Sub InitStatusBar()
		SETSTATUS(Button1, "先頭のボタンです")
		SETSTATUS(Button2, "真ん中のボタンです")
		SETSTATUS(Button3, "一番舌のボタンです")
		SETSTATUS(ComboBox1, "項目を選択します")
		SETSTATUS(TextBox1, "名前を入力します")
		SETSTATUS(TextBox2, "年齢を入力します")
		SETSTATUS(TextBox3, "住所を入力します")
	End Sub

こんな風に、SETSTATUS 関数を作ります。クラスを作って new SetStatus() With { … } な形で書いてもよいのですが、new やらクラス名やらを設定するのが面倒ですよね。所詮、使い捨ての関数ですから、べたべたに書いてしまいます。

		' イベントを追加
		Dim items As New List(Of Control)
		items.Add(Button1)
		items.Add(Button2)
		items.Add(Button3)
		items.Add(ComboBox1)
		items.Add(TextBox1)
		items.Add(TextBox2)
		items.Add(TextBox3)
		For Each c In items
			AddHandler c.MouseEnter, AddressOf Button1_MouseEnter
			AddHandler c.MouseLeave, AddressOf Button1_MouseLeave
		Next

マウスイベントも、こんな風にまとめて書いてしまいます。Handles に書いてもいいのですが、数が少ないときはいいけどこんな風に多くなると大変ですよね。なので、使い捨てのリストを使ってどしどしと追加します。

なんで、私がこんなコードを書くのかというと、

  • 使い捨てのコードは、効率よりも分かり易く書く。
  • 分かり易く書くと、あとからの変更がしやすい。
  • コードを見て分かり易いと、テストを省略できる。

からです。
コントロールの有効/無効の処理なんかは、if 文と control 名を使ってずらずらと書き並べることはできるのですが、それをやってしまうと、

  • 抜けがあると、何処が悪いのか分かりづらい。
  • 抜けがでやすいので、テストする必要がある。

ってことが理由なのです。先のように(トリッキーではありますが)あたかも Excel で設定しているように x と o を使って桁を揃えていくと、抜けが明確になります。

コードを短くすると生産性が悪くなるという弊害がw出ますが、まぁ、タイピングするのが仕事ではないので、昔から短いコードをたくさん書きます。そう、プログラマの仕事はコードを書くことではなくて、動くプログラムを作ることですからね、ってことです。

カテゴリー: 設計, 雑談, xUnit パーマリンク

コードを短く書く努力をすると、テストが省ける への3件のフィードバック

  1. konica のコメント:

    <プログラマの仕事はコードを書くことではなくて、
    <動くプログラムを作ることですからね

    確かにタイピングするのが仕事じゃないですね。
    現状、未熟な私は短いコードでその時、ウホ!できた!と喜ぶと・・・
    その後修正でアレアレする私がいる(´・ω・)ス

    • masuda のコメント:

      いやぁ、タイピングを主にする「コーダー」とか「パンチャー」とか「タイピスト」なる方もいらっしゃいますから。ただ、無駄にたくさんのコードを書いている場合(自分も含めて)、

      1.たくさんの行数ができる。
      2.おお、たくさん仕事をやった(やってる)

      で評価されるのが曲者で、自己満足も入っちゃう。これが困りものです。
      短すぎるコードは、one liner とかw 究極的には、c とか c# は改行がいらないので、1行で書けるって荒業がありますけどね。1行だけど、ファイルの大きさは、1MB あるとか。

  2. masuda のコメント:

    あと、オフレコですが(ここに公開しているけど)、
    コーディングを外注するときに、行数を少なくするマクロを提供して、外注費用を減らすという技があります。大抵、コードの行数で見積もりを出すので、行数が減ると見積もり金額が減るというのを、逆手に利用するということで。

コメントは停止中です。