Your SlideShare is downloading. ×
0
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

技術トレンディセミナー フレームワークとしてのTrac

3,957

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,957
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 技術 Trendy Seminar フレームワークとしてのTrac 2009/03/03 エスエムジー株式会社 鈴木貴典 ※資料中に記載の会社名および製品名は、各社商標または登録商標です。 ※本資料の無断転載・複写を禁じます。 Copyright © SMG Co., Ltd. All rights reserved.
  • 2. Hot Topic 1. 分散バージョン管理Git/Mercurial/Bazaar徹底比較(@IT) http://www.atmarkit.co.jp/fjava/rensai4/devtool03/devtool03_1.html 最近は、分散バージョン管理が流行り!? Gitは、はてなで標準として利用しているらしい – 「株式会社はてなの開発戦略」(デブサミ2009 ) Mercurialは、本も出ている – 「入門Mercurial Linux/Windows対応」(秀和システム) 2. Shibuya.trac 2009新年会の動画アップ(Shibuya.trac) http://gihyo.jp/news/report/2009/02/0301 gihyo.jpで公開 2 Copyright © SMG Co., Ltd. All rights reserved.
  • 3. 目次 1. Tracとは? 2. Tracのプラグイン フレームワークとして見たTrac 3. アークテクチャの詳細 4. まとめ 5. 3 Copyright © SMG Co., Ltd. All rights reserved.
  • 4. 1. Tracとは? 1. Tracの概要 ITS(Issue Tracking System)のひとつ – Subversionの流行から、利用者が増えている Pythonで開発されている – Google App EngineがPythonをサポートしているので、今後、利用者 がさらに増える可能性あり 2. Tracの特徴 Subversionと簡単に連携できる – リビジョン⇔チケットの相互関連付け プラグインが豊富 Wikiも提供 Eclipse、VisualStudioなどからも連携可能 4 Copyright © SMG Co., Ltd. All rights reserved.
  • 5. 2. Tracのプラグイン 1. Trac Hacksで公開 250個を超えるプラグインが公開 Trac Hacks自体もTracで構築 誰でも自由にプラグインを登録できる 2. アーキテクチャ コンポーネントベースのアーキテクチャ コンポーネントの1つ、もしくは複数から、 1つのプラグインとなる 詳しいチュートリアルはないが、他のプ ラグインを参考にすれば、初めてでも開 参考: 発できてしまう簡単さ Trac Component Architecture 5 Copyright © SMG Co., Ltd. All rights reserved.
  • 6. 3. フレームワークとして見たTrac 1. 優れたプラグインアーキテクチャ 基本は、必要な機能に合わせて、インタフェースを実装すれば、 Tracが必要なときに探し出して呼び出す IoC(Inversion Of Control=制御の反転)の見本となる 2. ビューの分離 HTMLテンプレートを利用 テンプレートエンジンであるGenshiで実現 3. 簡単なコンフィギュレーションの管理 設定ファイル(trac.ini)の読み込み/書き込みも、メソッドを1つ 呼び出すだけ カスタマイズ可能な設定を、ユーザに公開するのも簡単 6 Copyright © SMG Co., Ltd. All rights reserved.
  • 7. 4. アークテクチャの詳細 インタフェースの実装 1. 2. HTMLテンプレート 3. Web API 4. Ticket API 5. DB API 6. Permission API 設定ファイルの読み込み/書き込み 7. カスタマイズ可能な設定の公開 8. 今回は、アーキテクチャの有効性が分かりやすい一部のAPIについて、呼び出さ れる側(プラグイン)から、フレームワークを見てみることにします。 Pythonでの実装ですが、フレームワークとしての考え方は、言語に依らず、参考 になります。 7 Copyright © SMG Co., Ltd. All rights reserved.
  • 8. 【4. アーキテクチャの詳細】 インタフェースの実装 全てのクラスは、 class TicketTemplateModule(Component): Componetntクラスを継承 implements(ITemplateProvider, IRequestFilter, ITemplateStreamFilter) →Tracのプラグインとして認識 # ITemplateProvider method def get_htdocs_dirs(self): from pkg_resources import resource_filename return [('ticketext', resource_filename(__name__, 'htdocs'))] ITemplateProvider 静的なコンテンツを取得する # ITemplateProvider method 場合に利用する。 def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] # IRequestFilter method IRequestFilter def post_process_request(self, req, template, data, content_type): HTTPリクエストを処理する if template == 'ticket.html': add_script(req, 'ticketext/ticketext.js') 場合に利用する。 add_stylesheet(req, 'ticketext/ticketext.css') return (template, data, content_type) ITemplateStreamFilter # ITemplateStreamFilter method def filter_stream(self, req, method, filename, stream, data): ページにHTMLを埋め込み if filename != 'ticket.html': たい場合に利用する。 return stream インタフェースさえ実装すれば、良い構成になっている。 それだけ、メソッド粒度、引数などが洗練されているということ。 8 Copyright © SMG Co., Ltd. All rights reserved.
  • 9. 【4. アーキテクチャの詳細】 HTMLテンプレート <legend>チケットテンプレートの変更</legend> <div class=quot;fieldquot;> <label for=quot;typequot;>チケットの分類:</label><br /> <select id=quot;typequot; name=quot;typequot;> def _process_read(self, req, page_param): <div py:for=quot;type in template.typesquot;> <option py:if=quot;type.selected” ticket_types = [{ value=quot;${type.name}quot; 'name' : type.name, selected=quot;selectedquot;> 'value' : type.value, ${type.name} 'selected' : (type.name == ticket_type) </option> } for type in ticket.Type.select(self.env)] <option py:if=quot;not type.selectedquot; value=quot;${type.name}quot;> page_param['types'] = ticket_types ${type.name} </option> </div> </select> レスポンスパラメータに、 サーバで指定された値を、 </div> HTML内で指定。 画面に表示される値を格納。 Beanのようなオブジェクトも、 利用できる。 ifやforなどの処理は、 テンプレートエンジンが解決 ロジックとビューの分離は一般的。 HTMLテンプレートにより、簡単にレイアウトが確認できる。 9 Copyright © SMG Co., Ltd. All rights reserved.
  • 10. 【4. アーキテクチャの詳細】 Web API(画面の表示を処理する) # INavigationContributor methods def get_active_navigation_item(self, req): これだけ実装すれば、 return 'importer' タブメニューとして def get_navigation_items(self, req): リンクが表示される。 if not req.perm.has_permission('IMPORT_EXECUTE'): return yield ('mainnav', 'importer', html.a('インポート', href=req.href.importer())) # IRequestFilter method def post_process_request(self, req, template, data, content_type): 表示画面に、JavaScriptを if template == 'ticket.html': 追加。 add_script(req, 'ticketext/ticketext.js') add_stylesheet(req, 'ticketext/ticketext.css') return (template, data, content_type) 表示画面に、CSSを追加。 決まったレイアウトになったり、決まった処理をするものは、簡単に利用できるように、 ユーティリティメソッドなどを用意しておく。 10 Copyright © SMG Co., Ltd. All rights reserved.
  • 11. 【4. アーキテクチャの詳細】 Ticket API(チケットの変更に対する処理をする) # ITicketChangeListener method def ticket_created(self, ticket): self.action = 'created' self.ticket = ticket def ticket_changed(self, ticket, comment, author, old_values): self.action = 'changed' self.ticket = ticket self.comment = comment self.author = author 追加、変更、削除の処理が発生した際に、 self.old_values = old_values Listenerが呼び出される。 何らかの処理を実行する前後などで、 def ticket_deleted(self, ticket): 処理をフックしたい場合に利用する。 self.action = 'deleted' self.ticket = ticket そのシステムで中心的な処理の前後には、フックできるような仕組みを提供しておくと、 拡張が簡単になる。 11 Copyright © SMG Co., Ltd. All rights reserved.
  • 12. 【4. アーキテクチャの詳細】 DB API(DBアクセスの処理をする) DBアクセスが必要な処理であるが、 良く使われる処理であるため、 ユーティリティとして、値をメソッド1つで 取得できるようにしている。 def _delete_ticket(self, id): major, minor = self._get_trac_version() if major > 0 or minor >= 10: ticket = Ticket(self.env,id) SQLを簡単に発行。 ticket.delete() →commitメソッドで、コミット完了。 else: db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(quot;DELETE FROM ticket WHERE id=%squot;, (id,)) cursor.execute(quot;DELETE FROM ticket_change WHERE ticket=%squot;, (id,)) cursor.execute(quot;DELETE FROM attachment WHERE type='ticket' and id=%squot;, (id,)) cursor.execute(quot;DELETE FROM ticket_custom WHERE ticket=%squot;, (id,)) db.commit() DBアクセスが必要な処理も、頻繁に呼び出されるような処理は、フレームワークとして、 APIを提供する。 ただし、トランザクションの設計は注意しておく必要がある。 12 Copyright © SMG Co., Ltd. All rights reserved.
  • 13. 【4. アーキテクチャの詳細】 Permission API(権限に関する処理をする) プラグインに実装されて # IPermissionRequestor methods いる権限を取得し、 def get_permission_actions(self): yield 'TICKET_BATCH_MODIFY' 一覧へ表示する。 ユーザ毎に権限を設定 # ITemplateStreamFilter methods 権限を判定して、処理を分岐 def filter_stream(self, req, method, filename, stream, formdata): させる。 if filename == 'query.html' and ( req.perm.has_permission('TICKET_ADMIN') or req.perm.has_permission('TICKET_BATCH_MODIFY') ): return stream | Transformer('//div[@id=quot;helpquot;]').before(self._generate_form(req, formdata) ) return stream プラグイン毎に、権限を自由に設定することができる。 権限を一元管理する方法も考えられるが、プラグインアーキテクチャの場合は、 プラグインに権限処理の責務を持たせる。 13 Copyright © SMG Co., Ltd. All rights reserved.
  • 14. 【4. アーキテクチャの詳細】 設定ファイルの読み込み/書き込み self.run_server = self.config.getbool('ldap', 'autocomplete_run_server', False) self.width = self.config.get('ldap', 'autocomplete_width', '400') self.minChars = self.config.get('ldap', 'autocomplete_minchars', '1') 設定ファイルから、 self.delay = self.config.get('ldap', 'autocomplete_delay', '400') 設定値を読み込み。 デフォルト値を 「カテゴリ」+「項目」 # trac.ini 指定することも可能。 [ldap] で定義 autocomplete_run_server = True autocomplete_width = 500 template_key = type_name.encode('utf-8') + '.template' template = template.replace('¥r¥n', '¥n'); template = template.replace('¥n', self._LB); self.config.set('ticketext', template_key, template) enablefields_key = type_name.encode('utf-8') + '.enablefields' 設定値をセットし、 self.config.set('ticketext', enablefields_key, enablefields) saveメソッドを実行する だけ self.config.save() フレームワークだけでなく、システムには設定ファイルはつきもの。 頻繁に利用される処理であるため、ユーティリティで簡単にアクセスできるようにする。 14 Copyright © SMG Co., Ltd. All rights reserved.
  • 15. 【4. アーキテクチャの詳細】 カスタマイズ可能な設定の公開 「カテゴリ」 「項目」 class DiscussionApi(Component): 「デフォルト値」 「説明文」 default_display = Option('discussion', 'default_display', 'tree', を定義 'Default display mode of topic message list.') forum_sort = Option('discussion', 'forum_sort', 'id', →Javaでいうところの、 'Column by which will be sorted forum lists.' + クラス変数みたいなもの 'Possible values are: id group name subject ' + 'time moderators description topics replies lasttopic lastreply') クラスファイルを、 フレームワークが 自動で読み取り、 オプションとして表示。 設定値は、設定ファイ ルに保存される。 ユーザがカスタマイズすることを可能にする設定値を定義している。 フレームワークが自動で読み取り、保存可能にしているため、プラグイン側では 定義のみで済んでしまう。 15 Copyright © SMG Co., Ltd. All rights reserved.
  • 16. 5. まとめ 1. プラグインアーキテクチャとして、Tracのアーキテクチャ は参考になる。 2. IoC(Inversion Of Control=制御の反転)は、フレーム ワークとしての基本である。 3. ロジックとビューは分離する。 4. 頻繁に利用される処理は、ユーティリティなどを提供し、 簡単に利用できるようにする。 5. 権限、設定ファイルの管理など、共通機能に関しては、 全体に影響するため、特に早めにフレームワーク化し ておく。 16 Copyright © SMG Co., Ltd. All rights reserved.

×