ひよっこゲームブログ

なにもかも初心者のひよっこがゆったりと何かする

今までと、これからのこと

おかげさまで転職ドラフトで自身の過去最多指名を頂きましたーん

そのうち職務経歴書を書かないといけないので
今まであったこと&思ったこととか整理したいので書き残す

あとは個人的には、転職ドラフトの指名体験記書いてる人って
「学生時代はベンチャーインターンしてて~」とか「OSSコミッターでした~」とか
指名されるの当たり前じゃねーか!みたいな人ばっかだったので
こういった話に需要がないかなーって感じでのんびり書いてきます


おちこぼれの這い上がり経験談です
前半はプログラミング関係ないです



学生時代

高校は全科目ほぼドベ。でも数学はマジで死ぬほど大好きだった
プログラミングの勉強ができたらいいなってなんとか情報系の大学へ進学した

大学でも勉強はからっきしで、とにかく人から教わるのが苦手
今そこにあるものの理論の根っこが気になって仕方がないのですぐに物事を覚えられない
(でもこの考え方がプログラミング的には有用かも)

自分に見合ったやり方じゃないと
勉強ができないということにようやく気が付いたのはつい最近

プログラミングの実力に関しては、情報系大学出身とは言えないレベルだった
研究もお粗末だった。よく卒業させてもらえたな・・・


社会人1年目

めちゃくちゃでっかいメーカー企業
エンジニアで入ったはずがなぜか品質保証部になった

過去にブログで書いたように色々ありすぎた
この経験があったから、身体を壊すような働き方をしないと一生誓った

身体を壊して1年たたずに退職


無職1年目

数ヶ月療養してからはしばらく遊んでた
幸いにもお金を全く使ってなかった上に実家住まいだし貯金はあった

興味があったWebとか(今ではもう役に立たない知識ばかりだけど)触った
あとはラズパイとかで無意味な鯖立てたりした


無職2年目

どうせならやりたかったことをしようとゲーム会社を目指してみる
結論から言うとこの就活には失敗した

Unityで半年ちょっとでゲームを作った
ついったーのもーめんと
"作ったゲームのzipリンク(クリックでダウンロードが始まります)"

このとき一人で開発してた経験がめちゃくちゃ役にたってる
一人でものを1つ完成させることの大事さを知った。完成は正義

コーディングのアンチパターンを踏みまくって開発したので
何をしたらダメなのかを身をもって実感した

溢れかえるグローバル変数
1つのメソッドに大量の処理が書き込まれ
1つのクラスに様々な機能が盛り込まれ
めちゃくちゃな命名規則に始まり
複雑な条件分岐が構成され
〇〇フラグが大量に散在し
次の日には見たくないようなコードが生成された

マジで全部踏みつくした

再就職の活動には失敗し、貯金も底をつき
病院や年金が財布を襲い、どこでもいいから就職しないとって感じで
ひとまず働けるとこをって就活し始めた


再就職

なんか勉強意欲あるし、Javaちょっとやったことあるんでしょ?
って感じでAndroid開発にまわされた

給料は一般の新卒くらい
前職よりちょっとあがったけど賞与ないし見込み残業だったからトントン


入りたての頃

開幕Android担当が3人⇒2人になった
もちろんマニュアルなんてあるわけもなく、仕様も分からず
コードを片っ端から泣きながら読んでった。Javaを復習した


Kotlinに触れ始める

Kotlinがイケてるらしいからに脱Javaしようぜって空気が社内に流れ始めた

ここがエンジニアとしてのターニングポイントな気がする
もちろんKotlinなんて初めて触った
ひとまず本を買って必死に勉強した


プロジェクトが大きくなった

新人がぶわっと入ってきた
何人か抱えることになって、教えなきゃと思ってgitの復習とかした
間違ったことを教えないようにと思って基礎を固めた

コーディングの基礎とか、丁寧に書けるように意識し始めた
この辺で人へ教える技術のノウハウを入手する


技術書をあさり始めた

とにかく新しいことを覚えることが楽しくなり
家で勉強する機会が増えて、この辺でぐーんと実力が伸びた

CoroutineとかJetpackとかその辺をそこそこ使えるようになった
ようやくエンジニアとして働いてますって言えるかなって思い始めた


役職が上がった

給料が変わるわけじゃないけどサブリーダーにランクアップした
上の人がいないときに代替で色々やるようになった
チームビルディングとかの本を読んだ

GitHubの使用許可が下りなかったので
コードレビューをほぼペアプロ状態でやってた


転職を考え始めた

今いる会社ではやれることに限界があるなぁと感じ始めた
自分よりもっと強い人に囲まれて開発がしたい


プロジェクト強制異動

色々あって異動になった。原因は資金まわり
納得がいかなかったので近々の転職を決意する


現在

無理くりしてリモートワークを勝ち取って、ある程度平和に働いてるけど
まだAndroidに未練たらたらなので転職がしたい

あとAndroidが見せてくれる世界をまだまだ楽しみたい
Android11Betaきたし、Kotlinの1.4の正式リリースもそろそろかなぁ

今年で27歳なので、なるべく早めに動きたいなって思ってる
そんなに時間は残されてないのかな・・・


現在使えるもの

基礎的なコーディング技術
Androidライフサイクルへの理解
Kotlinの基礎的な理解
Coroutine
DataBinding
Espresso
UIAutomator
GooglePlayConsole
Git

ぼんやり使えるもの

Androidアプリケーションに必要な機能実装(いつも調べながらやる)
xmlによるレイアウト記述(割と適当に書いてるのでよくない)
LiveData
Room
Retrofit2
MVVMアーキテクチャ
Androidにおけるマテリアルデザイン
スクラム開発

勉強したもの(未実践)

RxJava
CleanArchitecture

今後勉強したいもの

Android Architecture Components(AAC)
CI / CD
Unitテスト
ドメイン駆動開発
テスト駆動開発


つまづいたこととか感じたこととか

自主学習する人は一握りである

「この本とか参考になるから」とか「これ覚えとくといいよ」とか
自分の中では親切にアドバイスをしたつもりなんだけど、特に意味をなさなかった

彼らにとって「プログラミング = 仕事」であり
プライベートで仕事はしたくないと
別にこの思想自体が悪いとは全く思わない(個人の自由だし)

僕もそりゃあプライベートの時間を削って仕事はしたくない
でも新しいものを知ることが好きだからときどき勉強する
もちろん勉強よりゲームやってる方が好き


Androidの環境変化のスピード

とにかく色々なツールが使えなくちゃならない
新しいライブラリやGoogle I/Oで発表されることとか
AndroidのOS Verは1年ごとに上がっていくし

僕はそれが楽しかったんだけど
チームで使えるツールなどはある程度制御していかないと
やたらと便利にしても使えない人が出てきてしまう

あとリファレンス読まないで
個人ブログの古い記事参照にして書いちゃう人とかで事故る

一部機能は担当の人しかメンテできないみたいなことが起きた


設計

スタートとゴールだけ考えてなんとなく作っていくのは明らかに難しい
ソフトウェア設計で使う図とか色々あるけど、なんとなくしか読めない
(そもそも使える人いなかったから書いても意味なかったんだけど)

世間では何がどのくらい使われているんだろう

今は何をどう実装したらいいかなーって紙に書いてから手を動かしてる
流石にこの辺は今後やっておいた方がいいな・・・

アーキテクチャの理解はまだまだ足りないなぁ、実践経験が少ない


世の中で使ってるツールが使えない / 実践できない

わりと重めな悩みのタネ
1人だと実践できなかったりで、解決もできない

GitHubのプルリクとか


日本語を母国語としない人とのコミュニケーション

日本語は難しい。文章もそうだけど、はなし言葉も難しい

単語だけで分節を区切って、日本語だと不自然だけど
短い文章で簡潔にすると伝わりやすかった

敬語も「です、ます」くらいに抑えて
やたらと礼儀正しい文章は使わない方がお互いに楽だった・・・
できればこんどこそ日本人の方が多いところで働きたい(切実)


今後

ひとまず転職したい

転職するする詐欺みたいになってたのは
自分の実力がまだ足りないなぁって思ってたのと
どうせならアプリ1個くらい作りたいなぁって考えてたのがあって
なかなか足が動かずにいた

世の中のAndroidエンジニアは誰しもが個人開発して
アプリのリリースを1回くらいはしてるよなぁ
って思ってたけど、実際に企業の人と話してみたら
「家庭がある人はそもそも時間取れないし、そうでもないよ」って言われた

ちょっと安心した
でもそのうち何かリリースしたいなぁ。ネタはあるので

転職ドラフトでちょこちょこ指名されたりしてるので
今のスキルでも必要としてくれる人はいると信じて

やってみてダメならまた考える

CleanArchitectureの話

記事を書くのに間が空き過ぎてしまった・・・
最近天則に復帰したりVLORANTが楽しかったりで忙しいです
転職したいならその時間を勉強にあてろ


CleanArchitectureの勉強はぶっちゃけ手間取りました
DDDもかじりながらボブおじのブログを読んだので・・・
あと原文をそのまま理解しようとするのは難易度が高い
そもそもCleanArchitecture自体がちょっと難しい・・・(個人差があります)


正直なところ記事にするけど内容の正確性に自信がない
まさかり募集


blog.cleancoder.com


CleanArchitectureを一言でまとめると
「抽象度でレイヤー分けして、依存性を排除したアーキテクチャ

具体的なモノ(抽象度が低いもの = UI, DB, etc...)は変更されやすいので
そこは一番いじりやすくしようぜ!みたいなニュアンスだと思ってます

ここからは和訳もかねて書いてく


みんな大好きなあの図。ボブおじのブログから引用

f:id:denden_kata:20200607222818j:plain


様々なアーキテクチャがあるが基本的に目的は同じであり
「ソフトウェアを機能ごとにレイヤー分けすることで関心の分離を行う」ことにある

  1. フレームワークに依存しない
    制限された状態でシステムに機能を落とし込む必要性が無くなる

  2. テスト可能
    外部に依存しないのでテストができる

  3. UIに依存しない

  4. DBに依存しない

  5. 外部から独立している。ビジネスルールは外部の状態を知らなくても良い

依存関係のルール

外側から内側に向けて依存する
内側はが外側の状態を知らなくても良い


エンティティ

不変なビジネスルールを記述
サービスの基幹部分(単一のアプリケーションであれば、アプリの仕様になる)
要はこれがなきゃサービスにならないレベルのもの(=ドメインオブジェクト )

ex.) twitterであれば「ユーザー」や「ツイート機能」などに当たる

外部の変更があった場合でも、変更される可能性が最も低い


ユースケース

エンティティに記述しないようなビジネスルールはこっちに記述する
ソフトウェアの仕様変更の影響を受ける

このレイヤーはエンティティへ影響を与えることは想定していない(無関心)
エンティティとのデータフローを調整
ユースケースの目的を達成できるようにエンティティへ指示する


インターフェースアダプター

エンティティやユースケースのデータを、DBなどで使える形に変換する
エンティティとユースケースはDBについては知らなくて良い

ようはぶっちゃけViewMode強化版みたいなとこ


フレームワークとドライバ

DB・UI・Webのフレームワーク
変更の多いところはここ


図について

あくまで例として4つのレイヤーにしただけで、増えることもある
仮に増えても依存性は外側から内側へなのは変わらない
内側へ向かうとソフトウェアはより抽象的になる


レイヤーの境界を超える

右下の図について説明

ユースケースと通信するコントローラーとプレゼンター
コントローラで始まりユースケースを内でデータを操作、プレゼンターで実行

普通は「依存性逆転の法則」を利用するんだとかなんだとか

直にやりとりすると依存性が高いので×


境界を超えるデータ

境界を越えてデータを渡す場合
常に内側の円に最も便利な形式で渡す
内側の円は外側の状態を意識しなくて良い!


個人的な感想

実装の仕方やモノによって、様々なデータの流れがあって複雑になりそう

抽象度が高い部分で、ロジックをどこに書くかというのが曖昧になりそう
別途ルールを作らないと、人によって書き方がバラバラになりそうかなー・・・?

ちょっとまだ理解がふわふわしてる

UIが一番上で、DBが一番下なアーキテクチャに馴染みがあるので理解するのに時間がかかった

リアクティブプログラミング10日目

結構間が空きました。元気になったので再開
無理はよくない、転職してぇ、そのためのRxJava

最近アプリ開発から強制立ち退きカウントダウンを食らって気分が沈んでます
自分が関わっているサービスが今後ボロボロになっていくと思うと辛い

別に僕が何かやらかしたとかそういうのが理由ではないのが本当に悔しい

Base class vs base type

性能比較でもすんの?
ざっと和訳

RxJavaの設計はReactive Streamsの仕様の影響を強く受けたため
ライブラリには各々にインターフェースが用意されている

「基本クラスが静的メソッドとインスタンスメソッドが多いので重い」
という記述があるが何の意味かわからん・・・

「considered heavy」って「重いと考えられる」だよな
重いって何?何が重いん・・・?


リファレンスに載っている表
「各々にインターフェースが用意してあるよ」ってことで記述されてるんだけど・・・

Type Class Interface Consumer
0..N backpressured Flowable Publisher Subscriber
0..N unbounded Observable ObservableSource Observer
1 element or error Single SingleSource SingleObserver
0..1 element or error Maybe MaybeSource MaybeObserver
0 element or error Completable CompletableSource CompletableObserver


Consumer is 何


表のTypeとclassで説明されていることはこれで説明した表の詳細

denden-kata.hatenablog.com

この表ですね

名前 説明
Observable 値が複数
Single 値が1つ
Maybe 値が1つ or なし
Completable 値なし

FlowableとObservableはバックプレッシャーがあるないだけ


んで、後ろの部分は何なんだ
Reactive Streamsの仕様を見てみる

(抜粋)
SPECIFICATION
1.Publisher

public interface Publisher<T> {
    public void subscribe(Subscriber<? super T> s);
}

あっこれかぁ

つまるとこインターフェースで呼ぶときはこうしろってことなんですかね
ちょっと良く分かんないです
というかこれ何の意味があるんですか(殴られそう)

RxJavaではなくてリアクティブプログラミングを根本から勉強しろと言われてる気がする

RxJavaトップページの翻訳はこれでおしまいです
あとは下の方に別のドキュメントとかwikiがあるのでそれを見ろという感じで・・・


総括

RxJavaの基本はコレクションをストリームで管理するという非常にシンプルなもの
多分これでいいと思います

ぶっちゃけ基本を学ぶだけでも覚えることめっちゃ多いのかと思っていたけど
いざ取り掛かってみるとそこまででもなかった

概念は結構シンプルで分かりやすい
まぁ実際に現場で使ってみたりすると沼にハマったりするんだろうけど・・・

Android開発で利用する場合はライフサイクルとかUIスレッドとか
色々と考えながら実装しないと思った通りに動いてくれないみたいな事故があるんですよね
変な実装しなければ割ときちんと動くはずなんですけど・・・

結構適当に読み解いているのでそろそろ警察に後ろから刺されそう


せっかくのGWなので
次はなんかいいサンプルコードがあれば復習がてら読み解いていくか
Clean Architectureの勉強をしていこうと思いまーす



おしまい

リアクティブプログラミング9日目

あーるえっくす じゃばーーー

Operatorの命名規則

使用できないキーワード

元のRx.NETで使ってた名前はJavaですでに使われていたのでダメだったという話

singleなアイテムを発行~完了するOperatorはReturn(T)という名前だった
return(T) ⇒ just(T)

そのほか
switch ⇒ switchOnNext
Catch ⇒ onErrorResumeNext


型消去

型消去 is 何?

型消去 = 「イレイジャ」と呼ばれる
Javaの機能でこれについて書くと記事が1つできるレベルなのではしょると

コンパイラによってパラメータ化された型や型引数を含まない型に変換された物(あいまい)
ex.) List<String>のイレイジャはList

型消去で色々起こるので、まぁ何とかしようとかそんな感じの項目
下記のコードはダメみたい

サンプルコード

Flowable<R> flatMap(Function<? super T, ? extends Publisher<? extends R>> mapper)

Flowable<R> flatMapMaybe(Function<? super T, ? extends MaybeSource<? extends R>> mapper)



Java8とラムダを使っている場合は曖昧で色々起こる可能性がある(キリがないのではしょります)

サンプルコード(concatWithの場合)

Flowable<T> concatWith(Publisher<? extends T> other);

Flowable<T> concatWith(SingleSource<? extends T> other);



ラムダ式のインターフェース

サンプルコード

someSource.concatWith(s -> Single.just(2))
.subscribe(System.out::println, Throwable::printStackTrace);



このときSingle.just(2)は機能しない
concatWithのOverloadの種類が多すぎてコケる

正しくは下記のように書く

サンプルコード

someSource.concatWith(Single.defer(() -> Single.just(2)))
.subscribe(System.out::println, Throwable::printStackTrace);



場合によってはフローでもコケるので下記のように書く

サンプルコード

Flowable<T> merge(Publisher<? extends Publisher<? extends T>> sources);

Flowable<T> mergeArray(Publisher<? extends T>... sources);



うーーーーーん。理解度が微妙だけど言いたいことはなんとなくわか・・・る・・・?
なんかこれも詰まった時ににらめっこ案件だな

正直今までで一番内容がふんわりしている・・・
理解したとは言い難いが立ち止まっても進まないので頭の片隅に置いておこう

今日はちょっとここまで、続きは明日

リアクティブプログラミング8日目

今日もRxJava

型変換

ソースやサービスがそこで動作するフローと異なる型を返すことがある

解決手段は2通りあって

1. 目的の型へ変換する
2. 異なる型をサポートする特定の演算子を使う

まぁなんかここははリファレンスを参照としか言いようがない・・・

各使い分け
FlowableはバックプレッシャーがついてるObservableなので説明省く

名前 説明
Observable 値が複数
Single 値が1つ
Maybe 値が1つ or なし
Completable 値なし


目的の型へ変換

RxJavaでは変換を実行して他の型へ一致させる演算子がデフォルトで実装されてる
表は利用可能な変換オプション一覧

Flowable Observable Single Maybe Completable
Flowable toObservable first, firstOrError, single, singleOrError, last, lastOrError(※1) firstElement, singleElement, lastElement ignoreElements
Observable toFlowable(※2) first, firstOrError, single, singleOrError, last, lastOrError(※1) firstElement, singleElement, lastElement ignoreElements
Single toFlowable(※3) toObservable toMaybe ignoreElements
Maybe toFlowable(※3) toObservable toSingle ignoreElements
Completable toFlowable toObservable toSingle toMaybe

※1 multi-valuedをsingle-valuedにする場合は、どの値を結果として返すか考える必要がある
※2 場合によって振る舞いを変更する必要性があるらしい
※3 ソースアイテムが1つの場合はバックプレッシャーを気にする必要はない


Overloadの利用

別の型へ変換してくれるOverloadなやつら

Operator Overloads
flatMap flatMapSingle, flatMapMaybe, flatMapCompletable, flatMapIterable
concatMap concatMapSingle, concatMapMaybe, concatMapCompletable, concatMapIterable
switchMap switchMapSingle, switchMapMaybe, switchMapCompletable


場合によって使い分けていけって感じだけど、そこそこ分かりやすい。ふむふむ
ここんとこ夜更かしばっかでよくなーい、寝る

リアクティブプログラミング7日目

今日もRxJavaのリファレンス読む

Continuations

和訳で「継続」


Dependent

和訳で「依存」

itemが利用可能になったとき、それに依存する計算をしたい
これをContinuationsと呼ぶ

最も一般的なパターンは
値を指定して別のサービスを呼び出し、結果を受け取って処理を継続するとか

サンプルコード

service.apiCall()
.flatMap(value -> service.anotherApiCall(value))
.flatMap(next -> service.finalCall(next))

サンプルコード見た感じだとまぁ見たまんまの処理


flatMapの中にflatMapを入れるみたいな場合

サンプルコード

service.apiCall()
.flatMap(value ->
    service.anotherApiCall(value)
    .flatMap(next -> service.finalCallBoth(value, next))
)

これもシンプルに見たまんまの処理


Non-dependent

和訳で「非依存」

原文読んでもピンとこなかったので読み解いてみる

サンプルコード(ダメなパターン)

Observable continued = sourceObservable.flatMapSingle(ignored -> someSingleSource)
continued.map(v -> v.toString())
  .subscribe(System.out::println, Throwable::printStackTrace);
  • flatMapSingle
    Flowableの各要素をSingleSourceにしてマッピングする
    Single = 値かエラーが1度だけ流れる

今までと違うところは、observableの宣言をしてflatMap
そのあとにmapで整頓してる

1回ずつoperatorを使いたいって感じ

この場合だとoperatorの処理でマッピングが複数の値をもたらす可能性があるみたい
んー、なぜだ?

あー・・・?
値が入り次第、次のmapが動作しちゃうみたい

こっちの方法で書くのが正解

andThenを利用することで、前のobservableが正常完了してから次のobservableが動作する
なるほど

サンプルコード

sourceObservable
  .ignoreElements()           // returns Completable
  .andThen(someSingleSource)
  .map(v -> v.toString())


Deferred-dependent

和訳で「遅延依存」

前と後ろでデータ依存があり
何らかの理由で「通常のチャンネル」をストリームしていない場合

サンプルコード(ダメなパターン)

AtomicInteger count = new AtomicInteger();

Observable.range(1, 10)
  .doOnNext(ignored -> count.incrementAndGet())
  .ignoreElements()
  .andThen(Single.just(count.get()))
  .subscribe(System.out::println);

これは全て「0」が出力されてしまう
Single.just(count.get()) がデータフロー実行前に評価されてしまうのでアウト

よってメインのストリームが終わってから評価する必要がある
=遅延依存


サンプルコード

AtomicInteger count = new AtomicInteger();

Observable.range(1, 10)
  .doOnNext(ignored -> count.incrementAndGet())
  .ignoreElements()
  .andThen(Single.defer(() -> Single.just(count.get())))
  .subscribe(System.out::println);

または

AtomicInteger count = new AtomicInteger();

Observable.range(1, 10)
  .doOnNext(ignored -> count.incrementAndGet())
  .ignoreElements()
  .andThen(Single.fromCallable(() -> count.get()))
  .subscribe(System.out::println);


あー、これは忘れたころにつまずきそうなパターンだ・・・


今日やった部分はデータフローの仕方がごちゃっとしてるなぁ(体感)
とりまここまで、おやすみなさーい

リアクティブプログラミング6日目

Dependent sub-flows

和訳で「依存サブフロー
依存サブフロー is 何

本文を読む

flatMapは強力なoperatorです
お、おう

サンプルコード

Flowable<Inventory> inventorySource = warehouse.getInventoryAsync();

inventorySource
    .flatMap(inventoryItem -> erp.getDemandAsync(inventoryItem.getId())
            .map(demand -> "Item " + inventoryItem.getName() + " has demand " + demand))
    .subscribe(System.out::println);

んー、コード見てもぱっと分からん

調べてみる

ReactiveX - FlatMap operator
説明を読んだ感じだと
map(itemを変換)とmarge(複数動作していたObservableをまとめる)が合体したみたいな

図を見る限り変換後の順番は保証してないっぽいね


次の項目がちょっと長いので、ちょっと短めでおしまい

今日はちょっと仕事もあったので精神的にもんにょり
リモートワーク始まってから休日に労働をせがまれるリスクを背負ってるなぁと

寝るーん