taisablog

taisa's engineer blog

image3

投稿日:

-

執筆者:

関連記事

PHPのモッキンフレームワークPhakeの使い方

前回に引き続きPHPUnit関連の記事です。今回はPHPのモッキンフレームワークであるPhakeの使い方を確認します。 Phakeについて 作者は? Mike Livelyという方のようです。 twitterGitHub Phakeって? こちらですね。 PhakeGitHub ファイル構成 一応ファイル構成を載せておきます。 . ├── Phake │   ├── Annotation │   │   ├── MockInitializer.php │   │   └── Reader.php │   ├── CallRecorder │   │   ├── Call.php │   │   ├── CallExpectation.php │   │   ├── CallInfo.php │   │   ├── IVerificationFailureHandler.php │   │   ├── IVerifierMode.php │   │   ├── OrderVerifier.php │   │   ├── Position.php │   │   ├── Recorder.php │   │   ├── Verifier.php │   │   ├── VerifierMode │   │   │   ├── AtLeast.php │   │   │   ├── AtMost.php │   │   │   ├── Result.php │   │   │   └── Times.php │   │   └── VerifierResult.php │   ├── ClassGenerator │   │   ├── EvalLoader.php │   …

Python Bottleのソースを読む プラグイン編

Pythonの軽量WebフレームワークBottleのソースを読む プラグイン編Bottleを触ってみると通常のWebフレームワークには用意されているであろう機能がなかったりします。これはマイクロフレームワークであるが故であり、すべてがそろってない状態がむしろ正しい状態と言えます。Bottleではそういったものを補うためにプラグインが用意されていてある程度の機能はそちらでまかなうことができます。また、Plugin Development Guide を参考にしてプラグインを自作することも可能です。 Class Hierarchy plugin用クラスはなくインターフェースが定義されているのでそれにしたがって実装します。 プラグインの使い方 公式ドキュメントに簡単な使い方が乗っているのでこちらを参考にすれば簡単に導入することができます。以下がサンプルコードで、簡単な流れとしてはinstall()で任意のプラグインをインストールするリクエスト時にプラグイン実行となります。サンプルコードでは、プラグインでkwargsにdbをセットされている為ルートのアクションでdb変数が利用できるようになってます。 from bottle import route, install, template from bottle_sqlite import SQLitePlugin install(SQLitePlugin(dbfile=’/tmp/test.db’)) @route(‘/show/<post_id:int>’) def show(db, post_id): c = db.execute(‘SELECT title, content FROM posts WHERE id = ?’, (post_id,)) row = c.fetchone() return template(‘show_post’, title=row[‘title’], text=row[‘content’]) @route(‘/contact’) def contact_page(): ”’ This callback does not need a db connection. Because the ‘db’ keyword argument is missing, the sqlite plugin ignores this callback completely. ”’ return template(‘contact’) プラグインの作り方 プラグインの作り方も公式ドキュメントにもっともシンプルな形のサンプルがあります。これは実行速度をレスポンスヘッダーにつけて返す処理ですが、サーバ起動時にstopwatchをインストールし、リクエストが来た際にデコレータを実行(表現あってるか分からない)することでリクエストの処理時間は計測できるようになっています。 from bottle import response, install, route import time def stopwatch(callback): def wrapper(*args, **kwargs): start = time.time() body = callback(*args, **kwargs) end = time.time() response.headers[‘X-Exec-Time’] = …

Python Bottleのソースを読む リクエスト・レスポンス編

Pythonの軽量WebフレームワークBottleのソースを読む リクエスト・レスポンス編   Class Hierarchy ここの部分 リクエスト受付からレスポンスまで 前回、サーバの立ち上げ時にルーティングが読み込まれるところまでを確認したので今回はリクエスト受付からレスポンスを返すまでを見てみる。 まずリクエストが来るとwsgiref/handlers.pyのrunが呼ばれ、Bottleの__call__が呼び出される wsgiref/handlers.py self.setup_environ() # リクエストを処理しレスポンスを取得する self.result = application(self.environ, self.start_response) # レスポンスを返す self.finish_response() bottle.py def __call__(self, environ, start_response): “”” Each instance of :class:’Bottle’ is a WSGI application. “”” return self.wsgi(environ, start_response) リクエストを処理する際に、LocalRequestのbindを呼び出しBaseRequestのコンストラクタにてenvironとLocalRequestをセットする。これでBaseRequestのラッパーからパラメータを取得可能になる。レスポンスも同様にLocalResponseのbindを呼び出す。 try: out = None environ[‘bottle.app’] = self request.bind(environ) response.bind() try: self.trigger_hook(‘before_request’) except HTTPResponse: return _e() # ここでリクエストの主処理を実行する out = _inner_handle() return out; finally: if isinstance(out, HTTPResponse): out.apply(response) self.trigger_hook(‘after_request’) BaseRequestのコンストラクタ self.environ = {} if environ is None else environ self.environ[‘bottle.request’] = self リクエスト情報は以下のように取得可能になる def index(): request.forms.get(‘test’) return ‘TOP’ LocalRequestは以下の通りマルチスレッドに対応している #: A thread-safe instance of :class:`LocalRequest`. If accessed from within a #: request …

Python Bottleのソースを読む ルータ編

Pythonの軽量WebフレームワークBottleのソースを読む ルータ編 Class Hierarchy ここの部分 Bottleのルータについて bottleのルータは特に継承関係はなくRouteとRouterクラスで構成されている Routerの役割 A Router is an ordered collection of route->target pairs. It is used to efficiently match WSGI requests against a number of routes and return the first target that satisfies the request. The target may be anything, usually a string, ID or callable object. A route consists of a path-rule and a HTTP method.The path-rule is either a static path (e.g. `/contact`) or a dynamic path that contains wildcards (e.g. `/wiki/`). The wildcard syntax and details on the matching order are described in docs:`routing`. RouterはRoute情報のコレクションを保持する。 Routeの役割 This class wraps a route callback along …

no image

2016年の振り返り

2017年になってもう3ヶ月が過ぎようとしているけど、今年初投稿なので今更ながら2016年の振り返りをする。 2016年前半 2016年前半はWeb業界に来て初めてWebサービスの受託開発をした。5年前にSIerからWeb業界に来て以来初めての受託開発だった。プロジェクト前半は若手エンジニア2人いたが、色々な都合により後半は自分1人になりそこからは1人最後までやることになった。 SIerにいた頃、小さめのプロジェクトであれば自分一人でやることはあったが、今回のような大きめのプロジェクトで0→1のサービス開発をマネージメントしながら開発するというのは初めてだった。ローンチ後は何事もなく稼働しているのでよくやったと思えたもののWebサービスの受託開発の難しさを思い知った。 Laravelについて 開発はPHP+Laravelを使った。初めて使ったフレームワークだったが、日本語ドキュメントがしっかりしているのでほぼそれだけで開発を進めることができた。 https://readouble.com/laravel/5.1/ja/installation.html 主なプラグインは以下を使った。 laravel-debugbar laravel-ide-helper Intellij Laravel-Plugin 2016年後半 サービス開発に戻り、戻ってからは主に以下のことをやった。 決済システム導入 CI環境の再整備 ステージング環境の整備と追加 PHPUnit+Phakeによるユニットテストの本格導入 サーバのオートスケール 決済システム導入 これは、受託開発が都合により伸びた為、設計までして他のメンバーに引き継ぐすることになってしまったが、その後、また引き継ぎ開発を進めていった。「決済」といったシステムを扱ったことで良い経験ができたように思う。 CI環境の再整備 サービスの拡大、人の入れ替わり、増加により以前自分で立てたJenkinsのCI環境が整備されずひどい状況になりつつあったので整備した。Jenkins2へのバージョンアップもこのタイミングで行った。 ステージング環境の整備と追加 人員に対してステージング環境があきらかに枯渇していたので再整備と追加をした。具体的にはシステムだけでなく運用者もリリース前テストで利用する為、ステージング環境利用待ちのようなものが発生している状況だった。また、いくつかのサービスがつながっていることもあり環境がブラックボックス化していたのを再構築しドキュメント化しつつ環境を増やした。テスト環境大事。 PHPUnit+Phakeによるユニットテストの本格導入 UnitTestも以前は書くよう推奨していたが形骸化している状況だった。また、新卒メンバーが入ってそもそもテストが書けないメンバーもいる状況だった。これに対して、ハンズオンを開催しある程度書けるところまで持っていき、それ以降はプロダクト開発時にフォローするという形で最終的にはメンバー全員が必ずUnitTestを書くというところまで持っていくことができた。また、テストが増える従って、修正時の確認コストが減り品質が上がってきている実感が得られた。 サーバのオートスケール アクセスが増え、ときに突発的に高負荷が来るという事象が増えてきて、その度にサーバをたて、デプロイスクリプトに新しいサーバを追加しデプロイするということをやっていた。それもいい加減面倒だし事前アナウンスがなければ対応ができないので、常にS3に最新ソースを配置しておき、あとは負荷検知により自動的にサーバを増やすという仕組みを導入した。 社外活動とアウトプット 2015年末に子供が生まれたことと2016年の前半の受託開発に忙殺されたことで全くできなかった。2017年は落ち着いて来たこともあり活動を増やす予定。 まとめ 2016年後半の取り組みに関しては、2017年から始めるスクラムの取り組みの為の下準備という意味合いもあり、テストや環境系の整備をメインに行った。これにより2017年からの取り組みをスムーズに始められたと思う。