2017年は生産性という概念を身に付けたいと思った話
著名ブロガーであるちきりんさんの新著「自分の時間を取り戻そう」という本を読みました。
結論から述べると、年の瀬に読めて良かったと思える本でした。高校生くらいから大学生、会社員、主婦の方、いろんな方に勧めたい本でもありました。 簡単に振り返りたいと思います。
まず、読み進めていくにつれ、頭が痛くなってきました。 というのも、この本が提唱していることに対して、真逆の行為をしていたなあと思うことが多々あったからです。この本では、自分のやりたいこと、人生で手に入れたいことを全て手に入れるにはどうすれば良いのか、といったことを「生産性」という概念を持つことでできるのではないか、ということを提唱していました。
生産性とは、自分の希少な資源(お金や時間など)を使って、手に入れることができること、効果の度合いとして説明がされています。 生産性が高ければ高いほど(より少ない希少資源の投資で大きな成果を得られるようになったら)、人生で得られることも最大化できるよね。という話です。
現代に生きる、ある4人の具体的なケース(できる中堅サラリーマン、子育てと仕事を両立したい女性、フリーランスに転身した人、起業家)をもとに、現代の社会の動き、個人の働き方についても踏まえて、具体的にどうすれば良いのか、述べられています。
本の内容については、これくらいにしておきたいと思います。(実際に読んだほうがはるかに有益なのでぜひ。kindle版もあるのでシュッと買って新年を迎えるのはありかなと思います。)
さて、ここからは個人的な話になります。 人生でやりたいこと。数え切れないほどあります。今やっていること(仕事)もやりたいことの一つであるし、おいしいものを食べたい、夏はサーフィンやダイビング、冬はスノボ、一年を通して映画館に通いたいし、本もたくさん読みたい。世界中を旅して友達を作りたい。これからもたくさんしたいことは増えるだろうし、家族ができるともっと多くなるかもしれない。
2016年を振り返ると、生産性の低い働き方をしていたなあと思うことが多くあることに気づきました。 4月からはほぼ自由に自分の時間があるだけ使って仕事をしていましたが、今振り返るといずれ破綻するだろう働き方でした。お金の使い方も、見直す必要が多々あります。
逆に、生産性という概念と照らし合わせてみて、その意に沿っていることもいくつかありました。 たとえば、数ヶ月前にオフィスに導入したコーヒーのドリップセット一式がそうです。もともと仕事中にほぼ毎日コーヒーを飲んでいて、そのコーヒーは歩いて10分ほどかかるところに買いに行き、オフィスに戻ってくるまでに大体25~30分くらいかけていましたが、ドリップセットがきてからはほぼ買いに行かなくなり、今は5分もかかりません。豆を挽いてドリップする楽しさも兼ねて息抜きできるので、その効果は大きいと思っています。
この本を読むまでは、深く考えていなかったのですが、生産性とはそういうことかなあと実感できました。
今のは一例でしたが、自分の希少資源をもっと有効に使う方法はたくさんあると思うので、2017年は仕事と生活において、生産性を強く意識していこうと思いました。
スタートアップに身を置いて8ヶ月経ったのでその備忘録
この記事は Ex CyberAgent Developers Advent Calendar 2016 - Adventar の 23日目 の記事です。
まずはじめに
Ex CyberAgent Developers Advent Calendar 2016 - Adventar の 6日目 の記事を書いた、劉くんの家族に新しい命が誕生しました。
おめでとう!!幸せな家庭を築いてください
さて、久しぶりのブログということで、どういう口調で書くんだっけ、といったところから考えているst_dskです。
最後に書いたのはいつだろうと思い、とりあえず自分のブログに飛ぶと2015年10月11日とありました。実に1年と2ヶ月ほども書いていなかったようです。
次に、その間に自分の身の回りになにが起こって、今との差分はどれくらいあるのだろうと考えると、ものすごい違いがあるなあと思いましたので、それを自分への備忘録も込めて、今回は綴ってみようと思います。
CyberAgent
2015年10月11日といえば、CyberAgentに入社して半年ほど、takusutaというライブ動画配信アプリのiOSエンジニアとして仕事をしていました。takusutaでは超優秀な先輩方、同期と働けて学ぶべきことが非常に多くありました。
この頃といえば、自分のスキルは本当に微々たるもので(今もですが)、学生の頃からやっていたiOSがちょっとできるくらい、程度のものでした。 スキルの幅も狭く、後の話にも繋がっていきますが、サーバなどの知識もほとんどないぐらいだったので、iOSのスキルを磨きつつ、サーバの勉強もしたりしていました。
その年の11月、友人3人と会社を創業しました。そして、年が明け、新卒1年目が終わりに近づいていた頃、CyberAgentを退職しました。
ちょうど一年でしたが、中々経験できないことを多く経験できて、非常に濃い一年間でした。
CyberAgentに新卒で入って、一番良かったことは、同期の優秀なエンジニアたちと出会えたことです。これは、同じように退職した同期の友達も100%同じことを言っているので、確かなことのような気がします。 この1年間で、今でも月一程度で行われる温泉同好会という行事も、みなEx CyberAgent Developerとなりました。笑
いま
さて、CyberAgentでの思い出もここまでで、ここからは今やっていることについて書きたいと思います。
11月に創業した会社で、「お金の貸し借りをメモするアプリCashD」を開発しています。
4月から本格的に開発を始めました。この頃、エンジニアは自分だけだったので、サーバからiOSまで一人で開発していました。
一応、Developerのアドベントカレンダーなので、技術的なことも書いておくと、Rails、Nginx、MySQLというあるあるな構成でAWS上にDockerコンテナをECSに乗せて構築していました。上述した通り、サーバ、インフラに関する知識はほとんどなく、AWSも触ったことがない状態で始まったので、ほとんどみようみまねで構築していきました。
Railsにしたのは、シュッと作るには手っ取り早かったのと、周りの友達で優秀なRailsエンジニアが多かったので、困ったらすぐに聞けるだろうぐらいの気持ちで選びました。案の定、困ったらSlackに投げると1分で解決したことが多々あり、本当に恵まれている状況で進めることができたのが非常に大きかったです。
iOSに関しては、学生の頃から開発していて慣れていたので、比較的楽に開発できました。
一介のエンジニアとしては、もっと堅牢で、しっかりした環境を構築して開発したかったという気持ちがありましたが、事業を前に進めなけばならない、という観点から目を瞑るところが多々ありました。ここらへんは、リソースが少ないスタートアップという環境での判断、あるいはジレンマなのかなと感じていました。
大きな会社での1エンジニアと、小さな会社でのエンジニアでは、考えることが大きく変わりました。 大きな会社では、自分の技術力を高めつつ、プロダクトの品質に貢献することが最優先であることが多いと思いますが、 小さな会社、特にスタートアップの場合は、そもそもリソースが足りていないので、やるべきことが大幅に増え、それらを学びつつ、速くアウトプットして前に進めることが最優先になります。
(といいつつ、この8ヶ月ほどで失敗したな〜と思うことがいろいろあったので、まだまだだなあと思う次第です。)
また、プロダクトを作る上で、なにか一つ得意な分野があると、スタートアップをするときには助かるなあと思っていました。 自分の場合は、iOSでした。 iOSの開発に関しては、CyberAgentに在籍していた時に伸ばせていたので、助かりました。 (RxSwiftも辞める前に勉強しておいてよかったと思いました。笑)
おかげさまで、2ヶ月後にリリースできました。
その後、現在に至るまで、仲間が二人増え(二人ともエンジニア!)、新しい機能の追加やAndroidアプリのリリース、そしてリリース間近のある重要な機能の実装と、かなり大きく環境が変わってきました。
技術も徐々に変わっていき、今はAPIサーバとしてRailsとGin(Go)の二構成、AWS上にdevelopment, staging、production環境をterraformを使って構築、CIでテストとDockerコンテナのpushとデプロイ、フロントエンド(web)の導入、iOS(swift)、Android(kotlin)両端末の開発といった感じになりました。
周りのいつも手伝ってくれる、優秀なエンジニアたちの賜物です。
これから
さて、先ほどチラっと触れましたが、もうすぐある重要な機能がリリースされます。
(本当は、今日Appleからの審査が降りて、リリースする予定だった。。。泣)
詳細は、リリースしてからまたお伝えしようと思いますが、ただのメモするアプリから大きく飛躍するものだと思っているので、ご期待くださいませ。
興味が沸いたら一度使ってみてください。 ダウンロードはコチラから!
ここ数年、毎年かならず来年は勝負の年だ。と思っていて、今年ももれなくそういう状況なので、引き続き来年も頑張っていきたいと思います。
iOSのプロジェクト内で共通のデザインを簡単に扱いたい
iOSに限った話ではないですが、一つのプロジェクト内で共通して使いたいモノって結構あると思います.
色やフォントなどのデザイン面は、アプリ内で統一するために共通して使うと思うのですが、色やフォントの指定を毎回書くのはめんどくさいですし、まあしたくありません. できるだけ簡単に扱いたいです.
ということでできるだけ簡単にかつ汎用的に扱えるようにUtility的な感じのものを作ってみました. (ライブラリとして使えるような感じにはしておらず、個人的にさくっとコピって使おうと思って書いたものです)
詳細はGithubに上げていますので、そちらをご覧いただきたいですが、一応使い方的なものだけ載せておきます.
アプリ固有の色とフォントの指定は以下のように書きます.
enum Color: String { case Theme01 = "#ff00ff" case Theme02 = "#00ff00" case Twitter = "#00aced" case Facebook = "#305097" case Line = "#5ae628" case Instagram = "#3f729b" case White = "#ffffff" case Black = "#000000" } enum Font: CGFloat { // Size case S = 12.0 case M = 16.0 case L = 20.0 // Style enum Style:String { case Reguler = "HiraKakuProN-W3" case Bold = "HiraKakuProN-W6" } func name(style: Style) -> String { return style.rawValue } }
定義したデザインはDesignという構造体を使って使用できます.
let label1 = UILabel() label1.backgroundColor = Design.color(.Theme01) label1.textColor = Design.color(.White) label1.font = Design.font(.M) let label2 = UILabel() label2.backgroundColor = Design.color(.Twitter) label2.textColor = Design.color(.Black, alpha: 0.8) label2.font = Design.font(.S, style: .Bold)
いろんな方法があると思いますので、これが最良かと言えばまったくそんなことはないと思いますが、現状こんな感じで落ち着きました.
もっと良い方法があれば、是非教えていただきたいです.
徳丸本を読みだした
「安全なWebアプリケーションの作り方」という参考書がある。
通称、徳丸本と呼ばれる。
体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
- 作者: 徳丸浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2011/03/03
- メディア: 大型本
- 購入: 119人 クリック: 4,283回
- この商品を含むブログ (144件) を見る
Webアプリケーションを作る上で必ず必要になってくるセキュリティ対策。脆弱性はどのように生まれるのか、その原理から実例、対策までを丁寧に説明してくれるということで、有名な本である。(IT企業の教科書になるとかならないとか)
を、読みだした。
昨今のWAFを使っていると、セキュリティ関連の便利なライブラリがあったりでなかなかその仕組みを理解せずになんとなく使ってしまっていることはあまりよろしくないんじゃないかと思ったので。
まだほんの少ししか読んでいないけど、実際に脆弱性を突いてみたり、自分で確認できるので面白い。
また読了した時にでも、感想を書きたい。
メモリ領域とインスンタンスの話
アプリケーションコード内の変数やクラスのインスタンスのメモリ確保、実行順序等、ざっくりとしか理解していなかったのですが、こちらの記事を見て、かなりクリアになりました.
・ main関数が実行されると、メインスレッドが作成される.
・ インストラクションコード(自分が書いたコード)が1行目からインストラクションポインタが指す行を順次実行していく.
・ スレッド毎にスタックメモリ領域が確保され、その領域に変数が確保される. データはヒープ領域に確保される.
・ ヒープ領域は複数のスレッド間で共有される.
・ スレッドにはメソッドステート単位でスタックされていき、インストラクションポインタに従って実行され、削除される.
・ メソッドステートでは(ローカル変数の格納領域、インストラクションポインタ、引数、クラス/インスタンス)といった情報が保持されている.
などなど。
まだ完全には理解していませんが、以前よりかなりクリアになってきました.
アプリケーションが複雑になってくると、スレッド間での共有でややこしくなったりするのでこういった知識を抑えておくことは大事かなと思います.
Swiftのプロトコル定義におけるSelfとは
Swiftのプロトコルで良くみるSelf.
これはなんぞやということで、調べてみたところ、簡単に言うとそのプロトコルを適合させた型自身を指すようです. (ちなみにSelfは予約語)
Self自体を型として使うことはできず、そのSelfの部分を、適合させた型で置き換える必要があります。
言い換えれば、プロトコルに適合した型でないと静的にエラーを吐いてくれるので、間違った型を指定することがなくなる、とも言えると思います.
例えば、MonsterTypeというプロトコルを定義し、Pockemonの列挙型に適合させるとします.
protocol MonsterType { //関数の返り値にSelfとする func type() -> Self } enum Pockemon:Int, MonsterType { case ピカチュウ case プリン case ポッポ //プロトコル実装 //この場合、Pockemon型で返す func type() -> Pockemon { return Pockemon(self.rawValue) } }
例としては微妙ですが、、、
MonsterTypeを適合させたPockemonは関数の実装時に、プロトコルの宣言ではSelfであった部分をPockemonに変更しています.
ここがSelfのままだと、エラーでコンパイルできません.
enum Pockemon:Int, MonsterType { case ピカチュウ case プリン case ポッポ //プロトコル実装 func type() -> Self { return Pockemon(self.rawValue) } //=> エラー : Type 'Pockemon' does not conform to protocol 'MonsterType' }
このように、プロトコル内で型を、そのプロトコルを適合させた型で実装したい時にSelfを指定させておくと、安全に便利に実装できそうです.
Swiftの列挙型でループを回す
Swiftの列挙型では、C言語のように整数値を定義するだけでなく、多くのメソッドの定義やプロパティの定義等、多機能です.
また列挙型にプロトコルを適応させることができます.
値型の列挙型で、各メンバをループさせて参照したい場合、提供されているプロトコルを用いることで実現可能であることを知ったのでメモ代わりに以下に示しておきたいと思います.
ForwardIndexTypeプロトコル
デフォルトで提供されているForwardIndexTypeというプロトコルがあります.
/// Represents a discrete value in a series, where a value's /// successor, if any, is reachable by applying the value's /// `successor()` method. protocol ForwardIndexType : _ForwardIndexType { }
継承元を辿っていくと、_incrementableというプロトコルに行き着きます.
/// This protocol is an implementation detail of `ForwardIndexType`; do /// not use it directly. /// /// Its requirements are inherited by `ForwardIndexType` and thus must /// be satisfied by types conforming to that protocol. protocol _Incrementable : Equatable { /// Return the next consecutive value in a discrete sequence of /// `Self` values /// /// Requires: `self` has a well-defined successor. func successor() -> Self }
関数successorは、適合しているインスタンスの次に大きいインスタンスを返す関数です.
このプロトコルで定義されているsuccessor() -> Self
を実装することでループを回せます.
enum Fruits: ForwardIndexType { case Apple, Banana, Grape, Lemon case _dummy //Rangeを合わせるために必要 func successor() -> Fruits { if self == ._dummy { return ._dummy } return Fruits(rawValue: self.rawValue + 1)! } }
上記のようにすると、各メンバをループできます.
for fruit in Fruits.Apple .. .Lemon { print("\(fruit.rawValue)") } // 0,1,2,3
プロトコルは構造体、クラス、列挙型で適合させることが可能なので、非常に強力なものだと感じます.
また、Swift2.0からは、プロトコルに実装を持たせることができるようになるそうなので、より便利に使えそうです.