JSTQB認定テスト技術者資格 Foundation Levelに合格しました

なんで取得したのか

体系的なテストの知識が薄いなと思ったから(お客さんと話していた時にC2カバレッジで〜〜という話がわからなくて困った)

自分の背景

開発の会社に新卒で入社して約3年

やった勉強

感想

  • 教科書を眺めた段階で一週間あればいけるなと思ってたら試験直前の一週間で自分の時間がほとんど取れない誤算があった
  • まとまった時間が取れるのが、試験前日の午前3時からという悲惨な状況
  • ここで教科書丸ごと読むのは一夜漬けでは無理だと判断し、シラバスに絞ったのは賢明な判断だったと思う
  • なんとなく(テスト界隈で)一般的な言葉をある程度網羅的に知れたのは良かったと思うが、シラバスわかりづらいというか、日本語怪しいところあって辛い
  • でもまあある程度体系的に(だいぶざっくりだけど)テストのことを知りたい、という場合には有用なのでは

Effective Javaを読んでいる㉘

例1

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List2<Object> list = new List2<>();
        List<String> sList = new ArrayList<>();
        List<Object> oList = new ArrayList<>();

        //List<String>はList<Object>のサブクラスではないので以下の呼び出しはコンパイルエラー
        list.merge(oList, sList);
    }
}

class List2<E> extends ArrayList<E> {

    public void merge(List<E> l1, List<E> l2){
        this.addAll(l1);
        this.addAll(l2);
    }

}
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List2<Object> list = new List2<>();
        List<String> sList = new ArrayList<>();
        List<Object> oList = new ArrayList<>();

        //List<? extends E>の型パラメータはEのサブクラスであるため以下は許容される
        list.merge(oList, sList);
    }
}

class List2<E> extends ArrayList<E> {
    public void merge(List<E> l1, List<? extends E> l2){
        this.addAll(l1);
        this.addAll(l2);
    }
}

例2

import java.util.ArrayList;
import java.util.Collection;

public class Test {
    public static void main(String[] args) {
        List2<String> list = new List2<>();
        //ArrayList<Object>はCollection<String>の親クラスではない
        list.merge(new ArrayList<Object>());
    }
}

class List2<E> extends ArrayList<E> {
    /**
    * 引数のコレクションに要素を全て追加
    */
    public void merge(Collection<E> collection){
        collection.addAll(this);
    }
}
import java.util.ArrayList;
import java.util.Collection;

public class Test {
    public static void main(String[] args) {
        List2<String> list = new List2<>();
        //ObjectはStringの親クラスであるため以下は許容される
        list.merge(new ArrayList<Object>());
    }
}

class List2<E> extends ArrayList<E> {
    /**
    * 引数のコレクションに要素を全て追加
    */
    public void merge(Collection<? super E> collection){
        collection.addAll(this);
    }
}

PECS

extendsの基準

メソッド内で入力された型パラメータの変数を使用する場合はextends

なんで?

メソッド内で入力された引数が、型パラメータに指定された型のサブクラスであった場合、親クラスとして使用しても問題ないから

superの基準

呼び出し元に返す(もしくは引数として破壊される対象)のオブジェクトにはsuper

なんで?

呼び出し元で型パラメータ化した変数にとって、その型パラメータのサブクラスを型パラメータ化した型として扱っても問題ないから

大事な前提条件

全ての子クラスは親クラスとしても使えなければならない(リスコフの置換原則)

import java.util.ArrayList;
import java.util.Collection;

public class Test {
    public static void main(String[] args) {
        ExtendsList<Child> list = new ExtendsList<>();
        //これが許容されないのは何故だろう
        Collection<Object> objs = list.merge(new ArrayList<Child>());
    }
}

class ExtendsList<E> extends ArrayList<E> {
    //     戻り値はEの親のコレクションとして使いたい      引数はEの子のコレクションとして使いたい
    public Collection<? super E> merge(Collection<? extends E> collection){
        this.addAll(collection);
        return this;
    }
}

class Child extends Object{
}

class ChildChild extends Child{
}

これが通らないのは何故だろう
CollectionはCollection<? super E>の親ではないから?

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        ExtendsList<Child, Object> list = new ExtendsList<>();
        Collection<Object> objs = list.merge(new ArrayList<Child>());
    }
}

class ExtendsList<E extends T, T> extends ArrayList<E> {
    public  Collection<T> merge(Collection<E> collection){
        List<T> list = new ArrayList<>();
        list.addAll(collection);
        return list;
    }
}

class Child extends Object{}

こんな感じにしたい場合は? ExtendedListの型パラメータにObjectを指定しないでこれをできてもいいような

こんなん?

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        ExtendsList<Object> list = new ExtendsList<>();
        Collection<Object> objs = list.merge(new ArrayList<Child>());
    }
}

class ExtendsList<T> extends ArrayList<T> {
    public  Collection<T> merge(Collection<? extends T> collection){
        List<T> list = new ArrayList<>();
        list.addAll(collection);
        return list;
    }
}

class Child extends Object{}

ExtendsListのインスタンスを最初からChildで宣言するのは無理なのかな

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        ExtendsList<Child> list = new ExtendsList<>();
        Collection<Parent> objs = list.<Parent>merge(new ArrayList<Child>());
    }
}

class ExtendsList<T> extends ArrayList<T> {
    public <E super T> Collection<E> merge(Collection<? extends E> collection){
        List<E> list = new ArrayList<>();
        list.addAll(collection);
        return list;
    }
}

class Parent{}
class Child extends Parent{}

なんとなくこんなんでいける気がするけどコンパイルが通らない

Effective Javaを読んでいる㉗

再起型境界

import java.util.List;

public class Test {
    //引数がCompareble2<T>型のリストであることが保証されるためOK
    private static <T> Comparable2<T> max1(List<Comparable2<T>> list){
        Comparable2<T> max = list.get(0);
        for(Comparable2<T> t : list){
            if(max.compareTo(t) > 0){
                max = t;
            }
        }
        return max;
    }

    //TはCompareble<T>を継承していることが保証されるためOK
    private static <T extends Comparable<T>> T max2(List<T> list){
        T max = list.get(0);
        for(T t : list){
            if(max.compareTo(t) > 0){
                max = t;
            }
        }
        return max;
    }

    //これはだめ
    private static <T> Comparable<T> max3(List<Comparable<T>> list){
        Comparable<T> max = list.get(0);
        for(Comparable<T> t : list){
            //Compareble<T>のcompareToの引数はT型であり、Compareble<T>型ではないため不可!!
            if(max.compareTo(t) > 0){
                max = t;
            }
        }
        return max;
    }
}

interface Comparable2<T>{
    /** 引数のがおおきかったら正、小さかったら負、同じだったら0を返す */
    int compareTo(Comparable2<T> t);

    //Comparebleではメソッドの範囲でTがComparableを実装していることを保証していない
    // int compareTo(T t);
}

読んでおきたい d.hatena.ne.jp

Effective Javaを読んでいる㉖

ジェネリクスを使おう

具象不可能型は配列を生成できない

DelayQueueってなに
→Delayedインターフェースを実装したクラスのみ格納できるキュー
→Delayedインターフェースを実装したクラスがオーバーライドしたgetDelayedメソッドの戻り値が0未満でないと、要素を取得できない
タイムアウトを設定して待機したりできる
APIを非同期で何回もよんで呼び出しと結果を管理するオブジェクトを突っ込んで云々みたいな?いまいちイメージがわかない
DelayQueue (Java Platform SE 7)

スカラー型への無検査キャストを抑制するよりは配列型への無検査キャストを抑制する方が、危険性は高いです。とは? java - What is a Scalar type and why is it riskier to suppress an unchecked cast to an array type than to a scalar type? - Stack Overflow ・EはObjectのサブクラスではない(EはObjectのサブクラスであるという話?)
・配列のキャストではコードが型安全かどうか保証するのが複雑になるから
いまいち理由としてはピンとこないけど↓の2人目の人が書いているサンプルコードはわかりやすい
配列自体が絶対に外から見えないようにするなら配列をキャストした方が安全な気はするけど http://stackoverflow.com/questions/14986765/what-is-a-scalar-type-and-why-is-it-riskier-to-suppress-an-unchecked-cast-to-an

まとめると以下のイメージ?
・Object型から総称型への配列のキャストは許可されている
・が、型そのものはObject型のままである
・外側から見た時、総称型のクラスを使用する際に、型変数には具体的な型を使用する
・総称型へキャストされた配列をクライアントが使用するとき、クライアントではその配列は「型引数に指定した配列」として使う(使いたくなる)。
・が、実態はObject型の配列であり、特定の型の配列に格納するとClassCastExceptionがスローされる

キャストについて − Java Solution − @IT

4コマ漫画を生産するためのアプリ

  • 各コマの画像を選ぶ
  • エディタで吹き出しの配置とセリフの設定ができる →ここ
  • 投稿できる
  • 自分で画像をアップロードして使うことも出来る
  • アップロードした画像は他の人も使える
  • 投票できる

ホームページレッカー

クライアントサーバ

クライアント:URLを入力してリクエス
サーバ:受け取ったURLへアクセスしページを取得
   :ページ内のURL(cssとか画像とか)を文字列変換で絶対パスに治す→ページはURLのものを表示したいけどドメインが変わるので※1
サーバ:DOMをランダムにぐちゃぐちゃにする(どうやる?いわゆるHTMLパーサーでできる?)※2
サーバ:ぐちゃぐちゃにしたページをクライアントに返却

・普通に考えるとXSSし放題なのでどうしようかな
・※1は対象絞ればふつうにテキスト置換でいいような
・※2は真面目に考えたいけどそもそも何でコントロールするのがいいのかな
・本当はスクショとってtwitterでシェアまでしたい気持ち

homepage wrecker

追記

一応動くとこまで作った

github.com

入力ページへのリクエストを送信したIPと実際にデータを送信したIPが違っていたらエラーにしたい

[https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgcmVxdWVzdCBmcm9tIHNhbWUgaXAgCgpVQS0-YXBwOgAYBwphcHAtPnNlc3Npb246aXAKAAQHAB8GABgGVUE6aW5wdXQgZm9ybQA4CVVSTAAvDgA-ByBpZAA3DmlwAF8GYXBwOmNoZWNrAIEGCApub3RlIHJpZ2h0IG9mIGFwcDogSWYgYWNjZXB0ZWQgaXAgaXMgbm90AIE2CWluIACBJAcsIHJldHVybiBlcnJvciBwYWdlLgCBJQkAFAdicmVhayB3ZWIgc2l0ZQCCAwZVUkwK&s=napkin:image=https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgcmVxdWVzdCBmcm9tIHNhbWUgaXAgCgpVQS0-YXBwOgAYBwphcHAtPnNlc3Npb246aXAKAAQHAB8GABgGVUE6aW5wdXQgZm9ybQA4CVVSTAAvDgA-ByBpZAA3DmlwAF8GYXBwOmNoZWNrAIEGCApub3RlIHJpZ2h0IG9mIGFwcDogSWYgYWNjZXB0ZWQgaXAgaXMgbm90AIE2CWluIACBJAcsIHJldHVybiBlcnJvciBwYWdlLgCBJQkAFAdicmVhayB3ZWIgc2l0ZQCCAwZVUkwK&s=napkin]

かんがえちゅう

あれこれCSRF対策のトークンじゃね

title request from same ip

UA->app:request app->session:ip session->app: app->UA:input form UA->app:URL app->session:session id session->app:ip app->app:check same ip note right of app: If accepted ip is not same ip in session, return error page. app->UA:return break web site from URL