Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ(20201028後編)RuboCop 1.0.0 stable版がリリース、Ruby DSLのGUIフレームワークGlimmer、Keycloakほか

こんにちは、hachi8833です。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙇

追記(2020/10/29): 来週の週刊Railsウォッチはお休みをいただき通常記事といたします🙇。

Ruby

RuboCop 1.0.0がリリース

rubocop-hq/rubocop - GitHub

koicさんの記事も公開されていました。


つっつきボイス:「RuboCop 1.0.0が出ました🎉」「これほど普及して使われ続けているRuboCopが今回初めて1.0.0になったというのが感慨深い」「リリースノートを見ると今回でstableになったとのことなので、メンテナーがstableにふさわしいと判断したんでしょうね」「この間のRubyKaigi Takeout 2020でもkoicさんがRuboCopについてお話しされていました↓」

Glimmer: Ruby DSLで書けるGUIフレームワーク(RubyFlowより)

AndyObtiva/glimmer - GitHub



同リポジトリより


つっつきボイス:「DSLで書くGUIフレームワークか」「こういうプロジェクトを久しぶりに見たかも」「DSLはSWT(Standard Widget Toolkit)、tk、Opal↓、XML、それにCSSまでサポートしてますね」

opal/opal - GitHub

「このGlimmerを見てて思い出したんですけど、こんな感じでGUIの記述言語やGUIエンジンをプラガブルにする抽象化手法はGoF本↓で見た覚えがあります」「あ、そうでしたか!」「こういう設計がきれいに動くとすごい達成感ありますよね」「研究やテストレベルならともかく、ここまで仕上げるのは大変そう」

「GlimmerではOpalも動いて、しかもこれはRailsサーバーじゃないですか↓」「この頑張りはスゴい」


同リポジトリより

# 同リポジトリより
class Person 
  attr_accessor :country, :country_options

  def initialize
    self.country_options=["", "Canada", "US", "Mexico"]
    self.country = "Canada"
  end

  def reset_country
    self.country = "Canada"
  end
end

class HelloListSingleSelection
  include Glimmer
  def launch
    person = Person.new
    shell {
      composite {
        list {
          selection bind(person, :country)
        }
        button {
          text "Reset"
          on_widget_selected do
            person.reset_country
          end
        }
      }
    }.open
  end
end

HelloListSingleSelection.new.launch

「tkだと以下のように起動できるみたい」「デスクトップGUIだ」

# 同リポジトリより
ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combo.rb'"
# 同リポジトリよりhello_combo.rb
# ... more code precedes
root {
  title 'Hello, Combo!'

  combobox { |proxy|
    state 'readonly'       
    text bind(person, :country)
  }

  button { |proxy|
    text "Reset Selection"
    command {
      person.reset_country
    }
  }
}.open
# ... more code follows


同リポジトリより

「腰を据えて本格的に作っている感じですね」「Glimmerはコミット数も2万越えていますし、おそらく自分たちのプロダクトでも使っているんじゃないかな」「作者のプロフィールを見るとEclipseConやEclipseWorldでも発表していて、UIに強そうな感じですね」

JavaのGUIライブラリよもやま話

「ところでSWTといえばEclipseで使われているのが有名ですけど、もしかするとJetBrains IDEのGUIもSWTベースなのかな?(調べる)何とSwingだけで作られているそうです↓」「え、JetBrains IDEのGUIがSwingとはちょっと意外!」

参考: JetBrains の IDE の GUI ってなんでできてるんだろう

「SWTは10年ぐらい昔にGUI作りで使ったことがあって、見た目がネイティブのGUIにとても近くてなかなか良かったんですけど重かったのを覚えてます(UIそのものの反応はいいんですが)」「SWTはEclipseのおかげで流行った印象があります」「その前のAWTは機能が少なくて、Swingはちょっと難易度が高かった気がしますね」

※このあたりは10年以上前の知識で書いているので今のJavaはもっと進化していると思います🙇。

参考: Swing - Wikipedia
参考: Standard Widget Toolkit - Wikipedia
参考: Java AWT 入門

私はnilを使わない(Hacklinesより)


つっつきボイス:「nilの利用を極力避けてNullObjectなどを使おうという記事」「NullObjectを使うパターンはRuby以外の言語でもよく見かけますね↓」

参考: Null Objectパターン -- デザインパターン紹介

上の記事では「GoF以外のデザインパターン」のひとつとしてNull Objectパターンが紹介されていました。

Rails tips: Null Objectパターンでリファクタリング(翻訳)

その他Ruby

つっつきボイス:「経験を積んで理解が十分進むまでは変数名やメソッド名を省略しない方がいいよ、という気持ちはとてもわかります」「いい記事❤️」「長い名前を入力するのが大変なんです、という人向けにも追記しているところが本当に親切」「IDEやエディタの自動補完機能は、まさにそういう長い名前を楽に正確に入力するためのものですよね」

「たしかに、どんなときに名前を省略してよいかという判断は簡単ではないんですよね」「他の人はこういうのをどうやって学んでいるんでしょう?『リーダブルコード』↓とか?」「いろんな人のコードを読んで自分でも書いているうちに、だんだんできるようになると思いますけど」「特に命名方法は独自にやるよりも、多くの人がこう書いているというのを見て参考にするのがよいと思います」「最終的にはコミュニケーションの問題なので、読む人に伝わることが大事ですね」

「開発する集団によって命名の文化が違うこともありますよね」「たしかに」「Javaのようにクラス名がものすごく長くなる文化だと、インスタンス名はクラス名の単語の冒頭を取り出して略語にしたりしますね」「はい、やります😆」

DB

table_to_xml関数とSQLインジェクション

参考: PostgreSQLドキュメント 9.14. XML関数


つっつきボイス:「BPS社内Slackに貼っていただいた記事です」「記事によると、table_to_xml()関数はテーブルをXMLに変換するものなんですが、引数にテーブル名を指定できるということは、アクセス可能な任意のテーブルにアクセスできるということで、さらに以下のようにposition()関数を使うと部分文字列も取得しようと思えばできるということだそうです↓」「ぽすぐれにこういう関数があるとは知らなかった...」「pg_shseclabelがテーブル名なのか」

test=# select position ( 'w3.org' in table_to_xml('pg_shseclabel',true, false, '')::text );
 position 
----------
       38
(1 行)

参考: 9.4. 文字列関数と演算子 -- position()関数

「これがどの程度脆弱なのかは詳しく見ないとわかりませんが、この問題は少なくともSQLインジェクションが可能な状態になっていることが前提なので、ひとたびSQLインジェクションをやられたときの被害範囲が広がる可能性はありますね」「たしかに」「そもそもSQLインジェクションを避けるべき」

参考: SQLインジェクション - Wikipedia

「PostgreSQLの関数のように独自に拡張された機能の中にはこういうことをやろうと思えばできてしまうものがあることを、この記事で知ることができたのはよかった👍」「これはなるほどという感じ」「こういうものが他の関数や他のDBMSにもあるかもしれませんね」

「PostgreSQLには独自機能が豊富に搭載されていて、自分が使わない機能でも内部的には存在する機能というのがたくさんあるので、SQLインジェクションのような任意コード実行をされてしまうと悪用される可能性の幅が広がる、というのは注意するポイントになりそう」「そうですね」「自分がPostgreSQLを好きな理由のひとつが豊富な独自機能なんですが、豊富な機能にはそういう一面もありうるということも考えさせられました」

「これは知らないとなかなか気づけなさそう...」「記事の最後にドキュメントを読みましょうとありますしそのとおりなんですけど、気づくにはそのつもりで注意して読む必要があるでしょうね」

クラウド/コンテナ/インフラ/Serverless

システムから分離したい機能


つっつきボイス:「はてブで知った記事です」「認証や認可や課金の機能がコアドメインと結合すると後々つらくなるよねという話、たしかにもっともだと思います」

Keycloak

「そういえば最近Keycloak↓を触る機会があったんですが、認証と認可を丸ごとワンストップで扱えるのがなかなかいいなと思っていたところです」「Keycloakとは?」「認証と認可を両方やれるオープンソースのツールです」「Red Hatがスポンサーになってる」

「KeycloakはいわゆるSSOサーバーのようなこともやれますし、IDプロバイダーのような機能もありますし、以下の記事↓などにもありますけどとにかく機能がものすごくいっぱいあります」「ホントだ!」「どうやって入れるんでしょう?」「Dockerで一発インストールできます」

参考: Keycloakとは - Qiita

「この種の認証認可系外部サービスには他にもAuth0↓やOkta↓などがあって、Keycloakと合わせてそのあたりを調べました」

「Auth0は強力だけどお安くなかった覚えがあります」「Auth0は有料な分、必要そうなサービスもひととおり揃っていて、管理画面などもよくできていると思いました」「おぉ」「Auth0は開発者向けのカスタマイズ機能が豊富で、特定条件のユーザーがログインした際にはこの権限を付与する、みたいなこともJavaScriptコードで実現できるようです」「へぇ〜!」「スクリプト情報はGitリポジトリとして管理できますし、今どき必要そうなモダンな機能はたいていありそうですね」「スゴい」

「認証についてはOAuth 2.0やSAMLやOpenIDなど色々なメジャーな方法がありますけど、認可機能についてはアプリケーション側からの要求が多彩なのと、権限管理が複雑になりがちなことから難しいんですよね」「KeycloakやAuth0、Oktaなどはそうした認可の機能も備えているみたいですが、それらが自分たちのアプリケーションとうまくつなぎこんでいい感じに作れるのかどうか、という部分はよく調べないと難しいなあと感じます」

参考: OAuth 2.0 — OAuth
参考: Security Assertion Markup Language - Wikipedia
参考: OpenID - Wikipedia


「最初の話に戻ると、認証機能は基本的に切り離されると思いますし、課金も当然切り離しますけど、認可機能も切り離したい」「認可機能を切り離さないと後で面倒になりますよね」「昔認可機能を自分で実装したことがあったんですけど、後でやっぱり切り離したいって言い続けたことがあります」「特殊なパーミッションが必要になると独自の認可機能が必要になったりするのが悩ましいところ」「あと認可機能はUIを作り始めると大変になりがち」「認可のUIはつらかったです...」

「それから、認証や認可や課金を最初から切り離して設計するとなると相応の初期投資が必要になりますけど、ビジネスの立ち上げ段階でそこまで投資するかどうかという問題もあります」「そこですよね」「サービスが売れて採算が見込めるようになった段階で、そういう機能を早いうちに切り離しておけるとうれしい」

「認証と認可は割と密接につながりやすい機能なので一緒になりやすい傾向があるかも」「それで言うと、少なくとも認証認可、課金、コアドメインの3つは切り離したい」「課金周りだと、お金のやり取りとしてのトランザクションの管理や、あと証跡管理も切り離したいですね」「返金機能やポイントの取消機能が入ると複雑になりそう」

「課金機能は、たとえばポイント付与みたいなことを始めると複雑になりやすいです」「ポイント付与の機能がコアドメインと癒着するとえらいことになりますよね」

ポイント管理と法律

「なお、いわゆるポイントの管理は資金決済に関する法律↓が絡むこともあるので、お金の管理とは分けておきたいです」「あ、法律の問題か!」

参考: 資金決済に関する法律 - Wikipedia

「ソシャゲ方面の言葉で言うと、たとえばユーザーがお金で買った、いわゆる有償の『石』の未使用分については、(条件に該当する場合)業者は供託金を積んでおかなくてはいけない、というのがあったりします」「むむ?」「詳しくは以下の記事↓などにも書かれています」(しばらく一同で読む)

参考: 石に貴賤はあるのです(有料ガチャのひみつ) - 現代パトロン学~だから僕らは寄付《ガチャ》をする~(ガリ=トーラス) - カクヨム

詳細は割愛するが、かいつまんで言うと「現金に準じた使い方ができるポイントを提供する場合、その保障をするために全体の半額分の供託金を積む必要があるよ!」という法律だ。その対象になるポイントとは「使用期限が6ヵ月以上かつ、未使用残高が1,000万円以上プールされているもの」となっている。
ケータイアプリの場合、一部プラットフォーム(りんご)側の都合により使用期限を設けることを禁じられているため、早い話が1,000万円以上の石が積みあがった時点で供託金を用意しなければならない。
kakuyomu.jpより

「そういうわけで、ポイントの管理は法律も絡んで複雑になりやすいので切り離しておきたい: それこそマイクロサービスに切り出せば機能としてもわかりやすいでしょうね」「たしかに」「それにポイントと課金はドメインが異なるので、ポイントと課金を一緒に扱おうとすると設計でうまく抽象化できなくなることが多いと思います」

ビジネスドメイン

「いろいろ話しましたけど、最初の話題に戻ると、認証/認可/課金は初期に様々な理由により密結合してしまったとしても、ある程度イケると分かってリソース投資できるようになったタイミングでコアサービスから切り離せるとうまくいきやすいんじゃないかなと思います」「そうですね」「最後に、冒頭の元記事はDDD(ドメイン駆動設計)の文脈で書かれていますけど、こういう要素はどちらかというとビジネスドメインに属するものだと思うので、技術的側面よりもビジネスとの関わりの方が大きいという点を押さえつつ元記事を読むとよいと思います」

参考: ドメイン駆動設計 - Wikipedia

その他

printf


つっつきボイス:「この記事いいですよね😋」「記事の本編より注釈の方が学び多いところも好き」「たしかに最適化オプションでコードの挙動が変わるのは基本的にはよくないでしょうね」


後編は以上です。

バックナンバー(2020年度第4四半期)

週刊Railsウォッチ(20201026前編)Shopifyのerb-lint gem、Form Objectを使いやすくするyaaf gem、railsrcの機能追加ほか

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。