2020年3月8日日曜日

[読書感想文]バイリンガルを育てる

バイリンガルを育てる

まとめ

英語教育やバイリンガル教育が専門の湯川笑子博士が自分自身の二人の子供にバイリンガル教育をさせたときの記録集。体験や観察をもとに論文も書いているようであり、詳細な記録は参考になる。

教育内容として大きく目をひかれるのは下記のような事柄

  • 子供には常に英語で話しかける。
  • 幼少期に英語の本の読み聞かせを毎日30分から2時間程度
  • ネイティブなEnglish Speakerと多くの交流があり、自宅にホームステイさせたり等、子供をInternationalな環境においていた。
  • 子供は幼少期に海外で教育させた。
    • 長男。4ヶ月-1歳半と5歳5ヶ月-5歳10ヶ月までハワイ、6歳-8歳ころにスウェーデンの幼稚園、学校に通う
    • 長女は4歳-5歳ころにスウェーデンの保育園に通う

感想

おうちでバイリンガルやおやこえいごなどを読んだときも同じ感想を抱いたが、やはり親(特に母親)の尋常でない献身ぶりが目を引く。毎日2時間も英語の本を読み聞かせるだけでも、尋常でない気力が必要だし、ましてや海外に引っ越して現地の教育を受けさせるなどというのは並々ならぬ覚悟がいるだろう。著者の場合は、自分の研究テーマと同一していることもあり、仕事のキャリアと英語教育のメリットを同一化させられたのも大きな要因であろう。

参考にはなるが、一般的な日本人にとってすぐさま真似できそうな実践はなさそうである。また、結局この本で行ったバイリンガル教育の結果、成人した子どもたちがどのような英語力・日本語力が身についたのかが不明なのも実践の効果を伺い知れる情報がなく残念ではある。



2020年2月29日土曜日

Programming Kubernetes: Developing Cloud-Native Applications

Programming Kubernetes

by Stefan Schimanski, Michael Hausenblas
Released July 2019
Publisher(s): O'Reilly Media, Inc.
ISBN: 9781492047094
Explore a preview version of Programming Kubernetes right now.

O’Reilly members get unlimited access to live online training experiences, plus books, videos, and digital content from 200+ publishers.What the book is for?
The books describes about how to customize kubernetes engine itself. It doesn't describe about how to make an application on kubernetes. Thus it helps to understand how kubernetes controllers and components works.

Programming Kubernetes

Who should read the book?

Anyone who would like to understand controllers and components running under the hood.
Anyone who would like to the architecture of kubernetes.
Anyone who would like to make custom controllers. 
Anyone who aspires to be a kubernetes contributer.
Anyone who would like to know about client-go library. 



Impression

The book is for advanced level kubernetes developers. Before reading the book, it is recommended to have understanding on what kubernetes controllers, API servers and Operators are and how they behave. Some experience of kubernetes application development might be good to understand the book deeply.




2019年12月22日日曜日

Designing Distributed Systems

Designing Distributed Systems

Patterns and Paradigms for Scalable, Reliable Services
By Brendan Burns
Publisher: O'Reilly Media
Release Date: February 2018
Pages: 166

Without established design patterns to guide them, developers have had to build distributed systems from scratch, and most of these systems are very unique indeed. Today, the increasing use of containers has paved the way for core distributed system patterns and reusable containerized components. This practical guide presents a collection of repeatable, generic patterns to help make the development of reliable distributed systems far more approachable and efficient.What the book is for?
The book describes about example of architecture which is assumed to be built on kubernetes. Yaml files for kuberenetes are also included with explanation as well as the codes.

Who should read the book?

Anyone who would like to know design and architecture patterns for kubernetes.


Impression

It's good as a recipe book. Some basic and easy to apply architecture patterns are described with use cases. It should be one to be recommended to every kubernetes application developers.


2019年8月12日月曜日

SCRUM BOOT CAMP THE BOOKを読んでみた

SCRUM BOOT CAMP THE BOOK




スクラムについて一通り学べる。基礎編と実践編の二部構成になっている。
基礎編で用語や概念が説明され、実践編ではそれをどのように適用していけばよいかが説明されている。

座学で得られる限りの情報はこの本で学べるのではなかろうか。

特に実践編ではスクラムを現場にどのように導入していく様子が漫画のストーリで描かれており、イメージが付きやすい。

スクラム導入のための本としては良本。

2019年1月12日土曜日

「エンジニアのためのマネジメントキャリアパス」を読んで管理職について考えてみた


エンジニアのためのマネジメントキャリアパス ―テックリードからCTOまでマネジメントスキル向上ガイド


を読んでみた。

入社されたばかりの被管理者であるSoftware Engineerから始まり、チームを束ねるTech Lead(TL)、管理職や管理職の管理職、そしてVP of Engineering(VPoE)やCTOなどの役職について、期待される役割や課題などを説明している。ざっくりと昨今のTech界隈の役職を俯瞰するのには最適の一冊であろう。

よくまとまってて読みやすい書籍ではある。ただ、ちょっと身も蓋もない言い方になるのだが、会社の役職なんて同じ名前でも役割が違うので、これを読んでどう活用するかは若干難しい。原著は米国の書籍であるので、当然のこととして、日米の文化的・法律的な差異もあるはずである。技術書のように、これを教科書として絶対視しても意味がないので、著者の界隈ではこういう共通認識で回ってるのだろう、といった参考程度に勉強するのが好ましいのであろう。


一点だけ大きく興味をそそられた箇所があった。
5.1節の「ITスキルの維持」の記述のところである。

管理職に転向した後の技術的知識のアップデートに関する主張であり、これ以上コードを書いても技術力が頭打ちになるラインまでは管理職になってもコードを書き続けよう、ということであった。技術力がしっかりと身につくまでは、管理職としても大成できない。そして上級の管理職になってからも何らかの技術的コミットメントを続けるべきだ、と。この意見はとても正しく思える。

私もソフトウェアエンジニアとしてのキャリアの中で、エンジニアから管理職に転向した方を多く知っている。ほとんどの方は、Mangerに転向したのを機にコーディングを行わなくなる。その結果、例えば20世紀にWindowsアプリの開発を行っていた人が、Windowsアプリのパラダイムのままネットの技術を語ったり、クラウド以前のInternet上でWebアプリを開発していた人が、その価値観のまま、クラウドの技術を捉える、といった状況に多く遭遇した。表面的な知識は間違ってないのだが、「それは根本的に考え方が違うんだよなあ」、と突っ込みたくなる状況である。

もちろん、管理職という立場で時間の許す限りキャッチアップは続けているのだろうが、Webの前後、あるいはクラウドの前後、そしてマイクロサービスの前後といったような大きなパラダイムの変換があるときには、業務を前提に深くコードを書いていない限り自分の中の技術的パラダイムはアップデートできない。プライベートな時間で自分しか見ないレベルのコードを書いたとしても、当然のこととして仕事で向き合うのと理解の度合いは違う。業務外でコミットしているオープンソースがあったり、副業としてエンジニアを続けているのでない限り、どの立場になってもコードを書き続けない限りいずれその人の技術的価値観は時代遅れのものになるのだろう。


ただ、言うのは簡単だが、マネージャ業務をしながら開発業務にもコミットし続けるのはとても厳しい。解決策としては、マネージャとエンジニアを数年おきに、すっぱりとJob Changeするくらいしかないかもしれない。米国ではよく(たまに?)あるとは聞くが、少なくとも日本ではあまり聞いたことがない。もしかしたら今後はこのようなJob Rotationが必要とされるかもしれない。


2018年12月16日日曜日

Golangのfake google searchフレームワークをjavaで書いてみた。その2

その1を投稿したあと、某友人から「CompletableFuture使ったらもっとスッキリできるよ」って情報もらった。なので、それ使って書き換えてみた。

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.Supplier;

class FakeSearch implements Supplier<String>{
    String name = null;
    public FakeSearch(String name){
        this.name = name;
    }
    @Override    public String get() {
        try {
            Thread.sleep((new Random().nextInt(10) * 1000));
        }catch (Exception e){

        }
        return name;
    }
}

public class CmpGoChannel2 {
    public static void First(Supplier<String> supplier1,Supplier<String> supplier2) throws Exception{
        CompletableFuture<String> future1 =
                CompletableFuture.supplyAsync(supplier1);
        CompletableFuture<String> future2 =
                CompletableFuture.supplyAsync(supplier2);

        CompletableFuture<Object> future3 = CompletableFuture.anyOf(future1, future2);
        System.out.println(future3.get());
    }

    public static void main(String... args) throws Exception{
        FakeSearch web1 = new FakeSearch("Web1");
        FakeSearch web2 = new FakeSearch("Web2");
        FakeSearch image1 = new FakeSearch("Image1");
        FakeSearch image2 = new FakeSearch("Image2");
        FakeSearch video1 = new FakeSearch("Video1");
        FakeSearch video2 = new FakeSearch("Video2");


        CmpGoChannel2 c = new CmpGoChannel2();
        List<Future<String>> list = new ArrayList<>();

        First(web1,web2);
        First(image1,image2);
        First(video1,video2);

    }

}
while(true)と終了フラグで乗り切ってた汚い部分がだいぶきれいになった。

public static void First(Supplier<String> supplier1,Supplier<String> supplier2) throws Exception{
    CompletableFuture<String> future1 =
            CompletableFuture.supplyAsync(supplier1);
    CompletableFuture<String> future2 =
            CompletableFuture.supplyAsync(supplier2);
    CompletableFuture<Object> future3 = CompletableFuture.anyOf(future1, future2);
    System.out.println(future3.get());
}


行数もざっくり60行程度まで収まった。

2018年12月15日土曜日

Golangのfake google searchフレームワークをjavaで書いてみた。その1

Go concurrency patternsで触れられていたGoogle SearchのFake frameworkのコードが非常にすっきり記載されていて感動したので、これをJavaで書いたらどうなるんだろうと好奇心から書いてみた。

まず、Go言語の方のやつを、書き出してみる。

package main

import (
   "time"   "math/rand"   "fmt")

var (
   Web1 = fakeSearch("web1")
   Image1 = fakeSearch("image1")
   Video1 = fakeSearch("video1")

   Web2 = fakeSearch("web2")
   Image2 = fakeSearch("image2")
   Video2 = fakeSearch("video2")
)

type Result string

type Search func(query string) Result

func fakeSearch(kind string) Search {
   return func(query string) Result {
      time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
      return Result(fmt.Sprintf("%s result for %q\n", kind, query))
   }
}

func First(query string, replicas ...Search) Result {
   c := make(chan Result)
   searchReplica := func(i int) { c <- replicas[i](query) }
   for i := range replicas {
      go searchReplica(i)
   }
   return <-c
}

func Google(query string) (results []Result) {
   c := make(chan Result)
   go func() { c <- First(query, Web1, Web2) } ()
   go func() { c <- First(query, Image1, Image2) } ()
   go func() { c <- First(query, Video1, Video2) } ()
   timeout := time.After(80 * time.Millisecond)
   for i := 0; i < 3; i++ {
      select {
      case result := <-c:
         results = append(results, result)
      case <-timeout:
         fmt.Println("timed out")
         return      }
   }
   return}

func main() {
   rand.Seed(time.Now().UnixNano())
   start := time.Now()
   result := First("golang",
      fakeSearch("replica 1"),
      fakeSearch("replica 2"))
   elapsed := time.Since(start)
   fmt.Println(result)
   fmt.Println(elapsed)
}


コードの解説はスライドに譲るとして、First関数の中での、return <-c の使い方が素晴らしい。

で、これをJavaで書いてみた。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

class Web1 implements Callable<String>{

    public String call() {
        try {
            Thread.sleep(10*1000);
        }catch (Exception e){

        }

        return "Web1";
    }
}


class Web2 implements Callable<String>{

    public String call() {

        return "Web2";
    }
}

class Image1 implements Callable<String>{

    public String call() {
        try {
            Thread.sleep(10*1000);
        }catch (Exception e){

        }

        return "Image1";
    }
}


class Image2 implements Callable<String>{

    public String call() {

        return "Image2";
    }
}

class Video1 implements Callable<String>{

    public String call() {
        try {
            Thread.sleep(10*1000);
        }catch (Exception e){

        }

        return "Video1";
    }
}


class Video2 implements Callable<String>{

    public String call() {

        return "Video2";
    }
}

public class CmpGoChannel {

    public static void First(ExecutorService executor1,Callable<String> callable1, Callable<String> callable2) throws Exception{
        List<Future<String>> list = new ArrayList<>();

        list.add(executor1.submit(callable1));
        list.add(executor1.submit(callable2));

        boolean loopDone = false;
        while(true) {
            for (Future<String> f : list) {
                System.out.print(".");
                if (f.isDone()) {
                    System.out.println(f.get());
                    loopDone = true;
                    break;
                }
            }
            if(loopDone){
                break;
            }
        }
    }

    public static void main(String... args) throws Exception{
        ExecutorService executor1 = Executors.newFixedThreadPool(2);
        ExecutorService executor2 = Executors.newFixedThreadPool(2);
        ExecutorService executor3 = Executors.newFixedThreadPool(2);

        CmpGoChannel c = new CmpGoChannel();
        List<Future<String>> list = new ArrayList<>();

        Callable<String> web1 = new Web1();
        Callable<String> web2 = new Web2();

        First(executor1,web1,web2);

        Callable<String> image1 = new Image1();
        Callable<String> image2 = new Image2();

        First(executor2,image1,image2);

        Callable<String> video1 = new Video1();
        Callable<String> video2 = new Video2();

        First(executor3,video1,video2);


        executor1.shutdown();
        executor2.shutdown();
        executor3.shutdown();
    }
}


まず気づいたのが、Javaにchannelに相当する仕組みがなかったこと。JavaのConcurrencyはそんなに人気のあるものではなかったが、そうは言ってもそれなりに使われている実績はあるので、書こうとしてみて「そういや、なかったな」みたいな気付きがあった。

なので、ここは

while(true) {
    for (Future<String> f : list) {
        System.out.print(".");
        if (f.isDone()) {
            System.out.println(f.get());
            loopDone = true;
            break;
        }
    }
    if(loopDone){
        break;
    }
}

といった感じで while(true)と終了フラグで乗り切るというちょっと汚いコードで対応した。
このあたりですでに、簡素なコードを書けるというGoの魅了が十分に表れている。