LINQのForEachメソッドで気になる点
なぜListクラスだけにForEachメソッドが定義されているのか?
「普通にIEnumerableに定義してしまえば良いじゃん」って思ったけど、単純な話ではないみたいだ。
疑問の発端が、次のコードのようにDictionaryクラスでForEachメソッドを使おうと思ったことだった。
dic.ForEach((v,k) => Console.WriteLine("{0}\t{1}",v,k));
上記コードは、DictionaryクラスにForEachメソッドがないので怒られる。
もしこの書き方ができるなら、単純な処理だけを繰り返して実行したいときにいちいちforeach文でコードブロックを作らずとも同じ結果をもらえるので、読みやすく感じる。しかし無いらしい。
まあ、こういう拡張メソッドを作ってしまえば良いだけの話ではある。
static DictionaryExtension{ public static void ForEach<T>(this Dictionary<T, T> dic, Action<T,T> action) { foreach (var item in dic) { action(item.Key,item.Value); } } }
ASP.NET MVC5 雑記
Web案件を受けたが、自分はWeb未経験。
なので、サーバーサイドがC#のASP.NETを触ってみることにした。
プロジェクトについて
App_Startフォルダ
- AuthConfig
- OAuth?の認証連携のサポートをするらしい
- BundleConfig
- JS,CSSの参照処理
- FilterConfig
- 全アクションに対して共通処理を行える
- trycatchによる例外処理やログ出力に使う
- バグ調査に使えそう
- RouteConfig
- 要求URIとControllerのアクションとの紐づけを行う
- WebApiConfig
- RouteConfigのWebAPI版
MVCにおけるエントリポイント
Global.asax.cs
MVC
- Controllerが要求を受ける
- 他のControllerに渡す場合もある
- Modelに対して更新を要求する場合もある
- Modelを要求する
- Modelが存在しない場合もある
- ModelをViewに渡す
- Viewを結果として送信、画面に表示する
View
- データの表示
- データの取得・更新などは関知しない(View以外の債務)
ViewBag
ViewとControllerにおけるグローバル変数的な立ち位置
dynamic型
@RenderBody
部分ビューを差し込むキーワード
WebFormにおけるマスターページ
HTMLヘルパー
ActionLinkはよく使いそう
拡張メソッドも定義できて使うなら
https://office-yone.com/technic/asp-net-mvc-htmlhelper/
モバイルサイト対応
Viewの拡張子の前に「.mobile」をつければ良いだけ
【例】Index.mobile.cshtml
Model
- 扱うデータやロジックをつかさどる部分
- データを取得し、加工し、然るべき処理に渡す
- データの表示には関知しない
- 更に機能を付加するならpartial classを用いる
- DataAnnotation
Controller
- ViewとModelの橋渡し部分
- Modelから受けたデータをViewに渡す
- ユーザー入力に合わせて処理を行う
- 橋渡しをする上でアクションと呼ばれるメソッドを使う
- ActionResult型を返すことで実現させる
- アクションメソッドを使いたくなければ明示的にNonAction属性を付加する
- https://msdn.microsoft.com/ja-jp/library/dd410269(v=vs.100).aspx
アクションフィルター
- 要求されたアクションに動作をアタッチする
- 既出のフィルター
- エラー時のハンドリング
- 認証要求と未認証ユーザーのブロック
- 出力のキャッシュ
- 既出のインターフェイス
- アクションの認証と承認
- コントローラーメソッドの実行前と実行後
- INFOまたはWARNログ
- 結果表示の前後に実行
- 例外発生時に実行
- ERRORログ
WebAPI
- IHttpActionResultがMVCでいうActionResultに近い
- OK, BadRequest, NotFoundなどがある
- それぞれHttpStatusCodeに対応する
- エラー時の処理が簡便になる
ルーティング
- ControllerにRoutePrefix属性をつけるとURLの指定を決められる
- 各メソッドに対してRoute属性をつけるとURLの指定を決められる
メッセージライフサイクル
Webアプリにおける作り
https://blogs.msdn.microsoft.com/chack/2013/02/17/asp-net-web-api-http/
Handlerについて
- アプリ全体ならGlobal.asax.csのGlobalConfiguration.Configuration.MessageHandlers.Addで
- Route全体ならWebApiConfigのMapRouteを使う
テスト
FiddlerはWebアクセスの試験ができる
Entity Framework
DBアクセスのためのフレームワーク
MVCとEFは親和性が高い
その他
WebFormとの差
リリース年月日
- MVC1.0は2009年3月
- MVC5.0が現在最新で2013年10月
- VS2013以降にコンポーネントが存在する
URIとURLの違い
既存の外部ライブラリ
新規モジュールを入れたいならNuGetを使えば勝手に追加されるっぽい
追加の際は依存関係に気を付けること
無暗に最新版モジュールにしない
ファイルに対して更新権限を決めておくと良いらしい
- bootstrap
- jQuery
- modernizr
ブラウザのデバッグについて
どのブラウザもF12キーを押すことで開発者ツールを開けるので
積極的に活用すべき
- html&cssの中身
- HTTPメソッドのログ
手順書が書ける
Databaseの作成からModelの作成、
スキャフォールディングによるControllerとViewの生成によって
CRUDのアプリケーションが実現できる
MVVMについて25%語る(その内5%は嘘かも)
MVVMは内部処理と画面の処理を分離させる設計。
Model View ViewModelの3つの要素に分ける。
その違いを備忘録としてまとめた。
Model View ViewModelの違い
View
- 端的に言えば「システムにおける画面表示」
- レイアウト定義
- ユーザー操作の割り当て
- 動的に変更したいコントロールや値はバインドする
ViewModel
- 端的に言えば「システムにおける画面表示処理」
- Viewにバインディングする情報をプロパティとして定義
- Modelから受け取った内部データを、画面表示用のデータに変換する役割
- 内部データは作らない。それはModelの債務
- 外部とのやり取りはしない。それはModelの債務
- Viewからユーザー操作を受け取ったら、対応する。また、DBのデータやシステム内部で保持しているデータが必要なら、Modelからもらう
-
Messenger(※1)を使うことでメッセージの登録を行い、Modelからメッセージが送信されたら受信時の処理を行い、画面へ結果を表示する
Model
- 端的に言えば「システムにおける内部処理」
- ViewModelから要求があればデータを作り、値をViewModelに渡す
- 外部からの要求があればデータを作りViewModelへ通知
- データを画面表示用に変換したりはしない。それはViewModelの責務
- 複数のViewModelが同一のModelインスタンスを参照させるためにはModelをシングルトン(※2)にする
実際にModel・ViewModel・Viewの違いがわかる例
ユーザー操作時
- Viewをユーザが操作
- ViewModelはModelのインスタンスからデータを取得するメソッドを呼び出す
- 呼び出したメソッドの戻り値を、ViewModelのプロパティにバインディング
- ユーザー操作反映完了
外部からのデータ受信時
- ViewModelはインスタンス作成時にメッセージのコールバックを登録
- 外部からデータを受信
- Modelは受信したデータを、Modelで保持するデータに変換する
- Modelはメッセージを発行し、作成されているViewModelに対してメッセージを送信
- ViewModelは受け取ったメッセージ種別に対応する処理を行う
※1
Messengerパターン。
Messengerというクラスを使って
メッセージを送受信できる
- メッセージを受信するインスタンスはMessengerクラスへ「Messageの種類と受信時の処理を記述して」登録する
- メッセージを送信するインスタンスは該当するMessageのインスタンスを作成し、送信したいデータがあればそのインスタンスのメンバへ代入。
- Messageクラスが持つSendメソッドでメッセージを送信する。
- メッセージを受信するインスタンスは、2で送った種別のメッセージを受信し、対応する処理を行う。
※2
オブジェクト指向におけるデザインパターンの一つ。
簡単に言えば、インスタンスを2つ以上作らせないようにする。
staticクラスと類似しているが違いがある。
詳しくは考察記事があるので見てみよう。
支払い金額を設定し、支払いを終えるのに何枚の硬貨が必要かを算出するプログラム
#include <stdio.h> int main(void){ int price; scanf("%d",&price); int coins[6] = {500,100,50,10,5,1}; for(int i = 0; i < 6; i++){ printf("%d円が%d枚",coins[i],price/coins[i]); price = price % coins[i]; if(i != 5)printf("、"); } }
入力
3333
出力
500円が6枚、100円が3枚、50円が0枚、10円が3枚、5円が0枚、1円が3枚
日付と曜日を表示するプログラム
javaでは一般的にカレンダークラスを使う。
今日からX日後の日付と曜日を出してほしいとのことなので
以下のコードを書いた
import java.util.*; public class Main { public static void main(String[] args) throws Exception { Scanner s = new Scanner(System.in); int dayDelay = s.hasNext() ? s.nextInt() : 0; String[] week = {"日","月","火","水","木","金","土"}; Calendar now = Calendar.getInstance(); now.add(Calendar.DATE, dayDelay); System.out.println(now.get(now.YEAR)+"/"+(now.get(now.MONTH) + 1)+"/"+now.get(now.DATE)+"/" + week[now.get(now.DAY_OF_WEEK) -1]); } }
入力
1
出力
2018/10/6/土
ハードコーディング恐怖症を患いました
ハードコーディング怖い
↓ハードコーディングしてるコード
import java.util.*; public class Main { public static void main(String[] args) throws Exception { Scanner s = new Scanner(System.in); //ログインステータスは1が成功でぇ~、0が入力ミスでぇ~、-1がシステムエラーだよ! int loginStatus = login(s.nextLine()); switch(loginStatus){ case 1: System.out.println("ログイン成功"); break; case 0: System.out.println("ユーザー名を正しく入力してください(8文字以上)"); break; case -1: System.out.println("致命的なエラー(適当)"); break; } } public static int login(String password){ if(password.length() >= 8){ return 1; }else if(password!= null){ return 0; } return -1; } }
enum使ってくれた女神のようなコード
import java.util.*; public class Main { public enum loginStatus{ Success, InvalidError, SystemError, } public static void main(String[] args) throws Exception { Scanner s = new Scanner(System.in); loginStatus ret = login(s.nextLine()); switch(ret){ case Success: System.out.println("ログイン成功"); break; case InvalidError: System.out.println("ユーザー名を正しく入力してください(8文字以上)"); break; case SystemError: System.out.println("致命的なエラー(適当)"); break; } } public static loginStatus login(String password){ if(password.length() >= 8){ return loginStatus.Success; }else if(password!= null){ return loginStatus.InvalidError; } return loginStatus.SystemError; } }
サンプルだからログイン状態を3種類にとどめたけど、
これが10種類もあったら何の値かわからんこっちゃになっちゃうよ・・・。
頼む。みんな気を付けてくれ。
俺の目の前でハードコーディングを絶対にしないでくれ
追記:loginの文字数もハードコーディングだから、サーバー側のコンフィグかどこかにpasswordの最低文字数が決められると良いね。
プログラミングの質問(と回答)はこうあるべき
こういう質問があった。
最初はまったく内容が分からなかったんだけど、
きちんとご説明されていたし、
知識の照らし合わせが互いに出来たと感じた。
この切磋琢磨してる感じが良かった。
回答していて楽しいと感じられた。
課題を丸投げするな質問者さんより、
こういう質問者さんが増えると良いなぁ~。
良質な質問者でした。
おやすみなさい。
2019/01/17 追記:
単に自分が「トークン」の意味を知らないだけだった。無知は恥ずかしい。
調べればちゃんと意味が書いてあるやん!
「プログラミングでは、ソースコードを解析する際にそれ以上細かい単位に分解できない文字列の並びの最小単位(要素名や演算子など)のこと」
トークンみたいな抽象的な言葉って、ついついその言葉の1部分だけを知ってるだけで分かった気になっちゃうけど、とても良くない考え方だね。
オブジェクト指向について語ってる記事がよく炎上する理由も分かる。