Performance Graph
Server | Language | request/sec | Comparison
---------|----------|-------------|------------
Curassow | Swift | 7715.83 |
Gunicorn | Python | 5269.49 | 32% less req/s than Curassow
Unicorn | Ruby | 4253.33 | 45% less req/s Curassow
Slide 14
Slide 14 text
No content
Slide 15
Slide 15 text
How
Slide 16
Slide 16 text
/// Format the given string for presentation
func formatForDate(date: NSDate) -> String {
let formatter = NSDateFormatter()
formatter.formatString = "DD MM yyyy"
return formatter.stringForDate(date)
}
Slide 17
Slide 17 text
func viewDidLoad() {
super.viewDidLoad()
// Using our date formatting in iOS
button.title = formatForDate(NSDate())
}
Slide 18
Slide 18 text
import Frank
get {
return formatForDate(NSDate())
}
$ swift --version
Apple Swift version 2.2
$ cd Stencil
$ swift --version
Apple Swift version 3.0-dev
Slide 36
Slide 36 text
Web Frameworks
Slide 37
Slide 37 text
Separation of
Concerns
Web Servers / Web Frameworks
Slide 38
Slide 38 text
Frank
Slide 39
Slide 39 text
get("users", "kyle", "followers") { request in
}
Slide 40
Slide 40 text
get("users", *) { (request, username: String) in
}
Slide 41
Slide 41 text
Custom Parameter Type
enum Status {
case Open
case Closed
}
Slide 42
Slide 42 text
Custom Parameter Type
extension Status : ParameterConvertible {
init?(parser: ParameterParser) {
switch parser.shift() ?? "" {
case "open":
self = .Open
case "closed":
self = .Closed
default:
return nil
}
}
}
Slide 43
Slide 43 text
get("issues", *) { (request, status: Status) in
return "Issues using status: \(status)"
}
Slide 44
Slide 44 text
Swift Safety
get("/users/:username") { (request, params) in
let username = params["username"]!
return "Hello \(username)"
}
Slide 45
Slide 45 text
No content
Slide 46
Slide 46 text
let router = Router()
router.get("/users/:username") { request, response, next in
let username = request.params["username"] ?? "(nil)"
try response.status(HttpStatusCode.OK).send("Hello \(username)")
}
let server = HttpServer.listen(8090, delegate: router)
Server.run()
Slide 47
Slide 47 text
Web Server
Slide 48
Slide 48 text
Curassow
https://curassow.fuller.li/
Slide 49
Slide 49 text
$ curassow --workers 5
[INFO] Listening at http://localhost:8080 (65416)
[INFO] Booting worker process with pid: 65417
[INFO] Booting worker process with pid: 65418
[INFO] Booting worker process with pid: 65419
[INFO] Booting worker process with pid: 65420
[INFO] Booting worker process with pid: 65421
There are {{ articles.count }} articles.
{% for article in articles %}
- {{ article.title }} by {{ article.author }}.
{% endfor %}
Slide 59
Slide 59 text
Users
{% for user in users %}
{{ user }}
{% endfor %}
Slide 60
Slide 60 text
Persistence
Slide 61
Slide 61 text
ORM
Object Relational Mapping
Slide 62
Slide 62 text
QueryKit
http://querykit.org/
let user = User.queryset(context)
.filter { $0.name == "Kyle" }
.orderBy {}
.first
Slide 63
Slide 63 text
No content
Slide 64
Slide 64 text
Redis (Redbird)
let client = try Redbird(config: ...)
// Set name to MCE
try client.command("SET", params: ["name", "MCE"])
// Get the name
try client.command("GET", params: ["name"])
Slide 65
Slide 65 text
PostgreSQL
let connection = Connection(host: "localhost", databaseName: "db")
try connection.open()
let usernames = try connection.execute("SELECT username FROM users").map {
try $0.data("username")
}
Slide 66
Slide 66 text
Testing
Slide 67
Slide 67 text
Spectre
http://spectre.fuller.li/
Slide 68
Slide 68 text
describe("a person") {
let person = Person(name: "Kyle")
$0.it("has a name") {
try expect(person.name) == "Kyle"
}
$0.it("returns the name as description") {
try expect(person.description) == "Kyle"
}
}
Slide 69
Slide 69 text
No content
Slide 70
Slide 70 text
XCTest
Slide 71
Slide 71 text
class PersonTests: XCTestCase {
let person = Person(name: "Kyle")
func testPersonName() {
XCTAssertEqual(person.name, "Kyle")
}
func testPersonDescription() {
XCTAssertEqual(person.description, "Kyle")
}
}