【案内】小説『エクストリームセンス』について

 小説『エクストリームセンス』は、本ブログを含めていくつか掲載していますが、PC、スマフォ、携帯のいずれでも読みやすいのは、「小説家になろう」サイトだと思います。縦書きのPDFをダウンロードすることもできます。

 小説『エクストリームセンス』のURLは、 http://ncode.syosetu.com/n7174bj/

2011年9月30日金曜日

簡単なソフトウェアを作ってみよう(5)

今日は、先に紹介したVB.NETのソースコードをEnterprise Architectでリバースしたクラスモデルを掲載します。

ClassModel
ClassModel posted by (C)Satohru

Employeeを永続化するXMLファイルはこんな感じです。


1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<?xml version="1.0" encoding="utf-8"?>
<root>
  <employee>
    <id>4</id>
    <name>たちつてと</name>
    <birthday>1957/07/11</birthday>
    <postid>1</postid>
  </employee>
  <employee>
    <id>88</id>
    <name>あいうえお</name>
    <birthday>1939/03/24</birthday>
    <postid>1</postid>
  </employee>
</root>


2011年9月25日日曜日

簡単なソフトウェアを作ってみよう(4)


データの永続化にはXMLファイルを採用しました。下記DataAccessクラスは、XMLファイルに対するデータアクセスを提供するクラスです。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
'データアクセス コンポーネント
‌ 
Imports System.Xml
‌ 
Public Class DataAccess
‌ 
    Private CurrentDirectory As String =
        System.IO.Directory.GetCurrentDirectory() & "\employee.xml"
    Private XMLDataFile As New XmlDocument
‌ 
    '==============
    'DataCreateメソッド
    Public Sub DataCreate(ByVal _employee As Employee)
        Dim oRoot As XmlNode =
            XMLDataFile.DocumentElement
        Dim oDocument As XmlElement =
            XMLDataFile.CreateElement("employee")
        Dim oID As XmlElement =
            XMLDataFile.CreateElement("id")
        Dim oName As XmlElement =
            XMLDataFile.CreateElement("name")
        Dim oBirthday As XmlElement =
            XMLDataFile.CreateElement("birthday")
        Dim oPostID As XmlElement =
            XMLDataFile.CreateElement("postid")
‌ 
        oID.InnerText = CType(_employee.ID, String)
        oName.InnerText = _employee.Name
        oBirthday.InnerText = CType(_employee.Birthday, String)
        oPostID.InnerText = CType(_employee.PostID, String)
‌ 
        With oDocument
            .AppendChild(oID)
            .AppendChild(oName)
            .AppendChild(oBirthday)
            .AppendChild(oPostID)
        End With
‌ 
        oRoot.AppendChild(oDocument)
        XMLDataFile.Save(CurrentDirectory)
    End Sub
‌ 
    '==============
    'DataUpdateメソッド
    Public Sub DataUpdate(ByVal Index As Integer,
                          ByVal TaegetEmployee As Employee)
        With XMLDataFile
            .SelectNodes("//name").Item(Index).InnerText =
                TaegetEmployee.Name
            .SelectNodes("//birthday").Item(Index).InnerText =
                CType(TaegetEmployee.Birthday, String)
            .SelectNodes("//postid").Item(Index).InnerText =
                CType(TaegetEmployee.PostID, String)
            .Save(CurrentDirectory)
        End With
    End Sub
‌ 
    '==============
    'DataDeleteメソッド
    Public Sub DataDelete(ByVal index As Integer)
        Dim TargetNode As XmlNode =
            XMLDataFile.SelectNodes("//root").Item(0)
        TargetNode.RemoveChild(TargetNode.ChildNodes(index))
        XMLDataFile.Save(CurrentDirectory)
    End Sub
‌ 
    '==============
    'FileLoadメソッド
    Public Sub FileLoad(ByVal list As System.Collections.IList)
        XMLDataFile.Load(CurrentDirectory)
        Dim nID As XmlNodeList =
            XMLDataFile.SelectNodes("//id")
        Dim nName As XmlNodeList =
            XMLDataFile.SelectNodes("//name")
        Dim nBirthday As XmlNodeList =
            XMLDataFile.SelectNodes("//birthday")
        Dim nPostID As XmlNodeList =
            XMLDataFile.SelectNodes("//postid")
‌ 
        Dim NodeIndex As Integer = 0
        For Each EmployeeNode In XMLDataFile.SelectNodes("//employee")
            Dim oEmployee As New Employee
            With oEmployee
                .ID = CType(nID(NodeIndex).InnerText, Integer)
                .Name = nName(NodeIndex).InnerText
                .Birthday = CType(nBirthday(NodeIndex).InnerText, Date)
                .PostID = CType(nPostID(NodeIndex).InnerText, Integer)
            End With
            list.Add(oEmployee)
            NodeIndex += 1
        Next
    End Sub
‌ 
    '==============
    'コンストラクタ
    Public Sub New()
        If System.IO.File.Exists(CurrentDirectory) = False Then
            Dim XMLFileFormat As String =
                "<?xml version=""1.0"" encoding=""utf-8""?><root></root>"
            System.IO.File.WriteAllText(CurrentDirectory, XMLFileFormat)
        End If
    End Sub
End Class

2011年9月24日土曜日

訂正記事:オブジェクト指向の基本的効用

昨日アップした「オブジェクト指向の基本的効用」の中で誤りを見つけましたので訂正します。

同記事の中で、

「下記コードのように、構造体では実現できなかった振る舞いをクラスは実現してくれます。」

と記述していますが、赤字部分が間違いでした。
下記コードのように、VB.NETの構造体は振る舞いも実装できます。
詳しくはMSDNのStructure ステートメントに関する説明を参照してください。


1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
 'VB.NET構造体へのプロパティ、プロシージャの実装例
    Private Structure PersonStructure2
‌ 
        Friend ID As Integer
        Friend Name As String
        Friend Birthday As Date
‌ 
        Friend ReadOnly Property Age() As Integer
            Get
                Dim _year As Integer =
                CType(Today.ToString("yyyy"), Integer)
                Dim _MMdd As Integer =
                    CType(Today.ToString("MMdd"), Integer)
                Dim _birthYear As Integer =
                    CType(Birthday.ToString("yyyy"), Integer)
                Dim _birthMMdd As Integer =
                    CType(Birthday.ToString("MMdd"), Integer)
                Dim _age As Integer = _year - _birthYear
                If _MMdd < _birthMMdd Then
                    _age = _age - 1
                End If
                Return _age
            End Get
        End Property
‌ 
        Friend Sub Initialize()
            ID = 0
            Name = ""
            Birthday = Nothing
        End Sub
‌ 
    End Structure
‌ 
    'PersonStructure2の使用
    Public Sub Test()
‌ 
        Dim foo As PersonStructure2
        With foo
            .ID = 1
            .Name = "Satohru"
            .Birthday = #5/25/1967#
        End With
        MessageBox.Show(foo.Age)
‌ 
        foo.Initialize()
        MessageBox.Show(foo.Name)
‌ 
    End Sub

アジャイルに関するつぶやきを見てみよう


2011年9月23日金曜日

オブジェクト指向に関するつぶやきを見てみよう


オブジェクト指向の基本的効用


オブジェクト指向の基本的効用について、プリミティブな状態から順に見ていきましょう。

Practice1 「バラバラのデータ」
人について、属性{ ID、Name、Birthday }を扱うとします。
このサンプルでは、4行目から9行目までに扱う人数×属性数分の変数を定義しています。
いうまでもなく、これではコーディングが大変ですし、応用が利きません。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 '   Practice1 ---------------------
    Public Sub Practice1()
‌ 
        Dim ID_1 As Integer = 1
        Dim Name_1 As String = "Satohru"
        Dim Birthday_1 As Date = #5/25/1967#
        Dim ID_2 As Integer = 2
        Dim Name_2 As String = "Ayase"
        Dim Birthday_2 As Date = #3/24/1985#
‌ 
        Dim Message As String =
            "登録者は、" & Name_1 & "と" & Name_2 & "です。"
‌ 
        MessageBox.Show("Practice1" & vbCrLf & Message)
‌ 
    End Sub

Practice2 「データの構造化」
このサンプルでは、構造体を用いて「バラバラのデータ」を構造化しています。
Practice1より理解しやすいプログラムになり、間違いが起こりにくそうです。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
 '   Practice2 ---------------------
    Private Structure PersonStructure
        Friend ID As Integer
        Friend Name As String
        Friend Birthday As Date
    End Structure
‌ 
    Public Sub Practice2()
‌ 
        Dim Person1, Person2 As PersonStructure
        With Person1
            .ID = 1
            .Name = "Satohru"
            .Birthday = #5/25/1967#
        End With
        With Person2
            .ID = 2
            .Name = "Ayase"
            .Birthday = #3/24/1985#
        End With
‌ 
        Dim Message As String =
            "登録者は、" & Person1.Name & "と" &
            Person2.Name & "です。"
‌ 
        MessageBox.Show("Practice2" & vbCrLf & Message)
‌ 
    End Sub

Practice3 「構造化されたデータを束ねる」
次は、構造体の配列を3行目で定義しました。
このように構造化されたデータを配列に束ねることによって、
16行目のループ処理によってシステマチックなデータ処理が可能になります。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
  '   Practice3 ---------------------
    Public Sub Practice3()
        Dim Persons(1As PersonStructure
        With Persons(0)
            .ID = 1
            .Name = "Satohru"
            .Birthday = #5/25/1967#
        End With
        With Persons(1)
            .ID = 2
            .Name = "Ayase"
            .Birthday = #3/24/1985#
        End With
‌ 
        Dim Message As String = ""
        For i = 0 To Persons.Length - 1
            Message &= vbCrLf & Persons(i).Name
        Next
‌ 
        Message = "登録者は、" & Message & "です。"
‌ 
        MessageBox.Show("Practice3" & vbCrLf & Message)
‌ 
    End Sub

Practice4 「構造化されたデータに振る舞いを加える」
生年月日から年齢を求めたい。そんな時に Person.Age とコーディングできたら便利です。
そこで、次のようなPersonClassを作ります。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
Friend Class PersonClass
‌ 
    Private m_ID As Integer
    Private m_Name As String
    Private m_Birthday As Date
‌ 
    Friend Property ID() As Integer
        Get
            Return m_ID
        End Get
        Set(ByVal value As Integer)
            m_ID = value
        End Set
    End Property
‌ 
    Friend Property Name() As String
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
‌ 
    Friend Property Birthday() As Date
        Get
            Return m_Birthday
        End Get
        Set(ByVal value As Date)
            m_Birthday = value
        End Set
    End Property
‌ 
    Friend ReadOnly Property Age() As Integer
        Get
            Dim _year As Integer =
                CType(Today.ToString("yyyy"), Integer)
            Dim _MMdd As Integer =
                CType(Today.ToString("MMdd"), Integer)
            Dim _birthYear As Integer =
                CType(m_Birthday.ToString("yyyy"), Integer)
            Dim _birthMMdd As Integer =
                CType(m_Birthday.ToString("MMdd"), Integer)
            Dim _age As Integer = _year - _birthYear
            If _MMdd < _birthMMdd Then
                _age = _age - 1
            End If
            Return _age
        End Get
    End Property
‌ 
End Class

下記コードのように、構造体では実現できなかった振る舞いをクラスは実現してくれます。
 *上記取り消し線部分が間違っていましたので、訂正記事を掲載しました。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
   '   Practice4 ---------------------
    Public Sub Practice4()
        Dim oPerson1 As New PersonClass With {
            .ID = 1,
            .Name = "Satohru",
            .Birthday = #5/25/1967#}
        Dim oPerson2 As New PersonClass With {
            .ID = 2,
            .Name = "Ayase",
            .Birthday = #3/24/1985#}
‌ 
        Dim Message As String =
            oPerson1.Name & "の年齢は、" &
            oPerson1.Age.ToString & "歳です。" &
            vbCrLf &
            oPerson2.Name & "の年齢は、" &
            oPerson2.Age.ToString & "歳です。"
‌ 
        MessageBox.Show("Practice4" & vbCrLf & Message)
‌ 
    End Sub

Practice5 「クラスを束ねるとさらに便利に」
PersonClassのインスタンスを13行目でコレクションクラスに追加しています。
 *Public Sub Practice5()を含むクラスは、System.Collections.CollectionBaseを継承しています。
これにより For Each(19行目) やLINQ(27行目)により、より一層データを便利に扱うことができます。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
  '   Practice5 ---------------------
    Public Sub Practice5()
‌ 
        Dim oPerson1 As New PersonClass With {
            .ID = 1,
            .Name = "Satohru",
            .Birthday = #5/25/1967#}
        Dim oPerson2 As New PersonClass With {
            .ID = 2,
            .Name = "Ayase",
            .Birthday = #3/24/1985#}
‌ 
        With List
            .Add(oPerson1)
            .Add(oPerson2)
        End With
‌ 
        Dim Message As String = ""
        For Each v As PersonClass In List
            Message &= vbCrLf & v.Name
        Next
‌ 
        Message = "登録者は、" & Message & "です。"
‌ 
        MessageBox.Show("Practice5-1" & vbCrLf & Message)
‌ 
        Dim rs = From v As PersonClass In List Select v.Age
‌ 
        Message =
            "登録者は" & rs.Count & "名で、" &
            "平均年齢は、" & rs.Average & "歳です。"
‌ 
        MessageBox.Show("Practice5-2" & vbCrLf & Message)
‌ 
    End Sub

全体は下記のようにコーディングされています。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
Public Class Sample
‌ 
    Inherits System.Collections.CollectionBase
‌ 
    '   Practice1 ---------------------
    Public Sub Practice1()
‌ 
        Dim ID_1 As Integer = 1
        Dim Name_1 As String = "Satohru"
        Dim Birthday_1 As Date = #5/25/1967#
        Dim ID_2 As Integer = 2
        Dim Name_2 As String = "Ayase"
        Dim Birthday_2 As Date = #3/24/1985#
‌ 
        Dim Message As String =
            "登録者は、" & Name_1 & "と" & Name_2 & "です。"
‌ 
        MessageBox.Show("Practice1" & vbCrLf & Message)
‌ 
    End Sub
‌ 
    '   Practice2 ---------------------
    Private Structure PersonStructure
        Friend ID As Integer
        Friend Name As String
        Friend Birthday As Date
    End Structure
‌ 
    Public Sub Practice2()
‌ 
        Dim Person1, Person2 As PersonStructure
        With Person1
            .ID = 1
            .Name = "Satohru"
            .Birthday = #5/25/1967#
        End With
        With Person2
            .ID = 2
            .Name = "Ayase"
            .Birthday = #3/24/1985#
        End With
‌ 
        Dim Message As String =
            "登録者は、" & Person1.Name & "と" &
            Person2.Name & "です。"
‌ 
        MessageBox.Show("Practice2" & vbCrLf & Message)
‌ 
    End Sub
‌ 
    '   Practice3 ---------------------
    Public Sub Practice3()
        Dim Persons(1As PersonStructure
        With Persons(0)
            .ID = 1
            .Name = "Satohru"
            .Birthday = #5/25/1967#
        End With
        With Persons(1)
            .ID = 2
            .Name = "Ayase"
            .Birthday = #3/24/1985#
        End With
‌ 
        Dim Message As String = ""
        For i = 0 To Persons.Length - 1
            Message &= vbCrLf & Persons(i).Name
        Next
‌ 
        Message = "登録者は、" & Message & "です。"
‌ 
        MessageBox.Show("Practice3" & vbCrLf & Message)
‌ 
    End Sub
‌ 
    '   Practice4 ---------------------
    Public Sub Practice4()
        Dim oPerson1 As New PersonClass With {
            .ID = 1,
            .Name = "Satohru",
            .Birthday = #5/25/1967#}
        Dim oPerson2 As New PersonClass With {
            .ID = 2,
            .Name = "Ayase",
            .Birthday = #3/24/1985#}
‌ 
        Dim Message As String =
            oPerson1.Name & "の年齢は、" &
            oPerson1.Age.ToString & "歳です。" &
            vbCrLf &
            oPerson2.Name & "の年齢は、" &
            oPerson2.Age.ToString & "歳です。"
‌ 
        MessageBox.Show("Practice4" & vbCrLf & Message)
‌ 
    End Sub
‌ 
    '   Practice5 ---------------------
    Public Sub Practice5()
‌ 
        Dim oPerson1 As New PersonClass With {
            .ID = 1,
            .Name = "Satohru",
            .Birthday = #5/25/1967#}
        Dim oPerson2 As New PersonClass With {
            .ID = 2,
            .Name = "Ayase",
            .Birthday = #3/24/1985#}
‌ 
        With List
            .Add(oPerson1)
            .Add(oPerson2)
        End With
‌ 
        Dim Message As String = ""
        For Each v As PersonClass In List
            Message &= vbCrLf & v.Name
        Next
‌ 
        Message = "登録者は、" & Message & "です。"
‌ 
        MessageBox.Show("Practice5-1" & vbCrLf & Message)
‌ 
        Dim rs = From v As PersonClass In List Select v.Age
‌ 
        Message =
            "登録者は" & rs.Count & "名で、" &
            "平均年齢は、" & rs.Average & "歳です。"
‌ 
        MessageBox.Show("Practice5-2" & vbCrLf & Message)
‌ 
    End Sub
‌ 
End Class
‌ 
‌ 
'   Practice4と5で使用するクラス
Friend Class PersonClass
‌ 
    Private m_ID As Integer
    Private m_Name As String
    Private m_Birthday As Date
‌ 
    Friend Property ID() As Integer
        Get
            Return m_ID
        End Get
        Set(ByVal value As Integer)
            m_ID = value
        End Set
    End Property
‌ 
    Friend Property Name() As String
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
‌ 
    Friend Property Birthday() As Date
        Get
            Return m_Birthday
        End Get
        Set(ByVal value As Date)
            m_Birthday = value
        End Set
    End Property
‌ 
    Friend ReadOnly Property Age() As Integer
        Get
            Dim _year As Integer =
                CType(Today.ToString("yyyy"), Integer)
            Dim _MMdd As Integer =
                CType(Today.ToString("MMdd"), Integer)
            Dim _birthYear As Integer =
                CType(m_Birthday.ToString("yyyy"), Integer)
            Dim _birthMMdd As Integer =
                CType(m_Birthday.ToString("MMdd"), Integer)
            Dim _age As Integer = _year - _birthYear
            If _MMdd < _birthMMdd Then
                _age = _age - 1
            End If
            Return _age
        End Get
    End Property
‌ 
End Class
‌