iOS開発初心者は何がわからないのか わからないを言語化するヒント
概要
この内容は、iOSDC2018 reject conで登壇した時の話をまとめたものです。gitのブランチやマージの概念がわからなくてターミナルの黒い画面が怖い、コンフリクトを出そうもんなら発狂しそうになる。くらす?なにそれ美味しいの?状態でアプリ開発者になりました。
わからないことを何がわからないのか、始めたばっかりの頃は言語化できません。
アプリ初心者がどこに躓き、何がわからないのかを紹介します。
当日の聞いていただいた方々の反応はこちら↓
iOS始めたばっかりの人やはじめての人を教えるメンターをしている人に届くといいなと思っています。
●大学時代
具体的にどんな大学でどんなことを学ぶのかは下記を見ていただけるとわかるんじゃないかと思います。
●社会人
コンピューターのことをきちんと理解してない感じで、社会人になって運良くエンジニアになりましたが、一言で言うと、とにかくわからない。
もう宇宙語。みんな宇宙語を喋ってるんじゃないかというくらいわからない。
日本語なのにわからないんです。
たとえば、下に例文を用意してみました。先輩から下記のように指示を受けたとします。gitを使いこなしてる方なら余裕な文章かと思います。
それでは、当時の私視点でこの例文を見てみましょう。
まあ、こんな感じ。
主語も動詞も述語もまるでわからないのです。もう0。何を聞いていいのかすら、何を質問すればいいのかすらわからない。
というか、あのターミナルの黒い画面が怖すぎて触りたくない・・・
こんな状態なのでもちろんiOSに関してもわかるわけないのでした。
まるで赤ちゃんに戻ったみたいな感じ。人間の言葉がわからないって、この感覚が久しぶりすぎてつらみが増しました。
わからなすぎると、何も質問できない、手が動かない、調べても調べても堂々巡りということが身にしみてわかりました。
↓ずっとこんなかんじ、生まれ直した気分
多少なりともわかった今、
なぜわからなかったのか、どうすればわかったのかを書き起こすことで、今同じようなところで躓いている人や、初心者のメンターをしている人に届いて、わからないを可視化することで橋渡しができたらいいなと考え、共有します。
それでは、自分が躓いたところを紹介していきます。
ここからは、当時の自分を召喚してコードを見てもらいます。
下記の例コードを用意しました。
iOS開発者にとっては見慣れたようなものだと思いますが・・・クラスのわからない初心者は何から何までわからないので面白いんじゃないかなとおもいます。
●一行目
(過去の自分)
そもそもViewControllerって何???
いままでずっとProcessingで作る時に使ってたdraw()関数みたいにずっとループしているやつどこ?
なんで、どの関数内でループさせていないのに実行できてるの謎すぎる・・
あとViewControllerとUIViewController何が違うの?
どうして隣に書いてあるの?
自分の過去のProcessingの経験に引きづられちゃっていますね。iOSのライフサイクル概念を知らなかったみたいです。また、クラスの継承という概念もわかっていないようです。
UIKitのドキュメントも先輩から読んでみて、とご指導いただきましたが、言ってることが訳わからなすぎてそっ閉じしました。
クラスの概念や、どんなクラスやプロパティがあるのかなど前提知識がないと本当に読めなかったです。
●2行目
(過去の自分)
overrideって何?
funcの前にoverrideついてるのとついてないのがあるけど何が違うの?
videDidLoad()ってどこから出てきた関数なの?
videDidLoad2()だとどうして動かないの?
これもクラスの継承を理解していなかったようです。Processingの経験から、自分で作った関数しか実行できないと思い込んでいるようです(もちろんライブラリがあるので使えます)
●3行目
(過去の自分)
このselfって何?
どうしてself.viewってつながるの?self.viewsだとなんでダメなの?
どうしてその後backgroundColorにつながるの?
なんで代入する時に
self.view.backgroundColor = UIColor.white
self.view.backgroundColor = .white
どちらでもいいの?
self.view.backgroundColor = white
だとどうしてダメなの?
どうやらインスタンス化という概念をわかっていないようです。
また、UIViewControllerのプロパティにviewが存在しているということがわかってなかったようです。backgroundColorも同様にUIViewという型のプロパティにbackgroundColorが存在していることがわかっていませんでしたね。
●4行目
(過去の自分)
()が後ろに付いてるから関数かな???
そもそもUILabelってなにどんな関数なの?
これはガチで関数って思ってましたね・・・・・・・(恥)
UILabelのインスタンス化したものなのですが、インスタンスという概念を理解できないがためにこんな感じになるのです。
●5行目
(過去の自分)
labelのtextに文字列を代入しているらしい
これはわかる
一つでもわかるところがあってよかったです
●6行目
(過去の自分)
色情報をどうやら入れているらしい
label.textColor につながるtextColorってことは色情報をいれたらいいみたい
よくわからないけどUIColor.blueっていれてる
しかしUIColorってなんだ? どうしてドットでつながるの?
UIColor.Blueとかないのかな?
(過去の自分)
えっ・・・この {} カッコ意味がわからない・・・・・
どうして囲むの? なんで=でつながるの?
: MyStackViewでどこから来たんだ・・・・・・・・・・
来ました。初心者が大体躓くクロージャーの登場です。
(過去の自分)
いやさっき前の行で let myStackViewって定義したやん・・・
同じ名前使ってるのになんでエラーにならないのよ・・・・・・
今度は let myStackView = MyStackView() 入れてるし
なにこの最後の()は さっき{}いれてたやん・・・なんなの
なんて調べればでてくるの
「Swift 同じ定義 カッコ内 何?」
全然わからん 調べ方もわからん
なんて説明したらいいのかもわからん
そうですね。これは当時本当にわからなかったところです。
なんて説明したら良いんですかね・・・
クロージャーの中でインスタンス化して、インスタンス化したクラスにプロパティを設定しておくと、まとめて用意できるしクラス内で散らばらないから楽だよ。
でしょうか。 うーん・・・
(過去の自分)
そもそも .axisってなに? .verticalってことは垂直らしいけどそれって何
設定すると何が違うの?
これはUIkitの中のStackView()の使い方を知らないとわからない気がします。
SwiftというよりはUIKitの使い方を知らないという問題のようです。
(過去の自分)
このながったらしい呪文はなんだろう
よくわからないけど、教科書にそう書いてあったからかいてみよ
エンジニアはこの長い文字をどうやって覚えてるの・・・記憶力いいなぁ
Xcodeでプロパティ名を補完できることを知らないようですね。
これもUIKitの使い方を知らないからわからないようです。
ドキュメントを読むというのも手ですが、おそらくこの時代に読んでもわからなかったんじゃないかなと思います。StackViewの使い方がなんとなくわかるようになったのは、クラスの概念を理解した後なので使うのが早すぎたかもしれませんね・・・
(過去の自分)
えっ なに・・・・・なんで return????????
唐突にreturnされても・・どこにreturnするんよ
次どこに行くの? 関数でもないのになんでreturnするんや・・・・
クロージャー知らないとまあそうだよね。そう思うよね。という感想を抱きました。
ここではMyStackView型のインスタンスを返して
let myStackView: MyStackView = {}で定義したmyStackViewに格納しています。
(過去の自分)
(唐突な最後の()に絶句する)
なにこれ・・・・・・・
なんて検索したら出てくるのかな?
「Swift {} の最後の() 何?」
とか・・・・(出てこない)
わからん・・調べ方すらわからん
これが何で、なんて名前なのかすらわからん(死)
最後の()はそのクロージャーを実行しています。
下記リンクのクロージャ(基本編)から引用しますが、入門書にたとえばこのようにコードが書いてあったとします。
// 引数と戻り値のないクロージャ
let closure = { () -> Void in print("クロージャテスト") }
// クロージャ実行
closure()
(過去の自分)
私が知りたいの
let closure = { () -> Void in print("クロージャテスト") }
これじゃなくて
let closure = { () -> Void in print("クロージャテスト") }()
最後に()がついたこうなってるやつ!!!!
ってなるわけです。
こんな感じで自分がわからないポイントが
●UIKitの使い方がわからない
●Swiftの文法がわからない
●クラスの概念や考え方がわからない
大体この3つに分けられました。
問題の切り分けができていなかったのです。
●特につまづいていたポイントを紹介
いろいろありますが。。
とりあえず3つに絞ってみました。
●1.delegateについて
処理を委譲するのにdelegate使うよという説明があるのですが、委譲といわれてもまあわからない。
delegateを設定するときは下記の図のように書くのがおなじみですが、クラスの概念を理解してないと厳しい感じがしますね・・・
では定義を見てみましょう。
UILabel()をcommandを押しながらクリックすると定義を見てみることができます。
public protocol UITextFieldDelegate : NSObjectProtocol {
~省略~
@available(iOS 2.0, *)
optional public func textFieldShoudReturn(_ textField: UITextField) -> Bool
}
定義を見ても当時は、どう使えばいいかわからなくて で・・?どうするのという感じでした。
上の図の実装と書いてある下部部分が、実際に実装する時のコードなのですが、定義から実装にどうやって移植させるのかがわからなかったというのが思い出です。
具体的に書くと
extension ViewController: UITextFieldDelegate {
func textFieldShoudReturn(_ textField: UITextField) -> Bool
}
(過去の自分)
あれ??これだとエラーになる?? なんで???
という感覚です。今見るとちゃんと定義書いてあるやん・・と思いますが、当時は定義を読めなかったのです。
自分が乗り越えた方法
どうやって理解したのかはちょっと覚えてないのですが、クラスの概念がわかりはじめてからだったと思います。
UITextFiledで文字を入力した時にreturnキーが押された時に発火するdelegate textFieldShouldReturn(textField: ) があります。この関数内にブレイクポイントを張って、きちんと止まった時にあっなるほど・・・という感覚を得ました。
この時に、もう少し自分にアドバイスがあったとしたら
UITextFieldのデリゲートメソッドの定義をもっと見て
・テキストフィールドがタップされ、入力可能になる直前
・テキストフィールドがタップされ、入力可能になった後
・キーボードを閉じる前
・キーボードを閉じた後
・returnキーが押された時
・テキストがクリアされる直前
・編集中
このそれぞれのデリゲートメソッドを定義の中から見つけて、中にブレイクポイントを張ってどの段階で止まるのかという、観察をしていたらよりdelegateを理解し、他の場面でも応用がきいただろうなぁと思います。
初心者本にはdelegateの説明はあるけど、使っているメソッドは一つだったりで、この世にはこのメソッドしか無いんじゃないかと勘違いをしていました。
経験者と一緒に考える方法
定義を一緒に見て、使い方がわかるかどうか、実際に使ってみてブレイクポイントを張ってみるなどをすると良いんじゃないかなぁと思います。
●2.クラスの概念、オブジェクト指向
これも自分が今きちんと理解しているかというと、理解はできてないと思うのですが、全くわからん状態からちょっとわかる状態になるまで時間がかかったので、なぜ躓いたかを解説します。
例えば、クラス自体の解説は多くの入門書に書かれているとおもいます。
上記の図のように、これだったらなんとなく定義の仕方はわかるのです。
では実際にアプリ開発に移動してみると、
今までMyClassと書いていたものが唐突にViewControllerになるわけです。自分で定義してないのに、どこからそうなったのかがわかりませんでした。
このtextをcommandを押しながらクリックすると定義に飛ぶことができます。UILabel内のプロパティにtextが存在していますが、これが、MyClassとなんの関係があるのかがさっぱりつながってこなくて苦労しました。
乗り越え方
業務でコードを修正していた時に突然、あっなるほど。。。そういうことだったのか。。って雷に打たれた感じで繋がりました。
定義をわからないなりにチラチラ見ていたのが良かったのかもしれません。
またプライベートの練習で自主制作アプリを作っていたというのもあってやっぱり手を動かしていくうちに何となく分かるようになるんじゃないかなぁと思いました
経験者と一緒に考える方法
定義を一緒にみて、このプロパティはどこから来たのかなを探すというのをやるといいかもしれません。定義の中から、次のクラスに次々と飛んでここにつながるんだねと見せると良いのかも。
例えば
self.view.backgroundColorのように
UIViewControllerの定義に飛んでviewのプロパティを確認した後、UIViewのクラスの定義に飛んでbackgroundColorを発見させるとかかすると、なぜ(.)でつながるのかがわかるのかも
●3.Swiftの文法(クロージャー)
そもそもクロージャーは、省略記法が可能なので、解説記事でも書き方がまちまちでどれが正しいのかがわかりませんでした。
(そもそも省略が可能であるということがわかってない)
また $0が何を指すのかがわかりませんでした。
下記に例を示します。
1つ目のクロージャーは標準的なクロージャーで()が省略されていません
2つ目のクロージャーは、最後の引数がクロージャーの場合外にだすことができる例です(後置記法)
3つ目のクロージャーは、引数が一つ且つクロージャーの場合、()を省略することができmap{ $0 * 2}を書くことができます。
省略されていることに気が付かないのです・・・・
初心者用記事にあるクロージャーは理解した気になりましたが、問題は下記みたいなやつ。
例えば、これはリクエストを送る例ですが、
URLSession.shared.dataTask(with: request)でもう私の中で関数は終わっていたのです。どうして、関数の後ろに{}がつながるのかがさっぱりわからない。
だから{}のなかの引数(data, response, error)がどこから来たのかがわからず。どう調べたら、わかるのかがわからなかったのです。
それではdataTaskの定義を見てみましょう
ここでまた過去の自分を召喚して、当時視点でコードを見てもらいます。
では今だったらどう見えるのかを見てみます。
こんな感じで世界の見え方がぜんぜん違うんだなと改めてびっくりしました。
乗り越え方
別件で何かを調べていた時に、たまたま目に入った接尾クロージャーという説明でようやくすべてが繋がりました。
あれは省略されていたのかと・・・・・・
じゃあ書いておいてよ・・・
勝手に後ろの方に置かないでよ・・・・と当時は思っていました。
名前がわかれば調べるのは簡単なのですが、まさか省略されているなんて思いもしないわけで、解にたどり着くまでに時間がかかりました。
経験者と一緒に考える方法
クロージャーを一切省略しないところから、どんどんどんどん省略させていく書き方をやってみるといいかもしれない。
UIKitのメソッドにしれっと出てくる接尾クロージャーはわかりにくいというのを意識するとつまづきやすいポイントがわかるかも。
まとめ
Appleのドキュメントもう少し使い方とか、例のコード書いてくれたら助かるのになぁと思いました。
入門書に、定義の読み方を書いてあれば、考え方がわかる且つ応用が効くのになぁと思いました。
私が入社して一番最初にやった本。
とりあえず写経して全部アプリを作った、・・・が理解をしてないので応用できないもどかしい、くやしい思いをした。このときはクラスの概念を理解できていなかった。
クラスを多少なりとも理解した後はこれをやりました。
Appleの公式チュートリアルで、データの保存、TableViewの使いかた、ページ遷移、テストのやり方まで解説されている。
業務で修正などをしていくうちにUIKitのクラスの名前はちょっと覚えていたあとでこれにトライしたので、最初の頃よりは挫折しなくなった。
これはストーリーボードを使ってレイアウトをするチュートリアルだったので、後ほど、コードでレイアウト出来るように自分で作り直した。
Appleのチュートリアルの英語でひぃひぃ言った後にこれをやると、なんとそのチュートリアルの日本語版だった
早く出会いたかった・・・・・・あの苦労はいったい何だったんだ
これも一応復習がてらやった、わかりにくいところは追加で説明が入っていたきがする。私はテキストしか見てないけど、ビデオ講座もあるのでテキストだけだとちょっと・・・というひとはこれをやるといいかも
オススメ
技術書典で出会った本
正直もっと早く出会いたかった。クラスを多少なりとも理解した後に、もっとキレイに書く方法をしりたいとか、デザパタ気になるけどどこから手を付けたらいいかわからん!という状態の時にこれに出会って全部写経した。
社内のプロダクトはコードでレイアウトしていて、初心者用の記事は大体ストーリボードでレイアウトされていてとても厳しかった。早くこの本に出会えればよかったのに・・・と後悔した。
技術書典はエンジニアのこれがほしいと思った本を作ってくれる方がいてすばらしいなと思います。
終わりに
こんな感じでしたがギリギリ一年目メンターとボスとチームの皆さんのやさしさのおかげで生き延びれました。みんな優しい・・・頭があがらない・・・ほんとすいませんという気持ち・・・・
一年目の振り返りはこちらです。
今もどこかで、何がわからないのかわからない状態で躓いている人が、
そう!これ!これがわからなかったんだ!!自分だけじゃないんだって思ったり、経験者にわからない、もどかしい気持ちを伝えるためのツールにこの記事がなったりしたらいいなぁと思っています。
今はRxSwiftをもっと深く理解したい、もっとキレイにわかりやすいコードを書くにはどうしたらいいのかなぁ、もっと早く実装できるようになるにはどうしたらいいのかなぁ、もっとwebのこと知るにはどうしたらいいのかなぁ、チームの皆さんに後継するにはどうしたらいいのかなぁって悩んでいます。
この悩みもいつか知見として、記録を残せたらいいなと・・・
これからも頑張ろう もっと知りたいしやってみたい。
エンジニアとして働いている成長記録やおもしろいと思ったこと色々書いていこうとおもいます 頂いたご支援は、資料や勉強のための本、次のネタのための資金にし、さらに面白いことを発信するために使います 応援おねがいします