=begin

  $Id: Design.rd.ja,v 1.5 2001/12/19 12:21:08 katayama Exp $

  Copyright (C) 2001 KATAYAMA Toshiaki <k@bioruby.org>

= BioRuby の開発方針とデザイン

新しくモジュールを追加する場合は CVS の以下のレポジトリに、内容に従って
適切に commit します。メーリングリストなどで contribute されたコードは
本人に committer になってもらうか、スタッフが commit します。

  bioruby/
  |-- README            はじめに
  |-- install.rb        インストーラ
  |-- COPYING
  |-- COPYING.LIB
  |-- bin/              アプリケーション
  |-- lib/              Ruby で書かれたライブラリ
  |   `-- bio/            配列など基本的なクラス
  |       |-- data/         生物学的な定数などデータそのもの
  |       |-- db/           各種データベースパーザ
  |       |-- io/           データの入出力
  |       |-- appl/         外部アプリの処理 (？)
  |       `-- util/         その他
  |-- doc/              ドキュメント
  |-- ext/              C で書かれたライブラリ
  `-- sample/           サンプルコード

== Ruby 部分についてのデザイン（bioruby/lib/bio/ 以下）

これまでに行なわれた実装のデザインコンセプトと、今後の方針などについてま
とめておきます。

BioRuby の全クラスは module Bio で囲むことで、名前空間を切り分ける事にし
ます。

=== lib/bio/ データ構造系

塩基やアミノ酸の配列、文献情報、データベースとエントリを一意に表す ID、グ
ラフなどの抽象データ構造を扱うクラスは lib/bio/ 直下に配置しています。こ
れらは各データベース・パーザなどからも直接呼ばれます。

他に、アライメントクラスなどの実装が必要かも知れません。また、生物種の系
統分類を表す Taxonomy クラスや GeneOntology などのクラスもあると便利かも
知れません。

=== lib/bio/db/ データベース・パーザ系

使い方の簡単さ vs 実装の複雑さ、処理の早さ vs メモリの重さ、などバランス
の問題で必ずしも良いとは言えない場合もありますが、lib/bio/db.rb では以下
のような独自のアイデア（すでに同様な試みがなされていたかどうかは調べてい
ません）を採用しています。新しくパーザを追加する場合も参考にして下さい。

  エントリ      それぞれのデータベースにおける１つのデータ単位
                例) GenBank なら LOCUS から // までの全ての行
  デリミタ      エントリとエントリを区切る文字列
                例) GenBank なら // だけの行
  タグ          エントリの左端数カラムなどに記されるトップレベルの識別子
                例) GenBank なら DEFINITION や FEATURES など
  フィールド    タグ毎に意味のある単位をなす複数行からなるブロック
                例) GenBank なら SOURCE に含まれる taxonomy までの行全部など

BioRuby のデータベース・パーザは、１エントリ分の文字列を .new に渡す事で
パースした結果を保持するインスタンスを返すデザインになっています。各デー
タベースからエントリ単位のデータを得る方法は、手元のフラットファイルを使
う場合、ネット越しに DBGET した場合、NCBI から取ってきた場合、など使い方
によって様々ですが、どこからエントリを得たか (io) に関わらず、パーザはエ
ントリをパースする処理に専念できます。

最終的には全てのデータはあらかじめパースして tab 切りのデータに切り刻み、
MySQL などに突っ込んでしまってパースの必要がないような世界にしたいです。
BioPerl の BioPerl-DB に似ていると思いますが、BioRuby 標準の DataBase と
いうことで BioRuby-DB (class BRDB) として開発を進めています。

+ データベース構造の抽象化

lib/bio/db/ 以下のモジュールは、lib/bio/db.rb を require し、少なくとも
DB クラスを継承します。さらに、いくつかのデータベースは類似の構造を持っ
ているため、とりあえず NCBI 型（KEGG も含む）、EMBL 型に分けて、パースの
際に共通で使えるメソッドを共有しようとしています。ただし、実際にはこれら
の形式に当てはまらないデータベースも多いので、DB だけを継承する場合もあ
るでしょう。

+ フィールドに対する共通の API を定義

様々なデータベースでよく共通して現れるようなフィールドに対しては、db.rb
内にあるドキュメントで示される共通のメソッド名を使って、データを取りだせ
るようにします。

このように、フィールドに対する共通のメソッド名が、各データベースのパーサ
で適切に実装されていれば、データベース毎にメソッドを覚える必要が減ります。
例えば、データベースが異なっても「エントリの説明フィールド」取得のための
メソッドは definition だろうと推測しやすくなります。

+ 必要な時までパースを遅らせる（on-demand parsing）

GenBank など複雑な構造のデータベースをパースする際にもスループットを良く
するため、最初はフィールド毎に切り分ける前処理だけを行ない、特定のフィー
ルド内のデータを要求するメソッドが呼ばれた時だけ実際にフィールド内のデー
タを細かくパースする処理を行ないます。もちろんこの時パースされるのは、必
要なフィールドだけです。

+ 一度パースした結果はキャッシュしておく

上記の on-demand parsing でパースした結果は、オブジェクト内にキャッシュ
しておくので、２度目以降のメソッドコールでは保持しているパース済みのデー
タを返します。これにより重いパースを繰り返すようなオーバーヘッドを無くし
ています。

=== lib/bio/data/ 定数、データ系

lib/bio/data/ 以下に、いくつかのデータ（アミノ酸の名前、KEGG での生物種
名、コドン表など）が定数として置かれています。

  Bio::AminoAcid → アミノ酸の名前を表すハッシュ、など

これらは、必要なクラスにアクセスメソッドを定義しても良いでしょう。

=== lib/bio/io/ インターフェイス、IO 系

lib/bio/io/ 以下には、ゲノムネットによるデータ取得を行なう DBGET クラス
と NCBI の PubMed による MEDLINE データ取得を行なう PubMed クラスがあり
ます。各メソッドはクラスメソッドとして定義されているので、あらかじめイン
スタンスを作らなくても Bio::DBGET.bget("eco:b0001") などと直接実行できま
す。

他には、フラットファイル形式のラッパーとなる flatfile.rb や、BioRuby-DB
を扱う MySQL に対して入出力を行なう brdb.rb、NCBI などへの Web ベースの
アクセスを行なうもの、などを実装していく予定です。

* flatfile.rb （実装済）

    # ローカルのファイルを GenBank フォーマットとして開く
    flatfile = Bio::FlatFile.open(Bio::GenBank, "genbank/gbest40.seq")

    # またはファイルは引数で与える
    Bio::FlatFile.new(Bio::GenBank, ARGF)

    # または IO で与える
    Bio::FlatFile.new(Bio::GenBank, IO.popen("gzip -dc nc1101.flat.gz"))

    # 最初のエントリを GenBank オブジェクトに
    gb = flatfile.next_entry

    # エントリごとに Bio::GenBank オブジェクトを生成
    flatfile.each do |gb|
      puts gb.definition
    end

* bioruby-db (brdb.rb) のアイデア

    db = Bio::BRDB.new('server')
    gb = db.get('gb', entry_id)

* ncbi.rb のアイデア（PubMed もここに？）

    gb = Bio::NCBI.new('GenBank', id)
    fa = Bio::NCBI::BLAST.new(query, target)

* genomenet.rb のアイデア（DBGET もここに？）
  * ncbi.rb と同様の BLAST と FASTA, CLASTALW などのサービス
  * SSDB の統合

あと、gb = Bio::Genbank.new() として箱だけ作っておいてデータをあとで渡す
gb.data(hash) のようなメソッドがあってもいいかも知れません。

=== lib/bio/appl/ ツール系

FASTA(SSEARCH), [PSI-]BLAST, HMMER, CLUSTALW などの外部アプリを使った処
理を行います。ローカルな実行、http などによるリモート実行、結果のフォー
マットなどを意識せずに、結果がパースされ格納された FASTA オブジェクトな
どが返るような感じにしていきます。

* query となるオブジェクトに、アプリを実行するメソッドを実装（必要な引数
  を与える）

    factory = Bio::Fasta.remote('fasta', 'genes')
    fa_res = f.fasta(factory)   # f は Bio::FastaFormat オブジェクト
    fa_res = seq.fasta(factory) # seq は Bio::Sequence::AA オブジェクトなど
    # 以下は実装されてない
    puts fa_res.top(10, with_id, by_optscore)
    puts fa_res.best.alignment

* 新しく生成したファクトリに、サーバ、query、target などを設定して、アプ
  リを実行するメソッドを呼ぶ

    factory = Bio::Fasta.local(prog, target, opt)
    fa_res = factory.query(seq)

などいくつかの実装方法が考えられます（Bio::Fasta では両系統インプリして
います）。ファクトリやメソッドへのオプションの渡し方は細々としたものは
hash を投げる感じでやっています。

    # ここまでやって全部 hash でもいいかもしれないし、重要度で分けてもいい
    hash['server'] = "fasta.genome.ad.jp"
    hash['db'] = "nr-aa"
    fa_res = seq.fasta(hash)

    hash['server'] = "local"
    hash['db'] = "/bio/db/fasta/genbank/hoge.f"
    fasta = Bio::FASTA.new(hash)

今後他のアプリのインターフェイスも実装しながら仕様を決めていきたいと思
います。

== コーディングスタイル

クラス設計、メソッド定義など全般において、KISS が基本です。ただし、なん
でもかんでも class に分解してしまえば良いわけではないでしょう。概念とし
て一つのまとまりだと思えるものまで分解すればよく、特に使い回しのきかない
オブジェクトを生成する必要はないと思います。

技術的な事については、常に改善の余地があると思います。書き換える事により
シンプルで分かりやすくなる場合、今後の開発がスムーズになると思われる場合
には、どんどん修正していきます。逆に、多少効率が良くなるとしても何をやっ
ているか分かりにくくなる場合、必要性が高いと思える積極的な理由が見つから
ない場合は採用を見合わせることもあると思います。いずれにしても、バージョ
ン 1.0 までは下位互換性を犠牲にした変更も行なう予定です。

ソースコード中には日本語など非 ASCII の文字列は含まないようにします。

=== ヘッダ部

ヘッダ部には、ファイル名、概要、著作権者、ライセンス、CVS の ID を書きます
（下の例では ID の＄を展開されないように全角にしていますが、実際は $ です）。

    #
    # bio/hoge.rb - biological hoge class
    #
    #   Copyright (C) 2000, 2001 KATAYAMA Toshiaki <k@bioruby.org>
    #
    #  This library is free software; you can redistribute it and/or
    #  modify it under the terms of the GNU Lesser General Public
    #  License as published by the Free Software Foundation; either
    #  version 2 of the License, or (at your option) any later version.
    #
    #  This library is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    #  Lesser General Public License for more details.
    #
    #  You should have received a copy of the GNU Lesser General Public
    #  License along with this library; if not, write to the Free Software
    #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    #
    #  ＄Id:＄
    #

アプリケーションやサンプルコードを書く場合は、ruby のパスに依存しないよ
うに１行目を

    #!/usr/bin/env ruby

のように始めるのも良いでしょう。

=== 本体

本体は module Bio で括り、必要なクラスを実装します。本体内では # を使っ
てコメントをつけ、RD を使ったコメントはファイルの最後のドキュメント部ま
では出てこないようにします。もし作成するクラスが bio/db/ 以下のデータベー
スパーザ系だったら、bio/db.rb のドキュメントも参照して下さい。

    require 'foo/bar'

    modlue Bio

      class Hoge

        # this method do hogehoge
        def hoge(fuga)
          @fuga = fuga		# storing data fuga
        end

        def gege
        end

      end

    end

=== テストコード部

テストコードはクラス定義など本体部分のあとにをつけることにします。テスト
コードの書き方はこれから検討していく必要がありますが、とりあえず以下のよ
うな構文でテストコードを囲みます。

    if __FILE__ == $0
      # test code here
    end

このおまじないのような構文は、ファイル hoge.rb がコマンドラインから

    % ruby hoge.rb

などとスクリプトとして起動された場合に実行されますが、ライブラリとして

    require 'hoge'

のようにロードされた場合には実行されないようにするための常套句です。

テストの方法は、Test::Unit が ruby の標準ライブラリとして添付されるよう
になれば採用してもいいと思いますが、それまでは色々試したいと思います。テ
ストに外部ファイルやネットワークなどが必要な場合どうするかとか、インストー
ル前に動作確認としてテストを実行する方法なども検討する必要があります。

=== ドキュメント部

これまで、各クラスについては、あまりドキュメント化されていませんでしたが、
今後はテストコードのあと、ファイルの最後尾に RD でメソッドなどのドキュメ
ントを追加することにしていきます。

    =begin

    = Bio::Hoge

    Hoge クラスの概要説明。

    --- Bio::Hoge.new(fuga)

          クラスメソッドの説明。

    --- Bio::Hoge#to_a

          メソッドの説明。

    == Bio::Hoge::Fuga

    内部クラス Hoge::Fuga の概要説明

    --- Bio::Hoge::Fuga.new(fuga)

          クラスメソッドの説明。

    --- Bio::Hoge::Fuga#to_a

          メソッドの説明。

    =end

ただし、

* ソースの中には ASCII 以外の文字を入れない方針のため、日本語のドキュメ
  ントは、この部分ではなく別ファイルに記述し、doc/ ディレクトリ以下に置
  くなどします。この際、拡張子に .ja を付けて、ファイル名からも日本語と
  分かるようにします。

* 前述のように、ソースコード本体内では RD によるドキュメントは禁止します。
  理由は純粋にコードが読みづらくなるからです。ソース中で # を使って必要
  なコメントを追加する事は歓迎します。

== 開発に参加するには

BioRuby のウェブサイト ((<URL:http://bioruby.org>)) を見て、メーリングリ
ストに参加するか、スタッフ <staff@bioruby.org> に連絡してください。

=end

