B-Teck!

お仕事からゲームまで幅広く

【本】SCRUM BOOT CAMP THE BOOK を読んだ

現在配属されているチームはスクラムで開発を行っていて、入社前は何も知らなかった自分も数ヶ月過ごすうちになんとなくでこなせるようになってきたと思う。
反面、それらのイベントに込められた意味や意義、メリットなどをちゃんとは理解していないのでは?と不安になったので本書を手にとってみた。

初めてスクラム開発を実践するチームが問題を解決しながらプロダクトのリリースまで進む、わかりやすいストーリー仕立ての漫画で解説されている。
チームが直面する課題や疑問、それに対してどう解決するべきなのかみたいな部分を自分の体験に当てはめながら読むことも出来て理解が深まった。

個人的に印象的だったのは、チームは約束を達成するために最大限努力するのであり、無理をして終わらせることには重きを置かないという部分。
序盤のベロシティの章で語られていた、「予測を可能にするための実績を積み上げる」という話も含めて、これまであまり意識して来れなかった部分かも。
どうしても割り当てられたタスクは期間内に終わらせなきゃ、と無理をしたり残業をしたりで解決してしまいがちなんだけど、それは継続可能な努力か怪しいし、無理して終わらせることでチームの現状が数字に現れなくなってしまう。
予測できなければチームをカイゼンすることも出来ないし、そもそもそんな余力なんて生まれないかも知れない。
もちろんどうしても間に合わせなければならないタイミングは存在するけど、頑張って終わらせるは最後の手段として考えるのがいいんだろうなぁ。

漫画部分があることもあってかページ数の割に気軽に読めてよかった。

【雑記】経歴振り返り

社会人になってからを振り返るメモを書いてたのでせっかくだから公開しておく。

ざっくり振り返り

高校時代

  • ひぐらしなどの当時のノベルゲーに感化されてNScripterに手を出すも作品としては未完
  • 開発に興味をもつ

大学

  • 情報系大学入学
  • ゲーム開発サークルに入るも前期で退部
    • ネトゲとバイトばかりしてた
  • 業務で直接使うことはないけどなんやかんやで学んだことは参考になってる気がする

1社目(2013-2017)

  • ほぼ未経験の状態から4年半ほど客先常駐
    • 保険・共済・金融の会社
    • ガチの素人のまま現場入りしたのでめちゃくちゃ迷惑かけたと思う
  • PHPでMVCのWebサービス書いてアーキテクチャの存在を知る
  • VBAとレガシーなJavaをたくさん書く
  • BPなのに設計からテストまで幅広くやらせてもらった
  • 納期が厳しい案件が結構あってたくさん泊まった

2社目(2018-2021)

  • サービス開発がしたくてtoCサービスやってる会社に転職
  • Java8を初めて触る
    • 入社半年でKotlin書きたくなってServer Side Kotlin導入する
  • 主にいくつかのサービスでひとりサーバーサイドとして色々する
    • サービスのフルリプレイスや部分的な作り直しをいっぱいやる
    • たまに人と一緒に開発できるとめちゃくちゃ嬉しかった
  • Java/Kotlin/Groovy/Go/Python/TSといろんな言語のプロダクト触らせてもらう
    • TSは数行直したくらい
  • 作り直し案件が多かったので設計に興味が出る
  • Kotlin触ってアンチ副作用になる
  • 社内Slackでミーム扱いされる

3社目(現職)

  • コロナ禍でダメージのあるサービスが主な担当だったこともありキャリア見直し
    • toBのSaaSやってる会社に入社
  • Scalaを初めてさわる
  • ちょっとした手直しでなくちゃんとTSのプロジェクトを触る
  • チームが大きい
  • システムも大きい
  • 今の所一番ホワイト

改めて自分の好き嫌い

好き/得意

  • 新しい知識の学習
  • 要点を把握してまとめること
  • 自由に情報が取れる環境では自走できる

嫌い/苦手

  • 刺激の少ない環境が苦手
  • 意味や意義を感じられないと思うとモチベーションが無になる

おわりに

振り返ると自分にとって良いタイミングで1社目の常駐先、2社目に関われたことが技術者として大きく成長できたきっかけだなぁと思ったり。
新卒の頃は自社でまともな教育を受けられなかったし、大学で業務で使うような開発論みたいなものをやるわけでもないので、何も知らない俺と根気強く向き合ってくれた当時の同僚・上司・プロパーの人たちには今でも頭が上がらない。
かなり無茶をして生き残ったから成長した部分もあるんだけど、もう時代も全然違うなと感じるしロールモデルとして人に勧めるのは厳しそうだった。

【JavaScript/AngularJS】今更AngularJSに入門したメモ

AngularJSをサクッと覚える必要があったので勉強したメモ。
生のJSで扱おうと思うとアロー関数使うとうまく動かない箇所があったので、昔ながらの無名関数で書く。
中で呼び出すスクリプト等は学習時に利用した教材に合わせているため古い。
記事中のコードはここにあります

最小限のアプリケーションの作成

AngularJSの仕組みを使って画面に要素を表示するまで。

<!DOCTYPE html>
<!--  ng-appでsampleAppモジュールを関連付け  -->
<html lang="ja" ng-app="sampleApp">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
    <!--  AngularJSの読み込み  -->
    <script src="//code.angularjs.org/1.5.0/angular.min.js"></script>
    <script src="app.js"></script>
    <!--  bootstrapの読み込み  -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
</head>
<body>
<!--  ng-controllerでsampleControllerを関連付け  -->
<div ng-controller="sampleController">
    <!--  sampleControllerのScopeのmsgを出力  -->
    <h2>{{ msg }}</h2>
</div>
</body>
</html>
// sampleAppモジュールを作成
const sampleApp = angular.module('sampleApp', []);

// sampleAppモジュールにsampleControllerを関連付ける
// AngularJSの機能で$scopeサービスを利用してコントローラーに紐づく変数を定義する
sampleApp.controller('sampleController', ['$scope', function ($scope) {
    $scope.msg = 'Hello, World!';
}]);

ng-modelによる双方向バインディング

操作によって変更された値を即座に画面に反映する双方向バインディングの仕組みがある。
テキストボックスの操作に応じて表示が変化するのを確かめられるサンプル。

<!DOCTYPE html>
<html lang="ja" ng-app="sampleApp">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
    <script src="//code.angularjs.org/1.5.0/angular.min.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
</head>
<body>
<div ng-controller="sampleController">
    <h2>{{ msg }}</h2>
    <!--  ng-modelによるbindingで入力に対応して表示が変わる  -->
    <input type="text" ng-model="msg">
</div>
</body>
</html>

ngRouteを使ったルーティング

AngularJSではURLの#より後ろの文字列をpathとしてルーティングを行うことができる。

<!DOCTYPE html>
<html lang="ja" ng-app="sampleApp">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
    <script src="//code.angularjs.org/1.5.0/angular.min.js"></script>
    <!--  ルーティング用のモジュールを読み込む  -->
    <script src="//code.angularjs.org/1.5.0/angular-route.min.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
</head>
<body>
<!--  ルーティング結果を埋め込む場所をng-viewでマークする  -->
<div ng-view></div>
<!--  切り替えを確認するためにボタンを置く  -->
<a href="#/" class="btn">Sample</a>
<a href="#/sample2" class="btn">Sample2</a>
</body>
</html>
const sampleApp = angular.module('sampleApp', ['ngRoute']);

sampleApp
    .controller('sampleController', ['$scope', function ($scope) {
        $scope.msg = 'Hello, World!';
    }])
    .controller('sampleController2', ['$scope', function ($scope) {
        $scope.msg = 'Hello, NewWorld!';
    }]);


// #/ の場合と、 #/sample2の場合のルーティングを設定する
sampleApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            template: '<h2>{{ msg }}</h2>',
            controller: 'sampleController'
        })
        .when('/sample2', {
            template: '<h2>{{ msg }}</h2>',
            controller: 'sampleController2'
        })
}]);

ルーティング時にpathからパラメータを渡す

ルーティングのpathにパターンを定義して、処理の中で値として利用することができる。
パターンはいくつかあるけど、単純なケースのサンプル。

<!DOCTYPE html>
<html lang="ja" ng-app="sampleApp">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
    <script src="//code.angularjs.org/1.5.0/angular.min.js"></script>
    <script src="//code.angularjs.org/1.5.0/angular-route.min.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
</head>
<body>
<div ng-view></div>
<a href="#/" class="btn">Sample</a>
<a href="#/sample2" class="btn">Sample2</a>
</body>
</html>
const sampleApp = angular.module('sampleApp', ['ngRoute']);

sampleApp.config(['$routeProvider', function ($routeProvider) {
    // #/ の場合と、 #/{何らかの文字列} の場合のルーティングを設定する
    // この定義の場合、#/{何らかの文字列}における何らかの文字列がparamにバインドされてControllerに渡される
    $routeProvider
        .when('/', {
            template: '<h2>{{ msg }}</h2>',
            controller: 'sampleController'
        })
        .when('/:param', {
            template: '<h2>{{ msg }}</h2>',
            controller: 'sampleController'
        })
}]);

// $routeParamsを利用してpathに含まれる文字列(paramに対応するもの)をViewに反映する
// 何も渡されなかったときはデフォルトの文字列を表示する
sampleApp
    .controller('sampleController',['$scope', '$routeParams', function ($scope, $routeParams) {
        $scope.msg = $routeParams.param || 'Hello, World!';
    }]);

templateを別のファイルに切り出す

ルーティングのサンプルでは直接記載したtemplateを別ファイルに切り出せるようにする。

<!--  元々templateの中に書いてたhtmlをここに書く  -->
<h2>{{ msg }}</h2>
const sampleApp = angular.module('sampleApp', ['ngRoute']);

// templateUrlに切り出したhtmlを指定する
sampleApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'template.html',
            controller: 'sampleController'
        })
        .when('/:param', {
            templateUrl: 'template.html',
            controller: 'sampleController'
        })
}]);

sampleApp
    .controller('sampleController',['$scope', '$routeParams', function ($scope, $routeParams) {
        $scope.msg = $routeParams.param || 'Hello, World!';
    }]);

controllerAsを使って$scopeを使わないでcontrollerを書く

ng-controllerの記述を ng-controller="sampleController as main" のように変えたり、$routeProviderの指定をcontollerAs に変えることによって$scopeを利用せず記述することができる。
Angularの考え方に近く、後期に書かれたAngularJSはこちらで書かれていることが多いっぽい。

<!--  $routeProviderで指定したctrlの別名から値を参照する  -->
<h2>{{ ctrl.msg }}</h2>
const sampleApp = angular.module('sampleApp', ['ngRoute']);

sampleApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        // controllerとcontrollerAsを分けて書く場合
        .when('/', {
            templateUrl: 'template.html',
            controller: 'sampleController',
            controllerAs: 'ctrl'
        })
        // templateに埋め込む形で書く場合
        .when('/:param', {
            templateUrl: 'template.html',
            controller: 'sampleController as ctrl'
        })
}]);

sampleApp
    .controller('sampleController',['$routeParams', function ($routeParams) {
        // $scopeじゃなくてthisに値を設定する
        this.msg = $routeParams.param || 'Hello, World!';
    }]);

AngularJSのService

ビジネスロジックをまとめるための仕組み。
AngularJSの仕組みで名称を指定すると自動でDIされる。($scope、$routeProvider、$routeParamsなど)。
$scope以外は基本的にシングルトンなので、コンポーネント間の値の共有に使われたりする。
Serviceは後述の方法で自作してAngularJSから理由することができる。

Serviceを自作する

const sampleApp = angular.module('sampleApp', ['ngRoute']);

sampleApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'template.html',
            controller: 'sampleController',
            controllerAs: 'ctrl'
        })
        .when('/:param', {
            templateUrl: 'template.html',
            controller: 'sampleController as ctrl'
        })
}]);

// Serviceを作成してモジュールに登録する
sampleApp.service('sampleService', function () {
    this.firstName = '太郎';
    this.lastName = '山田';
    this.fullName = () => this.firstName + ' ' + this.lastName;
});

// 登録したServiceをInjectして処理を呼び出す
sampleApp
    .controller('sampleController', ['$routeParams', 'sampleService', function ($routeParams, sampleService) {
        // $scopeじゃなくてthisに値を設定する
        this.msg = ($routeParams.param || 'Hello, World!') + ' ' + sampleService.fullName();
    }]);

AngularJSのDirective

Directiveを自作する

AngularJSの世界におけるDirectiveはコンポーネントのようなもので、独自に定義したtemplateや処理をelementやattributeの形で埋め込めるもの。
今回はelementとして扱う単純な例と、親から子のDirectiveにどのように値を渡すかのサンプルを書く

<!DOCTYPE html>
<html lang="ja" ng-app="sampleApp">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
    <script src="//code.angularjs.org/1.5.0/angular.min.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
</head>
<body>
<div ng-controller="sampleController as ctrl">
    <!--  双方向バインディングでディレクティブに値を渡す  -->
    <sample-directive-a value="ctrl.msg"></sample-directive-a>
    <!--  文字列でディレクティブに値を渡す  -->
    <sample-directive-b value="ctrl.msg"></sample-directive-b>
    <!--  interpolationで渡すとディレクティブに渡る文字列自体が変化するので見た目上双方向バインディングのものと同じになる  -->
    <sample-directive-b value="{{ ctrl.msg }}"></sample-directive-b>
    <!--  ディレクティブに関数を渡す  -->
    <sample-directive-c function="ctrl.upperMsg()"></sample-directive-c>
    <!--  値の変更の確認用  -->
    <input type="text" ng-model="ctrl.msg">
</div>
</body>
</html>
const sampleApp = angular.module('sampleApp', []);

// Directiveに渡す用の値を作るController
sampleApp
    .controller('sampleController', [function () {
        this.msg = 'Hello, World!';
        this.upperMsg = function () {
            return this.msg.toUpperCase();
        }
    }]);

// Directive
sampleApp
    .directive('sampleDirectiveA', () => {
        return {
            restrict: 'E', // elementとしてのみ呼び出せるよう制限
            template: '<h2>{{ value }}</h2>',
            scope: {
                value: '=' // scopeを=にすると親から渡されたその値は双方向バインディング状態になる
            }
        }
    })
    .directive('sampleDirectiveB', () => {
        return {
            restrict: 'E',
            template: '<h2>{{ value }}</h2>',
            scope: {
                value: '@' // scopeを@にすると文字列で渡されたことになる。
            }
        }
    })
    .directive('sampleDirectiveC', () => {
        return {
            restrict: 'E',
            template: '<h2>{{ function() }}</h2>',
            scope: {
                function: '&' // scopeを&にすると関数や配列を渡されたことになる。
            }
        }
    });

参考