DDD本の1章~5章までで気になったところまとめ

DDD本の1章から5章までで気になったところの個人的まとめです.

www.shoeisha.co.jp

2章

ユビキタス言語

とにかく用語などを使うのではなく,そのチームでの定義を設けその言語を使えということ. 一つのチームに一つのユビキタス言語を使用することが理想であると書かれていた

4章

レイヤードアーキテクチャ(LAYERED ARCHITECTURE)

  1. ユーザインタフェース層,プレゼンテーション層
  2. アプリケーション層
  3. ドメイン
  4. インフラストラクチャ層

以上の4つのレイヤーからなるアーキテクチャである.1.が一番上のレイヤーで4.が一番下のレイヤーである.

ユーザインタフェース層は表示周りの処理,アプリケーション層は上と下をつなぐインターフェース的な役割,ドメイン層はロジック周りの処理,インフラストラクチャ層はデータの永続化などドメイン層を支える処理を行う.

このアーキテクチャの特徴は,複雑なコードをレイヤーで分割し,それによって各レイヤーごとの責務に集中するだけでよくなる点である. 各レイヤーが下のレイヤーにのみ依存し,上のレイヤーとは疎結合な関係を保つことを容易に実行できる.

5章

エンティティと値オブジェクト

エンティティは,各エンティティに識別番号などを持たせオブジェクトごとの同一性を判断する. 例として,座席が挙げられていた. 座席はどれも同じものであるが,座席番号がついており座席ごとで区別することができる.

それに対して値オブジェクトは,同一性を判断しないオブジェクトである. この値オブジェクトの中にはエンティティなども含まれており,その場合は値オブジェクトの中のエンティティで同一性を判断することになる.

サービス

エンティティや値オブジェクトを触るインターフェースとして提供されているのが,サービスである. サービスを設けることにより,ロジック部分とエンティティや値オブジェクト部分を明確に分離できる. サービスは単にエンティティや値オブジェクトをつなぐだけなので,ステートレスである必要がある.

モジュール

ドメインロジックなどを他のコードと切り離すときなど利用する場面が多いらしい

感想

まだ序章

dartでjson配列のparse方法

個人的に残しておきたかったので,置いときます.

import 'dart:convert';

// 今回はUser型を定義しました
class User {
  final String name;
  final String hobby;

  User(this.name, this.hobby);

  // map to User
  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        hobby = json['hobby'];

  // map to json
  Map<String, dynamic> toJson() =>
    {
      'name': name,
      'hobby': hobby,
    };
}

void main() {
  // 対象json文字列
  final String json = """[{"name":"mituba", "hobby":"anime"}, {"name":"mit", "hobby":"ani"}]""";

  // string to List<User>
  List<Map<String, String>> jsonArray = JSON.decode(json);
  List<User> userList = jsonArray.map((i) => new User.fromJson(i)).toList();

  userList.forEach((i) => print(i.name + ':' + i.hobby));
  // ---output---- 
  // mituba:anime
  // mit:ani

  print(JSON.encode(userList));
  // ---output---- 
  // [{"name":"mituba","hobby":"anime"},{"name":"mit","hobby":"ani"}]
}

感想

非常に楽

python3でfirebaseのRealtime Databaseを使う

python3からfirebaseのRealtime Databaseにアクセスする方法なんかをまとめました.

install

pythonでfirebaseを利用するには,firebase-adminというものがいるのでそれを入れます. installは以下のコマンドで

sudo pip3 install firebase-admin

下準備

まずfirebaseで新規プロジェクトを作成してください. 作成したプロジェクトに入ると,こんな画面が出てくると思います.


f:id:MitubaEX:20180211150846p:plain
プロジェクト画面


まずはProject Overviewと書かれた文字の右側の歯車をクリックして設定画面へ行ってください. こんな画面になると思います.


f:id:MitubaEX:20180211151030p:plain
設定画面


そしてサービスアカウントに行って,一番下の新しい秘密鍵の生成で秘密鍵jsonを入手してください. 秘密鍵pythonコードと同じディレクトに配置してください.

次に左のメニューからDatabaseを選択します.

そうすると以下のような画面が出てくると思います.


f:id:MitubaEX:20180211151301p:plain
データベース画面


ルールを開いて,ルールを以下のように変更します.

{
  "rules": {
    "public_resource": {
      ".read": true,
      ".write": true
    },
    "some_resource": {
      ".read": "auth.uid === 'my-service-worker'",
      ".write": false
    },
    "another_resource": {
      ".read": "auth.uid === 'my-service-worker'",
      ".write": "auth.uid === 'my-service-worker'"
    }
  }
}

これで下準備は完了です.

アクセスする

pythonコードは以下のような感じです.

import firebase_admin
from firebase_admin import credentials
from firebase_admin import db

cred = credentials.Certificate('./<your service account json>')

firebase_admin.initialize_app(cred, {
    'databaseURL': 'https://<your database url>',
    'databaseAuthVariableOverride': {
        'uid': 'my-service-worker'
    }
})

ref = db.reference('/another_resource')

## add data to database
users_ref = ref.child('users')

users_ref.set({
    'alanisawesome': {
        'date_of_birth': 'June 23, 1912',
        'full_name': 'Alan Turing'
        },
    'gracehop': {
        'date_of_birth': 'December 9, 1906',
        'full_name': 'Grace Hopper'
        }
    })

# insert
users_ref.child('mituba').set({
    'date_of_birth': 'Aug 23, 1994',
    'full_name': 'Mituba Mituba'
    })

## get data
print(ref.get())

以上でアクセスできたと思います.

感想

Androidアプリ設計パターン入門を読んだ

この本を読みました.Androidアーキテクチャ周りの知識があまりなくても読みやすく,凄くためになる本でした.

peaks.cc

構成

本の構成は以下の三部構成になっていました.

  1. アプリの設計を知る
  2. 生きた設計を見る
  3. 設計を考える

以下で少し学んだ内容をまとめていきたいと思います.(もしかしたら間違った解釈をしている可能性があります)

1. アプリの設計を知る

MVVMパターン

MVVMパターンの概略図を図1に示します.

流れをざっくり文字化すると,

  • Viewで何かしらactionがあったら,ViewModelを呼ぶ
  • ViewModelはactionに対応した処理をModelに対して行う
  • Modelは処理を実行した後,ViewModelに結果を返すか通知を返す
  • ViewModelはその結果を受け取り,自身の状態を変更する
  • Viewの状態はViewModelとbindされており,ViewModelが変更されるとViewも変更される


f:id:MitubaEX:20180209191852p:plain
図1 MVVMパターンの概略図


このアーキテクチャの特徴はViewModelからViewへの参照が無い点です.これによりView部分とLogic部分を切り離せています.

しかし参照がないことで苦しむ面もあります.本で取り上げられていた事例として,Snackbarの例がありました.前提として,ViewModelはViewの参照を持っていません.なのでViewModelからViewに対して,処理の完了通知を表示する処理を実行できません.そこで本では,Viewにcallbackを登録しておきViewModelの値が変わったら,ViewにSnackbarを出力するようにしていました.

なるほど.

MVPパターン

MVPパターンの概略図を図2に示します.


f:id:MitubaEX:20180209200202p:plain
図2 MVPパターンの概略図


図2からわかるように,ViewとPresenterに参照があります.実際にはContractというインターフェースが,間にありますが省略しています.MVPはあんまり印象に残ってないのですが,PresenterがViewを触れるので,直接データをViewに送れます.

申し訳ない.

2. 生きた設計を見る

ここでは,どういったプロジェクトでアーキテクチャを使ったかなどの興味深い話が載っていました. 勉強になったこととしては,

Fluxは少し知っているつもりでしたが,改めて勉強になりました.

是非読んでみてください.

3. 設計を考える

Androidのライブラリが紹介されていました.

詳しくは本で

感想

MVVM,MVPを少し知ることができて嬉しかったです.Rxの理解がなかなか足りなくて,今後勉強しないとなぁとか思いました.

ABC007 幅優先探索

備忘録です.

問題

入力例

7 8 <- 縦, 横
2 2 <- start_y, start_x
4 5 <- goal_y, goal_x
########
#......#
#.######
#..#...#
#..##..#
##.....#
########

コード

言語はPython3.6です.

# Pair
class Pair:
    x = 0
    y = 0
    def __init__(self, x, y):
        self.x = x
        self.y = y

import sys
import queue
sys.setrecursionlimit(10000)

# define
dx = [1, 0, -1, 0]
dy = [0, 1, 0, -1]
input_map = []

# input
height, width = map(int, input().split())
start_y, start_x = map(int, input().split())
goal_y, goal_x = map(int, input().split())
sy = start_y - 1
sx = start_x - 1
gy = goal_y - 1
gx = goal_x - 1

for i in range(height):
    input_map.append(list(input()))

# bfs
def bfs():
    que = queue.Queue()
    INF = sys.maxsize
    d = [[INF for i in range(width)] for l in range(height)] # width x heightの配列を作って,INFで埋める
    que.put(Pair(sx, sy))
    d[sy][sx] = 0 # スタートを0に

    while not que.empty():
        p = que.get()

        # ゴールに到達した場合
        if p.x == gx and p.y == gy:
            break

        for i in range(4):
            nx = p.x + dx[i]
            ny = p.y + dy[i]
            if 0 <= nx and nx < width and 0 <= ny and ny < height and input_map[ny][nx] != '#' and d[ny][nx] == INF:
                que.put(Pair(nx, ny))
                d[ny][nx] = d[p.y][p.x] + 1
    return d[gy][gx]

print(bfs())

感想

置いておきます.

LINE BotのとりあえずHello Worldまでしてみた

LINE BotのとりあえずHello Worldまで

LINE Developer Meetup in Kyoto#26に参加して,botを作りたくなったのでとりあえずHelloWorldしてみた.

アカウント作成

以下のサイトでLINE@アカウントを作成します.作成するアカウントの種類は,一般アカウントを選択しました.

アカウントが作成できたら,下のような画面になると思います.

f:id:MitubaEX:20180130015330p:plain

Messaging API設定

以下の流れでAPI設定を行います.

  • 左のメニュー -> アカウント設定 -> Messaging API設定 を選択する.
  • リクエスト設定のWebhook送信を利用するにチェックを入れる
  • LINE Developersで設定するを選択する.

そうすると以下のような画面になると思います.

f:id:MitubaEX:20180130015410p:plain

アクセストークンの発行

以下の流れで必要な情報を取得していきます.

  • アクセストークンという項目があるので,そこでアクセストークンを発行する.時間を聞かれると思いますが適当で.
  • Channel Secretという項目があるので,その値をメモっておく.

サーバコードの記述

以下のSDKを利用し,サンプルコードもここに書かれているものを利用しました.

line-bot-sdk-python

実行方法はREADME.mdを参照してください.

ngrokの使用

サーバを起動するだけではLINEとの通信ができないので,今回はngrokでローカルのサーバにアクセスする形を取りました.

インストール

brew cask install ngrok

起動

pythonでサーバを立てている状態で以下のコマンドを実行します.

ngrok http <port番号>

後はLINEで自分の作ったbotにメッセージをオウム返ししてくれます.

不明点

接続確認を押した場合,replyTokenが0の羅列になっており不正だと起こられる問題がよくわからなかったができた.

感想

これから機能を追加していきたいと思います.

neovimをインストールしてdein, deniteの導入まで

環境

mac os 10.13.2

python3のインストール

# install
brew install python3

# PATH_setting (bashやらzshの設定ファイルに記述してください)
export PYTHONPATH=python3:pip3

neovimのインストール

pip3 install neovim

deinのインストール

# get installer.sh
curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > ./installer.sh

# run installer.sh
sh ./installer.sh ~/.cache/dein/. ; rm ./installer.sh

以下のようなことを~/.config/nvim/init.vimに書きます

"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=~/.cache/dein/repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('~/.cache/dein')
  call dein#begin('~/.cache/dein')

  " Let dein manage dein
  " Required:
  call dein#add('~/.cache/dein/repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here:
  call dein#add('Shougo/neosnippet.vim')
  call dein#add('Shougo/neosnippet-snippets')
  call dein#load_toml('~/dein.toml')
  if !has('nvim')
    call dein#add('roxma/nvim-yarp')
        call dein#add('roxma/vim-hug-neovim-rpc')
  endif

  " You can specify revision/branch/tag.
  call dein#add('Shougo/deol.nvim', { 'rev': 'a1b5108fd' })

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
"if dein#check_install()
"  call dein#install()
"endif

"End dein Scripts-------------------------

package管理用dein.tomlを~/直下に置いています dein.tomlは以下のような感じです.

[[plugins]]
repo = 'Shougo/dein.vim'

deniteのインストール

dein.tomlに以下のように追加します

[[plugins]]
repo = 'Shougo/denite.nvim'

vimを起動して,:call dein#update()やら:UpdateRemotePluginsを打ってインストールしてあげます

:Denite grepなどと打ってDeniteが起動したら完了です

感想

ぼちぼち楽