全知全能を目指す人のありがたい雑記

何かしら意味のあるありがた~い話か、意味のない雑念だらけの日記を書く予定です。

課題のお手伝いを始めました

何かご要望があれば是非ご利用ください。

プログラミングの課題をお手伝いします C,C++,C#,Java,Javascript等の課題

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はよく使いそう

拡張メソッドも定義できて使うなら

System.Mvc.Html名前空間を用いる

https://office-yone.com/technic/asp-net-mvc-htmlhelper/

 

モバイルサイト対応

Viewの拡張子の前に「.mobile」をつければ良いだけ

【例】Index.mobile.cshtml

 

Model

  • 扱うデータやロジックをつかさどる部分
    • データを取得し、加工し、然るべき処理に渡す
    • データの表示には関知しない
  • 更に機能を付加するならpartial classを用いる
    • 更新メソッドや特殊な検索メソッドなどに用いりたい
    • Controller内でLINQで処理できない内容を行う
    • Webサービスへの問い合わせ、書き戻しなど
  • DataAnnotation
    • メタデータを通してクラスやプロパティの情報を伝える
    • System.ComponentModel.DataAnnotations名前空間
    • 必須入力、データ範囲、カラム名、エラーメッセージなど
      • 簡単な内容なら、コードを書かずともDataAnnotationで代用できる
    • コード量が減る

 

Controller

  • ViewとModelの橋渡し部分
    • Modelから受けたデータをViewに渡す
    • ユーザー入力に合わせて処理を行う
    • 橋渡しをする上でアクションと呼ばれるメソッドを使う

アクションフィルター

  • 要求されたアクションに動作をアタッチする
    • 既出のフィルター
      • エラー時のハンドリング
      • 認証要求と未認証ユーザーのブロック
      • 出力のキャッシュ
    • 既出のインターフェイス
      • アクションの認証と承認
      • コントローラーメソッドの実行前と実行後
        • 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との差

  • 基本的な考え方がMVCと異なる
    • 単体テスト
      • 表示とロジックが密に結合されているため
    • 出力されるHTML
  • WebFormの長所
    • 小規模開発

リリース年月日

  • MVC1.0は2009年3月
  • MVC5.0が現在最新で2013年10月

URIとURLの違い

https://ferret-plus.com/4637

 

既存の外部ライブラリ

新規モジュールを入れたいならNuGetを使えば勝手に追加されるっぽい

追加の際は依存関係に気を付けること

 

無暗に最新版モジュールにしない

ファイルに対して更新権限を決めておくと良いらしい

ブラウザのデバッグについて

どのブラウザも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の違いがわかる例

ユーザー操作時

  1. Viewをユーザが操作
  2. ViewModelはModelのインスタンスからデータを取得するメソッドを呼び出す
  3. 呼び出したメソッドの戻り値を、ViewModelのプロパティにバインディング
  4. ユーザー操作反映完了

外部からのデータ受信時

  1. ViewModelはインスタンス作成時にメッセージのコールバックを登録
  2. 外部からデータを受信
  3. Modelは受信したデータを、Modelで保持するデータに変換する
  4. Modelはメッセージを発行し、作成されているViewModelに対してメッセージを送信
  5. ViewModelは受け取ったメッセージ種別に対応する処理を行う

※1
Messengerパターン。
Messengerというクラスを使って
メッセージを送受信できる

  1. メッセージを受信するインスタンスはMessengerクラスへ「Messageの種類と受信時の処理を記述して」登録する
  2. メッセージを送信するインスタンスは該当するMessageのインスタンスを作成し、送信したいデータがあればそのインスタンスのメンバへ代入。
  3. Messageクラスが持つSendメソッドでメッセージを送信する。
  4. メッセージを受信するインスタンスは、2で送った種別のメッセージを受信し、対応する処理を行う。

 ※2
オブジェクト指向におけるデザインパターンの一つ。
簡単に言えば、インスタンスを2つ以上作らせないようにする。
staticクラスと類似しているが違いがある。
詳しくは考察記事があるので見てみよう。

takachan.hatenablog.com

 

支払い金額を設定し、支払いを終えるのに何枚の硬貨が必要かを算出するプログラム

#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の最低文字数が決められると良いね。