ソースコードの重複の排除を関数で学ぶ

「ソースコードから重複を排除して保守性を高める」という考え方は、実務で良いコードを書く上で重要な考え方です。
この考え方が身に付かない内はオブジェクト指向の理解も不十分になるのですが、いきなりオブジェクト指向から入るとこの考え方の重要性がわかりにくくなることがあります。

そこで、ソースコードから重複を排除することの意義を、関数の使い方から学ぶことが有効になることがあります。

今回は、関数を使うことでソースコードから重複を排除し、保守性が高まる例を挙げていきたいと思います。
(サンプルコードはJavaで記述します)


今回のサンプルコードでは、複数の商品の販売価格を計算します。
まずは関数を使わないサンプルコードから書いていこうと思います。

【サンプルコード(関数未使用・修正前)】

・FunctionTestMain.java

【実行結果】


先ほどのソースコードに対して、「店舗独自の割引額を考慮する」という修正を入れていきます。

関数を使用しない場合、割引額(discountRate)を掛けるという修正を複数個所に入れることになります。
これが、ソースコードに重複が発生している状態です。

ソースコードに重複が発生していると、一部だけ修正を漏らすことによるバグに繋がりやすくなります。
このバグを潰すために、テストする範囲も広がってしまいます。

【サンプルコード(関数未使用・修正後)】

・FunctionTestMain.java

【実行結果】


次に、ソースコードを一旦修正前の状態に戻して、関数を入れていきます。

販売額を計算する関数(salesPriceCalc)を入れることで、ソースコードから重複を取り除くことができています。

【サンプルコード(関数使用・修正前)】

・FunctionTestMain.java

【実行結果】


関数を使用したソースコードに対して、先ほどと同じように割引額を考慮する修正を入れます。

重複が関数により排除されているので、割引額を入れる修正は1カ所で済んでいます。
修正箇所が減っているため、修正漏れを心配する必要がなくなり、ソースコードの保守が容易になっています。
言い換えると、時間をかけずにバグが出にくい修正を行うことができるようになります。
修正が繰り返される実務のソースコードでは、これは重要なことです。

【サンプルコード(関数使用・修正後)】

・FunctionTestMain.java

【実行結果】


今回解説したことは、実際の新人研修でも教えることが多いです。
このような簡単な例を用いることで、ソースコードの重複の排除について、わかりやすく説明することができます。


ところで、突然の発表なのですが、このブログでの私の記事はこれが最後となります。
このブログの記事を読んだことがある、と意外な所から声をかけていただくこともあり、大変嬉しく思っています。
少しでも皆様のお役に立てていたのであれば幸いです。

今まで記事を読んでいただき、ありがとうございました!

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

COBOLで使われているテクニックは過去のもののように思われがちですが、現在でもちょっとしたツールを作る時に役立ちます。
WindowsOS環境の場合は、ちょっとしたツールはC#で作るのが便利なので、今回はC#でCOBOLのマッチング処理を実装してみました。

今回は、下記の記事を参考に実装しています。
マッチング処理のロジック – サイゼントの技術ブログ

HIGH-VALUEを使う代わりにEOFを示すフラグ変数を使用しているので、その分だけ処理が複雑になっていることには注意してください。
また、この記事に限りませんが、ソースコードをコピペする場合は、「[」を「[」、「]」を「]」、「>」を「>」、「<」を「<」に変換するようにお願いします。

【フォルダ構成】

【ソースコード】

・execute.bat

・matching.cs

【実行前のファイル】

・files\master.csv

・files\transaction.csv

【実行結果】

execute.batをダブルクリックして実行する。

・files\matched.csv

・標準出力


Windows OSで作業や運用を行う場合は、C#を使いこなせると何かと便利です。
C#でツールを使う時に便利なソースコードは、これからも公開していきたいと思います!

文字コードの入門

この記事では、文字コードに関する初歩的な内容について簡単に書いていきます。

1.文字コードの概念とコード体系

コンピューターで取り扱う文字には、それぞれコードが割り振られています。
コードは1~4バイトの情報として取り扱われ、1バイトの文字は1バイト文字、2~4バイトの文字はマルチバイト文字と呼ばれます。
原則として、半角英数字記号は1バイト文字として扱われ、それ以外の文字はマルチバイト文字として扱われます。
(ここでは詳しく触れませんが、半角カナや人間には読めない制御文字は、1バイト文字のこともあればマルチバイト文字のこともあります)
これらの情報は、16進数で表現されることが多いです。また、プログラム上では、10進数で表現されることも多いです。

どの文字にどのコードが割り振られるのかは、コード体系によって決まります。

1バイト文字に関しては、今日のPCではASCIIというコード体系が使われます。
ASCIIにて、どの文字にどのコードが割り振られているのかは、以下の表から確認することができます。
(例えば、「A」には「0x41」(10進数で「65」)が、「a」には「0x61」(10進数で「97」)が割り振られています)
https://ja.wikipedia.org/wiki/ASCII

また、ホストコンピューターでは、1バイト文字にEBCDICという別のコード体系が使われます。
EBCDICの表は以下の通りであり、ASCIIとは異なる割り振られ方をしていることがわかります。
(例えば、「A」には「0xC1」(10進数で「193」)が割り振られています)
https://ja.wikipedia.org/wiki/EBCDIC

マルチバイト文字については、今日ではUTF-8やShiftJISといったコード体系が使われることが多いです。
(マルチバイト文字に関しては、この記事では詳細を割愛します)

2.ソースコード上で文字コードを取り扱う例

ソースコード上でも、文字コードを取り扱うことができます。
と言うより、文字は内部的には文字コードであり、「A」や「a」といった表示は人間が読みやすいように表現しているものです。

以下は、「A」や「a」といった文字が内部的にどのような文字コードを持っているのかを表示するJavaのプログラムです。
ASCIIコード表通りの文字コードが割り振られていることを確認できます。

■ソースコード

・CharCode1.java

■実行結果

また、文字の比較も、文字コードにより行うことができます。
以下は、「ABC」という文字列を前から1文字ずつ読み込み、「B」の文字を読みこんだ時だけ表示を行うJavaのプログラムです。

■ソースコード

・CharCode2.java

■実行結果

3.文字コードを意識する理由

ここで、「なぜプログラミングで文字コードを意識する必要があるのか」と疑問を持った方もいらっしゃるかもしれません。
確かに、人間には読みにくい文字コードを使ったプログラミングをするよりも、文字を直接使ったプログラミングの方が望ましいように思えます。
例えば、この記事で2つ目に取り上げたソースコード(CharCode2.java)では、文字コードを使用しなくても文字コードを使った時のような制御を実現でき、それならば文字コードを使った制御をしない方が望ましいように思えます。

それでも文字コードを意識する一番の理由は、バイナリの制御文字を取り扱うために必要だからです。
文字には、人間が読める文字の他に、コンピューターに命令を送るための制御文字が存在します。
多くの人にとって一番馴染みがある制御文字の一つが「改行文字」です。
コンピューターが改行文字を読みこむと、文章の改行が行われます。
(この記事が正しく改行されて読みやすくなっているのも、この「改行文字」のおかげです)
改行文字はOSによって割り振られている文字コードが異なりますが、Unix/Linuxの場合は「10」が割り振られています。
この文字は、プログラム上で”A”や”a”といった形で記述することができず、プログラミング言語やライブラリでサポートされない場合は、文字コードを参照しないと改行文字であるか否かを判定できません。

例えば、Javaで絵文字を含む文字列を1文字ずつ切り取る場合に、文字コードの参照が必要になります。
解説やコード例は以下の記事に書いています。
java:Unicodeの絵文字をjavaで取り扱う


いかがでしたでしょうか。

文字コードについてプログラミングの入門書に書かれていることは少ないですが、実務では度々目にします。
実務でプログラミングをするのであれば、文字コードについても早めに勉強しておくことをお勧めします。

SQL_select文の結果の結合等(集合演算子)

今回は、select文の結果を結合する文法の紹介です。
結果を結合するためには、集合演算子のUNION(重複排除したい場合はUNION ALL)を用います。
運用作業やプログラミングで複数のselect文の結果を1回のSQL文発行で取得したいことがあるので、知っておくと便利です。

ついでに、UNIONやUNION ALL以外の集合演算子についても紹介します。

【文法】

※集合演算子には以下のようなものがある

・UNION

前後のselect文の結果を結合する。
重複する結果は1行にまとめられる。

・UNION ALL

前後のselect文の結果を結合する。
重複する結果はまとめられない。

・MINUS、EXCEPT

前のselect文の結果から後のselect文の結果を取り除く。
OracleはMINUS、それ以外はEXCEPTを用いる。
(MySQLではサポート外)

・INTERSECT

前のselect文の結果と後のselect文の結果で一致するものだけを抽出する。
(MySQLではサポート外)

※「order by」は個別のselect文にはかからず、集合演算子で結合した結果全体にかかる。

【対象テーブル例】

・A支店商品

・B支店商品

【使用例】

・UNION

・UNION ALL

・MINUS(EXCEPT)

・INTERSECT


いかがでしたでしょうか。

今回は、UNIONに代表される集合演算子について記事を書きました。
何回かに分けて基本的なSQLの書き方に関する記事を書いてきましたが、これが最後になります。
これまで書いてきた文法は何れも実務では頻出なので、運用作業に携わっている人は特に覚えておいた方が良いものばかりです。知らない・使い方があやふやな文法があれば、これを機に覚えることをお勧めします。

これからも、様々な角度から役に立つ記事を書いていきたいと思います!

SQL_副問合せ・相関副問合せ

今回は副問合せと相関副問合せの紹介です。
この文法を用いると、問い合わせの結果を別の問い合わせに使い回すことができるようになり、複雑な問い合わせを1本のSQLで書けるようになります。

副問合せは相関副問合せよりも文法的に簡単で、実務、特に運用作業では頻出です。
また、性能面を考慮すると相関副問合せを使った方が良いケースが多いため、相関副問合せもプログラミングでは良く使われます。

なお、今回は紹介しませんが、副問合せはFROM句にも書くことができます。

【文法】

・副問合せ(単一行を返す場合のみ使用可能)

・副問合せ(副問合せの何れかの結果と一致することを確認)

・副問合せ(副問合せのどの結果とも一致しないことを確認)

・副問合せ(副問合せの全ての結果と比較し、全ての結果よりも(大きい、小さい等))

・副問合せ(副問合せの何れかの結果よりも(大きい、小さい等))

※SOMEの代わりにANYを使用しても良い

・相関問い合わせ(副問合せ部で存在する行のみ抽出)

※上記は正式な文法ではないが、通常は上記のように使う
※EXISTSの前のNOTをつけると存在しない行のみ抽出することができる
※EXISTSの中のSELECT文のカラム指定は問わない(1でなくても良い)

【対象テーブル例】

・商品

・消費者テスト結果

・合格基準点

【使用例】

asは省略可能である。
実務でも試験でも使用頻度が高い文法のみ例を記載する。

・=演算子

・不等号演算子

・IN句

・EXISTS句

※上記のIN句の例と同じ結果となる

【性能について補足】

EXISTS句と同様のことはIN句でも可能だが、性能面で違いが出ることが多い。
細かい所はRDBMSによって異なるため、最終的にはRDBMSの特性を調べたり実行計画を取得したりしながらチューニングするべきであるが、一般的に以下のようなことが言える。

1.実行順の違い

原則として件数の絞り込みはなるべく早い段階で行うべきであり、少ない件数に絞り込むことができる条件は先に実行するべきである。
例えば、100件中10件まで絞り込める条件と、100件中90件までしか絞り込めない条件がある場合、100件中10件まで絞り込める条件を先に実行すれば後に実行される条件はその10件(以下)のみ対象とすれば良くなるので、その方が性能が良くなる。
IN句とEXISTS句ではこの実行順が異なり、先に副問合せが実行されるのがIN句、後で副問合せが実行されるのはEXISTS句なので、副問合せで条件を絞り込めるか否かでどちらの句を使うのかを決めるべきである。

2.インデックスの使用有無

IN句、特にNOT IN句については、インデックスを使用しない逐次検索が行われてしまうことが多い。
そのため、一般論として、インデックスが使われやすいEXISTS句の方が性能が良くなることが多い。


いかがでしたでしょうか。

今回は、SQLでの副問合せと相関副問合せについて記事を書きました。
プログラムでSQLを発行する場合は複数回問い合わせを発行してその結果をプログラム側で突き合わせることの方が多いかもしれませんが、運用作業では重宝します。

複数の問い合わせを1つの問い合わせで済ませる文法としては、UNIONのような集合演算子も良く使います。
これは次回取り上げたいと思います!