MVCとMVVMについて
こんにちは、うつつです。
今回はMVVMについて。
次の案件で使っているというのでちょこっと調べて自分用にまとめました。
私は今まで入った案件が全てWebアプリだったこともあって、開発はほとんどModel、View、ControllerのMVC(Model2MVC)でやっていました。
ところが先日案件について話している中で出てきたのがこの"MVVMモデル"…Viewが2つにModelが2つ……めっちゃ…ある…(ない)という感じになり…
調べてみたらいやこれ全然違うやんけということが分かるんですが、聞いた時は何も分からず
「今回は一応MVVMでやっていて〜」
みたいな説明を聞きつつ心の中でずっと首を傾げていました。
🤔<MVVM……とは…………?
そもそもMVCとは?
- M…Model
- V…View
- C…Controller
そもそもMVCて何?という話ですが、MVCでは上記の図のようにデータ構造などの保持をModelクラス、画面表示がViewクラス、ロジック部分がControllerクラス、と役割毎にクラスを作成し、機能を分担しています。逆に言えば、Viewクラスは画面表示するだけ、ロジックを書くならViewには書かずにControllerクラスに書きます。
このように処理と表示を分けることでHTMLの中に唐突にロジックが挟まってくる>唐突な罠<みたいなことがなくなり、可読性、保守性の高いソースになります。
ただ、どうやらWebアプリ開発でいうMVCは一般的に言われているMVCとは少々異なるようで、MVCよりもMVCから派生したModel2MVCというものの方が近いらしいです。
MVVMとは?
- M…Model
- V…View
- VM…View Model
そこを踏まえてのようやくのMVVMです。
MVVMはロジック処理を行うModelクラス、表示、変更通知を担うViewクラス、データ保持、変換(Viewの制約吸収)の為のView Modelクラスから成り立ちます。(Viewと Modelが2つずつある訳ではなかった…)
MVVMは双方向のデータバインディングありきのモデルです。(Angularみたいな感じかな…?)
Viewは画面に変更があればそれをView Modelへ通知し、View ModelはModelへ処理を引き渡します。 Modelではデータの更新などを行い、データはView ModelからViewへと反映されます。
つまりViewとView Modelの間に変更を監視、反映する仕組みが必須となっています。
これを双方向データバインディングと言います。
基本的にView ModelはViewの制約を吸収してModelが処理出来るようにするという考え方が良いらしく、View Modelにごりごりとロジックを書くのは良くないとされています。(気を付けます…🙃)
まとめ
まとめると、MVVMモデルはデータバインディングなどによりViewとModel間をView Modelが支えるデータ構造なのかな。
メリットなど今のところ掴みきれていないので…案件が終わる頃追記したいと思います。
以上!
うつつがお送りしました。
LINQ(to Object)のメソッドまとめ
こんにちは、うつつです。
今回はLINQについて。
業務でC#を扱うこと早半年…今まで他の人が書いたソースを見ながら何となくの理解でLINQを書いていました(…)。
が、先日やっとこさ調べてみたらこんなことも出来るの?!みたいなのがあってなかなか楽しかった&積極的に使いたいので備忘録的な感じでまとめておきます。
※注
- LINQ to Object中心(これが理解できれば大体大丈夫な気がする)
- サンプルは私の好みでメソッド式で記述
- 出力には下記の出力用メソッドを使用
public static void WriteResult<T>(string tag, IEnumerable<T> e){ Console.WriteLine(tag.PadRight(15) + String.Join(",", e)); } public static void WriteResult<T>(string tag, T e){ Console.WriteLine(tag.PadRight(15) + e); } public static void WriteResultRoop<T>(string tag, IEnumerable<T> e){ Console.WriteLine(tag); foreach(var x in e) { Console.WriteLine(x); } }
そもそもLINQ(統合言語クエリ)とは?
ざっくりまとめるとデータ集合の操作を簡単に行うことができるライブラリのようなもの。
using System.Linq;
で使用可能。
C#以外でも様々な言語向けに開発が行われていて、javascriptやPHPでも実装が可能。
ex. javascript → jLinq
とか
Javaでも使用出来るけどJava8からのStream APIが同様の機能ぽいので出番は…😴
クエリ式/メソッド式
LINQの構文はクエリ式とメソッド式の2種類あります。
クエリ式
var result = from number in numbers where number < 50 select member;
メソッド式
var result = numbers.Where(x => x < 50).Selected(x => x);
ラムダ式
上記、メソッド式の例のメソッド内に書かれている式の構文をラムダ式と言います。
x => x < 50
簡略化された匿名型メソッドのことで、ここではxが50より小さいものを返し、Whereの条件にしています。
集計
// 最大値 WriteResult("Max:", list.Max()); // 最小値 WriteResult("Min", list.Min()); // 平均値 WriteResult("Average:",list.Average()); // 合計値 WriteResult("Sum:", list.Sum()); // 要素数 WriteResult("Count:", list.Count());
配列化・リスト化
// 配列化 WriteResult("ToArray:", list.ToArray()); // リスト化 WriteResult("ToList:", list.ToList());
集合
// 重複を除く WriteResult("Distinct", list.Distinct()); // 和集合 WriteResult("Union:", list1.Union(list2)); // 差集合 WriteResult("Except:", list1.Except(list2)); // 積集合 WriteResult("Intersect:", list1.Intersect(list2));
ソート
// 並び替え(昇順) WriteResultRoop("OrderBy:", fruitList.OrderBy(x=> x.Price).Select(x => x.Name)); // 並び替え(降順) WriteResultRoop("OrderByDescending:", fruitList.OrderByDescending(x => x.Price)); // 逆順 WriteResultRoop("Reverse:", fruitList.Reverse());
条件指定
// 指定数スキップして残りを取得 WriteResult("Skip:", list.Skip(3)); // 先頭から指定数取得 WriteResult("Take:", list.Take(3)); // すべての要素が条件を満たしているか WriteResult("All", list.All(x => x < 100)); // 条件を満たす要素が含まれているか WriteResult("Any", list.Any(x => x < 0)); // 指定した要素が含まれているか WriteResult("Contains:", list.Contains(50));
応用
// 重複を除き、要素を2つスキップした残りの要素を昇順に並び替える WriteResultRoop("resultList1:", list.Distinct().Skip(2).OrderBy(x => x)); // 偶数を取得し、昇順で並び替え、配列に変換し、x*3して出力 WriteResultRoop("resultList2:", list.FindAll(x => x % 2 == 0).OrderBy(x => x).ToList().ConvertAll(x => x * 3)); // 上と同様の処理 WriteResultRoop("Where&Select:", list.Where(x => x % 2 == 0).OrderBy(x => x).Select(x => x * 3));
結合
// 内部結合 WriteResultRoop("InnerJoin:", fruitList1.Join( fruitList2, outer => outer.Name, inner => inner.Name, (outer, inner) => new { outer.Name, outer.Price, inner.Stock })); // 外部結合 WriteResultRoop("OuterJoin:", fruitList1.GroupJoin( fruitList2, outer => outer.Name, inner => inner.Name, (outer, inner) => new { outer.Name, outer.Price, Stock = inner.Select(x => x.Stock).Sum() })); // 結合 WriteResultRoop("ConCat:", fruitList1.Concat(fruitList3));
まとめ
実際に使用して個人的に感じているメリットとしては以下
- DBの能力に依存しないため処理速度が向上する(こともある)。
- LINQを使用しない場合と比べて簡潔な記述になる(ことが多い)。
- ソース解析が楽。
特に、適切に使用した際ソースの可読性が上がる点がとても好きです(ある程度の理解が大前提になってしまいますが)。
DBのテーブルデータに大量の条件を付けて他のテーブルデータと結合してそれをまた…みたいに延々とやるとめちゃくちゃ読みづらそうですが(というかもうそれはSQLに任せたい)、
簡単なデータ操作はLINQを使って読みやすいコードにしていくのがいいと思いました!
以上、うつつがお送りしました。