the dawn of yuriko hisory

アニメやら漫画関係で何か作りたいものと勉強したことのメモ用

アイマスでデザインパターン Adapter

GitHubリンク

実装クラス一覧

IdolMaster - すべての作品をアイドルマスターとして取り扱うためのインターフェース
MillionLive - すでに実装がされているミリオンライブクラス
CinderellaGirls - すでに実装がされているシンデレラガールズクラス

今回はミリオンとシンデレラ両者がすでに実装されているが、アイドルマスターとしてともに扱いたい。
しかし、既存のクラスを変更はできないといった状態。
そのため、間にクラスを挟んで実装を行う
以下がそのクラス

IdolMasterMillionLive - ミリオンライブをアイドルマスターとして扱うためのAdapter
IdolMasterCinderellaGirls - シンデレラガールズアイドルマスターとして扱うためのAdapter

各クラス

IdolMaster
public interface IdolMaster {
        // あいさつするだけ
	public abstract void aisatu();
}
MillionLive
public class MillionLive {
  // キャラ名
  private String name;

  // 中の人
  private String cv;

  // ミリオンライブ
  public MillionLive(String name, String cv) {
    this.name = name;
    this.cv = cv;
  }

  // 挨拶 みりっほー
  public void mirihho() {
    System.out.println("ミリオンライブ" + this.name + "役の" + this.cv + "です。");
  }

}
CinderellaGirls
public class CinderellaGirls {
  // キャラ名
  private String name;

  // 中の人
  private String cv;

  // ミリオンライブ
  public CinderellaGirls(String name, String cv) {
    this.name = name;
    this.cv = cv;
  }

  // 挨拶 でれっす
  public void mirihho() {
    System.out.println("シンデレラガールズ" + this.name + "役の" + this.cv + "です。");
  }

}
IdolMasterMillionLive
public class IdolMasterMillionLive extends MillionLive implements IdolMaster{

  // super()を使用して名前とCVをセット
  public IdolMasterMillionLive(String name, String cv) {
    super(name, cv);
  }

  // あいさつ
  @Override
  public void aisatu() {
    // 親クラスのメソッドをそのまま使用する
    mirihho();
  }
}
IdolMasterMillionLive
public class IdolMasterCinderellaGirls extends CinderellaGirls implements IdolMaster{

  // super()を使用して名前とCVをセット
  public IdolMasterCinderellaGirls(String name, String cv) {
    super(name, cv);
  }

  // あいさつ
  @Override
  public void aisatu() {
    // 親クラスのメソッドをそのまま使用する
    deressu();
  }
}

動作確認

public static void main() {

  IdolMaster million = new IdolMasterMillionLive("箱崎星梨花", "麻倉もも");
  million.aisatu();

  IdolMaster cinderella = new IdolMasterCinderellaGirls("島村卯月", "大橋彩香");
  cinderella.aisatu();

}

実行結果

ミリオンライブ箱崎星梨花役の麻倉ももです。
シンデレラガールズ島村卯月役の大橋彩香です。

IdolMaserインタフェースを実装したので、これでアイドルマスターとしてミリオンとデレマスがアイドルマスターとしてともに扱うことが可能になる。
親クラスを継承したことによって、元のメソッドの挙動も変えずに済んでいる。

2017/11 30日間チャレンジ -デザインパターン-

久しぶりの更新です。

炎上案件→転職と少し慌ただしい日々を送っており、ようやく落ち着いてきたためブログを再開していきます。
それに伴い少しやることを考えていて30日間で何か目安を作って達成していこうかなと考えました。

最初のスタートとしてデザインパターンアイマスに置き換えて覚えていこうと思います。
デザパタ入門にあがっているうちの23個すべてができるかはわかりませんが、
出来る限りこなしていきます。


Iteratorパターン

アイマスでデザインパターン Iterator

GitHubリンク

実装クラス一覧

Aggregate - 集合体
Iterator - 数え上げ
Office - 事務所
OfficeIterator - 事務所のアイドルをスキャン
Idol - オフィスに所属するアイドル

各クラス

Iterator
public intrface Iterator {

  // 次のアイドルが存在すればTrue
  public boolean hasNext();

  // 次のアイドルを指し示す
  public Object next();
}
Aggregate
public interface Aggregate {
  public Iterator iterator();
}
Idol
public class Idol {

  // 名前
  private String name;
  // 年齢
  private int age;

  // コンストラクタ
  public Idol(String name, int age){
    this.name = name;
    this.age = age;
  }

  // 自己紹介
  public String selfIntroduction(){
    return name + "," + age + "歳です。";
  }
}  
Office
publc class Office implements Aggregate {
  
  // 事務所に所属しているアイドル
  private Idol[] idols;
  
  // 配列用インデックス
  private int index = 0;

  // コンストラクタ
  public Office(int number){
    this.idols = new Idol[number];
  }

  // Indexからアイドルを取得
  public Idol getIdol(int index){
    return idols[index];
  }

  // アイドルを事務所に迎える
  public void enteringCompany(Idol idol){
    this.idols[index] = idol;
    index++;
  }

  public int getLength(){
    return index;
  }

  // Iteratorの生成
  // thisでOfficeインスタンスを渡す
  @Override
  public Iterator iterator() {
    return new OfficeIterator(this);
  }
}
OfficeIterator
public class OfficeIterator implements Iterator {

  // 事務所
  private Office office;
  
  // インデックス
  private int index;

  // コンストラクタ
  public OfficeIterator(Office office) {
    this.office = office;
    this.index = 0;
  }

  // 事務所の所属アイドルがまだ存在していればTrue
  @Override
  public boolean hasNext() {
    if (index < office.getLength()) return true;

    return false;
  }

  // アイドルの情報を取得している大元
  @Override
  public Object next() {
    Idol idol = office.getIdol(index);
    index++;

    return idol;
  }
}

動作確認

public static void startIterator() {

  // 事務所作るよー
  Office 765Office = new Office(5);

  // アイドルスカウト
  765Office.enteringCompany(new Idol("七尾百合子", 15));
  765Office.enteringCompany(new Idol("高坂海美", 16));
  765Office.enteringCompany(new Idol("佐竹美奈子", 18));
  765Office.enteringCompany(new Idol("周防桃子", 11));
  765Office.enteringCompany(new Idol("田中琴葉", 18));

  // Iteratorインスタンスを作成して、アイドルを順番に呼び出す
  iterator iterator = office.iterator();

  while(iterator.haxNext()){
    Idol idol = (Idol)iterator.next();
    // 自己紹介をする
    System.out.println(idol.selfIntroduction());
  }

}

実行結果

七尾百合子,15歳です。
高坂海美,16歳です。
佐竹美奈子,18歳です。
周防桃子,11歳です。
田中琴葉,18歳です。


765で作るならASメンバーで作ればよかったなと作り終わってから後悔

動き的にはアイドルがいれば引っ張ってきて、いなければ処理終了なだけ
あまり意識してないけど拡張forの内部とかでIterator使われているらしい

Amazon Web Service 学習メモ①

DjangoAWS環境で作るための学習
AmazonWebServices 基礎からのネットワーク&サーバー構築の本を読んだので、学んだことをまとめ

システム構築について

インフラ知識を身に着けるメリット
  • 障害に対応できる
  • 堅牢なシステムを作成するためのコードを意識できる
サーバーの構築の流れ

1.LinuxWindows SeverなどのサーバーOSの設定

2.サーバーの用途に沿って必要なソフトウェアのインストール

Webサーバーなら『Apache』や『nginx』

ApacheはSpring等で組み込まれていたため知っていたがnginxは知らなかった
Djangoのデプロイ環境用に使用している人がいるみたいでqiita等で記事がいくつかあがってます

  • データベースサーバーなら『MySQL』など

※メールサーバーの存在自体を初めて知った

ネットワークの構成

1.IPアドレスを設定する
2.ルーターからデータが流れるように設定
3.DNSサーバーを設定

IPアドレスに対応するドメイン名をDNSサーバーに設定するらしい

例えばGoogle
IPアドレス:216.58.220.227
こちらで入力してもアクセスはできるけど
DNSサーバーで対応しているドメイン名として
https://www.google.co.jp/
となる

よくネットワークの接続がうまくいかないときにDNSキャッシュを削除しろ!みたいなのを見かけたけどDNSサーバーで取得してきたこの情報を消していたんですね

AWSの用語とサービス

リージョン

リージョン(Region)
Regionと書かれるとわかりやすい
データセンターの地域
日本で公開するなら東京リージョンがあるのでそちらを使用

Amazon VPC

IPアドレスの範囲を指定して、その中でのネットワークの構築ができる
この辺の設定はすごいインフラっぽい

Amazon EC2

Elastic Compute Cloud
仮想サーバー
LinuxとかWindows Sevrerなんかをこれで扱う
AWSっていうとイメージするのがこれな感じ

DjangoでミリオンライブキャラクターDB一応終了

今回作成物
GitHub - lilly-seventail/milliondb: 簡易ミリオンDB

終わり?

終わりです。
後は徐々に修正とアイドル達を増やしていきます。
Herokuあたりにでもデプロイはしようかとは思っています。
Model周りと個別ページの表示の仕方は修正します。
その他は気が向いたらです。

作成してみた感想

ほぼほぼDjangGirlsでやった内容で作れたんじゃないかなと
filterでの検索やImageFieldの扱いは調べながらになりましたがうまくいきました。

モデル1つと画面2つとだいぶ小規模になりましたが
自分の手で作るのはアウトプットとしてはやはり最適ですね。
今後も作りたいものがあれば作っていきます。

次やること

Django周りでいえばログイン処理だったりカスタムユーザーの作成なんかを勉強しておきたいです。
後は今回できなかったREST Frameworkを使ったものを作りたいですね。
今回勉強したことはそれなりにフルで使えた感じはするので、
しばらくまたインプットをしつつ、思いついたら何かを作っていきます。

DjangoでミリオンライブキャラクターDBを作成 ~検索処理作成~

現在までの完成形

https://i.gyazo.com/8ff55ceb5bc1e37f1249f487b0408c31.png

検索処理の説明

検索用のフォーム
from django import forms
from .models import Idol

class IdolForm(forms.Form):
    name = forms.CharField(label="名前")  //1

今回の検索フォームは名前での検索だけなので名前用のフィールドを作ってあげています。
ChoiceFieldとか使うと選択とかもできたり色々検索処理も色々と弄るのも楽しそう

検索用のView
def index(request):
    if request.method == 'GET': 
        form = IdolForm()
        idols = Idol.objects.all()
    elif request.method == 'POST': 
        form = IdolForm(request.POST) //1
        name = request.POST['name'] //2
        idols = Idol.objects.all().filter(name__contains=name) //3
    return render(request, 'mysite/index.html', {'idols' : idols, 'form' : form } )

1.検索用のフォームです。
ここでformにわざわざ指定しているのは、POST時の値を検索処理後に格納するためです。
IdolFormをGETとPOSTまとめて記述しておくと初期化されてしまいます。

2. request.POST['フィールド名']で該当のフィールドの値が取得できます。
名前に入れられた値をここに格納しておきます。

3.filter(name__contains=name)はフィルター機能を使っています
初めに検索処理を行うフィールド名のnameを指定して__(アンダーバー二個)をつけて
フィルターとして実行する処理を書いていきます。
今回は入力された名前に部分一致しているものを抽出したいのでcontainsを使用しています。
nameは漢字だけの検索になるので読み仮名でも検索したいとなった場合は
from django.db.models import Q
filter(Q(name__contains=name) | Q(yomigana__contains=name))
でいけます。

こちらのサイト様が参考になります。
thinkami.hatenablog.com

次やること

とりあえずあとは徐々に修正しつつでいいかなーと思っています。
APIJSON形式にしてViewModelを~とも思っていたのですが
結局やらずに作成してしまいました。
Ajax周りの処理とかも勉強しておきたいとは思っているのですが。

とりあえず今回はこれで完了ということで次また何か作ります。

DjangoでミリオンライブキャラクターDBを作成 ~メインページ初期表示の作成~

現在までの完成形

https://i.gyazo.com/fd1f311c1e4690d051d64529b00a8b7c.png

メインページのViewの説明

def index(request):
    idols = Idol.objects.all() //1
    return render(request, 'mysite/index.html', {'idols' : idols} )

1. 現状は初期表示に全件取得するだけを記述
この後検索処理用にPOSTメソッドと分ける必要があります。

メインページのテンプレートの説明

{% extends 'mysite/base.html' %}

{% block style %}
<style>
.img-over{            <!-- 1 -->
  transition: 0.3s;
}

.img-over:hover{
  transform: scale(2.2);
}
</style>

{% endblock style %}

{% block content %}

<form> <!-- 2 -->
  <label>名前:</label>
  <input type="text" name="name" />
  <button type="submit">検索</button>
</form>

<div class="col-md-12">
  {% for idol in idols %}
  <div class="col-md-1">
    <a href="{% url 'mysite:detail' pk=idol.pk %}"><img src="{{ idol.image.url }}" class="img-responsive img-circle img-over"/></a> <!-- 3 -->
  </div>
  {% endfor %}
</div>

{% endblock content %}

1.画像の背景が白なのでマウスオーバーしたときにわかりにくすぎたのでCSSでマウスオーバー用に書いています。
マウスオーバーしたときに画像が拡大されて表示されるようになっています。

2.今回は初期表示だけなので検索はべた書きしています。
実際は検索処理用にDjangoのforms.pyを利用していくことになると思います。

3.今回urlを渡すのに mysite:detailを利用しています。
最初のmysiteは
プロジェクトの方のurls.pyのnamespaceで指定したものです。
最初この指定してある値を間違えてて無駄に時間を取ってしまいました。

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^', include('mysite.urls', namespace='mysite')), 
] 

こうして書いておくことでどのアプリケーションのどのViewを渡しているのかわかりやすくなっていいですね。

次やること

検索フォームの実装に入ります。