1-1. はじめに

この授業のねらい

この授業では、高度なプログラミング技術を演習を通して学ぶことを目的とし ています。

まず、ソースコードの取扱として、バージョンコントロールシステム、テス トシステム、リファクタリングについて実習をし、オブジェクト指向を学び ます。 後半は並列処理についてのさまざまな演習を行います。

使用言語は Java を用います。

準備

  1. 授業のコメント収集システム tduitter を開発しました。まずはアカウントを作り、コメントをしてください。
  2. 次のソフトウェアをインストールしてください。
    1. Git(Mac は標準装備)
      1. Windows 用は gitforwindows からダウンロードする。 以下私家版 Git for Windows のインストール手順 を参考にした。
      2. 「Choosing the default editor used by git」 には、よくわからな い場合は Nano editor を選びましょう。 但し、歴史的な経緯から Vim が使われていました。癖はありますが、 Web などの文献はこちらを使っているものの方が多いです。
      3. Adjusting your PATH environment は Use Git from the Windows Command Prompt を選ぶと良いでしょう。 但し、コマンドプロンプトやPATHをカスタマイズしている人は、 一番上の Use Git from Git Bash only を選びましょう。
      4. 「Choosing HTTPS transport backend」はデフォルトの選択で 構いません
      5. 「Configuring the line ending conversions」はデフォルトは 自動変換ですが、無変換のCheck out as-is , comment as-is の 方がトラブルが少ないようですので、こちらを選びましょう。
      6. Configuring the terminal emulator to use with Git Bash はWindows の cmd.exe を気に入ってない限りは MinTTYを選びましょ う。
      7. Configuring extra options では、3つとも選びましょう。 Symbolic link にはチェックが入ってないですが、これは厳密に は互換性がないからですが、大抵はトラブルが起きにくいそうで す。
    2. Java10 の JDK
    3. Eclipse

      本家の英語版 が、バージョンの高さ、用語の検索のしやすさなどからお勧めする。 ただし、日本語化された Eclipse の方がとっつきやすいかもしれな い。 なお、授業ではメニューなどの指示はすべて英語版で行う。

      Eclipse IDE for java Developpers をインストールする。 出てくるメッセージは選択肢ではなく確認なので、内容を理解した上で、順次進めていく。

    4. Eclipse 中のEGIT

1-2. プログラムの管理

ソフトウェアは実行されるコード順や、定義の参照順に書くのではなく、書 く順番はプログラマーに任されています。 プログラムが単一のテキストファイルでなければならなかった Pascal 言語 では、プログラムの構成に関してもコンパイラの参照の順番を意識する必要 がありました。 一方 C 言語は、ヘッダファイルと関数ごとの分割コンパイルが可能になり、 様々なテククニックを要したものの、プログラムの作成は関数ごとに行えば 良くなりました。 さらに Java 言語ではクラスごとにコンパイルすることが可能になり、さら にクラス内のメソッドの配置順序も自由になりました。

プログラムは常に一気に書けるわけではないので、いくつかの工程ごとに作 業を分割する必要があります。 プログラムの特性上、最終的に全てが完璧でなければなりません。そのため には、プログラムを分割し、分割した部分部分でそれぞれが完璧であること を確認する必要があります。

プログラミングの自由度を減らさずに、ここに完璧を保証するようなプログ ラムの作成法を身につける必要があります。 その場合、常に大切なことは、部分的に作成したプログラムが、コンパイル可能だったり、テスト可能だったりと、何らかの意味で正当性のチェックができることが必要となります。

ソフトウェア管理

プログラムを工程に分割して作る場合、改良、修正や、試作、設計変更など、 作成したプログラムの変更をする必要が多くあります。 さらに、修正自体が失敗する可能性もあります。

古いプログラミングでは、ソフトウェアの内容とファイル名にそれほどの関 連性はありませんが、現代のプログラミング言語はファイル名とプログラム が密接に関連づいています。 例えば、 Java 言語では public class の名前とファイル名が一致していな ければなりません。 したがって、元のプログラム A.java を残して改良したプログラムを A2.java と別のファイルとして作っても、クラス A を使用している他のプ ログラムを全部を変更する必要が出てきます。

このため、保存したい時刻ごとに、すべてのファイルを保存することを考え ます。 すべてのファイルを入れたフォルダを時刻ごとに保存すれば、確かに目的が 果たせます。 但し、ファイル数が膨大になると、変更点などのドキュメント管理など、煩 瑣な作業があります。

このようなことをすべてコンピュータに管理させるのがバージョンコントロー ルシステムです。

バージョンコントロールシステム

バージョンコントロールシステムの歴史は古いですが、理想的なシステ ムができるまでに時間がかかりました。 しかし、歴史的経緯から従来のものも未だに使われています。

バージョンコントロールシステムには、ネットワークを使うものと使わ ないものに分けられます。 ネットワークを使うものは複数人が共有できるようになっています。

バージョンコントロールシステムは、管理するフォルダを定め、保管用 の領域(リポジトリ)を用意します。 リポジトリからはファイルを取り出せますが、バージョンを指定して 古いファイルも取り出すことができます。 一方、リポジトリへの登録方法ですが、ロック型とコピー/マージ型が あります。

通常の分散処理では、特定の値を書き換える場合、

  1. 元の値を読み込む前にその値を他のプロセスから書き換えられない ようにロックし、
  2. それから値を読み込み、
  3. 新しい値を計算し、
  4. 保存してから、
  5. ロックを解除します。

古い RCS はこの方式でした。ファイルをチェックアウトすると、その ファイルは編集可能になり、編集が終わった後にファイルをチェックイン すると新しいバージョンとして保存されます。

名前運用登録方式管理対象リポジトリ
RCS集中型ロック型ファイル単位フォルダ
CVS集中型コピー/マージプロジェクトサーバー
subversion集中型
git分散型

1-3. Git

Git の基本的な仕組みは、編集領域、ステージ、リポジトリの三層構造で、編 集ファイルを git addコマンドでステージングし、 git commitコマンドでステージングされたファイルをリポジトリ へコミットします。従来のバージョンコントロールシステムと異なり、バージョ ン番号は基本的に はハッシュコードとなっており、v1.0 などの人間にとって意味のある名前は tag として任意につけます。

さらに、ローカルに設定するリポジトリの他に、複数のプロトコルに対 応したリモートリポジトリをもち、相互に同期させることができます。

これにより、複数人が一つのファイルの編集に参加でき、ネットワーク の接続の有無に関わらず、任意のタイミングで同期できることです。

なお、コミットの列をブランチと呼び、ブランチごとの管理を行います。 デフォルトのブランチの名前は master と呼び、これは通常は最新のコ ミットを指します。 ブランチごとの管理や統合などもできます。

用語

repository
git の保存領域。git initにより初期化する必要がある。 リモートリポジトリの場合 git init --bare --shareと する。
staging
リポジトリに登録するファイルの候補を登録する。 git add ファイル名
commit
リポジトリの登録。登録コマンドも commit になる。 commit は長い桁数の commit ID がつけられる(自分でつけない)。 指定する際はすべてを打ち込む必要はなく、上位数桁で指定が可能。
branch
コミットの列。ブランチ名はその列の最新のコミットを指す
master
デフォルトのブランチ名名
origin
リモートリポジトリのデフォルトのブランチ名
HEAD
作業領域中のリポジトリ

commit

git commit 登録時に必ず1行以上のコメントを入力する。 無駄なコミットも rebase であとでまとめられるので、こまめにコミッ トすべきである。

branch

ソフトウェアを複数の方針で修正する場合、それぞれを別に管理すべき である。

branch を作成すると branch ごとに異なる方針で修正できる

checkout

任意のブランチ、タグ、コミットを展開する。HEADを指定コミットに移 動するとも解釈できる。 なんの警告も出ないが、現在編集中でコミットしていない変更はす べて消える。 checkout を行う前に必ずコミットを行っておくこと。

merge

コミットに矛盾が生じた場合は、警告が出て、矛盾しているファイル には
>>>>>
=======
と矛盾している変更点が含まれているので、修正の後、staging する必要があ る。

rebase

2つのブランチに対して、相手のブランチの変更点を解析し、自分のブ ランチに施す。これにより、自分のブランチの分岐点を相手のブランチ の最新コミットまで進めることができる。

1-4. 演習

Git にはいくつかのシステム、用法がありますので以下の共通のシナリ オを使って、用法ごとの演習をします。

Document フォルダの中に ex1 など、本日の課題用のフォルダを作りま す。

  1. class A を作る
  2. class A にメソッド1を作る。 tag1 とする
  3. class A にメソッド2を作る。
  4. タグ1 をチェックアウトし、メソッド3を作る。ブランチを作れと警 告が出るので、 branch1 と名付ける
  5. master と rebase すると、 class A がconflict すると出る。
    1. class A を修正
    2. class A を git add で staging
    3. git rebase --continue で rebase の継続
  6. master を checkout する
  7. branch1 を rebase する
  8. タグa をチェックアウトする。
  9. branch2 とする(git branch -b branch2)
  10. class B を作る
  11. master をチェックアウトする
  12. branch2 をマージする

演習1-1

Git をインストールし、任意のテキストエディターによるローカルリ ポジトリの操作を学びます

初期設定

  1. git bash と git gui を起動します
  2. git bash でgit config --global --listを打ち、環境 を確認します。
    user.name=自分の名前
    user.email=自分のメールアドレス
    core.quotentpath=false
    core.autocrlf=ture	  
    push.default=upstream
    
    などと表示される。user.name などを変更したい場合は、 git config --global user.name "Naoshi Sakamoto" などとし、再び上記のコマンドで設定内容を確認する。

演習1-3

Git bash による、任意のテキストエディターによるローカルリ ポジトリの操作を学びます

  1. Git Bash を起動し、演習用フォルダにカレントディレクトリを移 します。 cd Document/ex1
  2. 最初のファイルを作成します。
    1. この演習用のリポジトリフォルダ ex11 を作ります。mkdir ex11
    2. カレントディレクトリを ex11 に移します。cd ex11
    3. さらにパッケージとしてのフォルダ ex11を作ります。 mkdir ex11
    4. Git の最初の操作をします。
      1. ex1/ex11 のフォルダがカレントディレクトリだとします。 pwd で表示されるディレクトリ表示の最後が ex1/ex11 であることを確認します。
      2. git init
      3. この後、任意の状況で git status で状態を確認 できます。
    5. 今作成したフォルダ内に次の内容の A.java ファイルを作成します。
      package ex11;	
      public class A{	
      }
  3. 最初のコミットをします。
       
    1. 作成したプログラムをステージングする。git add *
    2. ここでもgit statusで状況を確認できる
    3. git commitでコミットする。コメントには 「initial commit」などと入力する。nanoエディタだと Ctrl-X,y,Enter で終了できる。
  4. A.java を編集して、次のようにする
    package ex11;	
    public class A
        public String id(){
            return "学籍番号";
        }
    }
  5. 編集をコミットします
    1. 編集したプログラムをステージングする。 git add ex11/A.java または git add *
    2. git commitでコミットする。コメントには 「add id method」などと入力する。nanoエディタだと Ctrl-X で終了できる。
  6. 今のコミットにタグをつけます
    1. git tag tag1
    2. git logで確認する
  7. A.java を編集して、次のようにする
    package ex11;	
    public class A
        public String id(){
            return "学籍番号";
        }
        public String name(){
            return "名前";
        }
    }
  8. 編集をコミットします
    1. 編集したプログラムをステージングする。 git add ex11/A.java または git add *
    2. git commitでコミットする。コメントには 「add name method」などと入力する。
  9. 履歴を確認するgit log。 ブランチの名前が master で、今編集中のファイル(HEAD)が「add name method」のコミットであることがわかる。
  10. id を加えた時期である tag1 に戻す。
    1. git checkout tag1
    2. ex11/A.java の内容を見て、戻ったことを確認すること。
    3. 「HEADが tag1 に動いただけなので、ブランチに影響を与えず に変更、コミットができる。作ったものをコミットとして残すため のブランチが必要なら、今でも後でも git checkout -b 新しいブランチ名 としなさい」のような警告が出る
  11. A.java を編集して、次のようにする
    package ex11;	
    public class A
        @Override
        public String toString(){
            return "A []";
        }
    }
  12. 編集をコミットします
    1. 編集したプログラムをステージングする。 git add ex11/A.java または git add *
    2. git commitでコミットする。コメントには 「add toString method」などと入力する。
  13. この変更を master ブランチにリベース(再設定)させる
    1. 今のコミットにブランチ名 branch1 をつけるgit checkout -b branch1
    2. master ブランチに移動git checkout master
    3. リベース git rebase branch1。 これで、A.java への矛盾した更新があることが報告される。 A.java には変更のコメントが含まれた状態になり、リベースの コミットにはまだ含まれておらず、staging もされていない状態になる。
    4. A.java を編集する
    5. git add ex11/A.javaでstagingする
    6. git rebase --continueでリベースを完了する
  14. tag1 をチェックアウトとし、新しいブランチ branch2とする。
    1. git checkout tag1
    2. 新しいブランチ名をbranch2 とする(git branch -b branch2)
  15. ex11/A.java を修正する
    package ex11;	
    public class A {
        private String id;
    }
  16. 編集をコミットします
    1. 編集したプログラムをステージングする。 git add ex11/A.java または git add *
    2. git commitでコミットする。コメントには 「add id field」などと入力する。
  17. master に branch2 をマージする
    1. master ブランチに移動git checkout master
    2. マージ git merge branch2。 ここで矛盾があれば、矛盾が報告される。 修正などの手順は rebase と同じで git merge --continueで終了する。

演習1-3

Git GUIと、 GUIのテキストエディターによるローカルリ ポジトリの操作を学びます

演習1-4

Eclipseでローカルリポジトリの操作を行う

  1. Eclipseを起動する
  2. クラスを一つ作る
    1. Java Project で ex11 を作る
    2. srcフォルダを右クリックして、new→class で public class A を作る
  3. 初期コミットする
    1. プロジェクトを右クリックし、 Team→share Projectを選ぶ。 ウィンドウが開くところで「create」ボタンを押してリポジトリを 作る。
    2. srcフォルダを右クリックして、 Team→Add to Indexでソースフォルダ内のすべてをステー ジに上げる。
    3. プロジェクトを右クリックして、 Team→commmitをする。 Git Standing ペインが開く。 Git Standing のタブをダブルクリックすると全画面とタイリングを 切り替えることができます。 「initial commit」などのコメントを入れて Commit ボタンを押します。 .project, .classpath を入れると設定項目も共有できます。 これは複数人で共有するときに便利です。
  4. class A に以下のメソッドを追加する。
    public String id(){	    
      return "自分の学籍番号";
    }
  5. commitする
    1. src フォルダを右クリックして Team→Add to Indexでソースフォルダ内のすべてをステー ジに上げる。
    2. プロジェクトを右クリックして、 Team→commmitをする。 「Add id method」などのコメントを入れて Commit ボタンを押します。
  6. さらに class A に以下のメソッドを追加する。
    public String name(){	    
      return "自分の名前";
    }
  7. commitする
    1. src フォルダを右クリックして Team→Add to Indexでソースフォルダ内のすべてをステー ジに上げる。
    2. プロジェクトを右クリックして、 Team→commmitをする。 「Add name method」などのコメントを入れて Commit ボタンを押します。
  8. ブランチを作ります
    1. Window→Show View→Other...で Show View ウィ ンドウを開き、Git→Git Reflog を選ぶ
    2. Git Reflog ウィンドウでは、今までのコミットの状況が表示 されています。
    3. 「Add id method」などとされているコミットについて、右ク リックして Check out を選びます。 編集対象(HEAD)がその時点に戻り、class A から name メソッド が消えます。
    4. プロジェクトを右クリックして Team→Switch to→New Branchを選び、新しいブラン チ名「branch1」を入れる。 プロジェクトの表示が 「ex11[repository master]」 から 「ex11[repository branch1]」 に切り替わる
  9. A に toString メソッドを作る。
    1. 編集画面で class A にカーソルを置く
    2. Source → Generate toString()...
    3. 「Generate」を押す
  10. commitする
    1. src フォルダを右クリックして Team→Add to Indexでソースフォルダ内のすべてをステー ジに上げる。
    2. プロジェクトを右クリックして、 Team→commmitをする。 「Add toString method」などのコメントを入れて Commit ボタンを押します。
    3. File→Saveでセーブする
  11. master ブランチにマージする
    1. Team→Switch to→で master を選ぶ
    2. Team→Merge
    3. Local で branch2 を選び merge を押す

演習1-5

CLI でリモートサーバーとの接続を行います。

GitHUub, ssh でログインできる端末、Webサーバー、USBメモリーなど なんでもできますが、 ここでは、USBファイルやローカルファイルシステムとやり取りします。

リモートリポジトリの作成

自分でリモートリポジトリを作成します。 GitBash でリモートリポジトリを作るフォルダを作ります。

    • USBメモリーを挿して、それが E: ドライブだとすると
      1. mkdir /e/git
      2. mkdir /e/git/ex15
      3. cd /e/git/ex15
    • ローカルで作るには
      1. mkdir ~/Documents/ex1/ex15
      2. cd ~/Document/ex1/ex15
  1. リポジトリを作りますgit init --bare --share

操作

  1. 演習1-3のフォルダに行きます cd ~/Document/ex1/ex11
  2. リモートリポジトリのブランチ名を指定して接続します。
    1. ローカルなら、 git remote add origin file://~/Document/ex1/ex5、 USBメモリーなら git remote add origin file:/e/git/ex5 など、リモートリポジトリを作ったフォ ルダを指定する
    2. master ブランチのすべてを origin に送る git push orign master
    3. プログラムを修正した後、commit してから、また push するとリモート ブランチも更新される。

演習1-6

リモートブランチを元に、ローカルリポジトリを作ります。

  1. ローカルリポジトリを作るフォルダを作り、移動します。 mkdir ex16 cd ex16
  2. リモートブランチを指定して、クローンを作ります。 git clone file:///c/Users/sakamoto/Document/ex1/ex11remote
  3. フォルダを移動します。 cd ex11remote
  4. 以後、コミットしたら git push origin master、リ モートリポジトリの変更があったら git pull origin

積み残し

  1. GitHub との接続
  2. Eclipse での git clone
  3. 番号の食い違い