Sphereとともに

scalaとかplayframeworkとか。技術ブログにしたいなと。環境は Windows7x64, mac です。たまに声優さん情報が混ざります。最近ちょっとClojure触りました。

Kindleはとても良い

今まで電子書籍って紙と違って読みにくいから、と勝手に苦手意識を持っていたが Kindle を購入してその考え方が変わった

Kindle paper white は非常に読みやすい。流石よく考えられて作られている。

また、荷物量が減るのはとても大きい

SRE本のような本を持ち歩くのではなく、Kindleを持ち歩くだけで良くなったのはかなりでかい

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

Kindle Paperwhite 32GB、マンガモデル、Wi-Fi 、ブラック

Kindle Paperwhite 32GB、マンガモデル、Wi-Fi 、ブラック

Akka with SQS

Akka stream

playframework上で動かすので特にインストールは要らない。(play2.5)

library

developer.lightbend.com

elasticMQ

Kitematicを利用してElasticMqをdocker上に立ち上げておく。

設定を変更してport番号9324で立ち上がるようにしておくと吉。

aws cli

pip install awscli でインストールしておく。

AWS コマンドラインインターフェイス | AWS

aws configure で適当に値を設定しておく。

キューを作成する

$ aws sqs create-queue --queue-name test --endpoint-url http://localhost:9324
{
    "QueueUrl": "http://localhost:9324/queue/test"
}

メッセージを作成する

aws sqs send-message --queue-url http://localhost:9324/queue/test --message-body "Information about the largest city in Any Region." --endpoint-url http://localhost:9324

参考

qiita.com developer.lightbend.com

Angular + firebase with playframework(scala)

Angular

app.component.ts

import { Component, OnInit } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule, AngularFireAuth } from 'angularfire2/auth';
import { AuthService } from './auth.service'

import * as firebase from 'firebase/app';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    user: Observable<firebase.User>;
    constructor(public afAuth: AngularFireAuth, public authService: AuthService) {
      this.user = afAuth.authState;
    }
    login() {
      this.afAuth.auth.signInWithPopup(new firebase.auth.TwitterAuthProvider());
    }
    logout() {
      this.afAuth.auth.signOut();
    }
    auth() {
      firebase.auth().currentUser.getToken().then(token => this.authService.auth(token).subscribe(
        s => console.log(s),
        e => console.log(e)
      ))
    }
}

auth.service.ts

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions, Jsonp } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import * as firebase from 'firebase/app';


@Injectable()
export class AuthService {
  private authUrl = '/api/auth';

  constructor(private http: Http, private jsonp: Jsonp) { }

  auth(token: any): Observable<any> {
    let headers = new Headers({ 'Content-Type': 'application/json' });
    // "Access-Control-Allow-Origin", "*"
    let options = new RequestOptions({ headers: headers });

    let data = {token: token};

    return this.http.post(this.authUrl, JSON.stringify(data), options)
                    .map(this.extractData)
                    .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body.data || { };
  }

  private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

playframework

package modules

import java.io.FileInputStream
import javax.inject.Singleton

import com.google.firebase.{FirebaseApp, FirebaseOptions}
import com.google.inject.AbstractModule

import collection.JavaConverters._

/**
  * Created by fscoward on 2017/05/28.
  */
class FirebaseModule extends AbstractModule {
  def configure() = {
    bind(classOf[Firebase])
      .asEagerSingleton
  }
}

@Singleton
class Firebase {
  lazy val options = new FirebaseOptions.Builder()
    .setServiceAccount(new FileInputStream("秘密のjsonファイル名"))
    .setDatabaseUrl("https://<プロジェクト名>.firebaseio.com/")
    .build()

  FirebaseApp.getApps.asScala.toList match {
    case Nil => FirebaseApp.initializeApp(options)
    case list => println(list.mkString)
  }
}

AuthController

package controllers

import javax.inject.Inject
import javax.inject.Singleton

import com.google.firebase.auth.{FirebaseAuth, FirebaseToken}
import com.google.firebase.tasks._
import play.api.mvc.{Action, Controller}

/**
  * Created by fscoward on 2017/05/25.
  */
@Singleton
class AuthController @Inject()() extends Controller {
  def auth = Action(parse.json) { implicit req =>
    val firebaseAuth = FirebaseAuth.getInstance()
    val task: Task[FirebaseToken] = firebaseAuth.verifyIdToken((req.body \ "token").as[String])
    val result = Tasks.await(task)
    Ok(result.getUid)
  }
}

Scalaスケーラブルプログラミング第3版

Scalaスケーラブルプログラミング第3版

ng-cli & angular4 & firebase でtwitter連携

ほぼ↓にあるとおりにやればいいんだけど、ちょっと変えないと動かなかったのでメモ

github.com

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { AngularFireModule } from 'angularfire2';
import { environment } from '../environments/environment';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireDatabaseModule, // imports firebase/database, only needed for database features
    AngularFireAuthModule, // imports firebase/auth, only needed for auth features
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule, AngularFireAuth } from 'angularfire2/auth';

import * as firebase from 'firebase/app';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    user: Observable<firebase.User>;
    constructor(public afAuth: AngularFireAuth) {
      this.user = afAuth.authState;
    }
    login() {
      this.afAuth.auth.signInWithPopup(new firebase.auth.TwitterAuthProvider());
    }
    logout() {
      this.afAuth.auth.signOut();
    }
}

app.component.html

<button (click)="login()">Login</button>
<button (click)="logout()">Logout</button>

{{ (user | async)?.displayName }}

{{ (user | async)?.displayName }} のところは Async pipe というものを利用していて、?は値があればdisplayNameを呼び出し、なければ呼ばないという感じ

イヤーカフのambieを買ってみた

ちょっと仕事中集中して作業したいけど、完全に耳を塞いでしまうといろいろと厄介なのでどうしようかと思ってたときに知ったのが ambie

ambie.co.jp

他の人のレビューを見ると低音が残念とか書かれてたりするけど、それは事実

でいくつか曲を聞いてみたけど、ジャズが非常に良い

ピアノ曲も良い

落ち着いて作業用BGMとして流しておくことだけを考えれば最高のアイテムだと思う

集中して音楽を楽しみたいのなら別のイヤホン使うし、仕事中のBGM用に割り切って持つなら全然ありです

チームビルディング?マネジメント?よくわからない

チームで働くということ

助け合い

  • 全員で一つのEpic、Storyに取り組むスタンスで行きたい

今まではEpicやStoryがあったとしても誰か一人が主担当になって動いていてどうしてもチームという感覚が薄かった 今後はチーム全員で一つのEpic、Storyに取り組むスタンスで行きたい 保守チケットは暇な時にやる

私が死んでも代わりはいるもの

https://pbs.twimg.com/media/CqEgVtDUkAQEM9t.jpg

全員が全員の代わりになれるようにする

  • 仕様を全員で共有する

新しい案件に取り組むときには内容をチーム全員に共有する できればチーム全員で案件について考える時間を取りたい 設計は二人で進める(サーバーサイドとフロントエンド一人ずつ) 設計が完了した時点でチーム全員に共有する 実装は全員で進める

  • 技術を全員で共有する

サーバーサイドのエンジニアは時間がかかってもいいからフロントエンドのコードを書けるようにしたい 同じくフロントエンドのエンジニアは時間がかかってもいいからサーバーサイドのコードを書けるようにしたい まずは読めるようになることからでいい

へーきへーき!フレンズによって得意なこと違うから!

http://nizidara.com/wp-content/uploads/2017/02/106-16.jpg

それぞれが得意な分野を伸ばして、苦手な分野は他の人で補い合えばいい それがチームで働くということ

無理はしない

頑張れる人が頑張ればよい

休みたい

一人で案件を抱えてたら休めない 全員で携わっていれば代わり代わりに休める

すべてを知っていたい

知らないことは怖いこと もし自分しかいなくなったときにわかりませんじゃ怖い ドキュメントに残すのも一つの手だが、普段からみんなで知識を共有することが一番コストが低い

最高のチームを作りたい

チームで働いているという感覚を持ちたい

責任の所在が曖昧にならないように

一人ひとりが責任を持って仕事をする 責任を取れと言うことではない 失敗は自分の責任だと思って反省する必要がある 他人のせいにするなということ

チームとして何を重視するか

生産性

そもそも生産性とは何であって何でないのか。

生産性とは 売上/コスト である。

つまり生産性を上げるには売上を上げるか、コストを下げるかの二択。

  • エンジニアとして売上を上げるには機能を早くリリースして営業が売りやすくする。
  • エンジニアとしてコストを下げるには機能を早くリリースして1機能のリリースまでにかける時間を減らすこと。

— 売上を上げる コードを綺麗にしておきたいが、どんなにコードが綺麗でも価値を生み出さないプロダクト(サービス)は意味がない。 とにかく機能を早くリリースするにはそれぞれが強みを活かしてそれぞれを補って動く必要がある。 まずは多少汚いコードだとしても良い。 もちろんリファクタリングの時間を取れるようにする必要はあるが、赤字垂れ流してるのにコードを綺麗にすることに熱心になってリリース遅くしてどうするの? 現実を見て!営業側にどれだけの負担をかけているのかを理解して! 自分が営業だったらどうする?「コードが綺麗なんです!」なんて営業トークしてお客さんがお金を払ってくれるの?コードが綺麗かどうかなんてどうでも良いでしょ?動くものがほしいでしょ?

— コストを下げる コードを綺麗に保つことがコストを下げることに貢献するなら、コードを綺麗に保つための施策を打てば良い。不具合を減らすことが出来て、営業の負担を減らすことができるならそうすれば良い。

コードが複雑すぎてコストが跳ね上がっているならそのためにどう動くべきかを考える。

新しい技術やアーキテクチャがあって、自分がいいと思ってやってみたいと思ったら、まずはチームに広めればいい。 チームメンバーがそれに共感しないなら、うまく伝わっていないか価値がないかのどちらか。 一人で進めるのは辛いが、それがコストを下げるために価値があると数人が感じたならそのメンバーで推進すれば良い。

— 機能を早くリリースする

機能を早くリリースする一番の近道は作らないこと。作るものを減らすこと。

— ユーザーストーリーマッピング p.14 より引用 アウトプットを最小限に抑え、最大限の成果とインパクトを獲得しよう

— ユーザーストーリーマッピング p.16 より引用 あなたがしなければならないことは、より早くより多くのソフトウェアを作ることではない。 作ると決めたものから最大限の効果とインパクトを生み出すことだ。

生産性とは個人で測るものではない。測れるものではない。

自分で作って自分で売ってるわけではない。 必ず誰かと一緒にやっている。

我々の仕事は何か

— ユーザーストーリーマッピング p.9 より引用 あなたの仕事は世界を変えることだ (中略) 製品に転化されたすばらしいアイデアは、それを使う人々からすれば、世界を少し、あるいは少なからず変えるものなのである。実際にそうなっていないなら、あなたの取り組みは失敗だ。

なぜ振り返りが必要なのか

  • チームの改善
  • 生産性を上げるために動けているかの確認の場
  • 「どんな意識で仕事に取り組んでいるか」「どうすれば効率的に仕事ができるか」といった仕事の進め方について話し合う場の提供

チーム内ペアプロ

フロントエンドの人材が足りないのが、圧倒的にボトルネックになっている。 フロントとサーバーのペアでやってみたい

エピックのススメ方

http://qiita.com/Koki_jp/items/6aebc73bedd0a932dcb8 バックボーン(ストーリーの骨格) - PM ↓ ナラティブフロー(物語の流れ) - チームリーダー ↓ ユーザーストーリーの詳細出し - チーム全員 ↓ 詳細設計 - チーム全員(作業分担) ↓ 実装 - チーム全員(作業分担) ↓ テスト - チーム全員(作業分担)

マネジメントしようとしてはいけない?

  • (悩み中
  • リーダーの仕事は露払い?
    • 仕事がしやすいように環境を整えること?