tixture55’s diary

主にプログラミング関係の日記です。

C#の書き方(LINQ、クラスの継承の禁止、outキーワード)

※この記事はC#初学者による初学者用の記事です。

 

C#を使うと、PHPに比べ、制限をかけるような書き方ができるのが特徴です。またソート処理と一口に言っても、ラムダ式を使うソート、LINQを使ったソート、Comparisonデリゲートを使ったソートなどいろいろ方法があります。
 個人的には、方法が多い分、どのようにクラスやメソッドを指定するか、どんなソート方法を使うかなど柔軟に書いていく必要があるのかなぁと思ったりします。

 

LINQを使ったソート

 
 
using System;
using System.Collections.Generic;
using System.Linq;

namespace Sample
{
  class Sample
  {
     static void Main()
     {
        int src = {3, 1, 5, 4, 2};

        // LINQでソート
        var dst = src.OrderBy(a => -a);

        Console.WriteLine("[{0}]", string.Join(", ", dst));
        Console.ReadKey();
     }
  }
}

{5,4,3,2,1}が結果として出力されます。これは一次元配列ですから、あんまり恩恵的にはぱっとしないですが、二次元配列になっても極端にコード量を増やすことなく、ソート処理を書くことができます。

 

 

using System;
using System.Linq;

namespace Sample
{
  class Sample
  {
     static void Main()
     {
        //ジャグ配列
        var jag = new {
          new {0, 1, 200},
          new
{1, 3, 100},
          new {2, 4, 100},
          new
{3, 2, 300},
          new [] {4, 0, 200},
        };

        var sorted = jag.OrderBy(e => e[1]); //昇順(index=1)

        foreach (var s in sorted) {
           foreach (var e in s) {
              Console.Write(e + ", ");
           }
           Console.WriteLine();
        }
     }
  }
}


感覚的にはすごくすっきりした感じです。LINQいいですね。(速度的にはArray.Sort()より遅めだけど、配列の要素数が何十、何百じゃなければ無視してよさげ)

 

クラスの継承を禁止する

 
 
sealed class Asealed class A
{
  public virtual void VirtualMethod() { } //エラー
  protected void ProtectedMethod() { } //警告
}

上記のclass Aは親クラスとなることはできません。 上記のclass Aは親クラスとなることはできません。 基本的にクラスは拡張できる余地を残すべきで、むやみにシールクラスにする必要はありません。 ソフトウェアの再利用性の観点からも多用すべきではありませんが、継承したくないときには使えるキーワードです。

 outパラメータ付き引数での変数宣言

 outパラメータを使用するには、メソッド定義と呼び出し元のメソッドの両方でoutパラメータを使用するには、メソッド定義と呼び出し元のメソッドの両方で outキーワードを明示的に使用する必要があります。outキーワードを使うと呼び出されたメソッドで 引数の値を変更することができます。(inキーワードのパラメータは不可)

 
class Point { 
  public int X { get; }
      public int Y { get; private set; }
      public void GetCoordinates(out int x, out int y)
      {   
            x = X;    y = Y; 
      }
}

■C#6.0でのメソッド呼び出し方は↓

 
 
void OldStyle(Point p)
    int x, y; //事前に変数を宣言する必要があった 
    p.GetCoordinates(out x, out y);
      WriteLine($"({x}, {y})");
}

C#7.0では下記のように宣言できるようになった。

void PrintCoordinates(Point p)
{
  WriteLine(x1); // 変数のスコープ内であっても宣言前には参照するとコンパイルエラー
  p.GetCoordinates(out var x1, out int y1);
  WriteLine($"(x1,y1)=({x1}, {y1})"); // 変数のスコープはメソッド呼び出しと同じスコープ内
}

 

参考サイト 

www.sejuku.net

www.buildinsider.net

djangoでmodel定義やas_viewクラスメソッド、tests.pyを触ってみる。

今回はdjangoでmodels.pyやtests.pyを触ってみましたのでまとめます。

 

djangoのバージョン:1.11.8

 

models.pyへの記述をmysqlへ反映させる

python manage.py makemigrations (App名) python manage.py migrate

 

ちなみにテーブル名は(App名)_(models.pyで定義したclass名)となる。

idはデフォルトで作られる(auto_incrementもデフォルト)

 

特異?だなと思ったのは、URLのフィールドをURLFieldという形でCharFieldとは分けてmodelに定義できる。 また、外部キーもForeignKeyという形で特別に定義できる。

 この辺がURLとして、外部キーとしてデフォルト機能で特別に定義できるのは個人的には嬉しいです。この辺をcakephpとかで やろうとすると、いろいろ面倒なのではと思います。テーブルを確認すると、urlのフィールドの型は普通にvarcharとなってました。

  

modelでの関数の定義

def _get_full_name(self):    
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)

                                              
 上記のメソッドはプロパティです。これはマネージャーアトリビュートともよばれます。

 

抽象モデルによる同一フィールドの定義

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

 

上記のように書くと、Studentモデルは home_group, name, age のフィールドを持つことになります。 コードの保守上、このように書くのがいいかと思います。

 しかし、上記の書き方だとDBには親テーブルは反映されません。(DBにCommonInfoは作られない)親クラスも反映させたい場合、下記のようにマルチテーブル継承を使います。

 

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

 

as_viewクラスメソッド 

as_viewメソッドを使うと、インスタンスを作ったり、そのインスタンスプロパティへの代入処理を書くメソッドを簡略化できます。具体的には下記のdispatchメソッドの返り値を簡単に取得できます。

from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request, *args):
return HttpResponse('Hello, World!')
def myview(request, *args):
view_obj = MyView()
view_obj.request = request
view_obj.args = args
return view_obj.dispatch(request, *args)
myview = MyView.as_view()

上記のように書くことで、djangoがリクエストがgetかpostかdeleteなのかなどリクエストの種類を内部的に判定してくれます。(クラスベースビューは最初の起点が dispatch メソッドとなり、リクエストメソッド を判定してくれます。)もしgetなら、自動的にMyview.getを実行してくれます。(dispatch が実装されてるメソッドに応じて処理を自動的に分岐してくれる。)

 

tests.pyを編集してユニットテストを書く

デフォルトの状態のtests.py

from django.test import TestCase
# Create your tests here.

 

 

tests.pyにtestで始まる関数を追加していくことでユニットテストが可能となる。

その他の条件

  • アプリディレクトリの下にtestから始まるファイルを作る
  • django.test.TestCaseを継承したクラスを作る

 

python manage.py testでテストを実行すると、テスト用のDBが自動的に作られる。テスト実行後、テスト用の DBは削除されます。


参考サイト

Djangoフレームワークにおけるmigrations機能の学習ノート(1) - Qiita

qiita.com

qiita.com

Django: Model — 苦労する遊び人の玩具箱 1 ドキュメント

qiita.com

scala✕playframeworkのフォーム

コンパイル時にエラーが見つかる、型を意識したプログラミングをしたいということで今回はscalaを使ったフォームの構築です。

 

formの入力値を取得して別ページに渡す ○application.scala
play.api.data.Formとplay.api.data.Formsのimportが必要

 

val form = Form( "hope_date" -> text )
def formSample = Action {
   implicit request => val name = form.bindFromRequest.get
      Ok(name)         
}

 

前提として、conf/routesに遷移先のrouteを設定しておく。

 今回は GET       /form_sample           controllers.Application.formSampleを追記した。

これでnameがhope_dateのelementからtext型で入力値を受け取れる。


年齢や個数など、数値型として受け取りたい場合は val form = Form("age" -> number)としてやる。 複数のそれぞれ型の違うelementの値を受け取りたい場合は、クラスを作り、それをFormオブジェクトに関連させてやる。 普通はこのやり方で書く。

 

感想

きちんとtext型としてelementから値を受け取りますよとvalで指定できるところがscalaっぽくて好き。

 

react.js触ってみた感想

Djangoの学習のついでにフロントエンドをreact.jsにして、いまさらながらいろいろ触ってみました。その備忘録。

 

Reactの基本的な考え方

  •  Component間での親子の関係を意識して、親がStateを持っていて子にPropとして渡す というのが基本
  • Stateはブラウザを閉じたり、リロードするまでは保持される
  • renderで返すComponentは単一の親でなければならない

 

createClass({})

とにもかくにも、reactの開発ではまず、React.createClass({})でコンポーネントを作成する。

var Parent = React.createClass({
getInitialState: function(){
return {
//初期値を定義
}
}
})

 

 

下記のように初期値、返すマークアップを定義する。このとき、子をタグとして定義できる。 

var Parent = React.createClass({
//State(状態は親が管理)
getInitialState: function() {
return {
textval: "",
children: []
};
},
// State(textVal)を変更
setStateTextVal: function(textVal) {
this.setState({ textVal: textVal });
},

//<Parent />の表示
render: function() {
return (
<div>
<p>入力してEnterを押す</p>
<ChildInput onChange={this.setStateTextVal} onSave={this.setStateChildren} />
<Child textVal={this.state.textVal} children={this.state.children} />
</div>
);
}
});

 子側では、関数を持ったマークアップとアクション毎に実行される関数を定義する。

 

予め定義された配列を読み込む

例えば、入力された英単語(apple)について、用法を表示するアプリだと、下記のように子側のreturnに返したい用法をベタ書きするのは好ましくない。

return (
<div>
<ul>
<li>this is a baked apple.(これは焼きリンゴだ)</li>
<li>An apple is round in shape.(りんごの形は丸い。)</li>
<li>The apple fell from the tree.(りんごが木から落ちた。)</li>
</ul>
</div>
);

上記の用法を予め配列として定義しておけば、変数として読むことで子側で使用できる。

<script type="text/jsx">

const numbers = [this is a baked apple.(これは焼きリンゴだ),
         An apple is round in shape.(りんごの形は丸い。),
        The apple fell from the tree.(りんごが木から落ちた。)];
const listItems = numbers.map((number) =>
<li>{number}</li>
);

// 親:<Parent />の定義
var Parent = React.createClass({
           //以下略 return (

//子側のreturn処理
return(
<div>
<ul>{listItems}</ul>
</div>
);
);

フックのポイント

例えば、componentDidMountはコンポーネントレンダリングされた後に実行される。

 

componentDidMount : function() {    
    this.loadCommentsFromServer(); 
},

ここでは、loadCommentsFromServerを呼び出している。 チュートリアルではここにAjaxの処理を書いてるので、それにならって、pythonからの結果を取得する処理を書く予定。処理はできるだけ小分けにする。

 

まとめ

いろいろ書いたあとに気づいたのですが、私が書いてたのってES5でした。しかし、もちろん本家は、

Our eventual goal is for ES6 classes to replace React.createClass completely,

 とおっしゃっておりますので、今後はES6で書いていきたいと思います。

 

 

Java Network Programmingを読んでみて その1

最近は英語の技術書読んだり、RFClinuxの勉強がメインになってます。今年はc書いたり、python書いたり、いろいろ学習の幅を広げていきたいと思います。今回はJava Network Programmingを読んでの感想です。

 

In fact, writing network programs in Java is quite simple, as this book will show.

Indeed, there is very little application layer network software you can write in C or C++ that you can't write more easily in Java.

 

Java is the first(through no longer the only) language to provide such a powerful cross-platform network library
for handling all these diverse tasks.

 

I hope you'll find this fourth edition an even stronger,I hope you'll find this fourth edition an even stronger,
longer-lived, more accurate, and more enjoyable tutorial and reference to network programming in Java than the previous one.

 

 

シンプルではあるが、既存のCやC++で書かれたソースをJavaで書き直すのは容易ではない。Javaを使うことで多様なタスクをハンドリングできる。14 editionでは、以前のものよりもっと正確で、かつもっと楽しめるチュートリアルとリファレンスが用意されている。

 すごいざっくりな訳ですが、14のバージョンは当然ながら前のバージョンよりも楽しめる内容になっているようです。

 

 

input and output(I/O)input and output(I/O) in Java is organized differently than it is in most other languages, such as Fortran, C, and C++.

 

Filter streams can be chained to either an input stream or an output stream. Filters can modify the data as it's
read or written--- for instance, by encrypting or compressing it----- or they can simply provide additional methods
for converting the data that's read or written into other formats.

 

結局、Cで書いてもC++で書いても暗号化したり、圧縮したりとやってることは同じで、JavaはI/O処理についてはちょっと他の言語と違うんだよということが分かりました。

検索してみると、Javaでは文字コードエンコード、デコードが必要な箇所では大体Streamが使われてるみたいですね。バイトストリームにはInputStreamおよびOutputStreamがあります。および文字ストリームにはReader,Writterがあります。バイトストリームはメモリ上に保持するだけです。

  • ByteArrayInputStream
  • ByteArrayOutputStream

 Javaにおいて、

public static byte[] getBytes(char[] chars, String encordingsetName) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        Writer writer = null;
        try {
            writer = new OutputStreamWriter(os, encordingsetName);
            writer.write(chars);
            writer.flush();
        } catch (IOException ioe) {
            handleIOException(ioe);
        } finally {
            closeStreams(writer);
        }
        return os.toByteArray();
    }

 のようなStreamを使ったメソッドがありますが、ここで使われているwrite.flush()はバッファに書き込まんだ内容をHDDなどに恣意的に書き込む処理です。ちなみにclose()を呼んでもflush()が行われています。

ソケットとは

双方がデータのやりとりを行う際、双方を結んで情報を運ぶための線が必要となります。Javaにおいてはこの線のことを「ソケット」と呼びます。仮にAとBという2つのプログラムが通信を行うとすれば、一方の通信線がAにとっての「InputStream」であり、かつBにとっての「OutputStream」となります。

 通信を始める一番最初の段階ではまだこのソケットは2つのプログラムを結んでいません。クライアント側からサーバ側にソケットが送り込まれて初めて通信が開始されます。

 

詳細な仕様や実際のソースコードを読む作業を引き続きやっていこうと思います。

 

まとめ

今回は序盤をさらっとなめただけですが、徐々に読み進めていこうと思います。

 

 

参考サイト

第8講・その1 Javaプログラムにおける通信のしくみを理解する

Javaにおける文字コードまわりの話(4) - あしのあしあと

www.atmarkit.co.jp

対広島 選手たち続々登場〜プロ野球

 

 

巨人の助っ人、テイラー・ヤングマン異次元の角度を披露
198cmで腕が長く、右打者からすれば珠が背中からくるような軌道は大きな武器になりそうだ。 「子供の時からこのフォーム。三塁方向へステップしてから投げるユニークなフォームかもね」 カーブ・チェンジアップなどがウィーバーを彷彿とさせる。

 

DeNA補強と選手の意気込み

対するDeNAは先日結婚した筒香や来日したロペスで今年も戦っていく。ロペスいわく、 「筒香と二人で200打点」を目指すそうだ。シリアコが退団し、代わりにネフリト・ソトが入ってきました。

ソトは一塁をロペスが守れないとき重宝しそうです。打率もいいです。また、満塁時に強い戸柱にもがんばってほしいですね。

 

とにかく昨年優勝の広島は点が取れ、盗塁数も多かった。中日は松坂や岡本、2mを超えるモヤなど今年楽しみな選手を 率い、これらを迎え撃つ。

 

まとめ

個人的には注目度抜群の菅井のシンカーやスイーツを絶って肉体改造したゲレーロの活躍が楽しみです。特に松坂は年齢も近いし、衰えを感じさせない大胆な投球で チームを引っ張ってもらいたいと思います。

WAFの機能とOPENSSLの脆弱性

WAFも調べてみると、種類があり、物によってできることに差異があったので、ざっくりまとめておく。

 

WAFの歴史

WAFは従来のレイヤー2,3を守るファイアウォールとは異なり、レイヤー7(アプリケーション層)を守るために作られた。2008年当初はブラックリスト型が多く、以前に攻撃のあった内容しか防がれなかったが、近年はホワイトリスト型のWAFも登場し、HTTPS通信もチェックできるようになった。

 

WAFは何するもの?

  HTTP通信の中身をチェックするレイヤー7を監視する機器。また、WAFにも種類があり、ブリッジ型のWAFはネットワークに透過的に作用するため、 SSLで暗号化された通信は見ることができず、HTTPSの内容をチェックすることができません。   

   対してプロキシ型のWAFはいわゆるリバースプロキシとして働くため、やや設置環境に影響を与えます。自身がSSLでのリクエストを 待ち受けた後に内容のチェックを行い、結果としてHTTPSにも対応できます。 このため、通常、WAFではプロキシ型が採用されています。

 

WAFの検査項目

 HTTPリクエストの検査項目

  • リクエストライン(メソッド、URI、クエリストリング)
  • ヘッダ(ジェネラルヘッダ、リクエストヘッダなど)
  • メッセージボディ

 HTTPレスポンスの検査項目

apacheにもフィルタリング機能はある

mod_securityを有効にして、下記のようなURLにアクセスしようとすると、きちんとブロックしてくれます。(Forbiddenの画面に飛ぶ)

https://centos7.co.jp/?a=\<script\>alert(0)\</script\>

 

apacheのモジュールmod_securityには下記機能がある。

  • hiddenやCookieなど個々の特定のパラメータおよび値に対してフィルタリングを行うことができる
  • 通常のWebサーバでは記録されないPOSTのログを含め、詳細なログを取得することができます。
  • HTTPSのリクエストもフィルタリングできます。

 

OPENSSLの脆弱性

opensslはapacheやnginxで採用されているオープンソースツールです。2014年に見つかった脆弱性では、heartbeatパケットを送信することで、ペイロードのレスポンスに.htacessやhttpd.confの内容が返されてしまうという事態が起こりました。

 heartbeatパケットは64KBだと偽って1KBのデータをサーバに送ります。サーバは64KB要求されたと勘違いして、64KBクライアントに返してしまいます。ちなみに不足分の63KB分は適当にメモリから取って返してしまうので、もしSession Keyとかを返してしまってそれが露見したら、

TSL/SSLで暗号化した内容が筒抜けになるので、あるユーザの情報はすべて盗まれてしまいます。

 

この話の怖い所は2014年に問題になるまで、その信頼性の高さからAMAZONやYAHOOや銀行業務でずっとTLS/SSLが使われていてずっと情報が漏れ続けていたであろうこと。

 Heartbleedによる脆弱性があるのは、OpenSSLのバージョン「1.0.1」から「1.0.1f」までとなっており、サイト管理者はこれをバージョン「1.0.1g」にアップデートすることなどで脆弱性を修正できる。

 

 ちなみにSSL通信に利用するメモリにはユーザのセッションIDや公開鍵、サーバのSSL証明書秘密鍵など危ないデータが含まれている。