仮想DOMとは
Vue.jsを触ると仮想DOMという概念が出てくるので簡単に整理してみる。
概要
効率良くDOMを操作するにはどうすれば良いか?
例えば、以下のようなコードがありage
を+10するボタン
を3回押してみるとage
は50になる
この場合のDOMの変化は<p>age: {{ age }}</p>
のみである、他は変化していない
ということは変化した部分のみを差し替えればいいのではないか!!!
そこで登場するにが仮想DOMである。
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script> <div id="example-1"> <button v-on:click="counter += 1">Add 1(num)</button> <p>The button above has been clicked {{ counter }} times.</p> <p>name:{{ name }}</p> <p>age: {{ age }}</p> <button @click="age += 10">Add 10(age)</button> </div>
new Vue({ el: '#example-1', data: { counter: 0, name: "太郎", age: 20 } })
- 初期画面
Add 10(age)
ボタンを3回押したので50になった
WikipediaのReactより
もう1つの注目すべき機能は、仮想DOMの使用である。Reactでは仮想DOMとしてメモリ上にDOMの状態をキャッシュしておき、仮想DOMに差分が発生した場合にのみ差分を計算し、実際のDOMに差分のみを反映させることにより効率的な描画を実現している
実際の動き
仮想DOMを二つ用意
- 一方の仮想DOMをJavascriptで操作(一般的にリアルDOMを操作するより速い)
- 変更前後の仮想DOMの差分を比較
- 差分だけをリアルDOMに反映
- 反映されたリアルDOMをブラウザがレンダリング
ということで最終的にリアルDOMを操作するのですが、通常、リアルDOMを操作する場合はリアルDOMが変更されるたびにブラウザがHTMLを解析してレンダリングするのでコストが高いです。
結局、結論としては「設計と速度が両立させるため」。
Vueを触る際の注意点
一点だけパフォーマンス上の理由で知らないといけないものがあります。
key 特別属性は、主に古いリストの代わりにノードの新しいリストを差分算出する VNode を識別するために Vue の仮想 DOM アルゴリズムに対するヒントとして使用されます。キーがない場合、Vue は要素の移動を最小限に抑えるアルゴリズムを使用し、可能な限りその場で同じタイプの要素にパッチ適用/再利用しようとします。
キーがある場合は、キーの順序の変化に基づいて要素を並べ替え、そして、もはや存在しないキーを持つ要素は常に削除/破棄されます。
同じ共通の親を持つ子は、一意なキーを持っていなければなりません。重複するキーはエラーを描画する原因になります。
- 例を使って実際の動きを見てみる
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script> <div id="example-2"> <ul> <div v-for="fruit in fruits"> <p>{{ fruit }}</p> <input type="text"> </div> </ul> <button @click="remove">先頭を削除</button> </div>
new Vue({ el: '#example-2', data: { fruits: ["apple", "orange", "grape"] }, methods: { remove: function() { this.fruits.shift() } } })
- それぞれに文字を打ってみる
- 削除ボタンを押すとズレる
なぜこうなるのかというと先ほどの引用にあるこれが原因
「キーがない場合、Vue は要素の移動を最小限に抑えるアルゴリズムを使用し、可能な限りその場で同じタイプの要素にパッチ適用/再利用しようとします」
この予期せぬバグに対処するためにkey属性を指定します
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script> <div id="example-2"> <ul> <div v-for="fruit in fruits" :key="fruit"> <p>{{ fruit }}</p> <input type="text"> </div> </ul> <button @click="remove">先頭を削除</button> </div>
key属性をつけることにより意図したように先頭が削除されました。
key属性については
- v-forでは必須
- 一意になるようにする
- 要素をkey属性にする場合、重複していると一意にならないのでオブジェクトでidを指定するなど
- indexをkey属性にしない
アジャイル開発について
アジャイル開発について調べたので書いて整理します。
アジャイル(agile)の意味を調べてみると「機敏な」、「素早い」という意味になる。
そして、アジャイル開発を日本語にすると機敏な開発、素早い開発となり、そのまま解釈すると、開発期間が短縮される開発手法になる。
実際、アジャイル開発は納期が短縮されることが期待される開発手法であり、またリスクを最小化できるというメリットがある。
では、具体的にアジャイルソフトウェア開発宣言が示している4つの価値をなぞりながらアジャイル開発を整理していく。
- プロセスやツールよりも個人と対話を、
- 包括的なドキュメントよりも動くソフトウェアを、
- 契約交渉よりも顧客との協調を、
- 計画に従うことよりも変化への対応を、
価値とする。すなわち、左記のことがらに価値があることを
認めながらも、私たちは右記のことがらにより価値をおく。
動くソフトウェアとは、価値のあるソフトウェアを早く継続的に提供するということである。
価値のあるソフトウェアとは分析、設計、開発、テストされた(この一連の工程を短期間で繰り返す開発サイクルのことをイテレーションという)リリース可能なソフトウェアのことである。そして、動くソフトウェアこそが進捗の最も重要な尺度になる。
定期的に素早く成果を届けることで、顧客からフィードバックをもらうことができる。
フィードバックは顧客の意思を確認することにつながり、開発の方向性を調整するきっかけにもなる。
これらの顧客との協調においては、当初の計画の変化が起きうることもある。 アジャイル開発では変化を恐れず、よりよい成果を生み出す機会と捉える。 機敏に、そして柔軟に計画を変更することが顧客のニーズに答えることにつながる。
また、開発する上でチームが円滑に成長し続けていることも重要である。 例えば、イテレーションごとにミーティングを開催してもっとチーム内の状況を確認したり、チームの効率をもっと上げるためにはどうすれば良いかを検討することでベロシティ(一回のイテレーションの量)を高めることにつながる。
イテレーションとは?スプリントとの違いや開発プロセスを解説!|ITトレンド
アジャイル開発 ~顧客を巻き込みチーム一丸となってプロジェクトを推進する~ (前編): コラム | NECソリューションイノベータ
DOMとは
javascriptに触れて数ヶ月、DOMについて何となく知っていたがまだフワッとしているので調べました。
DOMとは「Document Object Model」の略であり、日本語にすると「文書オブジェクトモデル」である。
文章をオブジェクトの木構造で表現する。そして操作するための仕組み、方法である。
文章とはWebページのこと。マークアップがなされた文章もdocumentである。
マークアップとはタイトルや見出しなどの各構成要素に「タグ」と呼ばれる識別のための目印を使い、意味付けを行っていくこと(htmlがまさにそうである)
そして、
Document内にはマークアップによって区切られるまとまりがあり、各まとまりを特定種のオブジェクトで表現する(例: <主語>これは</主語> = 主語オブジェクト)。
DOMにおいてオブジェクトは総称してNodeと呼ばれる。
Node(ノード)とは直訳で節であり、点と線で構成図を書いたときの点の部分のこと。
さらに、
Nodeは入れ子構造をとるため、これを木構造(親Nodeと子Nodeの入れ子構造)でモデル化できる。
具体的にHTMLでNodeを見て見る。
bodyタグ、sectionタグ、pタグで囲まれたものがオブジェクトであり、Nodeである。
そしてsectionタグを基準に見るとbodyタグは親ノード、pタグが子ノード、親を通して対にあるsectionノードが兄弟姉妹ノードである。
このように親ノードを根として枝分かれしていく様子が木構造である。
Vue 描画について
”Mustache” 構文(二重中括弧)を利用したテキスト展開
”Mustache”とは口ひげの意味
プロパティ名を書くことで表示できる
<div id="app"> <p>{{ message }}</p> </div>
new Vue({ el: '#app', data: { message: "hello world" } })
templateプロパティを使って表示
HTMLの方に書いていたものをそのまま書ける
<div id="app2"></div>
new Vue({ el: '#app2', data: { name: "John" }, template: "<h1>hello {{ name }}</h1>" })
render関数を使って描画する
<div id="app3"></div>
new Vue({ el: '#app3', data: { name: "山田" }, render: function(h) { return h("p", "こんにちは" + this.name + "さん" ) } })
VueCLIを使うとmain.jsに最初からある
new Vue({ router, render: h => h(App), }).$mount('#app')
どんなものがあるか簡単に書いてみました。
プロセスとスレッド
気になってい他ことなので、メモがてら書きます。間違っているところもあるかもしれません。
意味
プロセス
プロセスとは、処理のことである。
コンピュータプログラムは命令の受動的集合体である。プロセスはそれら命令の実際の実行である。
例えでいうと、
chromeやターミナルを開くことや
lsコマンドやwcコマンドを叩くこと。
それぞれが一つのプロセス (プログラム)。
スレッド
スレッドとは、CPU利用の単位。
CPUは基本的に1つのコアで1つの処理しか実行することはできません。
例えでいうと、
ターミナルでlsコマンドを叩くと
「ファイルが読み込まれる」、「ターミナルの幅を計測する」、「最大文字数のファイル名を見つける」、「何列で表示するか決める」などなど
たくさんの処理が内側で行われている。それらひとつひとつがスレッド。
つまり
1つのプロセスは、1つ以上のスレッドから構成される。
マルチプロセスとマルチスレッド
マルチプロセス
chrome・ターミナルなどそれぞれのプログラム(プロセス)を同時に開き、使うことができる。また、ターミナルのvimで複数のファイルにプログラムを書くことができ、それぞれのファイルは影響はしない。
このようにプロセスを同時に実行(並列処理)することをマルチプロセスといいます。マルチスレッド
シングルスレッドのプロセス:1つしかスレッドを持たないプロセス
マルチスレッドのプロセス:複数スレッドを持つプロセス
マルチスレッドの利点は、例えば、シングルスレッドの場合だと重い処理を待つ必要があり利便性にかけイライラする。しかしマルチスレッドの場合、重い処理と他の処理を分けることで並列処理できる。
メモリ領域
プロセスはシステム全体の動作の安定性および安全性の観点から、プロセスごとにメモリは独立して割り当てられる。
しかし。独立したメモリ空間が不必要な場合では、メモリの利用効率が悪くなってしまう。プログラムによっては、処理ごとに別々の空間にあるメモリを利用するのではなく、単一の空間内のメモリを共有しながら複数の処理を行なう「共有メモリ方式」のほうが、ロジックの実装のしやすさやメモリ効率の面で優れている場合がある。
これを可能にするのがスレッドである。
スレッドを使うことで、同一プロセス内の複数スレッドを同一メモリ空間上で実行でき、メモリ消費量などが軽減できるようになっている。
しかし、注意点もあり、同じデータを複数のスレッドが同時に書き換えることによる不整合が生じるので、排他制御(あるスレッドがリソースにアクセスしているときは、ほかのスレッドがアクセスできないようにロックをかけること)を行う必要がある。
また、複数のスレッドが協調動作する際、お互いの処理完了を待ち合わせてデッドロック (2つ以上のスレッドあるいはプロセスなどの処理単位が互いの処理終了を待ち、結果としてどの処理も先に進めなくなってしまうこと) 状態に陥ることのないよう配慮する必要もある。
ビンゴカードプログラム作成してみた(Ruby)
class Number def dimentional_number_array array_of_each_numbers = [] array_of_each_numbers.push(select_five_numbers_in_B, select_five_numbers_in_I, select_five_numbers_in_N, select_five_numbers_in_G, select_five_numbers_in_O) array_of_each_numbers.transpose end private def select_five_numbers_in_B (1..15).to_a.sample(5) end def select_five_numbers_in_I (16..30).to_a.sample(5) end def select_five_numbers_in_N (31..45).to_a.sample(4).insert(2, ' ') end def select_five_numbers_in_G (46..60).to_a.sample(5) end def select_five_numbers_in_O (61..75).to_a.sample(5) end end class Bingo def initialize @dimentional_number_array = Number.new.dimentional_number_array end def create_card enumerate_in_a_low(bingo_words) @dimentional_number_array.each do |number_array| enumerate_in_a_low(number_array) end end private def bingo_words 'BINGO'.split(//) end def enumerate_in_a_low(array) print ' ' array.each do |e| print e.to_s.rjust(2) if e == array[4] puts else print ' | ' end end end end Bingo.new.create_card
- コンソール表示
~ % ruby bingo.rb B | I | N | G | O 13 | 16 | 45 | 46 | 71 8 | 19 | 44 | 60 | 68 6 | 24 | | 56 | 61 15 | 22 | 34 | 49 | 63 2 | 29 | 33 | 55 | 72 ~ % ruby bingo.rb B | I | N | G | O 5 | 22 | 32 | 46 | 62 4 | 24 | 44 | 52 | 75 2 | 26 | | 50 | 73 15 | 17 | 35 | 51 | 69 12 | 20 | 40 | 55 | 65
オブジェクト指向実践ガイドを読んでいて、コードを書きたくなったので書いてみました。
実際に書くと難しいです。
悩んだ点は
GitHubでリポジトリ作成時のコマンドについて
リポジトリ作成時のコマンドでわからないことがあったので調べました。
echo "# sample2" >> README.md git init git add README.md git commit -m "first commit" git branch -M main git remote add origin git@github.com:OOOO/sample.git git push -u origin main
git branch -M main
-m
も-M
も違いはない
git branch -m <new branchname>
-m、もしくは、--moveオプション。 現在チェックアウトしているブランチ名をに変更する。 git branch -m で変更元を指定することもできる。
以下2つは同じ意味
git branch -M main git branch -M $(git rev-parse --abbrev-ref HEAD) main
git rev-parse --abbrev-ref HEAD
は今いるブランチ名を表示
git rev-parse --abbrev-ref HEAD master
masterがmainに変更されたということ
% git branch -m main % git rev-parse --abbrev-ref HEAD main
git push -u origin main
オプション
-u
について 今回対象とするブランチを上流ブランチとして設定する(一度指定すると次回以降も対象となる) だから初回のプッシュで-u
をつけるoriginとは
リモートリポジトリのアクセス先(URL)に対してGitがデフォルトでつける名前です。
git remote add origin git@github.com:OOOO/sample.git
この設定を行うことで、リモートリポジトリに対してpushやpullができるようになります。