book cover
需要が
あれば
やる!!
書影は検討中のものです

Effective Swift

書籍『Effective Swift(仮)』はプログラミング言語Swiftの正しい理解と、簡潔で明瞭で正確なソフトウェアの設計に役立つガイドとなる書籍です。 もし需要がありそうなら、2022年1月くらいにリリースしようと思っていましたが、 2月末あたりリリース予定です。

ベータお知らせ登録は終了しました
登録されたメールアドレスはベータまたは正式版リリース時のお知らせ用途のみに利用され、第三者へ共有されることはありません。 事前登録者数はN人でした。

書籍の内容

言語仕様が常に進化しているSwiftの動向をしっかり押さえながら、それらの最新の機能をどのように使うべきかについて実践的な観点から逆引きにしてその技法をまとめた書籍となる予定です。

可読性の高いコードのために

プログラムを他者が理解しやすく、保守しやすく、拡張しやすくするため

ガイドラインとして

より効率的なコードを書くためのガイドラインとなる項目を説明します。

ソフトウェアの設計のために

言語の正しい理解と簡潔で明瞭で正確なソフトウェア設計のための項目を説明します。

目次(仮)

  • はじめに
  • Swiftに慣れよう
    • 可能ならいつでもletを使おう
    • varを使う必要がある場合はデメリットを局所的にしていこう
    • できるだけイミュータブルなオブジェクトを使う
    • 可能ならselfを省略しよう
    • 必ずしもクロージャで[weak self]が必要ないことも理解しよう
    • guardを恐れずに使うためにguardの条件を明確にしよう
    • strongSelfなどせずselfをシャドーイングしても問題はない
  • オブジェクトの生成と消滅
    • 依存する処理を直接結び付けるよりも依存の注入を選ぶ
  • class
    • 静的メソッドはclass funcではなくstatic funcを選択する
  • enum
    • Int定数の代わりにenumを使う
  • struct
    • 値のやりとりをする場合にstructの利用を検討しよう
    • 状態を保持しその監視の役割としたstructを使わないようにしよう
  • 非同期処理
    • 可能であればwithCheckedContinuation(function:_:)でクロージャベースの非同期処理を置き換える
    • 必要があればwithUnchecked~を利用する
    • シングルトンを利用する場合にactorを検討する
    • メインスレッドから呼び出されて困るメソッドにはglobalActorを検討する
    • DispatchQueueよりもTask APIの利用を選ぶ
    • 副作用の非同期処理中にawait MainActor.run {}を乱用しない
  • デザインと宣言
    • 外部公開しないプロパティはprivate宣言する
    • 配列を返すメソッドではnilを返すのではなく空配列を返す
    • オプショナルにする必要のないパラメータはオプショナルにしない
    • インタフェースはCommandとQueryの区別を意識する
    • 可能であればインスタンスメソッドよりインスタンスのプロパティを使う
    • プロパティによるgetterの計算量がO(1)より複雑になる場合はメソッドを検討する
    • 一般的な使用方法を単純化する場合には、関数にデフォルトのパラメータを利用する
    • デフォルトのパラメータを利用する際にクロージャならOptionalを使わず空のクロージャを利用する
    • 遅延評価の使用を検討する
    • initで他の型を引数とするメソッドをなるべく利用しない
    • 成功失敗の情報を表現するためにResult型を使う
  • 命名(基本的にはswift.orgのAPI Guidelinesを見る)
    • 引数をうまく区別できない場合は、すべてのラベルを省略する
      • min(number1, number2), zip(sequence1, sequence2)
    • 引数を区別する必要がある場合はラベルを省略せず表現する
      • func move(from start: Point, to end: Point)
    • 値を保持する型変換のためのイニシャライザは最初の引数のラベルを省略してよい
      • Int64(someUInt32)
    • 絞り込むような場合は型をラベルを省略せずその絞りこみ方法をラベルとする
      • extension UInt32 { init(truncating source: UInt64) }
      • extension UInt32 { init(saturating valueToApproximate: UInt64) }
    • 最初の引数が前置詞を含む場合にはラベルにそれを示す
      • x.removeBoxes(havingLength: 12)
    • 複数の引数が1つの前置詞に対して必要な場合は前置詞をメソッドに含める
      • a.move(toX: b, y: c) => a.moveTo(x: b, y: c)
      • a.fade(fromRed: b, green: c, blue: d) => a.fadeFrom(red: b, green: c, blue: d)
    • フレーズとして正しくても引数が行う意味をラベルで伝える必要がある
      • view.dismiss(false) => view.dismiss(animated: false)
    • Factoryメソッドの命名は"make"で始める
      • let iterator = x.makeIterator()
    • mutatingなメソッドでは"from"で始める
      • y.fromUnizon(z)
    • 能力を表すプロトコルはサフィックスにable,ible, ingのいずれかつける
      • Equatable, ProgressReporting
    • プロトコルでも役割を説明する場合には名詞でいい
      • Collection
    • 独自の省略された命名を作り出さない
    • Objective-Cからアクセスしないのであればenumによるnamespaceを検討する
  • 開発
    • デバッグオプションを活用する
    • 開発時にassertを利用したコードを書いて異常系の対応を後回しにする
    • preconditionを利用して事前条件を明確にする
    • fatalErrorを利用して異常実行に関する情報量を増やす
  • SwiftUI
    • (@)Publishedを利用するとViewが更新されることを理解しよう
    • Generic型を使ってUITableViewCellやUICollectionViewCellをSwiftUI.Viewにする
    • SwiftUI.Viewのinitで時間のかかる処理を書かない
    • SwiftUI.Viewのプレビューが常にできるようにinitで依存の注入ができるようにする
    • プレビューのためにCore Dataのデータが関係する場合はオンメモリに書き込める
    • プレビュー高速化のためにプレビュー時Run Scriptを実行しないようにしよう
  • その他
    • Selfを使う
    • private extensionを使ってextensionをまとめてprivateにする
    • ループ時にforではなく高階関数のmap, filter, reduceを検討し副作用を実行しないことを表現しよう
    • 高階関数内で複雑なコードを書いてしまうと可読性が落ちることを理解しよう
    • 確実な後片付けのためdeferキーワードを利用する
    • NSPredicateでプロパティの変数名を利用する場合は#keyPathを利用し変更時に気がつけるようにする
    • Bindする必要がある戻り値にはタプルを使うと漏れがないことを知っておく
    • テストコードを階層化して情報量を増やす
    • コンパイラの警告に注意を払おう
    • 機能開発を外注する際のことを考えてEmmbeded Moduleに分割する
    • UUIDをString型とする前にUUID型を検討しよう
    • 可能であればuuidという変数名は避ける
    • IDの型としてtypealiasを検討する
    • IDの型として専用の型を検討する
    • 型の命名などはClean Architecture本を参考にすべきではない
  • 公式のドキュメントの場所
  • おわりに
  • 誰のために?

    Swift以外のプログラミング言語を知っている前提のプログラマもしくは、 初級以上のSwiftプログラマからをターゲットにしています。 具体的には『クロージャが何か』『従来のDispatchQueueを用いた非同期処理についてのコードを見て何が起こっているか』は理解している必要性があります。 値型と参照型についての違いなど初級以前の基礎的な内容を含むかは悩ましいところですが、その部分が大きな特色でもあり、項目を用意するかもしれません。

    すでにSwift利用経験があるプログラマ

    DispatchQueueについて知っていて、クロージャについてもそれが何かを知っている。

    その他のクライアントアプリのプログラマ

    クロージャを見てそれが自分の知っている別の言語で例えられ、クロージャによるコールバックな非同期処理について知っている。

    What's Included

    devises
    対応しているファイルフォーマット
    • PDF EPUB

    ベータ版お知らせの反響

    Twitter上での反響を集めました。

    すでにリリース済みの書籍

    BOOTHで販売中です。
    RxSwiftの基礎にフォーカスしています。
    RxSwiftのエラーハンドリングについて言及しています。
    RxSwiftで制約のないViewModel設計についての問題を提起し、様々なViewModelの設計を紹介します。
    より深くリアクティブプログラミングフレームワークについて理解するため、最小限の機能しかないRxSwiftクローンを作る過程を解説します。
    MutualMobile社によって2013年に提案されたVIPERというクリーンアーキテクチャを参考にしたシステムアーキテクチャの解説を行う書籍です。 クリーンアーキテクチャについての疑問点にフォーカスし、Web上に公開された様々なVIPER実装の共通点や差分について述べます。
    すでにSwiftUIに触れたことがある読者をターゲットにし、SwiftUIをより理解していくことを目的としています。 具体的にはAppleのSwiftUIチュートリアルをひととおりこなしていることが目安になるはずです。
    WWDC19でAppleにより発表されたCombineフレームワークはリアクティブプログラミングを宣言的に行うためのフレームワークですが、リアクティブプログラミングに慣れていない開発者にとって、決して雰囲気だけで使えるフレームワークではありません。Combineには名前だけでは動作を想像できないオペレーターが複数あり、納得しづらい理屈もあります。 本書では基礎的な概念の説明とともに、歴史的背景を参考にすることで理解を深めることを目的としています。
    image

    About The Author

    BOOTHにてキュリオシティソフトウェア書店として Swiftを中心としたモバイルアプリ開発に関連する電子書籍を公開しています。 RxSwiftやVIPERアーキテクチャなど、他では取り扱わないようなテーマを筆者の利用経験を交えて書いています。