デザインパターン・template method / Strategy

最近デザインパターンをまた勉強していたのでその考察点を記載します。

ソースは基本的に結城浩『増補改訂版Java言語で学ぶデザインパターン入門』(デザパタ本)から引用しています。

継承を用いる「Template Method」

Template Methodパターンは、abstractクラスにな抽象メソッドを記載し、それを継承したサブクラスに実装を強制するパターンです。 すると、似たような動きをするメソッド群を一つのabstract classの下に集結させることができます。

public abstract class AbstractDisplay { 
    public abstract void open();        
    public abstract void print();       
    public abstract void close();       
    public final void display() {       
        open();                             
        for (int i = 0; i < 5; i++) {       
            print();                    
        }
        close();                            
    }
}

継承したサブクラスは以下のようになります。

public class CharDisplay extends AbstractDisplay {  
    private char ch;                                
    public CharDisplay(char ch) {                   
        this.ch = ch;                               
    }
    public void open() {                           
        System.out.print("<<");                     
    }
    public void print() {                           
        System.out.print(ch);                       
    }
    public void close() {                           
        System.out.println(">>");                  
    }
}

これにより何が嬉しくなるかというと、Displayクラス群を他の場所で使いたい場合、それが具体的にどのサブクラスなのかを気にしなくてよくなります。

public class Main {
    public static void main(String[] args) {
        AbstractDisplay d1 = new CharDisplay('H');                  
        AbstractDisplay d2 = new StringDisplay("Hello, world.");    
        d1.display();                                               
        d2.display();                                               
    }
}

Mainクラスで AbstractDisplayクラスに代入する必然性は、これだけでは見えづらいように見えますが…。

委譲を用いる「Strategy」

Template Methodの関連パターンとして紹介されているのが、Strategyパターンです。extendsではなくimplementsが使われています。

デザパタ本では、じゃんけんを例に手の出し方を決めるStrategyインタフェースを記載しています。

public interface Strategy {
    public abstract((別にここはabstractでなくてもいい気がする)) Hand nextHand();
    public abstract void study(boolean win); // 勝敗に応じて手を変えることを想定
}

出す手を決めたり、勝敗数を保持したりするPlayerクラスは以下になります。

public class Player {
    private String name;
    private Strategy strategy;
    private int wincount;
    private int losecount;
    private int gamecount;
    public Player(String name, Strategy strategy) {        
        this.name = name;
        this.strategy = strategy;
    }
    public Hand nextHand() {                                
        return strategy.nextHand();
    }
    public void win() {                 
        strategy.study(true);
        wincount++;
        gamecount++;
    }
    public void lose() {                
        strategy.study(false);
        losecount++;
        gamecount++;
    }
    public void even() {               
        gamecount++;
    }
    public String toString() {
        return "[" + name + ":" + gamecount + " games, " + wincount + " win, " + losecount + " lose" + "]";
    }
}

Strategyインタフェースを実装したクラスは省略します。

「継承より委譲」の理解とデフォルトメソッド

やっていることが類似している継承と委譲ですが、調べてみると「多くの場面で、継承より委譲を用いるべき」という主張(定説?)がありました。 が、これが元を辿ろうとするとはっきりした記述をネット上で見つけられず、一旦保留とします。

僕が言えそうなのは疎結合にできるならするべきだし、委譲ならそれが実現しやすかったよねということです。

しかし、Java8ではデフォルトメソッドが登場したことにより、ますます両者の区別が難しくなったように見えます。

d.hatena.ne.jp

導入の背景について調べてみましたがこれしか出てきませんでした。

Java SE 8のラムダ式の基礎──なぜ必要なのか? 従来記法のリファクタリングを通して、その本質を理解する - page3 - builder by ZDNet Japan

これってJava側の都合では?って印象を受けました。まあしかし深いところについては分からず……。

『Clean Code アジャイルソフトウェア達人の技』を読んで心に残った3つのフレーズ

こちらの技術書をざっと読みましたので、心に残った3つのフレーズを紹介していこうと思います。

Clean Code アジャイルソフトウェア達人の技

Clean Code アジャイルソフトウェア達人の技

コメントとは常に失敗なのです。

おそらくこの本を今回読んでいて最もハッとしたのが4章の冒頭にある上の一文です。

コメントを書く目的は、読んでも分かりづらいコードの内容を補足説明するためだと思いますが、コメントなんかなくてもコードを読んでわかるようにできればそれが一番いい、というのが作中での主張です。

「読解しづらいコードになったからコメントを書こう」ではなく、「コメントを書かずに済むようにコードを改良できないか?」と考えるべきなのです。

懇切丁寧なコメントを書くことがよいプログラムへの第1歩だとなんとなく思っていた僕にとっては、かなり衝撃的な主張で、これ以降を真面目に読み進めるようになりました。

ちなみにコメントについては当たり前というか笑ってしまうような記載もありました。例えば「 /* add by alek3 */ やめろ」みたいなことが書いてあり、昔常駐していたプロジェクトに思いを馳せました。

熟練したプログラマなら、オブジェクト指向が常に優れているという考え方が神話であることを理解しています。

「手続き型っぽいコードの書き方と、オブジェクト指向っぽい書き方がある*1」というのはプログラムを書くようになるとすぐに耳にしますが、その分かりやすい例が紹介されていました。 まずは手続き型っぽい書き方は以下のとおりです。

public class Square {
    public Point topLeft;
    public double side;
}

public class Rectangle {
    public Point topLeft;
    public double height;
    public double width;
}

public class Circle {
    public Point center;
    public double radius;
}

public class Geometry {
    public final double PI = 3.141592;

    public double area(Object shape) throws NoSuchShapeException{
        if (shape instanceof Square){
            Shape s  = (Square)shape;
            return s.side * s.side;
        }
        else if (shape instanceof Rectangle) {
            // 四角形面積計算処理
        }
        else if (shape instanceof Circle){
            // 円の面積計算処理
        }
        throw New NoSuchShapeException();
    }
}

次にオブジェクト指向っぽい書き方です。

public class Square implements Shape {
    private Point topLeft;
    private double side;

    public double area() {
        return side * side;
    }
}

public class Rectangle implements Shape {
    private Point topLeft;
    private double height;
    private double width;

    public double area() {
        return height * width;
    }
}

public class Circle implements shape {
    // 略
}

この2つの書き方で、実現できることは同じですが、拡張のしやすい点が異なります。手続き型の場合、新たな関数の追加は容易ですが、新しいクラスを追加するのは手間です。例えば、周りの長さを求める関数 around を追加するのは容易ですが、三角形のクラス Triangle を追加するためには関数を書き換える必要があります。オブジェクト指向の場合は逆になります。

「複雑なシステムでは、新たな関数を追加することよりも、新たなデータ型を追加することのほうが多い」ため、オブジェクト指向を採用したほうがいい場合が多いというロジックです。

小さいこと!

関数であれクラスであれ、とにかく小さく分割することを主張していました。大きい関数やクラスは複雑化し、あとでメンテする人が大変な思いをすることになります。関数に関してはさらに、引数を減らすことも大事です。

クラスを分割する指針として、SRP(Single Responsibility Principle、単一責務の原則)の話も出てきます。どういう状態がSRPであるか、読んでいるだけでは今ひとつわかりませんでしたが、

  • クラスの概要を日本語でおよそ100字以内で表せること
  • 「もし」「そして」「あるいは」「しかし」といった単語が含まれないこと

この2つが満たされているべきと述べられています。

補足

発行日付

この書籍自体の発行は2017年ですが、原書は2008年であり、一部情報が古いところがあります。例えばMapに関する記述であったり、フレームワークの記述であったりです。

デザインパターン

本書ではデザインパターンがいくつか登場しています。例えば、

  • Adapter
  • Decorator
  • Factory Method
  • Template Method

があります。デザインパターンは20以上あり、全部一度に覚えようとするとなかなか大変*2なのですが、今回のように数個再登場するのでいいタイミングで復習することができました。

*1:関数型言語については記述がなかったと思います

*2:Javaを書き始めたころ、結城浩デザインパターン本を読んで挫折した

#PLAID_Party 参加記

株式会社プレイドのオフィス移転パーティーに、ありがたいことにご招待受けましたので参加してきました。

プレイド、オフィス移転のお知らせ GINZA SIXに「完成しない」オフィスを構築 | 株式会社プレイド

パーティー雰囲気

ガツガツ食べさせてもらいましたがめっちゃ美味しかったです!

オフィスに芝生がありました!靴を脱いで歩くと気持ちい~

参加者全員プレゼントでTシャツとコースターもらいました!うれしいですね。

パーティー中の展示

プレイドの主力サービス、カルテを支える技術について展示がありました。

僕は特にSREの話が面白いと思いました。初めはAWSでやっていたのが、MongoDBが思ったよりパフォーマンスが出ず、BigQuery(だったかな?)を擁するGCPをメインに据えるようになりました。しかし、GCPはしばしば障害を起こす(特にネットワーク系の障害)ため、AWSをサブとして現在はマルチクラウド体制をとっています。

僕のクラウド力の都合上詳しいことは書けないのですが、1秒あたり15,000リクエストをさばくために頭を悩ませている姿はかっこいいなと思いました。

その他

  • ぷよぷよをやるスペースがあったのでちょっとやったのですがボコされましたw

  • gamiさんの友人がたくさんいらっしゃった。

  • ベンチャーやスタートアップの偉い人が結構いらっしゃって会話を聞いていて楽しかった。逆に僕が何も提供できてなくてアレ。

AWS 認定ソリューションアーキテクト – アソシエイト 攻略法

先日合格したので自分の対策を残します。

対象読者

  • AWS 認定ソリューションアーキテクト – アソシエイト」に合格したいけど、AWS力に自信がない人
    • AWSのサービスをあんまり知らない……
    • そもそもネットワークを自分で考えたり組んだりしたことがない……

私のレベル

  • ネットワークの知識はあまりない
  • AWSを業務で取り扱っている

AWS 認定ソリューションアーキテクト – アソシエイトとは

  • 試験概要 AWSのサービスを用いたアーキテクチャ設計に関する問題が出ます。2018年2月から新しいバージョンが登場し、現時点では新旧両方のバージョンを受験することができますが、旧バージョンは2018年8月12日までしか受けることができません。ちなみに会場があいていれば数日後には試験を受けることができますし、試験自体は毎日行われています。

新旧バージョンの違い

旧バージョンではEC2とS3の細かい知識を問う問題が多かった一方、新バージョンでは他のサービスのこともバランスよく問われるようになった印象です。

勉強内容

① 参考書

他のブログでも上げられていますが、こちらの書籍です。

合格対策 AWS認定ソリューションアーキテクト - アソシエイト

合格対策 AWS認定ソリューションアーキテクト - アソシエイト

初学者向けです。この本から入って、全体像を把握するにはいいと思います。ただし、扱っていない事項も数多くありますので、これだけでの合格は難しいかなと思います。例えば、RedShift、Kinesis、EMRあたりは記述がありません。

② WEB問題集

こちらのサイトになります。

aws.koiwaclub.com

700問以上の問題があり、それぞれのサービスや、サービス同士のの関連性など、幅広い知識を身につけられます。一方で、NATインスタンスなど一部抜け漏れがあるので他の勉強法で補う必要があります。

AWS Black Belt

こちらのサイトになります。

aws.amazon.com

ここの「コンピューティング」から「分析」まで(「開発者用ツール」を除く)を読むといいと思います。そのサービスの全体像がわかります。 私は全部に目を通していないのですが、上記のWeb問題集を解いていてわからないサービスが出てきたらこちらを参照するというやり方をとっていました。

試験中、「全然わからない、受かる気しないわ」となったときにすべきこと

僕は一発合格ではありませんでした。初回の試験は解いている最中もボロボロで、全く合格できる感触ではありませんでした。*1

もしもう一度受験できるチャンスがあるときは、やるべきことがあります。分からなかったサービスや用語を試験中に覚えておくことです。*2

合否は回答提出後すぐに判明します。残念ながら不合格になってしまった場合は、意味のわからなかった単語はもちろんですが、サービスの理解があいまいな部分があったものも、試験後にBlack Beltで調べましょう。試験はテストセンター開催され、メモ等を持ち帰ることはできないので、頭の中に頑張って記憶しましょう。

所感

身も蓋もないのですが、一番効いたのは実務経験です。ここでVPCを軸とした、EC2・RDS・ELBの関係性がなんとなく把握できた感じです。次に役に立ったのはWeb問題集です。こちらで細かい知識が自然と頭に入りました。

模試は受けておけばよかった気がする。

他の合格記

総じてどの記事もよくまとまっていると思いました。

*1:合格したときも感触は良くなかった

*2:試験中、僕はメモをたくさん取り、理解があやふやだった部分を記憶するようにしていました

『試して理解 Linuxのしくみ』前編

第4章まで読んだので一旦まとめたいと思います。ちなみに私はLinuxを使うことはありますが、中身については無知です。

第1章 コンピューターシステムの概要

重要なことを一点挙げると、CPUにはユーザモードとカーネルモードがあるということです。 プロセス管理システム、プロセススケジューラ、メモリ管理システムなど「通常のプロセスから実行できると困る処理」はカーネルモードで動作します。

ちなみにカッコつきなのは本文からの引用なのに加えて、じゃあなぜ困るんじゃって聞かれてもうまく答えられないからです。(´;ω;`)

第2章 ユーザモードで実現する機能

ここで取り上げられていたのはシステムコールです。通常ユーザモードで処理されているプロセスが発行するもので、カーネルに処理を依頼します。

実験プログラムでは、ユーザモードとカーネルモードを行き来するプログラムを動かしました。

第3章 プロセス管理

プロセス管理のために、fork()とexecve()の2つの関数があります。

と、章の冒頭でいきなり宣言されて、???という感じでした。しかし、章を最後まで読むと、プロセスを複製する場合はfork()単体で、全く別のプロセスを新規生成する場合はfork()とexecve()を組み合わせるという使用法があるということがわかりました。

また、プログラムファイルの構造を示されてこれまた???となりましたが、プログラムをメモリ上にマップするための情報とわかり納得できました。

第4章 プロセススケジューラ

Linuxカーネルが複数プロセスを同時に動作させる仕組みを解説しています。冒頭にある

  • 1つのCPU上で同時に処理するプロセスは1つだけ
  • 複数プロセスが実行可能な場合、個々のプロセスを適当な長さの時間(=タイムスライス)ごとにCPU上で順番に処理する。

という原則で以降の説明が理解できるので、比較的わかりやすい章でした。

コンテキストスイッチの説明で「ソース上では次の行にある処理であっても、直後に呼ばれるとは限らない」ということがしっかり理解できたのが良かったです。

おわりに

第4章はあまり自分で手を動かしていないのですが、それでも非常に理解しやすく、初学者向けに丁寧に書かれていると感じました。 目的に沿った実験、わかりやすい図表がその原因なのかなと思いました。図表の充実っぷりは本当にすごいと思います。

『体系的に学ぶ安全なWebアプリケーションの作り方』3章まとめ

あの徳丸本が第2版になったと聞いて、最近セキュリティのことも仕事でちょっと触っているのもあり早速買って読んでいます。

600ページ超の充実した内容です。今回読んだのは3章「Webセキュリティの基礎~HTTP、セッション管理、同一オリジンポリシー、CORS」です。基礎的なこともよくわかっていないこともあり、内容を自分なりにまとめようと思います。

3.1HTTPとセッション管理

  • リクエストメッセージとレスポンスメッセージがある
  • レスポンスメッセージの1行目であるステータスラインはたとえばHTTP/1.1 200 OK
  • レスポンスメッセージの2行目はヘッダで、Content-LengthやContent-typeが入っている
  • POSTメソッドによるリクエスト・メッセージにはボディという部分がある
  • GETメソッドは参照(リソースの取得)のみに用いる。副作用がないことが期待される。
    • GETで秘密情報を送信した場合、様々な漏洩のリスクがある
  • 秘密情報の送信にはPOSTメソッドを使う
  • hiddenパラメータは利用者自身で書き換えられる
  • サーバー側がアプリケーションの状態を覚えておくことをセッション管理とよぶ
  • クッキーは値の個数や文字列長で限界があり、クッキーの値を利用者本人に参照・変更できるので、秘密情報の格納には向かない
    • セッションIDだけを持たせるべき
  • セッションIDに求められる要件は以下の3点
    • 三者がセッションIDを推測できないこと
    • 三者からセッションIDを推測されないこと
    • 三者にセッションIDが漏洩しないこと
  • セッションIDは認証後に変更するべき

後ろの2項に比べると基本的な内容。とはいえ知らないことも結構あり、勉強になった。セッションIDのセキュリティ上の重要性が理解できた。対話にたとえた説明が非常にわかりやすい。

3.2 受動的攻撃と同一オリジンポリシー

  • 受動的攻撃:Webサイトの利用者に罠を仕掛け、罠を閲覧したユーザーを通じてアプリを攻撃する。パターンが3つ紹介されている
    • 罠サイト
    • 正規サイトに罠を仕込む
      • この手法はよく用いられている
      • 正規サイトに罠を仕込む方法は後の章で記載されている
    • サイトをまたがった受動的攻撃
  • 受動的攻撃にはブラウザが対策を講じている
  • サンドボックスとは、JavaScriptや、ActiveXなどができることを制限する
    • JavaScriptの場合は以下の通り
      • ローカルファイルへのアクセス禁止
      • プリンタなどの資源の利用禁止
      • ネットワークアクセスの制限=同一オリジンポリシー
  • 同一オリジンポリシーとは、サイトをまたがったアクセス(クロスドメインアクセス)を禁止すること
  • アプリケーションに脆弱性があった場合、同一オリジンポリシーの制約を受けていても攻撃をすることが可能
  • クロスドメインアクセスは全面的に禁止されているわけではない

受動的攻撃の3手法は、2つ目が頻度・流出する情報の二点から特に危険なものだと感じた。あと3つ目については仕組みがまだよくわかっていない。

JavaScriptがやりたい放題できると危険極まりないから、ブラウザで制約をかけているという認識を持った。

3.3 CORS(Cross Origin Resource Sharing)

サイトを超えてデータをやり取りできる仕様のこと。 たとえばXMLHttpRequest

  • Access-Control-Allow-Origin:クロスオリジンからの読み出しを許可するための仕掛け
  • シンプルなリクエストの場合、相手の許可無しでHttpリクエストを送れる
    • メソッド、リクエストヘッダ、Content-Typeに制約がある
  • 条件を満たさない場合は、プリフライトリクエストを送る必要がある

全般的にこの項はついていけなかった。

まとめ

基本といいつつ、僕にとっては知らないことがかなり多かったので勉強になった。4章も折を見て進めていきたい。その前に環境構築が先かもだが。

『退屈なことはPythonにやらせよう』流し読み

タイトルの通りです。1章だいたい2,3分で読んで何が書いてあるか確認したという状況です。

目次一覧

  • 第1章 Python入門
    • 整数、小数、print出力など
  • 第2章 フロー制御
    • if、for、while
  • 第3章 関数
    • スコープの話とか
  • 第4章 リスト
    • リスト、タプル
  • 第5章 辞書とデータ構造
  • 第6章 文字列操作
    • 取り出し、置換など
  • 第7章 正規表現によるパターンマッチング
  • 第8章 ファイルの読み書き
    • ファイルの作成
  • 第9章 ファイルの管理
    • ZIPファイルの取り扱い
  • 第10章 デバッグ
    • アサートやログ
  • 第11章 Webスクレイピング
  • 第12章 Excelシート
    • 読み書きとレイアウト
  • 第13章 PDFファイルとWord文書
    • 読み取りと作成、簡単な加工
  • 第14章 CSVファイルとJSONデータ
    • 読み取りとそこからの加工
  • 第15章 時間制御、自動実行、プログラム制御
    • timeモジュール、マルチスレッド
  • 第16章 電子メールやSMSの送信
    • 受信もある
  • 第17章 画像の操作
    • Pillow
  • 第18章 GUIオートメーションによるキーボードとマウスの制御
    • pyautoguiでマウスや画面を制御

所感

「ノンプログラマーにもできる」と謳っている通り、ノンプログラマーが頻繁に触っていそうなExcel、Word・PDFの章があります。ちなみに前回の記事で書いたツールは、この書籍のExcelの章をヒントにしています。

11章から18章で取り扱っているものを見て、自動化できそうな作業があれば、まずは読んでみるといいと思います。