komoto / エンジニアブログ

プログラミングについてアウトプットします。

LOCカウンターを開発する機会があったので公開します

LOCカウンター(行数計測カウンター)を開発する機会があったので、その時に開発したカウンターをgithubに載せたことを報告しておきます。

自分でも思うのですが、おそらく使いどころはかなり限られると思いますし、関数ベースでプログラミングしているので設計にちょっと失敗しているかもしれない。

後で、暇でやる気になったときクラスベースで書き換えようと思います。

でもせっかく開発したので、オープンにしたいと思ってこの記事書いてます!!

なお、LOCというのは行数と同義です。

ダウンロードはこちらから(counter.exe)

開発経緯

PROBE法という見積もり法で見積もりを行う際に、クラスのLOCを計測する必要があったため開発しました。

これまで納期などを意識することなく趣味のようなものでプログラムやアプリ開発をしてきたのですが、クラウドソーシングなどで案件を受注したいと思い、そろそろしっかりプロジェクト管理について学ぼうと考えました。

そこで、プログラムの追加&修正規模から総開発時間を見積もるPROBE法というものを勉強していました。

PROBE法では、まず新規に開発するクラスや再利用するクラスなどのLOCを用いてプログラム全体の追加&修正規模を求めます。 そしてその追加&修正規模から総開発時間を見積もることになります。

そのため、クラスや関数のLOCを計測するカウンタープログラムを開発しました。

LOCカウンタープログラムで計測できるもの

  • クラスのLOC
  • 関数FunctionのLOC
  • 1クラスのメソッド数

以下に実行例を記載しておきます。

f:id:tkmt-hrkz:20200610221936p:plain

LOCカウンターの仕様

  • OS=Windows10
  • 対象ファイル拡張子は .cpp または .h(それ以外だとプログラムが終了します)
  • コマンドプロンプトなどでcounter.exe yourprogram_filesで引数のファイルのLOCをカウントできます(引数はいくつでも可)
  • 空行コメントのみの行{ または }のみの行はカウントしません
  • LOCをカウントしたいクラスの定義箇所の先頭に// class beginを、末端に// class endを付ける(以下に具体例を示します)
  • LOCをカウントしたい関数の定義箇所の先頭に// function beginを、末端に// function beginを付ける(以下に具体例を示します)
  • クラス名、関数名の後ろに半角スペースを空けたあと引数を定義する(以下に具体例を示します)
  • 1クラスのメソッドを数えたい場合は、メソッドの定義箇所の先頭に// methodを付ける(以下に具体例を示します)

具体例

#include<iostream>
#include<string>
using std;

class HelloWorldObj // class begin
{
    private: 
        string str;
    
    public :
        HelloWorldObj()
        {
            str = "Hello World!";
        }
        
        HelloWorldObj(string name)
        {
            str = "Hello World! " + name;
        }

        void add_name(string name) // method
        {
            str += name;
        }

        void print() // method
        {
            cout << str << endl;
        }          
} // class end

int main (void) // function begin 
{
    HelloWorldObj hwo1 = new HelloWorldObj();
    HelloWorldObj hwo2 = new HelloWorldObj("taro");
    hwo1.print();
    hwo2.print();

    hwo2.add_name("ziro");
    hwo2.print();
    return 0;
} // function end

上記の内容のファイルmain.cppがあるとしたら

コマンドプロンプトでcounter.exe main.cppで実行したら

ファイル名 クラス・関数名 メソッド数 LOC 合計LOC
main.cpp
main 0 7
HelloWorldObj 2 11
23

となります。(これは手で数えてますので、間違ってたらごめんなさい)

実行ファイルはGithubにあります

興味ある方はこちらから

【Git】個人開発でよく使うGitコマンド

個人的によく使うGitコマンドをまとめてみました。

git init

ディレクトリをGit管理下に置くコマンドです。
これで、git関連ファイルが作成され、Gitを使ってディレクトリのバージョン管理ができるようになります。

git status

git管理下にあるディレクトリの変更箇所を一覧で見ることできます。
ステージング前のファイルでの変更箇所を見たい場合は、git diff
ステージング後のファイルでの変更箇所を見たい場合は、git diff -cached

git log

ローカルリポジトリのコミット履歴を表示する。これでコミットID、日時、コメント、変更箇所などが見れる。
基本的にはこれでいいと思う。
1行で簡易表示させたい場合は、git log --oneline
変更箇所と変更行数を表示したい場合は、git log -p

git add -A

git add ○で指定したファイルをaddできます。○=ファイルパス
git add -Aで、管理下にあるディレクトリで変更分のみ、addできます。
変更したかどうかに関わらず、git管理下にあるすべてのファイルをaddしたい場合は、git add . で出来ます。

git commit

git commitでaddして保存された内容にコメントを付けて、コミットできます。
git管理下にあるディレクトリの変更箇所のみをローカルリポジトリに保存できます。
オプションなし(= git commit)に実行することそのままエディターが開き、そこでコメントが打てます。

簡単なコメントを添えてコミットしたい場合は git commit -m "your comment " でコミットできます。

addとcommitを合わせて実行したい場合は、git commit -amend

git push

リモートリポジトリ(githubなど)にローカルリポジトリの内容を反映できます。

マスターブランチのものを反映したい場合は、git push origin masterとなります。

サブブランチのものを反映したい場合は、git push subbranch_nameで出来ます。

git pull

リモートリポジトリをローカルリポジトリに反映したい場合は、git pull origin masterで出来ます。
個人開発では2台のPCを使って開発を進めたいときなどに使えると思います。

git checkout -- filename

ステージング前の変更を取り消す。
つまり、追加・修正など変更を加えていたものすべてを最新のステージング後の状態に戻す。

git commit --amend

直前のコミットの内容を変更する。 直前のコミットを取り消す場合は、git revert HEAD
git revert HEAD^で、2つ前のコミットを取り消すこともできる。
これらはpushしてしまったコミットには、使えません。

git reset --hard HEAD

1つ前のコミットの状態に戻ることができる。
2つ前のコミットの状態に戻るには、git reset --hard HEAD^

git mv filename, git rm filename

git管理下にあるファイルを移動する。(git mv filename)
git管理下にあるファイルを削除する。(git rm filename)
git管理下にあるファイルの場合、通常のLinuxコマンドmv filename, rm filenameでは移動・削除はできない。

git config --global alias.〇 △

○=エイリアス名(短縮名)、△=コマンド名(add, commit, statusなど)
命令(add, commit, statusなど)にエイリアス(短縮名)を付けて実行できるようにする。
例)git config --global alias.ci commit
することで、git ciでコミットできるようになる。
設定したエイリアスを確認するには、git config -l

ここからは補足です。興味ある方は見てみて下さい。

add, commit, pushは具体的に何してるのか

まずはGitの仕組みについて簡単に説明するよ

Gitには現在作業をしているGit管理下のディレクト「ワーキングツリー」
バージョンを管理したいファイルを置いておく「インデックス」(ステージングエリア)
過去の変更履歴を管理したりリモートリポジトリに送る変更履歴がある「ローカルリポジトリ
複数人で変更履歴を共有できる「リモートリポジトリ」の4つのエリアがあります。

上記でも少し出てきたブランチというものもありますが、今回は割愛します。

add

git addではワーキングツリーからインデックスに管理したいファイルやフォルダを追加すること(ステージング)を行っています。

ファイルはインデックスに追加すればバージョン管理できますので、変更したファイルはインデックスに追加しておきましょう。

ただし、パスワードなど外部に漏れたら困る情報が記載されたファイルはステージングしないようにしましょう。(特定のファイルを無視するには.gitignoreファイルを使えば無視できます。)

commit

git commitではインデックスのファイルの変更内容をコメントを付けてローカルリポジトリに記録することを行っています。

push

git pushではローカルリポジトリからリモートリポジトリにアップすることを行っています。

これでローカルリポジトリの変更履歴をリモートリポジトリに反映させることができます。

イメージとしてこんな感じ

分かりやすい図があったので、引用してます。

f:id:tkmt-hrkz:20200601011301p:plain 引用元:【Git入門】初めに知るべき仕組み・基本知識 全まとめ【これだけでOK】 | 初心者向け完全無料プログラミング入門

Git管理ファイル作成からpushまでの流れ(Github利用)

作業用ディレクトの最上位に移動

git init

git remote add origin repository_URL

git add -A

git commit

git push

参考サイト

Gitの仕組み kray.jp oldbigbuddha.dev

Git管理ファイル作成からpushまでの流れ(Github利用) techacademy.jp

オブジェクト指向と単体・結合テスト

最近テストについてちゃんと考え理解しはじめたので、現時点での自分の理解を整理しておこうと思います。

私は最初はテストって言うと、ただ単にビルド・コンパイルが上手くいって、そして入力データに対する正しいデータが出力されればいいと思っていました。

条件網羅とかも一応知ってはいたのですが、それがどう関係してくるのか、いまいちピンと来なかったんです。

また、テストコードについても知りませんでした。最近はようやくこのテストの重要性に気づきはじめた次第です。

以下に書くことは、あくまで個人的な見解ですので参考までにしていただけるとありがたいです。

前置きはこのくらいにして、少しずつ本題に入って行こうと思います。

オブジェクト指向とテスト

一応誤解を生まないために言っておきますが、オブジェクト指向とはオブジェクト指向プログラミングのことです。

ここでは、オブジェクト指向プログラミングについては割愛します。

気になる方は、個人的に分かりやすいサイトへのリンクを貼り付けているので、そちらを参照下さい。

thinkit.co.jp

一応、「オブジェクト」と「クラス」の違いまで読んでいただければ良いです。

少し話がそれました。

設計レベルまでのテストだと、単体テスト結合テストというものがあります。 以下の図をご覧ください。

f:id:tkmt-hrkz:20200524214934p:plain

単体テストは詳細設計(内部設計)に対応するテストです。
そして、結合テストは基本設計(外部設計)に対応するテストです。
この説明で理解できる人は、この記事を読まなくていいです。

ここからは私の見解です。間違っていたらごめんなさい。

まずは設計から

「とある1つの配列の平均、分散、標準偏差を求め画面上に表示するプログラム」を例に挙げて考えてみましょう。

オブジェクト指向の考え方に則って、プログラム設計を考えると、

  • 計算機能を担当するCalcクラス
  • 計算結果の表示を担当するShowクラス

に分けられます。(人によって分け方は様々ですが)

画像が大きすぎて、申し訳ないです。

f:id:tkmt-hrkz:20200524215931p:plain

f:id:tkmt-hrkz:20200524215946p:plain

Calcクラスには、平均を計算するメソッド、分散を計算するメソッド、標準偏差を求めるメソッドがあります。

Showクラスには、計算結果を箇条書き形式で表示するメソッドがあります。(箇条書き形式でなく表形式とかでも構いません)
イメージとしてはこんな感じ。

f:id:tkmt-hrkz:20200525191242p:plain

さてではこの例で、テストについて考えていきましょう。

単体テスト

単体テストの概念をのせておきます。

単体テストユニットテストと呼ばれることもあります)は、プログラムを構成する比較的小さな単位(ユニット)が個々の機能を正しく果たしているかどうかを検証するテストです。 通常、関数やメソッドが単体テストの単位(ユニット)となります。 プログラムが全体として正しく動作しているかを検証する 結合テストは、開発の比較的後の段階でQAチームなどによって行なわれることが多いのとは対照的に、単体テストは、コード作 成時などの早い段階で開発者によって実施されることが多いのが特徴です。

ここで言う、単位(ユニット)とはクラス(またはメソッド)です。

つまり、Calcクラス、Showクラスそれぞれが持つ機能を満たしているのかを確認するのが単体テストとなります。

具体的には、Calcクラスは平均、分散、標準偏差を正しく計算できるか?
Showクラスは与えられた値を箇条書き形式で表示できているか?、ということを確認することです。

結合テスト

単体テストと同じ要領で説明していきます。
結合テストの概念をのせておきます。

結合テストとは、システム開発におけるプログラムの検証作業の中でも、手続きや関数といった個々の機能を結合させて、うまく連携・動作しているかを確認するテストのことである。 結合テストでは、個々の機能を果たすためのプログラム部品(プログラムモジュール)を組み合わせて、データの受け渡しがうまく行われているか、コードの記述様式は揃っているか、データを授受するタイミングはずれていないか、といった点が確認され る。結合テストで不備が発見された際には、再度コーディングが行われる。

つまり、CalcクラスとShowクラスを繋げてみて、平均・分散・標準偏差を正しい値で表示できるかを確認するテストです。

学びはじめて間もないと、オブジェクト指向プログラミングとかテストとかあまりイメージしにくいと思いますが、参考になれば嬉しいです。

参考サイト

単体テスト

www.techmatrix.co.jp

結合テスト

https://wa3.i-3-i.info/word15917.html