2020/02/24

メタプログラミングRubyの感想

「メタプログラミングRuby 」を一通り読み終えた。
まだ全ては完全理解できていないが、やっとRubyの面白さを感じ取れた気がする。
理解したことをラフなメモ書き。
まだ初心者なので間違っていたら後で直す。

【参考】
メタプログラミングRuby - ククログ(2010-09-13)

メタプログラミングRubyを読んだ - razokulover publog

「メタプログラミングRuby」オススメです - UUUM攻殻機動隊(エンジニアブログ)

「メタプログラミングRuby」ことはじめ?開発本部・TechLunch? - Medley Developer Blog

【1】JavaやC#、VB等と違って、Rubyの特徴や面白さはどこにあるのだろうか?
「メタプログラミングRuby 」を読んで、自分はRubyの威力を完全に理解できていないことが分かった。
特徴は3つあると思う。

【2】一つは、ArrayやHash等の基本ライブラリが十分揃っていること。
VBはリストやハッシュのライブラリが貧弱で、ちょっとした操作にかなりの行数が必要になる。
JavaはArrayListやMapなどにはライブラリは揃っているが、Rubyほどないように思う。

Rubyならmap, collect, find, select, inject, reduceなど、配列やハッシュの単純な操作を短く書ける。
オープンクラスだから、後でいくらでも機能追加できる。

後から発展してきたプログラミング言語ほど、リストやハッシュのような基本的なデータ構造を扱う機能は豊富だ。
昔のプログラミング言語ほど、リストやハッシュの簡単な操作だけに色々考えさせられて疲れてしまう。
だからこそ、低いレイヤで考える部分が少なくなり、本来の機能のレイヤを考える方へ労力を費やせる。

【2】Rubyのオブジェクト指向はJavaとかなり違う。
Javaはクラス重視だが、Rubyはメソッドを重視しているように感じる。

Rubyと大クラス主義とダックタイピング、そして名前重要 - ゆとRubyist日記

つまり、Rubyはメソッドを実行するレシーバよりも、メソッドというインターフェイスを重視している。
Rubyでメタプログラミングを読んでいると、メソッドなのか変数なのか最初は判別できない時がある。
たとえば、シンボルを渡して、ブロックに変更して処理を実行させる、とか。
むしろ、わざわざそう書いているとしか思えない。

オブジェクト指向の技術としては、Javaでは継承や委譲くらいしかないが、Rubyには、incude, prepend, extend, refineなど色んな技法が多い。
Javaはオブジェクト指向言語と言いながら、実際のプログラムは手続き型言語の気持ちで書いてる。
手続きで書いていって、ソースが長くなったら、OOPの技術でリファクタリングする、みたいな感覚。

一方、Rubyでは、メソッド探索や継承チェーン、method_missingのように、常に継承関係を意識しながら書いている。
Rubyの方が複雑な機能をスマートに書ける場合が多いように思う。
RailsのValidationで、フック処理と特異メソッド(クラスメソッド)を上手く使いこなしている解説を「メタプログラミングRuby 」で読んで、なるほどと思った。

【3】Rubyのライブラリは、メタプログラミングに向いた機能が多い。
むしろ、すごく多すぎてやり過ぎなくらい。
class_eval, define_method, instance_evalくらいならまだ良かろうが、evalで文字列のプログラムを実行評価できるのはやり過ぎなくらい。コードインジェクションのリスクもある。

でも、そのおかげで、似たような操作で名前の違うメソッドを一括処理することで、プログラム行数を相当短くできる。
たとえば、メソッドを文字列でGrepして、ヒットしたらある処理、ヒットしなかったら、ゴーストメソッドでmethod_missingで一括処理、とか。

また、Rubyでは、privateメソッドも外部から自由に扱えてしまうので、テストコードが書きやすいはず。
JUnitもリフレクションを多用しまくっていたし。
たぶん、Rubyの方が自動テストに向いているのだろうと思う。

一方、JavaやC#でメタプログラミングっぽいことをやろうとしたら、XML地獄になる。
XMLを書いている時間の方が長いくらいだ。
つまり、Javaは外部DSL、Rubyは内部DSLが扱える、ということなのだろう。
その分、Rubyだけで全て書ききれるから、ストレスも低いと思う。

そういう設計思想の元で、「メタプログラミングRuby 」では、Rubyは進化的設計に向いている、という解説があり、なるほどと思った。
たとえば、RailsのライブラリもVer1.0からVer4までVerUpするたびに、メタプログラミングで書いた部分をオブジェクト指向で書き直したり、method_missingを多用して性能悪化した部分を性能改善していくなど、色んな手間がかかっている。
そういう進化的設計は、アジャイル開発と相性が良い。
最初はまず機能をリリースして、ユーザに使える機能を提供し、VerUpするたびに機能を改善したり、性能を改善していく、というやり方だ。
そういう開発スタイルは、開発プロセスがフレームワークとして運用できるだけでなく、ソフトウェア開発技術そのものもレベルが高くなければ、コントロールできない。

つまり、Rubyはメタプログラミングとオブジェクト指向という2つの技術を使いこなすことで、適用できる場面をスムーズに変えることができ、スピード感のある開発と柔軟な開発という相反する手法をコントロールできているのだろう、と思った。


| | コメント (0)

2020/02/22

PlantUMLでAWSのインフラ構成図を描くやり方

PlantUMLでAWSサービスを含む図が作れるらしい。
以下の内容を試してみる。

【参考】
PlantUMLでAWSサービスを含む図を作る | 秋元@サイボウズラボ・プログラマー・ブログ

AWS Labs製のPlantUMLライブラリ『AWS Icons for PlantUML』の使い方 - Qiita

AWS 構成図を PlantUML で描画できる『AWS-PlantUML』の紹介 ? サーバーワークスエンジニアブログ

従来、インフラ構成図はシステム開発で重要な成果物なのに、非常に作りにくかった。

最悪なチームは、Excelでインフラ構成図を何とか書き切ろうとして、だいたい上手く描けていない。
Excelでああいう複雑なダイアグラムを描くには、Excelは機能が貧弱すぎる。
Excelで描いた図はどこかで何かが漏れているし、頻繁な変更に耐えきれず、すぐに古くなってしまう。

僕の経験では、Visioでインフラ構成図を書いているチームが一番まともだった。
Visioなら、複雑なダイアグラムもまだ描きやすい。
しかし、Visioはライセンスが高価なので、余裕のある会社や開発チームでしか使えなかった。

そういう問題点をずっと抱えている現場では、PlantUMLとAWSアイコンを使ってインフラ構成図を描く手法は試して見る価値がある。
PlantUMLはテキストベースなので、慣れればDSLっぽく書けるし、Gitでも構成管理がやりやすいので変更にも強い。
AWSアイコンが使えるならば、PlantUMLのインフラ構成図は一目で理解できるようになるだろう。
昨今ではAWSでシステム開発をするのが普通なので、こういうインフラ構成図を即座に書いて情報共有できるツールがあると非常に心強い。

PlantUMLについては過去にも色々考えていたが、インフラ構成図も描けるならば、非常に強力なツールだ。
この辺りもいろいろ考えてみる。

PlantUMLを使ってExcel設計書をテキスト化するアイデア: プログラマの思索

歴史の流れをPlantUMLのシーケンス図で書き起こす事例のリンク: プログラマの思索

| | コメント (0)

2020/02/21

astah* System Safetyのリンク

安全分析設計論証に特化したモデリングツールastah* System Safetyをリンクしておく。

astah* System Safety | 安全分析設計論証に対応したMBSEツール

以前から、SysML、GSN、STAMPなどの図を1個のモデリングツールで描けるといいな、と思っていたので、興味はある。
1つの事象、考えたいアイデアは、複数のモデルを描きながら、関連性や整合性を検証していくことで、本質を深堀りできるから。
この辺りのアイデアも蓄積していく。

| | コメント (0)

2020/02/14

SmalltalkとLispから来たメソッドmap と collect、reduce と inject


SmalltalkとLispから来たメソッドmap と collect、reduce と injectをメモ。

【参考】
map と collect、reduce と inject ―― 名前の違いに見る発想の違い

【Ruby】
[3, 4, 5, 6].map {|i| i + 1 }
=> [4, 5, 6, 7]

【Lisp】
(map 'list (lambda (i) (+ i 1)) '(3 4 5 6))

【Ruby】
[3, 4, 5, 6].collect {|i| i + 1 }
=> [4, 5, 6, 7]

【Smalltalk】
#(3 4 5 6) collect: [:i | i + 1 ]

【Ruby】
[3, 4, 5, 6].reduce {|i, j| i + j }
[3, 4, 5, 6].reduce(:+)
=> 18

【Lisp】
(reduce (lambda (i j) (+ i j)) '(3 4 5 6))
(reduce '+ '(3 4 5 6))

【Ruby】
[3, 4, 5, 6].inject {|i, j| i + j }
[3, 4, 5, 6].inject(0) {|i, j| i + j }
[3, 4, 5, 6].inject(:+)
=> 18

【Smalltalk】
#(3 4 5 6) inject: 0 into: [:i :j | i + j ]

(引用開始)
map と collect の発想の違い
まずは map と collect の発想の違いを見てみましょう。
map
map は「データ構造を保ったまま3、あるルールに従って元のデータ構造を別データ構造に変換する」という発想になります。
(中略)
collect
collect は「データ構造内の全ての要素に対して、ある処理を繰り返し実行し、その結果を集めたもの」という発想になります。
(中略)
reduce と inject の発想の違い
次は、reduce と inject の発想の違いを見てみましょう。
reduce
reduce は「あるルールに従ってデータ構造内の要素数を縮小していき、最後に残った値を返す」という発想になります。
(中略)
inject
inject は「値をプールしておくバケツを用意しておき、データ構造内の全ての要素をひとつずつ、ある処理にしたがってバケツに注入していく」という発想になります。
(中略)
しかし別々の発想をしていても、それぞれで「こうした処理は必要だ」という結論になって、違う名前で同じ機能が実装されたということはとても面白いですね。実は今回取り上げた二つの機能、ひとつは「map と collect」が表現している「巨大なデータを構造を保ったまま別のデータに変換する」機能4、もうひとつは「reduce と inject」が表現している「巨大なデータのすべての要素を使って何らかの計算結果を求める」機能5は、巨大なデータを処理する場合の最も基本的な処理、つまり基礎となる機能なのです。
(中略)
5.数学ではこれを「畳み込み」と呼びます。
(引用終了)

mapはRuby初心者も慣れるが、injectの発想は面白い。
injectでは明示的にブロックを渡すのではなく、[3, 4, 5, 6].inject(:+) のように、メソッドのシンボルを渡すことで配列の要素に作用させる。

この辺りの考え方に、Rubyが過去の言語の良い所取りをしている感じがする。


| | コメント (0)

2020/02/09

Redmineのトラッカーをヘーゲル弁証法とフッサール現象学の観点で議論してみた議論のリンク

@tw_yukiaさんとの楽しい会話と、自分のラフな考えをメモ。

【参考】
Redmineのトラッカーをヘーゲル弁証法とフッサール現象学の観点で議論してみた - Togetter

Redmineをどうも好きになれない人のための、20%の基礎を抑えれば、80%位の業務に対応できると気がついた長話。|ゆきあ|note

「Redmineのトラッカーは弁証法の結論的なので、人に向けて説明する事でしか適切な説明が出来ない」という@tw_yukiaさんの仮説は、僕も完全に分かっていない。
おそらく「トラッカーとは行動パターンの大分類である」という主張から、実際に行動してみて初めてトラッカーの意義が分かることかな、と推測したりするが分からないので、今度聞いてみようと思う。

僕が理解する弁証法は、「勝つための論文の書き方」に記載のある、人文科学や社会科学でよく使われるアウトラインのイメージ。
つまり、ある人の主張に対し、その主張の穴を見つけて論理的に崩し、最後に自分が正しい回答を提示するイメージ。

論文作成の技法part1~論文の構造: プログラマの思索

僕が理解するトラッカーは、ワークフロー、帳票、Issue Trackingの3種類。
個人的には、@g_maedaさんが主張される「トラッカーとは帳票である」意見が重要と考える。
理由は、業務のExcel管理台帳や紙の帳票は、トラッカーにマッピングできれば、全てチケット管理で実現できるからだ。
そのおかげで、Redmineがソフトウェア開発以外に社内の簡単な業務ワークフローにも応用された事実があると思う。

だから、@g_maedaさんはRedmineの「トラッカー」を「チケット種別」へ変更するチケットが提案されたのだ、と理解している。

Redmineの「トラッカー」を「チケット種別」へ変更するチケットが提案されている: プログラマの思索

一方、@akahane92さんが主張されるIssue Trackingの意見も重要と思う。
僕は、Issue Trackingとは、No ticket, No commitに代表されるトレーサビリティがその性質の核心にあると考えている。
単にチケットにログが記載されているだけでなく、構成管理の配下にあるソースや設計書の変更履歴とチケットが密接に連携されることで、変更管理もチケット管理で代用できる、という考えだ。

Patch #29045: Change Japanese translation for Tracker - Redmine

(引用開始)
--- Japanese Part ---
意見者の背景
Redmineを利用して10年余りになります。主に製造業の業務システムと装置研究開発向けのIssue Tracking System及び知識基盤としてRedmineを利用しています。現在、国内外1400名の利用者があり、300プロジェクトに40万チケットが記録され、閲覧回数は70万ページビュー/月です。( 事例紹介論文とスライド )
意見
この翻訳提案には賛成できません。
「トラッカー」のままに維持するか、どうしても和訳を変更するなら「課題追跡様式」が良いと私は思います。
理由
Redmineの最大の価値は「追跡パターンの選択によって課題解決を促進させる仕組み」にあると私は考えています。
現実社会の多様かつ難解な課題を解決に導くには、戦略(ここでは「課題解決のための追跡パターン」を指す)の選択が不可欠です。
どのような戦略で課題にアプローチするのかが、複雑な課題を解決できるかどうかの決め手になります。
Redmine における Issue Trackerとは、課題を解決に導くための戦略をパッケージ化して、ITSプロジェクト毎の取捨選択を可能にしたものなのです。
なぜなら、解決対象のプロジェクトの領域と目的よって、選択すべき戦略(パターン)の組み合わせは異なるからです。
ゆえに、Redmineの最大の価値を体現している Issue Tracker の和訳には、追跡戦略、パターンといった特徴が包含され、利用者に向けて表現されていなければなりません。
(引用終了)

こういう議論も次回のRedmine大阪でやってみたいと思う。

第21回 Redmine大阪 これからはじめる Redmine 2020(令和2年) 2020/04/04(土) 13:00~- connpass


| | コメント (0)

«「確率思考の戦略論」の感想