Riot Games API + Rails + React + Ant design でLeague of Legendでチャンピオンごとにガイドを共有できるwebアプリをつくりました
なにができるか
チャンピオンを選んでそれぞれ関連する記事を保存できるってだけのアプリです。
名前を入れるとインクリメントサーチでキャラが絞り込まれるUIだけ凝りました。もっとアニメーションつけたりしたら面白そう
アカウントそれぞれで保存していく方式ではなく、みんなが保存したものをみんなが見る形式です。
チャンピオンのデータや現在のフリーチャンピオンとかはRiot Games APIを叩いて取得してます。
URLはるだけなので動画ページでもTwitterのつぶやきでもなんでも載せれます。
また、URLを貼るとはてなブログカードっぽく表示するようにしました。
なんでつくったか
LOLのガイドっていろいろな所にあるし、記事、動画、はたまた一つのツイートと形態も様々ですが、それらをチャンピオンごとにまとめておける or 見れる集約サイトがあると楽だなと。
使った技術
React及びJavaScriptの勉強を兼ねてreact-railsを使ってRailsのviewにAnt Design を導入して作ってみました。
やっぱり出来のいいコンポーネントが多数用意されてると便利です。
フロントとサーバー側を分けた構成にしているわけではないのでページ遷移は直接aタグを使っています。悲しい。
ひらがなでもカタカナでも検索できるようにしてあります。
かなり恥ずかしいですが、下記がソースコードです
ひらがなをカタカナにするメソッドはこの素晴らしい記事を参考にしました。コピペですすいません。
最初にチャンピオンのデータを全部propsで渡してstateにセットして、検索時にはpropsに検索語句でfilterかけてまたstateにセットしてます。
stateは親以外は知らないような構造になるようにし、直接変更しないようにしました。(そうしろってreactチュートリアルでやってた)
既知の問題点
記事のURLはURLであるかぐらいしかvalidationはってないので、URLがそのチャンピオンに関係あるか?そもそもLOLに関係あるか?等々を全く見ていません。
あと最大の問題点は
めんどくさくて記事の削除機能をつくってないことですかね。
「オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方」を読みました
オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方
- 作者: Sandi Metz,?山泰基
- 出版社/メーカー: 技術評論社
- 発売日: 2016/09/02
- メディア: 大型本
- この商品を含むブログ (6件) を見る
を読んだ備忘録です。
5章 ダックタイピングでコストを削減する
ダックタイピングは、たとえオブジェクトのクラスや型が違っても、同じふるまいをするのであれば共通化できるということです。
特に特定のクラスであれば〇〇を行って、別のクラスだったら✗✗をするのような感じのcase文を見かけたときには、それぞれに共通のインターフェースをもたせて依存を減らすことができます。
例えばこんな感じのコード
class Test def make(questions) questions.each { |question| case question when SelectiveQuestion question.make_selective_question when DescriptiveQuestion question.make_descriptive_question end end end end
Student#answerは渡された問題のクラスによって処理を分岐しています。
これは他のクラスへ依存を増やすことになり、更に問題の種類を増やしたらcase文をまた一段追加しなくてはなりません。
ここで登場するのがダックタイピング
questionsにはmake_questionという振る舞いを期待して、make_questionすればダックじゃなくてもダックなのです。
class Test def make(questions) questions.each do |question| question.make_question end end end
これで各Questionクラスにmake_questionを実装すれば、いちいちクラスを増やすたびにケース文を追加することもなくなります。振る舞いを抽象化して他のクラスを信頼することが大事。
6章 継承によって振る舞いを獲得する
本書では継承とコンポジションという2つのコード構成のテクニックが紹介されています。
1つ目がこの章の主題の継承で、クラスの継承は依存を強くしてしまうリスクはあるけど、親クラスの小さな変更で全てを変えたり、サブクラスの追加が簡単に行えたりとメリットも大きいです。
この章で一番大事なことは、「親クラスは小クラスにとっても当てはまることのみ持っているべき」という継承の契約でしょう。
この契約を守る方法として、一度それぞれ具体的にクラスを作って、全てに共通する抽象的な部分だけ集めて親クラスにしようというものが書かれていました。
親クラスは抽象的であるべき、の典型的な例はStandardErrorとかでしょうか。エラーという概念のみ表していますよね。
また、この章ではもう一つ継承による構造での依存を下げる具体的な案として、superを減らすということも書かれています。
フックを親クラスに持たせるテクニックはまさにそれで、制御を抽象的な親クラスにうつしてクラス同士の結合を減らす作業が紹介されていました。
第七章 モジュールでロールの振る舞いを継承する
引き続き継承を扱っている章です。6章の内容がより具体的に書かれているのと、モジュールのミックスインにたいしても、メソッド探索の中に追加されるものだから継承と基本的に同じ考え方で行おうねと書いてあります。
第八章 コンポジションでオブジェクトを組み合わせる。
継承とは別のコードの構成としてコンポジションについて書かれています。
継承はいわゆる階層構造(is_a?)でしたが、コンポジションではhas-aの関係、例えば本書では自転車はPartsをもち、PartsはPartをもっている...という考え方でコードを構成します。
#オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 225pより class Bicycle attr_reader :size, :parts def initialize(args = {}) @size = args[:size] @parts = args[:parts] end def spares parts.spares end end require 'forwardable' class Parts extend Forwardable attr_reader :parts def_delegators :@parts, :size, :each def initialize(parts) @parts = parts end def spares parts.select(&:needs_spare) end end require 'ostruct' class Part attr_reader :name, :description, :needs_spare def initialize(args = {}) @name = args[:name] @description = args[:description] @needs_spare = args.fetch(needs_spare, true) end end require 'ostruct' module PartsFactory def self.build( config, parts_class = Parts ) parts_class.new( config.collect do |part_config| create_part(part_config) end ) end def self.create_part(part_config) OpenStruct.new( name: part_config[0], description: part_config[1], needs_spare: part_config.fetch(2, true) ) end end
なかなかコードがないと伝えづらいのでコードを引用させていただきました。(ForwardableとかOpenstruact初めて知りました…)
個々のわかりやすい動作をするオブジェクトを集めて最終的に複雑なオブジェクトを作り出すという構造です。
コンポジションは継承に比べてそれぞれのオブジェクトの関係を明示しないと関係をもってくれませんが、よりオブジェクト同士の依存を少なくする事ができます。
しかし、それがデメリットでもあり、自転車、Parts、Partそれぞれの構造はわかりやすいですが、全体像はわかりにくく、委譲を明示しなくてはならないので、継承のように少ない記述でコードの共有をサポートしてくれたりはしません。
継承とコンポジション、どちらを選択すべきか?という問いに対しては、コンポジションでできそうだったらコンポジションのほうが依存を少なくできるので有効な場合が多い、と書かれていて、パーツがおおければコンポジションのほうが、パーツそれぞれを深く掘り下げて、抽象的な共通部分を見つける継承が適していると判断できれば継承を利用すると良い可能性が高いとのことです。
第9章 費用対効果の高いテストを設計する
テストの大切さや入力と出力の部分だけ考えるべき、といった部分はよくある意見と特に変わらないのですが、よりコードの構造に沿ったテストを無駄なく書こうとする具体的な方法が書かれていました。
継承されたコードをテストする時は、抽象的な親クラスのテストはインクルードして全てパスするようにする、というびはこの本で初めて認識した考えかでした。
まとめ
全章を通して、オブジェクトの責任を明確にすること、オブジェクト同士の依存は少なくすること、依存してもより変更がないものにすること。関係をつくるインターフェースを注意して設計することの大切さが説かれていました。デザインパターンの話がすこし出てきて、しっかり理解できてないこともあるので今度はrubyによるデザインパターンとかいいかな?と考えております。
「失敗から学ぶRDBの正しい歩き方」を読んで
Twitterでおすすめされていたので
失敗から学ぶRDBの正しい歩き方 (Software Design plus)
- 作者: 曽根壮大
- 出版社/メーカー: 技術評論社
- 発売日: 2019/03/06
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
何がわかりやすいか
図もサンプルクエリも豊富でわかりやすいことに加えて、一つ一つのアンチパターンの小話形式?の話が、日本で実際にありそうなことなのがイメージの助けになりました。職業エンジニア二ヶ月目で実際にアンチパターンみたいなのを体験したことがまだないのが悲しいところですが。(気づいてないだけでもうしているかも)
噛み砕いた説明
噛み砕いて書いてある本だとも感じました。
例えば、INDEXがそもそも有効に利用されるのか?、実行するテーブルの規模を意識してクエリを組み立てているか?という視点から丁寧な解説が書いてありましたし、強すぎる制約を判断する基準なんかは、長くエンジニアとして働いてきたゆえの知見を端的に書いていただいてるなと感じました。
条件に列を使わない、カーナビリティの高低でのRDBMSの処理の違い、エグゼキューターの評価順序なんかは取り入れやすい知見だと思うので、なんとかアウトプットをだしたいです。
RDBに対しての無知
「テーブルに状態をもたせる」なんかも知らないとデメリットを理解せずやってしまいそうですし、トランザクションの分離等にいたっては初耳です。 まだまだRDB、RDBMSに対して無知であるなぁと強く思いました。 データベースから情報をとってきたり、データベースに情報をいれたり、というのはサーバーサイドであれば言語やフレームワークが変わろうとも(恐らく)ずっとやり続けることだと思うので、転ばぬ先の杖をもっとたくさん持ちたいです。
オブジェクト指向設計実践ガイド 四章まで読んで気になったこと
序盤の章は具体的に自分のコードにしてみました。
メソッドの責任の分割
メソッドの責任を分割してみました。
自分より変更されないものに依存しなさい
引数の依存を避けるためにキーワード引数を導入してみました。
これで別の場所でインスタンスを作る際にクラスがどの順番で処理しているかを考える必要がなくなります。
もちろん世の中これがデファクトではなくていくつかの順番に依存する引数と残りをオプションハッシュにしているメソッドが多いですね。
オブジェクトは相手を信頼して隣人にしか声をかけない
Player
がHardware
を使ってSoftware
をプレイしようとしてもPlayerはSoftwareに直接メッセージを送るのは避けるべきで、PlayerはHardwareを信用して、遊びたい中身はSoftwareだとしてもPlayerにはplayというパブリックインターフェイスをもたせて詳細な実装は隠すべき
こうするとplayするゲームがVRになってplay以外のことをHardwareとSoftwareを使ってするようになっても、player.experience等一般化して対応できるようになる。
player.hardware.software.run #ではなく player.play #とするべき
オブジェクト指向とは
オブジェクト指向ってなんだ(困惑)。
単一責任とか疎結合とかパブリックインターフェイスとか他のオブジェクトを信頼はしても依存はしないのが良いということはわかりました。人間関係かな。
StackEditで簡単にシーケンス図がかけるので最高
はじめてのペアプログラミングをしたので感想とか
はじめてのペアプログラミング
会社でペアプログラミングをやる機会がありました。ペアプログラミングという経験は初めてだったのですがとてもいい経験だったので所感と反省を書きます。
今回ペアの方はベテランで、自分はエンジニア歴一ヶ月のペーペーなので教育的要素があったペアプロでもあった前提で読んでいただければと思います。
やってみて感じたメリット
明らかにコードの質が高まる。
- ベテランの方一緒に作業したので当然ですが自分一人で書くよりコードの質がよくなり、考慮した要素が多いものになりました。単純に手戻りが少なくなりそうです。
他の人のコーディングを逐一質問しながら進められる。
- 新人側の視点でのメリットですね。オブザーバーとしてどういう考えでこのコードを書いているのかその場で聞けるので設計とかの仕組みが頭に入ってきやすかったです。
二人でやるので開発の手順をしっかり踏むことになる。
- やる前はあんまり考えていなかったのですが、これが一番大きいなと思ったメリットです。自分だけで開発を進めるわけではないので なんとなくでコードを書いたりすることなく、現状の仕組みを把握し、問題を理解して、解決策を具体的にタスクとして実行するというステップを決めて開発することになります。お互いの足並みが揃わないのにいい開発ができるわけがありませんからね。自分たちが今何をやっているのか、方向性がわかりやすく開発効率が明らかに良かったです。
ペアプロと合わせてやってみて良かったこと。
-
- 今回はモデルをいじる開発で、テストから先に書く開発を行いました。テストを先に書くので開発途中にテストが落として修正するというサイクルが発生し、二人で話し合って分析する対象が明確になります。二人で一つの画面をみて開発するペアプログラミングでは相性が良いと感じました。
自分のやろうとしてる事と考えをどんどん声にする。
反省点
二人で進めるものという認識が甘かった。
- ペアプログラミングをスタートした時に、僕がすぐさまコードを書こうとしたらペアの方に「最初に手順について確認しましょう」という助言がありました。二人で一つのコードを書くのだから現状の問題、仕組みに関する共通認識と、解決策と具体的な実行手順をお互い把握することがまず最初にあるべきなのは当たり前です。
自分は最初は自分がコードを書いて、それに間違いがあれば指摘してもらうのが新人とベテランのペアプログラミングだろうという認識があったことが招いた行動だと思います。もちろん教育の要素は多分にあるとは思いますが、二人で一つの問題に対して解決策を見つけ、実行する、というのが前提にあるのがペアプログラミングです。
次回機会があればまず二人でこの問題を解決するにはどうしたら良いか、の認識、共有を一番に考えてペアプログラミングを始めるとよりスムーズに行くんじゃないかと思いました。
- ペアプログラミングをスタートした時に、僕がすぐさまコードを書こうとしたらペアの方に「最初に手順について確認しましょう」という助言がありました。二人で一つのコードを書くのだから現状の問題、仕組みに関する共通認識と、解決策と具体的な実行手順をお互い把握することがまず最初にあるべきなのは当たり前です。
いつ始めるか明確に定義してなかった。
- これは細かい点なんですが始める時にこれからやる?ok?と声をかけて頂いて始めた(もちろん前日に明日ペアプロやってみるみたいな話はありました)のであいまいな感じでスタートしたのはあんまり良くなかったかもしれないです。
やっぱり二人でやるものですからきっちりこれから始めるという区切りがあるとより良いと感じました。
- これは細かい点なんですが始める時にこれからやる?ok?と声をかけて頂いて始めた(もちろん前日に明日ペアプロやってみるみたいな話はありました)のであいまいな感じでスタートしたのはあんまり良くなかったかもしれないです。
まとめ
ペアプログラミングって普段の開発と違って喋りながらやるので単純に疲れます。ですが思考が整理されていくのを感じますし、やっぱり二人で一つの物を作ったというのは達成感も違います。新人側なのでメリットばかり享受している気もしますが、次もやりたいと思える経験でした。ペアをくんでくださった方には感謝しかないです。
SQLアンチパターン 第六章を読んで
を読んでの要約、感想です。
目的
複数の親を持つテーブルが欲しい。例えばキャラクターに関するコメントもアイテムに関するコメントもおなじコメントテーブルに置きたいとうのが今回の目的です。
アンチパターン
ポリモーフィック関連を定義するというのがアンチパターン。 ポリモーフィック関連とは親のテーブルの名前をカラムとして追加してその後外部キー制約なしに外部キーに当たるものをカラムに格納する関連付けの方法です。
comment_id | target_type | target_type_id |
---|---|---|
1 | Characters | 1 |
2 | Items | 1 |
デメリット
- target_typeに他のテーブルの値のみが入ること、target_type_idに他のテーブルの主キーが入ることを保証できない
- Characters、Itemsと結合しようとしても全ての行が一つのテーブルと関係があるわけではないので内部結合はできない
使用してもいい場合
外部キー制約使えってあります。フレームワークがしっかりしてるならまぁ使っても良いんじゃない?って感じです。使用してもいい場合の文章割と身も蓋もないです。
解決策
参照を逆にします。今回の例で言えばCommentsテーブルをCharactersとItemsの親にして関係テーブルを仲介させることでtarget_typeカラムを使わずに関係を表すことができます。 共通の親テーブルを作成することも有効です。今回ならGuidesテーブルを作成してguide_idを主キーとしてそれぞれのテーブルにもたせればそれぞれのテーブルが比較可能なカラムをもつので結合が簡単になります。
感想
毎日書くペースだとまとめ過ぎな気もしてきた(後大変)なのでさっくりまとめる感じでいきたい。どうせならもっと短くしたいという気持ちが強まってきました。この章は解決策がしっかりしていてポリモーフィック関連を使わないのも十分可能だなと感じました。ただSQLの正義が絶対正義ではないみたいな話を職場できいたのでメリデメしっかり理解するのが大事ですね。多分この本全てに言えますけど。
React チュートリアルをやってみた感想とか
はじめに
ぎょーむでReactをつかうらしいのでチュートリアルやってみました
すごい良くできていて、途中のコードも全てサンプル載せていて、ローカルの準備までかいてあり、アロー関数宣言とかもコラムにまとめてあったり、なんでこの処理をするのかとか、処理がどんな順番で実行されているのかとか丁寧に書いてあり、JSがそもそもそんなにわからんおじさんでもなんとかなる感じに作ってありました。
簡単な機能からつくって、段々と一つのコンポーネントに機能を盛り込んでほかは表示するだけのコンポーネントにしていく構成になっています。
いくつかなるほどなぁと思ったことを書きます。
コンポーネントのstateはそのコンポーネントだけの物
チュートリアルでは○×ゲームを作るために、マス、ボード、ゲームそのものという感じでコンポーネントを作っていくんですが、
最終的に作るマスもボードもゲームコンポーネントからプロパティを受け取って表示してるだけのコンポーネントなります。
function Square(props) { return ( <button className="square" onClick={props.onClick}> #渡されたプロパティを参照してる {props.value} </button> ); }
class Board extends React.Component { renderSquare(i) { return ( <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} #渡されたプロパティを参照してる、Boardコンポーネントはマスの番号だけ渡している /> ); } render() { return ( <div> <div className="board-row"> {this.renderSquare(0)} .............
class Game extends React.Component { constructor(props) { super(props); this.state = { history: [ { squares: Array(9).fill(null) } ], stepNumber: 0, xIsNext: true }; } (中略) return ( <div className="game"> <div className="game-board"> <Board squares={current.squares} onClick={i => this.handleClick(i)} /> #ここでコンポーネントクラスの中での関数とかをプロパティとして渡している。 </div>
ここで重要なのはGameコンポーネントはstateを持っていてsetStateしてstateに情報を追加したりしていくんですが、BoardコンポーネントもSquareコンポーネントでもstateの変化は考えません。
GameコンポーネントのstateはGameコンポーネントの中でのみ扱ってプロパティとして子コンポーネントにわたす必要があります。 子コンポーネントが子コンポーネント同士や親コンポーネントと連携が取れなくなってしまうからです。
stateは不変性が大事
この○×ゲームではターンの履歴を前回のボードの状態を一度コピーしてからそのコピーに変わった状況を書き込んで、stateに加工したコピーを追加しています。state直接変えないです。途中の履歴とかを意識しない段階でもstateを一度コピーしてから加工したコピーをsetStateしています。
これは何故かと言うとReactの利点である、変更されたもののみ描画し直すという機能のために、変更されたものと変更前がわかる必要があるからです。直接変更してしまうと、前と後がないためstateの変化が検出できません。stateそのものは不変であるべき、というのがおすすめされています。pure components
つくっていきたいザウルスですね。
functionコンポーネント
そのコンポーネントがstateを扱わないときはReact.Component継承しないでfunctionでコンポーネントつくるのもよい、とチュートリアルにあります。
逆にfunction componentsみたらそれはstateは扱っていないんだな、と考えるとコードが読みやすくなるかも、と感じました。
Reactというよりは、、、
職場でもきいた話なんですけど、Reactが難しいというより、どういう形でコンポーネントの組織が作られていて、どこでstateをどのように管理しているか把握するのが難しいのかなと感じました。適当にやるとコンポーネント同士の連携がめちゃんこになって「React わからない 人生」とかで検索することになりそう。