web-dev-qa-db-ja.com

bashまたはpythonのシェルコマンド?カプセル化の量は多すぎますか?

私は自分の作業を適切な名前の関数名の背後にカプセル化するか、それを公開するほうがよいかをどのように決定するかを考えています-これは開発者が何が起こっているかをより迅速に理解するのに役立ちますか?この種の問題の研究に名前はありますか?

具体的には、最終的に多数のbashコマンドを実行しているが、それらのコマンドの周りに非常に複雑なロジックがある場合、実際のbashを難読化しても、Pythonのような高水準言語でこれを書くのはどの時点で意味がありますか実行されているコマンド?

詳細な問題

現在、大まかに次の手順でプロジェクトのJenkinsビルドスクリプトを記述しようとしています。

  • Githubからコードをプル
  • SassファイルをCSSにコンパイルする
  • 別のgithubプロジェクトからサブフォルダーをプルダウンします
  • プロジェクトを圧縮する
  • 一意のIDでオブジェクトストアにアップロードする

これを将来の開発者ができる限り簡単に記述できるようにする方法を考えています(このコードはエンドユーザーには表示されません)。これらの開発者は、Pythonをかなり上手に使う可能性がありますが、絶対ではありません。彼らは間違いなくコマンドラインに精通していますが、より複雑なbashスクリプトに慣れていない可能性があります。

このビルドスクリプトの最初の反復は、次のようなシーケンシャルコマンドのリストにすぎません。

git clone [email protected]:username/project.git
git clone [email protected]:username/sub-project.git project/sub-project
sass --update project/css
tar -czf project.tgz project
Swift upload my-container project.tgz --object-name=project-`sha1sum project.tgz`.tgz

ただし、gitプロジェクトがまだ存在しない場合はそれだけを複製し、それ以外の場合は更新してビルドを高速化するなどの作業を開始したため、このコマンドセットはすぐに複雑になりました。それを知る前に、50行とかなりの数の条件文がありました。

したがって、私が最初に行ったのは、これらをbash関数にカプセル化することでした。 pdate_git_dir なので、ビルドスクリプトは次のようになります。

#!/usr/bin/env bash

source helper_functions.sh

update_git_dir project [email protected]:username/project.git
build_sass project/css
create_archive project project.tgz
upload_to_Swift project.tgz

これはカプセル化の1つのレベルです。これで、git cloneなどのコマンドを直接理解したはずの開発者は、実際に何が起こっているのかを知ることができません。彼らはhelper_functions.shを調べる必要があります。

しかし、時が経つにつれ、ヘルパー関数の多くが、実際のコマンドよりも多くの条件ステートメント、変数割り当て、関数呼び出しで構成されていることに気付きました。これらの条件ステートメントは、bashスクリプトに慣れていない人にとっては非常に不透明なものになる可能性があります。

function create_archive {
    project_name=${1}
    archive_filename=${2}

    # Get revision ids
    dependencies_requirements_revision=$(cat ${project_name}/sub-project/requirements-revision.txt)

    requirements_context=${project_name}/${requirements_file}
    requirements_dir=$(dirname ${requirements_context})
    if [ "${requirements_dir}" != "${project_name}" ]; then
        requirements_context=${requirements_dir}
    fi
    latest_revision=$(git-revision-hash ${project_name})

    ...

それで、コードをPythonに移行し始めました。したがって、私のビルドスクリプトは次のようになります。

#!/usr/bin/env python

from builders import GitProjectBuilder

builder = GitProjectBuilder(
    project_name='my-project',
    Swift_container='my-container',
    git_repository='[email protected]:username/project.git',
    sub_project='[email protected]:username/sub-project.git'
)

# Compress and upload
builder.build_sass(directory='css')
builder.get_sub_project(repo='[email protected]:username/sub-project.git')
builder.build_archive(name='archive.tgz')
upload_location = builder.upload_archive_to_Swift(archive='archive.tgz')
print upload_location

builders.pyを見ると、ロジックを理解するのがはるかに簡単です-ifステートメントと関数呼び出しははるかに読みやすくなっていますが、実際のシェルコマンドからはさらに離れています。私のpythonコードでは、シェルコマンドを直接実行するのに最も近いコードは次のようになります:

def build_archive(self, archive):
    print subprocess.check_output(
        (
            'tar --exclude-vcs --create --file '
            '{archive_filename}.tar {project_dir}'
        ).format(
            archive_filename=archive_filename,
            project_dir=self.project_name
        ).split()
    )

開発者が実行されているコマンドを正確に把握する必要がある場合、これははるかに困難になります。

要約

それでは、複雑さをカプセル化しながら透明性を最大化するための最良のアーキテクチャをどのように決定すればよいでしょうか?

この問題は、依存性注入を使用しているときに、カプセル化ではなく注入する依存性が多いほど、初期化コードが複雑になるのと似ています。また、線の描画にも同様の問題があります。

この分野の名前はありますか?

5
Robin Winslow

xonsh を試してみます。シェルとpythonの巧妙な組み合わせです。

xonshは、Pythonのような、BASHwards互換のシェル言語およびコマンドプロンプトです。この言語は、Python 3.4のスーパーセットであり、BASHおよびIPythonで使用されている追加のシェルプリミティブが含まれています。xonshは、専門家や初心者の日常的な使用を目的としています。

Python(3)の抽象化およびパッケージシステムを、Nice条件文と組み合わせて利用しますが、シェルに必要なものをシェルと同じように記述します。

例えば。、

_#!/usr/bin/env xonsh

def exists(filename):
    return filename in $(ls)

if exists(".git"):
    git checkout master
    git pull
else:
    git clone $GITURL
_

Python内のインラインシェルに必要なのはわずかな醜さ$()だけであり、物事を明確に行で分割している場合(たとえば、ifステートメント行)

チュートリアルの詳細(pythonシェル行への@()の埋め込みを含む)) http://xonsh.org/tutorial.html

あなたはそれをあなたのシステムシェルとして使うことができます。しかし、あなたができるだからといってすべきではない:-)

2
0atman

私は即時のイエス/ノーの答えを提供しませんが、状況についてのいくつかの考えを提供します。

多くの人がスクリプトに依存しているため、ビルドスクリプトは、コードの最も理解しやすい領域である必要があります。簡単に理解できる限り、長い「退屈な」bashは問題にならないと私は主張します。さまざまなuniceでCの「構成&&ビルド&&ビルドインストール」に関するヒントを追加します。

あなたのbashスクリプトは変数の初期化とデフォルトの割り当てを行っているようですが、それらはどれも深いif-then-else構造に入りません。

Bashスクリプトのサイズの見積もり(確かに議論の余地はありますが)は、コードが100行を超える場合、「適切な」プログラムに書き込む必要がある場合よりも多いということです。前の文は意見の問題ですが。

Bashルートを経由しないことにした場合は、この目的のためだけに作成されたビルドツールを使用する必要があります。 Ant / Maven / Gradle Java世界およびその他の多くの異なるプラットフォーム向け。私は一種の Rake タスクまたは bazel タスクのシーケンスとして、過去に使用したいくつかのツールの一連のビルドターゲットとして例を参照してください。

私はあなたがそのルートをたどるなら、可能であればプロジェクトの最もよく使われる言語の1つであるべきだと思います(維持するのが簡単です)。

フィールドの名前があるかどうかはわかりませんが、日々これを行う人を「統合エンジニア」と呼ぶ会社もあります。

私があなたの立場にあった場合、私は http://paver.github.io/paver/ を使用します。これは基本的にRake for pythonです。

1
Bon Ami

ビルド/統合ツールにとって抽象化が多すぎることを心配するのではなく、代わりにPython開発者がこの種のことを行うために一般的に使用するツールを選択してください。よく知られているが非常に抽象化されたビルドツールのうち、同じことを行う最も明確に記述された最も単純なビルドツールからのビルドツール。

理解しておくべきより重要なこと:Bashでgzipファイルがどのように作成されるかについての詳細、またはこれらのファイルが一緒にgzipされ、省略されるとすべての方法でカオスとパニックが発生することを知っていますか?

Pythonビルドツールを検索することをお勧めします。pythonコミュニティに彼らが推奨するものを尋ね、オープンソースプロジェクトを選択してください。おそらくあなたが持っているよりも多くの機能を持っています。ビルドされ、おそらくより完全にテストされています。

0
Greg Burghardt