技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

PlantUMLの紹介

PlantUMLは、テキストからUMLの図を生成することができるツールです。
UMLをPlantUMLで書くことで、Gitでの管理が容易になり、差分比較もできるようになる、というメリットがあります。
 
下記のページにアクセスするだけで、すぐに使うことができます。
図の書き方(文法)についても説明されています。
https://plantuml.com/ja/
 
オンライン上で図を生成することが可能で、上記ページ中で試しに作ることができる他、「オンラインサーバ(https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000)」のページにアクセスすることで大きな画面で作ることができるようになります。
 
セキュリティや作業効率等の問題でオンライン上で図を生成したくない場合は、ローカル上で図を生成することもできます。
ローカル上で図を生成する方法は、「クイックスタートガイド(https://plantuml.com/ja/starting)」に書いてあります。
 
以下、試しに、シーケンス図を書いてみたものです。
javaでのスレッド制御(joinとsynchronized)(https://cyzennt.co.jp/blog/2019/12/07/java%e3%81%a7%e3%81%ae%e3%82%b9%e3%83%ac%e3%83%83%e3%83%89%e5%88%b6%e5%be%a1%ef%bc%88join%e3%81%a8synchronized%ef%bc%89/)」の「①のコメントアウトを外した場合(join)」のケースについて書いています。
 
【サンプルコード】
@startuml
participant ThreadMain as tm
participant ThreadBody_1 as tb1
participant ThreadBody_2 as tb2
participant ThreadCounter as tc
tm -> tb1 : スレッド起動
tb1 -> tc : カウントアップ
tc -> tc : カウント表示
rnote over tc
 ThreadBody_1による
 カウントアップ指示が
 あと4回繰り返される
endrnote
tm -> tb2 : スレッド起動
tb2 -> tc : カウントアップ
tc -> tc : カウント表示
rnote over tc
 ThreadBody_2による
 カウントアップ指示が
 あと4回繰り返される
endrnote
@enduml
 
【生成結果】

f:id:akira2kun:20220211211529p:plain

Vue.js:「算出プロパティ(computed) vs 監視プロパティ(watch)」を実際に書いてみた

Vue.jsの公式ドキュメントにて、算出プロパティ(computed) と 監視プロパティ(watch) の違いについて触れられています(https://jp.vuejs.org/v2/guide/computed.html)。
しかし、例となるコードはユーザー入力を受け付けないごく簡単な例であるため、computedとwatchの違いを実感するのが少し難しいのでは、と個人的に思いました。
そこで、私の方でユーザー入力を追加したより実践的なコードを書きましたので、公開します。
 
【画面の動き】
以下のように、2つのテキストボックスを用意しました。

f:id:akira2kun:20220122194916j:plain

 
テキストボックスに入力を行うと、入力した内容をスペース区切りでリアルタイムに表示されます。

f:id:akira2kun:20220122194941j:plain

 
【サンプルコード】
watchを使う場合
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vue.js - Test</title>
</head>
<body>

<div id="app">
  <input v-model="firstName">
  <input v-model="lastName"><br>
  {{ fullName }}
</div>

<script src="https://unpkg.com/vue"></script>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: '',
      fullName: ''
    },
    watch: {
      firstName: function (val) {
        this.fullName = val + ' ' + this.lastName
      },
      lastName: function (val) {
        this.fullName = this.firstName + ' ' + val
      }
    }
  })
</script>
</body>
</html>
 
・computedを使う場合
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vue.js - Test</title>
</head>
<body>

<div id="app">
  <input v-model="firstName">
  <input v-model="lastName"><br>
  {{ fullName }}
</div>

<script src="https://unpkg.com/vue"></script>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: ''
    },
    computed: {
      fullName: function () {
        return this.firstName + ' ' + this.lastName
      }
    }
  })
</script>
</body>
</html>
 
【computedとwatchの違いの補足】
公式ドキュメントでは、watchについて「命令的で冗長」と書かれています。
watchでは、監視対象のそれぞれの変数について、値が変わった時に実行する処理を記述する必要があります。
また、computedのように変数を定義するという形の記述ではないため、dataにて変数を別途定義する必要が出てきます。
watchを使用する場合は変数「fullname」をdataで別途定義しているが、computedを使用する場合は変数「fullname」をcomputedで定義できる)
そのため、watchでは記述が冗長になる傾向にあります。
 
しかし、公式ドキュメントに書かれている通り、watchでないと実装できない場合もあるので、使い分けが大事です。

サブシステムとは

1つのシステムでは、様々な業務を実現しています。
そして、場合によっては、業務毎でシステム内で別々のシステムに分かれていることがあり、この分かれているシステムのことを「サブシステム」と呼びます。
 
この記事では、サブシステムが生まれる理由や、サブシステム同士のデータのやりとりについて、一般的なことを説明していきたいと思います。
例として、架空の証券総合取引システムを挙げて説明したいと思います。
 
【サブシステムの例】
今回紹介する証券総合取引システムの例では、「勘定系サブシステム」「取引所接続サブシステム」「Web取引サブシステム」の3つに分かれています。
これらのサブシステムを合わせることで、現代の証券取引を実現しています。
 
それぞれのサブシステムでは、サーバーやRDBMSも分かれているのが一般的であり、一つの会社内・システム内であったとしてもあたかも別のシステムとして扱われています。

f:id:akira2kun:20220115163659j:plain
 
【サブシステムが生まれる理由】
サブシステムが生まれる理由としては主に2つあり、1つは業務の拡大、もう1つは事業の統合です。
以下では、それぞれの理由について詳しく説明します。
 
1.業務の拡大
時代や企業戦略と共に業務が拡大すると、既存のサブシステムを拡張するだけでは技術的に対応が難しく場合があります。
そのような場合に、拡大した業務についてサブシステムを構築して対応するのが望ましくなります。
 
例えば、証券総合取引システムの場合、1980年代までは証券会社の社員が人の手により証券取引所に注文を取り次いでいました。
当時は企業向けの大規模なシステムはメインフレームで構築するのが一般的であったため、メインフレームでシステムを構築することが多かったです。
 
しかし、1990年代に証券取引所がシステム化されることで、証券取引所のシステムとのインターフェースが必要になりました。
インターフェースを合わせるため、また性能要件を満たすために、既存のメインフレームのサブシステムとは別に新たなサブシステムを構築するのが一般的であったと思います。
 
また、2000年代に入ると、インターネットが普及し、個人投資家がWeb画面から直接取引をするのが一般的になりました。
Web画面からの直接取引についても、メインフレームのサブシステムでは実現が難しく、新たなサブシステムを構築するきっかけとなりました。
 
2.事業の統合
部署や会社を合併した場合、システムの一本化が求められます。
システムの一本化の方針の一つとして、お互いのシステムをサブシステムとして寄せ集めるという手法が取られることがあります。
このような理由によっても、サブシステムは生まれます。
 
今回挙げている例では、証券総合取引システムを扱う会社同士の合併により、サブシステムが生まれることが考えられます。
例えば、Web取引サブシステムについて、証券会社毎に見た目や機能が異なるため、証券会社毎でサブシステムを分けるというケースが考えられます。
 
また、現実の例としてはみずほ銀行が有名です。
みずほ銀行は、銀行の合併により、複数のサブシステムに分かれています。
情報も多く出回っているので、調べてみると勉強になると思います。
 
【サブシステム同士のデータのやりとり】
前述の通り、サブシステムはあたかも別のシステムのようなものとして扱われているので、データのやりとりについても他者システムと同じような方法でやりとりが行われます。
一般的には、リアルタイムのやりとりと、定時のやりとりに分かれます。
 
1.リアルタイムのやりとり
これは、電文やAPIによって実現されます。
ある時点でのデータを取得したい場合、及びトランザクションデータが発生した場合に、電文やAPIによりデータを送受信します。
 
例えば、証券会社の社員の手により勘定系サブシステムから注文が入力された場合、勘定系サブシステムから取引所接続サブシステムへ電文を送信することで、取引所接続サブシステムから証券取引所への発注が可能になります。。
また、Web取引サブシステムで株価情報を表示したい場合、取引所接続サブシステムのAPIを呼び出すことで、取引所接続サブシステム内で保持されている株価情報を取得できます。
 
2.定時のやりとり
これは、主にファイルの送受信によって実現されます。
サブシステム内で取りまとめたデータをファイルとして連携することで、サブシステム間のデータの同期を効率的に行うことができます。
 
例えば、Web取引サブシステム内に蓄積された取引履歴をファイルとしてとりまとめて勘定系サブシステムへ送信することで、勘定系サブシステム側でも取引履歴を把握し、ハガキの出力や不正取引がなかったかの分析等が可能になります。

試験工程管理の概論

SI業界では、開発に関する知識や経験が不十分なメンバーを試験工程の管理者として任命することが少なくありません。
本来であれば、応用情報処理技術者試験(最低でも基本情報処理技術者試験)に相当する知識、及びその知識を実務で使った経験を備えた者を管理者として任命するべきだと思うのですが、そうすることができない事情もあると思います。
 
そこで、今回の記事では試験工程の管理に必要な知識の概要を書いていきます。
当記事では概要しか書きませんので、細かい所は別途書籍やWEBで調べて下さい。
また、現場毎で試験の進め方が微妙に異なりますので、現場の進め方に適宜合わせていただければと思います。
 
なお、当記事では、ウォーターフォール(要件定義→設計→製造→試験→リリース、という順番に沿って、数ヶ月~数年の大規模な開発プロジェクトを予定通りに進める開発手法)を前提とします。
アジャイル(要件をこまめに取り入れながら、1週間~数週間毎に小規模なリリースを繰り返す開発手法)の場合は、各々の開発者が試験に関しても自主的にコントロールする形になるので少し違う話になります。
(しかし、アジャイルのプロジェクトに関わる場合も、ウォーターフォールのプロジェクトで培った試験管理に関する知見を活かすことはできます)
 
【試験工程の分類】
試験工程はいくつかの工程(段階)に分かれます。
具体的には以下のように分かれます。
 
・単体試験(単体テストユニットテスト、UT)
単独のプログラムを対象とした試験。
この工程では、プログラムの開発者自らが試験を行うことが多い。
あるプログラムから別のプログラムを呼び出すことがあるが、どちらかのプログラムが未完成の場合は「スタブ」や「ドライバ」といった仮のプログラムが使用される。
「スタブ」は呼び出し先のプログラムに相当する仮のプログラムであり、「ドライバ」は呼び出し元のプログラムに相当する仮のプログラムである。
試験で使用される仮のプログラムについては、比較的新し目の技術を使う現場では「モック」(完成品のような見た目に見せかけた仮のプログラム)と呼ばれることも多い。
 
・結合試験(結合テスト、IT)
あるプログラムから別のプログラムへの呼び出しの箇所の担保を取ることに着目した試験。
単体試験の延長線上のような体制で行われることもあれば、専任のテストチームが試験を実施することもある。
 
・総合試験(総合テスト、システムテスト、ST)
プログラム等の改修を行ったシステムについて、システム全体の挙動を確認する試験。
人数の少ないプロジェクトである場合や技術的なサポートが必要な場合は開発者が試験実施に携わる場合もあるが、原則としては専任のテストチームが試験を実施する。
他システムとの連携についても、この段階で行う。
 
・受入試験(運用テスト、UAT)
改修後のシステムについて、実運用上の問題がないかを確認する試験。
システムの実際の利用者が試験を実施するが、利用者が一般ユーザー(エンドユーザー)である場合、受入側の会社の社員が代わりに試験を行う場合が多い。
 
それぞれの試験の工程がウォーターフォールのプロセスの中でどのような立ち位置にあるのかは別の記事(ウォーターフォールモデルとV字モデル(https://cyzennt.co.jp/blog/2019/10/26/%e3%82%a6%e3%82%a9%e3%83%bc%e3%82%bf%e3%83%bc%e3%83%95%e3%82%a9%e3%83%bc%e3%83%ab%e3%83%a2%e3%83%87%e3%83%ab%e3%81%a8%ef%bd%96%e5%ad%97%e3%83%a2%e3%83%87%e3%83%ab/))に投稿していますので、よろしければそちらもご参照ください。
 
【試験工程のスケジュール】
それぞれの試験の工程では、一般的に以下のような順番で作業が行われます。
(いくつかの作業は省略される場合があります)
 
試験の計画の策定

試験項目の作成

試験の準備の実施(テストデータやテスト環境やテスト用プログラムの作成)

試験の実施とバグ対応(バグが頻出する場合はこの時点で品質強化を行う場合がある)

上長への試験結果の報告(試験の一部再実施や品質強化を指示される場合がある)
 
それぞれの作業については、プロジェクト初期の見積もり段階で
「どのような役割の人を何人投入して、いつからいつまで作業を行うのか」
という計画が原則として立っています。
この計画については、それぞれの作業についての工数を積み上げて計画が立てられている場合もあれば、全体の工数を見積もった後に「単体試験は全体の20%、結合試験は全体の15%…」といった形で概略的に立てられている場合もあります。
見積もりと計画についての詳細は、別の記事(「見積もり概論」社内勉強会用のパワポの公開(https://cyzennt.co.jp/blog/2022/04/19/%e3%80%8c%e8%a6%8b%e7%a9%8d%e3%82%82%e3%82%8a%e6%a6%82%e8%ab%96%e3%80%8d%e7%a4%be%e5%86%85%e5%8b%89%e5%bc%b7%e4%bc%9a%e7%94%a8%e3%81%ae%e3%83%91%e3%83%af%e3%83%9d%e3%81%ae%e5%85%ac%e9%96%8b/))に投稿しています。
また、
「どのプログラムについてどのようなテストが必要か。そのためにどのような準備を行うのか。」
といった細かいことについては、各々の試験工程の序盤で行うことが多いですが、これは開発に携わっているメンバーでないと実施困難であり、必要となる知識も広範かつ各々のプロジェクトに寄る所も大きいので、この記事では詳細は書けません。
試験の準備の実施、その他バグ対応や品質強化の実作用についても同様に、開発に携わっているメンバーでないと実施困難な作業になります。
 
試験項目の作成方法については、いくつかのテクニックがあります。
キーワードだけ書いておくと、「ホワイトボックステスト/ブラックボックステスト」「デシジョンテーブル」といったテクニックが使われます。
(詳しくは、情報処理技術者試験の情報を参考にするのが良いと思います)
なお、試験項目を挙げ終わったら、試験の項目数を集計し、総件数/着手件数/完了件数を把握できるようにするべきです。
これは、試験工程の進捗を確認する上で必要になる情報の一つになります。
 
予定通りの試験実施を妨げる最も典型的な問題の一つとして
「特定のプログラムでバグが頻発し、そのことが原因で関連するプログラムの試験項目を消化できない」
という問題があります。
この問題の対処のために
「バグが頻発するプログラムについて追加レビューや追加テストを集中的に実施し、バグを見つけきって、見つかった全てのバグを直して、元の作業に戻る」
という追加作業を実施する場合があります。
この作業は、「品質強化」と呼ばれることが多いです。
品質強化については、別の記事(類似バグを効率的に見つけ出すための観点(https://cyzennt.co.jp/blog/2022/01/25/%e9%a1%9e%e4%bc%bc%e3%83%90%e3%82%b0%e3%82%92%e5%8a%b9%e7%8e%87%e7%9a%84%e3%81%ab%e8%a6%8b%e3%81%a4%e3%81%91%e5%87%ba%e3%81%99%e3%81%9f%e3%82%81%e3%81%ae%e8%a6%b3%e7%82%b9/))に詳しくテクニックを紹介しています。
 
【バグ管理表の運用】
それぞれの試験工程では、試験で見つかったバグを一覧にして管理するためのバグ管理表(不具合管理表、障害管理表)を用います。
バグ管理表はExcel若しくはスプレッドシートで作成されることが多く、フォーマットのイメージについてはWEBで調べることができます。
(プロジェクトによっては、BacklogやJiraといったチケット管理ツールが用いられる場合もあります)
 
バグ管理表には、一般的に、以下のような項目が含まれます。
それぞれの項目について、管理者が着目するべきポイントも合わせて説明していきます。
 
・通番、タイトル
見つかったバグを一意に特定するための情報です。
報告書上や会議の場でも、「『No.3 ○○システムで作成したユーザーでログインできない』の対応状況に関しましては…」といった書き方/言い方をするので、通番と完結なタイトルがあると便利です。
 
・発生日
バグが発見された日を記入します。
詳しくは後述しますが、試験工程の進捗を確認する一つの方法として、バグが何件発見されたのかを日毎に確認する、というものがあります。
その際に必要となる情報になります。
 
・ステータス
それぞれのバグについて、対応が現在どの段階にあるのかを記入します。
順番に書くと、最低限「起票」「原因調査中」「バグ修正中」「修正確認中」「対応完了」といった段階に分ける必要があるでしょう。
試験工程が予定通りに進んでいない場合、ステータスからどこがボトルネックになっているのかを掴める場合があります。
例えば、「起票」「原因調査中」「バグ修正中」で止まっているバグが多ければ、バグが多すぎて開発者の手が回っていないことが予想されますし、「修正確認中」で止まっているバグが多ければ試験担当者の手が回っていないことが予想されます。
どこがボトルネックになっているかで対策も変化します。例えば、開発者の手が回っていない状況で試験担当者を増やすことだけしても意味がありません(開発者が抱えている作業の一部を試験担当者に回す、という手を併用するなら意味があります)。
なお、バグではない事象が書き込まれたり、一つのバグが複数個所に重複されて起票されたりする場合もあるので、それを示すためのステータス(「バグではない」「重複起票」等)も必要でしょう。
詳しくは後述しますが、試験工程毎で見つけるべきバグ数を計測する場合があります。
その際に、バグとしてカウントする必要がないものは計測対象外とする必要があります。
 
・バグ内容
バグの内容やバグを発生させる手順を記入します。
ここを参照するのは基本的にバグを修正する開発者ですが、品質強化策を考えるヒントを得るための情報の一つにもなり得ます(ここからヒントを得るためには、開発に関する知見が必要になる場合があります)。
 
・原因、修正方法、対象プログラム
バグの原因や修正方法、修正する必要があるプログラム名、といった、バグ修正に必要な情報を記入します。
単純なバグであれば試験担当者が記入できる場合もありますが、基本的にはバグを修正する開発者が記入する項目であり、開発者のための項目でもあります。
この項目も、品質強化策を考えるヒントを得るための情報の一つになり得ます。
特に、対象プログラムについては、開発に関する知見が無くとも機械的に数を集計できる項目であるため、品質強化が必要なプログラムを特定する上で有用な項目になります。
 
・バグ修正予定日、完了予定日
開発者によるバグの修正が完了する予定日、及び試験担当者による修正確認が完了する予定日を記入します。
この項目は進捗管理に使用することができ、上がってきたバグの対応が試験期間内に終わるかどうかを確認することができます。
試験期間終了日が近づいてくればくるほど重要な意味を持ってくる項目です。
 
・発見するべき工程
そのバグがどの工程で発見するべきだったのか、ということを記入する項目です。
例えば、現在が総合試験工程である場合、システム内の修正対象外のプログラムとの連関で発生したバグなら「総合試験工程で見つけるべきバグ」となりますが、プログラム内の単純なロジックのミス(製造ミス、修正ミス)で発生したバグであれば「単体試験工程で見つけるべきバグ」となります。
これは、品質強化策を考える上で重要な項目になります。
ウォーターフォールでは「前工程が完全に終わってから次工程に進む」というのが前提となっており、この前提が崩れている場合、現工程の作業が前工程の問題により進めることができなくなり、予定通りに作業を完了させることができなくなります。
もし、前工程で発見するべきバグが多ければ、この前提が崩れているということになりますし、この前提が崩れているプログラムについては品質強化が必要となります。
これは私見ですが、目安として、前工程で発見するべきバグが全体の20~30%程度であれば品質強化を検討、50%を超えたら品質強化が必須、と考えて良いと思います。
現場によっては、品質強化を行うべきラインが計測・策定されている場合もあるので、そのような数字が現場あればその数字に従うべきです。
 
【バグの発生数と進捗の関係】
バグの発生数を見ることでも試験の進捗を見ることができますが、これには少々コツが必要です。
一般的には、一定のペースでバグの発生数し続けるということはなく、試験実施の初期はバグが発生しにくく、中期にバグが多量発生し、後期にバグの発生が少なくなる、という経緯を辿ります。
 
試験手順が確立していないため、バグがなかなか見つからない

試験手順が確立したため、順調にバグが見つかる

品質が向上し残りの試験項目もレアケースのみとなるため、バグが見つかりにくくなる
 
という流れに一般的にはなるため、先に挙げたような経緯を辿ることになります。
(これをグラフにして表したものをゴンペルツ曲線(信頼度成長曲線)と呼びます。詳しくは別の記事(ゴンペルツ曲線(信頼度成長曲線)とは(https://cyzennt.co.jp/blog/2021/01/01/%e3%82%b4%e3%83%b3%e3%83%9a%e3%83%ab%e3%83%84%e6%9b%b2%e7%b7%9a%ef%bc%88%e4%bf%a1%e9%a0%bc%e5%ba%a6%e6%88%90%e9%95%b7%e6%9b%b2%e7%b7%9a%ef%bc%89%e3%81%a8%e3%81%af/))を参照して下さい。)
 
もし、このような経緯を辿らない場合は、何かしらの問題があることを示しています。
 
例えば、初期からバグが大量発生している場合や、いつまでもバグが大量発生し続ける場合は、プログラムの品質が悪いことが伺えますので、品質強化を考える必要があります。
逆に、試験手順が確立したのにも関わらずバグが発見されない場合は、テストケースの作り込みが甘いケースが考えられます。
 
なお、試験工程で見つけるべきバグ数については、現場によっては計測・策定されている場合があります。
そのような数字があれば、それに従ってバグ発生数が多い/少ないを判断すれば良いですが、無い場合は、肌感覚で判断せざるを得ない場合もあります。これには、開発に関する知見や開発経験が必要になります。

保守作業をスピードアップする方法のまとめ

システム保守の作業では、通常のシステム開発の他に、システム・データの調査依頼や、データの抽出・補正の作業依頼等、様々な作業が行われます。
これらの作業は不定期に、時に大量に依頼されるため、作業のスピードアップが重要になります。
 
この記事では、作業をスピードアップする方法について、簡単に網羅的に書いていこうと思います。
 
【作業をスピードアップする方法】
1.タイピング速度の向上
 文章を書くにもコマンドを発行するにも、タイピングが必要になります。
 タイピング速度の向上は、作業のスピードアップに直接的に繋がります。
 
 タイピング速度を向上させるためには、ホームポジションを覚えた上で、
 タッチタイピングができる程にタイピングに慣れる必要があります。
 
 チャットやSNS等でタイピングに慣れている方であれば、問題はないと思います。
 普段PCを使わないという方は、タイピング練習ゲームで練習するのが良い方法です。
 
2.ショートカットキーの利用
 Windows端末はマウス操作でも作業を行えますが、
 ショートカットキーを使用してキーボードで作業をすると作業スピードが速まります。
 
 最も初歩的な例として、多くのソフトでは、
 Ctrl+Sの同時押しでファイルの上書き保存ができます。
 また、Explorer(フォルダやファイルを操作するWindows標準のソフト)では、
 F2キーを押すことでフォルダ・ファイル名の変更が可能です。
 他にも、数多くのショートカットキーが存在し、
 マウス操作でしか行えない作業は基本的に無いと思って良いぐらいです。
 
 全てのショートカットキーはとても覚えきれないですし、
 ショートカットキーを調べたり思い出したりするのに時間がかかっても本末転倒です。
 しかし、よく行う作業については、ショートカットキーを覚えた方が良いです。
 
3.作業のスピードアップを図るツールの利用
 作業のスピードアップを図るツールを利用するのも有効な手段です。
 
 例えば、ディスプレイに表示されている画面の中から一部を抜き出したい場合、
 PrintScreenキーで画面をキャプチャしてからMSPaintで必要な個所だけ切り出す、
 と作業すると時間がかかります。
 そこで、WindowsOSに標準でついてくる「Snipping Tool」を使用すると、
 マウスで選択した範囲のみキャプチャを取ることができるので、
 作業をスピードアップさせることができます。
 
 また、ファイルの差分を見たい場合、
 コマンドプロンプトのfcコマンドでも差分を見ることができます。
 しかし、フリーソフトの「WinMerge」を使った方が、
 差分比較結果が視覚的にわかり作業が速くなりやすいですし、
 フォルダごと比較したり3ファイル同時比較したりする機能もあります。
 
4.マクロやプログラム等で自動化する
 複雑な作業を繰り返し行う場合は、
 マクロやプログラム等を作ることで作業のスピードアップを図れる場合があります。
 
 作業のスピードアップに使えるものとしては、例えば以下のものがあります。
 ・Windowsバッチ、WindowsPowerShell
 ・C#(プログラム言語として生産性が高く、WindowsOS標準のコンパイラも使える)
 ・Excel 関数、ピボットテーブル、VBAマクロ
 ・サクラエディタ マクロ(操作を記録できる、コマンドラインからの実行も可能)
 
 基本的には手作業で行っていることを
 そのままマクロやプログラム等で自動化すれば良いのですが、
 複雑な作業の場合は自動化のアルゴリズムが思い浮かばない場合もあります。
 その場合は、C言語で良く書くファイルをシーケンスで1バイトずつ読み込む手法や、
 COBOLで良く書くコントロールブレイク処理・マッチング処理といった、
 昔のCUIプログラムで使われていた手法を応用すると、
 アルゴリズムを思い浮かびやすくなります。

COBOLのマッチング処理をC#で実装する

COBOLで使われているテクニックは過去のもののように思われがちですが、現在でもちょっとしたツールを作る時に役立ちます。
WindowsOS環境の場合は、ちょっとしたツールはC#で作るのが便利なので、今回はC#COBOLのマッチング処理を実装してみました。
 
今回は、下記の記事を参考に実装しています。
https://cyzennt.co.jp/blog/2019/06/01/%E3%83%9E%E3%83%83%E3%83%81%E3%83%B3%E3%82%B0%E5%87%A6%E7%90%86%E3%81%AE%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF/
 
HIGH-VALUEを使う代わりにEOFを示すフラグ変数を使用しているので、その分だけ処理が複雑になっていることには注意してください。
 
【フォルダ構成】
execute.bat
matching.cs
files┬master.csv
     └transaction.csv
 
ソースコード
・execute.bat
@echo off

C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe matching.cs
matching.exe
del matching.exe

pause
 
・matching.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Program
{
    class Program
    {
        // EOFフラグ
        static bool isSrmEof = false;
        static bool isSrtEof = false;
        
        static void Main(string args)
        {
            // ファイルオープン
            StreamReader srm = new StreamReader
                (@"files\master.csv", Encoding.UTF8);
            StreamReader srt = new StreamReader
                (@"files\transaction.csv", Encoding.UTF8);
            StreamWriter sw = new StreamWriter
                (@"files\matched.csv", false, Encoding.UTF8);
            
            // 先読みRead
            string
mRecord;
            string tRecord;
            mRecord = mRead(srm);
            tRecord = tRead(srt);
            
            // マッチング処理のループ
            while (!isSrmEof || !isSrtEof)
            {
                // masterのみの場合
                if ((!isSrmEof && isSrtEof) ||
                    (string.Compare(mRecord[0],tRecord[0]) < 0))
                {
                    // 何もしない
                    // master読み込み
                    mRecord = mRead(srm);
                }
                
                // マッチした場合
                else if ((!isSrmEof && !isSrtEof) &&
                         (string.Compare(mRecord[0],tRecord[0]) == 0))
                {
                    // transactionが次のキーに進むまでループ
                    while ((!isSrtEof) &&
                           !(string.Compare(mRecord[0],tRecord[0]) < 0))
                    {
                        // ファイル出力
                        sw.WriteLine(mRecord[1] + "," + tRecord[1]);
                        
                        // transaction読み込み
                        tRecord = tRead(srt);
                    }
                    
                    // master読み込み
                    mRecord = mRead(srm);
                }
                
                // transactionのみの場合
                else if ((isSrmEof && !isSrtEof) ||
                         (string.Compare(mRecord[0],tRecord[0]) > 0))
                {
                    // エラー出力
                    Console.WriteLine("Error:" + tRecord[0] + " is tran only.");
                    
                    // transaction読み込み
                    tRecord = tRead(srt);
                }
            }
            
            // ファイルクローズ
            srm.Close();
            srt.Close();
            sw.Close();
        }
        
        // MasterファイルRead
        static string
mRead(StreamReader srm)
        {
            if (srm.Peek() == -1)
            {
                isSrmEof = true;
                return null;
            }
            else
            {
                string str = srm.ReadLine();
                return str.Split(',');
            }
        }
        
        // TransactionファイルRead
        static string[] tRead(StreamReader srt)
        {
            if (srt.Peek() == -1)
            {
                isSrtEof = true;
                return null;
            }
            else
            {
                string str = srt.ReadLine();
                return str.Split(',');
            }
        }
    }
}
 
【実行前のファイル】
・files\master.csv
0000001,hoge                
0000002,fuga                
0000004,piyo                
 
・files\transaction.csv
0000001,20180401,00100,00010000
0000001,20180402,00200,00020000
0000003,20180401,00001,00001000
0000004,20180401,00002,00002000
 
【実行結果】
execute.batをダブルクリックして実行する。
 
・files\matched.csv
hoge                ,20180401
hoge                ,20180402
piyo                ,20180401

 
・標準出力
Microsoft (R) Visual C# Compiler version 4.7.3062.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, w
hich is no longer the latest version. For compilers that support newer versions of the C# programming language, see http
://go.microsoft.com/fwlink/?LinkID=533240

Error:0000003 is tran only.
続行するには何かキーを押してください . . .