Python/Rubyとgitによる開発の流れについて

最近、社内で使用するシステムを内製する動きが出始めました。これまで開発経験のない人たちに、一通りの開発の流れを説明するために使用した情報をまとめておきます。

# はじめに
大学や専門学校などでプログラミングを少々学んだものの、その後開発を特に行ってこなかった、ぐらいの人たちを想定しています。能力的には、プログラミングとは何かを一から教える必要がなく、但しgitやpyenv等を使った開発のお作法を知らないくらいの人たちです。
この記事では、こうした人たちに開発環境の用意から実際の開発環境の用意、展開の準備までに必要なタスクを説明することを想定しています。但し、各環境やコマンドの導入については言語やOS毎に手順が異なるため、説明を省きます。また、本記事で想定している言語はpythonやrubyなどの、最近のスクリプト言語です(つまりトラディショナルなCやC++などのコンパイル言語は想定しません)。
# 1.ローカルリポジトリを整えよう
gitの特徴の一つとして、各ユーザがローカルにリポジトリを用意し、そのリポジトリで開発を行い、最後にリモートリポジトリに変更をアップロードするところがあげられます。そのため、まずは開発を行う前に、ローカルにリポジトリを作成する手順について説明します。
## 1-1.リポジトリ用ディレクトリを整えよう
開発用のローカルリポジトリを用意するには、二つのやり方があります。
一つは既存のリモートリポジトリをcloneするやり方です。すでに開発中のプロジェクトに参加したり、先に空のリモートリポジトリを作成した場合などです。基本的にはこちらの方法になるでしょう。
ただ、ローカルで作っていたものが目処がついたのでgitで管理したいという場合もあるでしょう。その場合は、ローカルの既存ディレクトリをローカルリポジトリ化し、gitで管理していくことになります。その場合、以下のコマンドを入力します。

```shell:ローカルディレクトリのリポジトリ化
$ cd /path/to/local/repo
$ git init
$ git add [リモートディレクトリへのアドレス]
```
## 1-2.readme.mdを書こう
gitのリポジトリには、readme.mdというファイルを用意するのが一般的です。ファイル名からわかる通り、リポジトリについて説明したマークダウンテキストとなっています。
いきなりリポジトリの取説を書けと言われても戸惑う人も多いと思います。私見ですが、ひとまず以下の内容を含むようにしておくとよいでしょう。

* 概要  
  ex. L2/L3スイッチのログを取得するスクリプトです。
* 説明  
  ex. 同一ネットワーク上のL2/L3スイッチについて以下のコマンドの結果を取得し、テキストとして出力します。
* インストール方法  
  ex. リポジトリをコピーし、スクリプトに実行権限を付与してください。
* 使い方  
  ex. 次のコマンドを実行してください

それでもなお、何を書けばいいかわからない、という場合はひとまず書ける内容を書いてみるとよいでしょう。そして数日後にでも全文を読み直してみると、不足する点に気づくでしょうから、その時に追記・修正していくことをお勧めします。
一か月後の自分は他人といいます。しばらくいじっていなかったプロジェクトを、開発再開する段になって何の資料も残っていない、などとならないよう、面倒でも一通り作成しましょう。
## 1-3..gitignoreを書こう
開発中、自分のローカル環境固有のファイルで、gitに追加されたくないファイルが発生することがあります。例として言語処理系が作成するキャッシュファイルや、エディタが作成する設定ファイルなどです。
このような、gitにignore(無視)してほしいファイルやディレクトリを指定するために、.gitignoreファイルを作成します。

```.gitignore:サンプル
*.pyc      # 拡張子がpycのファイルを無視する
pycache/   # pycacheというディレクトリ以下のファイルとディレクトリを無視する
```

なお、.gitignoreファイルに記載する内容は言語やOS、エディタごとにおおむね決まっており、それらをまとめたサンプルがgithubで公開されています。最初はいちいち手で書くよりこちらをコピーして使い、不足が出てきたら追記していくといいでしょう。
https://github.com/github/gitignore

さらに便利なことに、使用するエディタやOS、言語を指定するだけで上記のgitignoreを自動で取得してくれるgiboというコマンドが公開されています。windowsの場合導入まで一癖ありますが、linuxやMac OSではコマンド一つで導入できるため、利用するとよいでしょう。
https://qiita.com/tmknom/items/c4bcebe17d25381fa45d
https://github.com/simonwhitaker/gibo

```
$ gibo -l
$ gibo python MacOS VisualStudioCode >> .gitignore
```
# 2.開発環境を用意しよう
## 2-1.バージョン管理システムを利用しよう
リモートとローカルのリポジトリを作成し、さて開発となった時に、顧客やサーバの処理系のバージョンと、ローカルの処理系のバージョンが異なっていることがよくあります。この時、相手に合わせてローカルのバージョンを入れ替えていては煩雑ですし、トラブルのもとになります。このため、最近の開発言語では処理系のバージョンを管理する仕組みが用意されています。
pythonではpyenv、rubyではrbenv、node.jsではndenvがバージョン管理システムです。これらの導入については説明を省きます。ググればたくさん出てくるでしょう。
## 2-2.ライブラリをローカルにインストールしよう
pythonやrubyなど、モダンな処理系ではパッケージを管理するためのシステムが整っています。パッケージのインストールやアップデート、一覧表示などはこのパッケージ管理システムを利用して行います。
一方で、OS上どこからでも参照できる領域にパッケージをインストールするのは、ライブラリを参照する側からすると好ましくありません。なぜなら、自分が想定しているライブラリとバージョンが異なっていたり、あるいは名前が同じだけで中身が全く違うライブラリだったりしても、参照する側からは判別のしようがないためです[^1]。別のプロジェクトでパッケージをインストールした際に、このプロジェクトで参照するパッケージをアップデートしていた、なんていうのはよくある話です。
このような場合に備え、モダンな処理系では、インストールしたパッケージを参照できる範囲を制限する仕組みが備わっています。このようなパッケージのインストールの仕方を、ローカルにインストールする、などと呼びます。rubyではプロジェクトのディレクトリからしか参照できないようにするbundlerというパッケージがありますし、pythonでは仮想の環境を作成してしまい、その環境にパッケージをインストールするvirtualenvというパッケージが存在します[^2]。
## 2-3.開発しよう
バージョン管理システムで必要なバージョンの処理系を用意し、仮想環境を作成してその中に必要なライブラリをインストールしたら、いよいよ開発開始です。基本的にgit上に都度ソースコードをcommitしつつ開発を進めていくことになると思いますが、この時必要なのがbranchの使い分けになります。
まずmasterブランチがあり、それを元に各機能を追加中の各ブランチがあり、開発とテストが終わったらmasterブランチにmergeしていくというのがbranchの使い分けになります。もしmasterブランチで全ての開発を進めていくと、開発が終わり落ち着いた時のコードと、開発中の書きかけコードが同じbranch上に存在することになり、非常に混沌とします。もし開発中に行き詰まって迷路に迷い込んでしまった時、とりあえずスタート地点に戻れるのと戻れないのでは、開発の安定感が全く異なります[^3]。面倒だろうが何だろうが、ちゃんとbranchの使い分けは行いましょう。
# 3.展開しよう
無事に開発とテストが終わり、実用に耐えるソフトウェアができたとします。次はそれを本番環境に持っていき、無事に動作させなければなりません。しかし、開発環境と本番環境は当然別の環境です。したがって、本番環境上に開発したソフトウェアが動作するための環境を用意する必要があります。
# 3-1.開発環境をエクスポートしよう
本番環境上に必要な環境を用意するとき、一番手っ取り早いのは手元の環境を参考に、新しい環境を用意することです。現在の手元の環境は、バージョン管理システムで処理系を用意し、パッケージ管理システムでライブラリを用意したものです。したがって、各管理システムの持っている情報を、本番環境の管理システムに教えてやり、必要なバージョンの処理系やライブラリを用意させるのが望ましいです。
そのため、各管理システムには現在の処理系のバージョンや、仮想環境にインストールされているライブラリの一覧を出力させる機能が備わっています。この辺りは処理系ごとに随分異なった操作になるため、説明は割愛します。
# 3-2.本番環境にインポートしよう
3-1で開発環境をエクスポートした後、その内容はなんらかのファイルに出力されているはずです。この出力されたファイルを本番環境へもっていき、そちらのバージョン管理システムやパッケージ管理システムで読み込んで必要なバイナリをインストールすれば、開発したソフトウェアが動作する環境は整ったことになります。あとはgitからソースコードをcloneするだけです。

# 4.おわりに
基本的な開発の流れは以上になります。開発を行うだけでも大変なのに、gitの設定や仮想環境の作成など、余計なタスクが増えてうんざりした人もいるのではないでしょうか。
その場合、まず最低限パッケージのローカルインストールだけは行うようにしましょう。.gitignoreの作成やら複数の処理系の管理やらは後から追加することが可能ですが、OS上の処理系に直接パッケージをインストールしてしまうと、取り返しがつきません。特にMac OSやLinuxの場合、OSやミドルウェアがOS上の処理系を利用している場合があり、これらを破壊してしまった場合、最悪OSが動作しなくなる恐れがあります。



---
[^1]: 大昔は[DLL地獄](https://ja.wikipedia.org/wiki/DLL%E5%9C%B0%E7%8D%84)とか呼ばれており、まさに地獄じみた苦しみを与えてくれました。
[^2]: 厳密には、仮想環境を作成するライブラリがvirtualenvで、その仮想環境上でpipコマンドを実行します。
[^3]: 他には、新しいメンバーが開発に参加した際に、cloneするべきポイントを確保する意味でも、masterブランチはクリーンな状況に保つべきです。新しいメンバーに開発中のコードを読んで、全体を把握させるのは困難です。

2h