UdemyのサーバーサイドSwiftのコースをやってみた

Udemy にある下記のコースをやってみました。

www.udemy.com

概要

  • 有料コース(セールで1200円のときに購入)
  • 英語
  • Kituraの基本的な使い方と、Swiftで書いたサーバーサイドのコードをDockerでテストしたり、Bluemixにデプロイする方法が丁寧に紹介されている
  • 使用するDBはCouchDBというNoSQL
  • コース公開時の最新バージョンがSwift3.0だったので、コードが少し古い

良かった点

  • Xcodeでサーバーサイド側のコードが書けるのはとても気持ち良い
  • サーバーサイドのコードを書いてる気がしないというか、使い慣れたXcodeで開発するのでサーバーサイドを書く負担がすごく下がる
  • iOS開発ではほとんど利用しない、Docker や Swift Package Manager の基本操作が分かるのも良い

悪かった点

  • 講師の方の本業がiOSエンジニアではないようでコードの書き方はあまり良くない
  • クライアント側の実装は参考にしないほうが良いと思う

全体を通した感想

途中でXcodeの使い方やSwiftの書き方のレクチャーがあるが、サーバーサイドSwiftだけ興味ある人は飛ばして良い。俺も飛ばした。クライアント側の実装はあまり参考にはならなかったが、サーバーサイド側は良かった。

講中にSwift3.1がリリースされたので、コースで紹介されているOSSライブラリが全てバージョンアップしなければならくなった。バージョンを上げてもそのままでは動かないコードもあり、コース外で調べないといけないことが増えてしまった。しかし、そのおかげでサーバーサイドSwiftの理解がより深まったし、こういう発展途上の分野を少しずつ対応していくのはとても面白いので結果的によかった。

で、面白かったけど、これでiOSのサーバーサイドを全てSwiftで書く気になるのかと言われると、簡単なJSONを返すぐらいならいいかもというのが正直なところ。今はAWSやFirebaseなど、そもそもサーバーサイドを気にせずにアプリを開発する方法もあるので、わざわざSwiftでサーバーサイドを実装して作業量を増やさなくてもいい。でも、面白いのは本当です。

これから受講したいと思っている人は、最新のXcodeではビルドできなくなっているので、ハマりそうなところのコードを下記にのせておく。

コースの内容をSwift3.1に対応させてみる

  • だいたいはXcodeのサジェスト通りにやればなんとかなると思う
  • docker pull ibmcom/swift-ubuntu とかしてイメージを最新にしないと docker上のテストが失敗します
  • Package.swiftを更新したら、.build と Package.pins と xcodeproj を削除してから、swift build して swift package generate-xcodeproj しないと更新状態が反映されない
  • Swift-cfenv がコースの内容と、かなり乖離があるのでハマる人が多い
  • UdemyのQ&Aにいくつか質問があがってるので参考にすると良い

Package.swift

import PackageDescription

let package = Package(
    name: "FoodTruckAPI",
    targets: [
      Target(
        name: "FoodTruckServer",
        dependencies: [ .Target(name: "FoodTruckAPI")]
      ),
      Target(
        name: "FoodTruckAPI"
      )
    ],
    dependencies: [
      .Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1, minor: 7),
      .Package(url: "https://github.com/IBM-Swift/Kitura-CouchDB.git", majorVersion: 1, minor: 7),
      .Package(url: "https://github.com/IBM-Swift/Swift-cfenv.git", majorVersion: 4, minor: 0),
    ]
)

main.swift

import Foundation
import Kitura
import HeliumLogger
import LoggerAPI
import Configuration
import CloudFoundryEnv
import FoodTruckAPI

HeliumLogger.use()

let trucks: FoodTruck

do {
    Log.info("Attempting init with CF enviroment")
    let service = try getConfig()
    Log.info("Init with Service")
    trucks = FoodTruck(service: service)
} catch {
    Log.info("Could not retreive CF env: init with defaults")
    trucks = FoodTruck()
}

let config: ConfigurationManager = ConfigurationManager()
let controller = FoodTruckController(backend: trucks)

let port = config.port
Log.verbose("Assigned port \(port)")

Kitura.addHTTPServer(onPort: port, with: controller.router)
Kitura.run()

Config.swift

import Foundation
import LoggerAPI
import CouchDB
import Configuration
import CloudFoundryEnv

struct ConfigError: LocalizedError {
    var errorDescription: String? {
        return "Could not retreive config info"
    }
}

func getConfig() throws -> Service {
    let config: ConfigurationManager = ConfigurationManager()
    config.load(.environmentVariables)  // これがないとBluemix 上で環境変数が取得できない

    Log.warning("Attempting to retreive CF Env")
    
    let services = config.getServices()
    let servicePair = services.filter { $0.value.label == "cloudantNoSQLDB" }.first
    guard let service = servicePair?.value else { throw ConfigError() }
    
    return service
}