Extending Swift Value(s) to the Server David Ungar and Robert Dickerson Beijing Boston Farnham Sebastopol Tokyo Extending Swift Value(s) to the Server by David Ungar and Robert Dickerson Copyright © 2017 IBM Corporation All rights reserved Printed in the United States of America Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472 O’Reilly books may be purchased for educational, business, or sales promotional use Online editions are also available for most titles (http://safaribooksonline.com) For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com Editors: Nan Barber and Susan Conant Production Editor: Shiny Kalapurakkel Copyeditor: Christina Edwards Proofreader: Eliahu Sussman Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Rebecca Panzer First Edition January 2017: Revision History for the First Edition 2017-01-25: First Release The O’Reilly logo is a registered trademark of O’Reilly Media, Inc Extending Swift Value(s) to the Server, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc While the publisher and the authors have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the authors disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work Use of the information and instructions contained in this work is at your own risk If any code samples or other technology this work contains or describes is sub‐ ject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights 978-1-491-97196-3 [LSI] Table of Contents Preface: Swift for the Rest of Your Application v A Swift Introduction Types and Type Inference Syntax Simple Enumerations Tuples Custom Operators Closures Object Orientation Protocols Define Interfaces Extending Classes, Structures, and Enumerations 2 3 7 Optional Types, Structures, & Enumerations 13 Optional Types Exterminate Nil-Value Bugs Structures Isolate Mutation Enumerations with Associated Values Choosing an Aggregate 13 15 21 24 Swift Promises to Tame Asynchrony 29 Step 1: Chaining Synchronous Errors Step 2: Linearizing Nested Callbacks Step 3: Coping with Asynchronous Errors 30 35 40 Swift Package Manager 43 Semantic Versioning Creating an Application 44 44 iii Importing a Library in Your Project Developing in Xcode Creating Your Own Library Producing More Complex Projects Using C Dynamic Libraries 47 50 51 54 55 Writing a To-Do List with Kitura 57 Servers and Routers Creating a Web Service Deploying Your Application to Bluemix More Elaborate To-Do Items Adding Authentication Setting up the Database Connecting to the Database 57 59 62 65 68 69 71 Conclusions 75 iv | Table of Contents Preface: Swift for the Rest of Your Application Q: Why did the human put on his boxing gloves? A: He had to punch some cards Today’s applications not run on a single platform Rather, some parts run on resource-limited devices, and other parts run on a vast and mysterious cloud of servers This separation has led to a schism in how we build these applications because different platforms have different requirements: the mobile portions must conserve battery power, while the server portions must handle a large number of requests simultaneously Consequently, programmers use different languages for different parts of applications—for instance, JavaScript for the browser, and Java for the server However, constructing an application out of multiple languages is fraught with drawbacks: different teams in the same organization speak different languages—literally—and must master different developer ecosystems Precious time must be spent translating con‐ cepts across language barriers and a few developers must know all of the languages in order to be effective Test cases and data models must be replicated in different languages, introducing bugs and incurring future maintenance efforts Because third-party libraries cannot be shared across groups, each team must learn different APIs to obtain merely the same functionality Swift was introduced by Apple in 2014 and replaced Objective-C as the recommended language for all new applications running on Apple devices Later, when Swift became open source in 2015, it spread to new platforms Currently, Swift is available on x86, ARM v (including Raspberry Pi), and zOS architectures, as well as Linux, macOS, tvOS, watchOS, and iOS operating systems So, it is now possible to write a whole end-to-end mobile application— front-end, middle, back, and even toaster—all in Swift That’s why we wrote this book; we wanted to help you, the developer, who is most likely writing in Java or JavaScript, to consider a switch to Swift Why adopt Swift? • The Swift language may well be better than what you are cur‐ rently using • You can develop and debug in a consistent environment Inte‐ grated development environments (IDEs) offer a tremendous amount of functionality such as text editing, static analysis, code completion, debugging, profiling, and even source-control inte‐ gration Switching back and forth between say, Eclipse and Xcode is a bit like switching between French horn and electric guitar: neither easy nor productive • You can reuse code When each bit of functionality is expressed exactly once, there is less work, more understanding, and fewer bugs • You can leverage Swift’s features—such as optional types, value types, and functional programming facilities—to detect many bugs at compile time that would otherwise be hard to find • Since Swift uses the LLVM compiler toolchain for producing native-code binaries, your applications have the potential for competitive performance in terms of speed, startup time, and memory usage However, examination of performance is out‐ side the scope of this book • You will find an active and approachable community of Swift developers who are creating web posts, books, and videos In 2016, Swift was cited as the second “Most Loved” language in a StackOverflow survey, and the third most upward trending technology This book will introduce you to the Swift language, illustrate some of its most interesting features, and show you how to create and deploy a simple web service Let’s get started! vi | Preface: Swift for the Rest of Your Application Coding Style & Implementations In the examples, the space constraints of this medium have led us to indent, break lines, and place brackets differently than we would in actual code In addition, space has precluded the inclusion of full implementa‐ tions and blocks of code in this edition contain incon‐ sistencies in color and font If the inconsistencies confuse you, please consult the repositories in Table P-1 Table P-1 Where to find code examples Repository name Book snippets MiniPromiseKit Pipes Kitura To-Do List Referenced in Code snippets from the book Created in Chapter 3; used in Chapter Used in Chapter Created in Chapter Acknowledgments This book would not have been possible without the support, encouragement, and guidance of the IBM Cloud and Swift@IBM leadership team, including Pat Bohrer, Eli Cleary, Jason Gart‐ ner, Sandeep Gopisetty, Heiko Ludwig, Giovanni Pacifici, John Ponzo, and Karl Weinmeister In addition, we want to extend our thanks to the many IBM Swift engineers and Swift community members working to bring Swift to the server—including Chris Bai‐ ley, Hubertus Franke, David Grove, David Jones, and Shmuel Kall‐ ner—for sharing their collective technical insights and creating the tools and libraries described herein The Swift community’s embrace of Swift on the server reassured us that our contribution would be valued The growing number of their instructive blog posts, videos, conference talks, and books have been of great help We would like to thank our technical reviewers: Chris Devers, Shun Jiang, and Andrew Black Nan Barber and the O’Reilly team had the daunting task of editing our lengthy technical drafts and producing this book We owe a huge debt of gratitude to the Apple Core Swift Team for their courage, intelligence, talent, wisdom, and generosity for bring‐ ing a new language and ecosystem into existence and moving it to open source Language design involves many difficult and complex tradeoffs, and bringing a new language to the world requires a tre‐ Preface: Swift for the Rest of Your Application | vii mendous amount of work The rapid acceptance of Swift by devel‐ opers is powerful testimony to the quality of the language Words fall short in plumbing the depths of our gratitude for the support and love of our sweethearts, Barbara Hurd and Valerie Magolan viii | Preface: Swift for the Rest of Your Application Deploying Your Application to Bluemix There are many options for deploying a Kitura web application If you use a Docker-based platform, there is a Swift Dockerfile and image at DockerHub If you use a CloudFoundry environment, you can use a Swift buildpack for deploying your application Swift applications are compiled to native binary, which means that the binary must match the platform that will be running the application This ahead-of-time compilation might be different from what you are used to if you use NodeJS, where the code is just-in-time com‐ piled, or Java, where the compiled byte-code runs in a virtual envi‐ ronment The IBM Bluemix cloud application platform supports Swift as a first-class language along with JavaScript (NodeJS) and Java (Lib‐ erty) If you choose to deploy your application with IBM Bluemix, you may consider using the IBM Cloud Tools for Swift The tool can be used to generate new starter applications, such as a TodoList ser‐ vice or an image-sharing service It can help you deploy any Swift application to Bluemix You can monitor a deployed application as shown in Figure 5-1 It will also help you configure your iOS appli‐ cation to direct network requests to the URL of the deployed web service once it’s on Bluemix 62 | Chapter 5: Writing a To-Do List with Kitura Figure 5-1 IBM Cloud Tools for Swift helps users create new Kitura applications or start with sample applications and deploy them to Bluemix If you are not on a Mac, or wish to use the command line, you must first create some files to prepare your project for deployment Because Bluemix is a CloudFoundry-based hosting platform, it uses buildpacks for deploying your code These buildpacks are scripts that are used to build your project in the cloud When you push your application to Bluemix, your code is bundled and uploaded to a build server The code is compiled based on the Swift buildpack Next, Bluemix uploads copies of the binary onto the number of vir‐ tual machine instances that you provisioned When the application is launched, and a load balancer distributes network traffic to all of your instances running your server To describe your deployment, your application must have a manifest.yml in the root path This manifest file declares the appli‐ cation’s memory requirement, the number of instances, hostname, and the address to the buildpack Deploying Your Application to Bluemix | 63 applications: - name: todolist memory: 256M instances: random-route: true buildpack: https://github.com/IBM-Swift/swift-buildpack.git Next, you must include a Procfile It specifies the executable to run once the instance has been provisioned and ready for running Assuming the executable name is “Server,” the Procfile would be: web: Server When the application runs on Bluemix, it will be automatically assigned a port that it must listen on This port number can be retrieved with the Swift-cfenv library and used in a new HTTP server as follows: import CloudFoundryEnv { let appEnv = try CloudFoundryEnv.getAppEnv() let port: Int = appEnv.port Kitura.addHTTPServer(onPort: port, with: router) } catch CloudFoundryEnvError.InvalidValue { print("Oops, something went wrong Server did not start!") } You might consider adding the preceding code to all of the applica‐ tions you intend to deploy to Bluemix, because when the application is running on Bluemix, the port will match what Bluemix gives your application However, if these cannot be found in the environment variables, the application is assumed to be running in a development environment, and therefore localhost:8090 will be used instead When you’re ready to deploy your application, you can install and use the Bluemix CLI tools Once installed, you can use the cf utility to push the code to the server: $ cf push This step will take roughly four to five minutes After your applica‐ tion has been deployed, you will see the assigned hostname Navi‐ gate your browser or use cURL to test your app: $ curl https://.bluemix.net/v1/string/item 64 | Chapter 5: Writing a To-Do List with Kitura More Elaborate To-Do Items You might want a to-do item to have more properties than just a String, for example, ID, completion status, and due date For now, you’ll extend the code so that each item includes an ID and a title Start with a Dictionary Before moving straight to using a structure for this purpose, you will use a dictionary to store these fields Such a Dictionary is denoted by [String: Any], and an array of them by [[String: Any]] Define the array of items and the semaphore: var itemDictionaries = [[String: Any]]() let itemDictionariesLock = DispatchSemaphore(value: 1) This simple, untyped model corresponds so closely to JSON that only small changes are needed to the handlers func handleGetItemDictionaries( request: RouterRequest, response: RouterResponse, callNextHandler: @escaping () -> Void ) throws { response.send(json: JSON(itemDictionaries)) callNextHandler() } func handleAddItemDictionary( request: RouterRequest, response: RouterResponse, callNextHandler: @escaping () -> Void ) { guard case let json(jsonBody)? = request.body, let title = jsonBody["title"].string else { response.status(.badRequest) callNextHandler() return } itemDictionariesLock.wait() itemDictionaries.append( [ "id": UUID().uuidString, "title": title ] ) itemDictionariesLock.signal() response.send("Added '\(title)'\n") More Elaborate To-Do Items | 65 callNextHandler() } Register the handlers: router.get ("/v1/dictionary/item", handler: handleGetItemDictionaries) router.post("/v1/dictionary/item", handler: handleAddItemDictionary) Test: $ curl -H "Content-Type: application/json" \ -X POST \ -d '{"title":"Reticulate Splines"}' Added 'Reticulate Splines' $ curl localhost:8090/v1/dictionary/item [ { "id" : "2A6BF4C7-2773-4FC9-884C-957F205F940A", "title" : "Reticulate Splines" } ] Move to a Structure Now, represent an item with a structure This change will allow the item to be expressed in Swift more naturally, and has the benefit of guaranteeing type safety on the properties: struct Item { let id: UUID let title: String } var itemStructs = [Item]() let itemStructsLock = DispatchSemaphore(value: 1) The transition from a dictionary to a struct requires you to write some code to convert Items to and from JSON Create the conver‐ sion routines for Item: enum ItemError: String, Error { case malformedJSON } extension Item { init ( json: JSON ) throws { guard let d = json.dictionary, let title = d["title"]?.string else { throw ItemError.malformedJSON } id = UUID() 66 | Chapter 5: Writing a To-Do List with Kitura title = title } var dictionary: [String: Any] { return ["id": id.uuidString as Any, "title": title as Any] } } Write the new handlers: func handleGetItemStructs( request: RouterRequest, response: RouterResponse, callNextHandler: @escaping () -> Void ) throws { response.send( json: JSON(itemStructs.dictionary) ) callNextHandler() } func handleAddItemStruct( request: RouterRequest, response: RouterResponse, callNextHandler: @escaping () -> Void ) { guard case let json(jsonBody)? = request.body else { response.status(.badRequest) callNextHandler() return } { let item = try Item(json: jsonBody) itemStructsLock.wait() itemStructs.append(item) itemStructsLock.signal() response.send("Added '\(item)'\n") callNextHandler() } catch { response.status(.badRequest) let err = error.localizedDescription response.send(err) callNextHandler() } } Register the handlers: router.get ("/v1/struct/item", handler: handleGetItemStructs) router.post("/v1/struct/item", handler: handleAddItemStruct) More Elaborate To-Do Items | 67 Test: $ curl -H "Content-Type: application/json" \ -X POST \ -d '{"title":"Finish book!"}' localhost:8090/v1/struct/item Added 'Item(id: 054879B8-B798-4462-AF0B-79B20F9617F4, title: "Herd llamas")' $ curl localhost:8090/v1/struct/item [ { "id" : "054879B8-B798-4462-AF0B-79B20F9617F4", "title" : Finish book! } ] Adding Authentication You may not want to allow a user to add a task to someone else’s list In order to prevent that from happening, you must first add a layer of authentication User identity will be assured by the client securely sending a token that uniquely identifies the user This token is obtained by a third-party service the user already has an account on, such as Facebook, Google, GitHub, or LinkedIn This method is convenient and more secure because your application’s database will not need to store each user’s login name and password The database can just link each user’s login name to that user’s to list items Kitura has a middleware library called Kitura Credentials that makes it easy to add authentication to your application There are several plug-ins that currently support Facebook, Github, and Goo‐ gle OAuth token validation In addition, there are plug-ins for HTTP basic and digest authentication The middleware intercepts each RouterRequest, and then ensures that the token in the header correctly authenticates the user The RouterRequest will only pro‐ ceed to execute the handler if the authentication succeeds The example below shows how to use the Facebook plug-in After credentials middleware is created, the Facebook plug-in is registered with the middleware Next, the routes matching the item resource are protected with the authentication layer This is useful, since there might be other routes that you might not want to protect; for instance, the welcome page The following sets up the authentica‐ tion: 68 | Chapter 5: Writing a To-Do List with Kitura let credentials = Credentials() let facebookCredentialsPlugin = CredentialsFacebookToken() credentials.register(facebookCredentialsPlugin) router.all("/v1/*/item", middleware: credentials) The login flow works as follows: The client must first obtain a Face‐ book OAuth token using the Facebook login web service If you are developing an iOS application, this is done through the Facebook SDK for iOS If you are developing a web application, you will use the Facebook SDK for JavaScript When the user imports the Face‐ book iOS SDK, it will allow you to present a Facebook login panel to the user requesting a username and password If the user has already signed into Facebook (and a cache exists with the token), the login screen is bypassed The username and password are sent to the Facebook server through HTTPS and, assuming the username and password checks out, an OAuth token is returned to the client The client then must include that token in the header of future requests to add or get items For Kitura Facebook Credentials to use this token, the client must bundle the token in the access_token header field, and “FacebookToken” in the X-token-type field for all HTTP requests The user’s Facebook profile information can be read using the userProfile attribute of the RouterRequest The code can obtain the user’s unique user ID from request.userProfile.id For brevity, we did not show how to relate a user ID to the to-do items, but this would be an easy modification to make to the above examples Setting up the Database There are many different databases to choose from if you are build‐ ing a to-do list in Swift You can see some examples by cloning our example Kitura TodoList applications, which will show you how to interface with some of the most popular databases You will see, for instance, MongoDB, PostgreSQL, Redis, and more There are many different database drivers for Swift in the Swift Package Cata‐ log Some were written using C bindings to existing database drivers written in C, so you may need to install some development headers and libraries before you can use them Others have been developed from the ground up with pure Swift and therefore will not require the installation of any additional libraries Setting up the Database | 69 In this section, we explain how to use CouchDB with your to-do list We chose this database since it will demonstrate how to make out‐ bound network calls from your server CouchDB uses a simple REST API that receives and accepts JSON payloads CouchDB is supported well on Bluemix as an offering called Cloudant Everything in CouchDB is a document In order to query the data‐ base, you must write a special kind of document called a design document that contains some logic that should be run in the data‐ base When that logic is run, it prepares a “view” that is returned to the user The map function is run on every document in the data‐ base Usually some condition is checked, and if it passes, a new document is emitted containing the values of that document Another kind of logic is the reduce function It is useful for collaps‐ ing the documents down to a single document For instance, if you wanted to get the count or the sum of many documents To create a design, open a new file named todolist_design.json, and add the following to it: { "_id": "_design/tododesign", "_views" : { "all_todos" : { "map" : "function(doc) { emit(doc._id, [doc._id, doc.title]); }" } } } Since CouchDB uses a REST API, you can make new designs, add documents, and query for documents all using basic HTTP calls Before showing how to write the Swift code for these network calls, it is helpful to see what the cURL commands would be for each of these operations For instance, to create a new database called todo‐ list: $ curl -X PUT http://127.0.0.1:5984/todolist To upload the todolist_design.json document to the newly cre‐ ated database: $ curl -X PUT http://127.0.0.1:5984/todolist/_design/tododesign \ data-dinary @todolist_design.json Then, in order to get back all the to-dos, you could make a request to: 70 | Chapter 5: Writing a To-Do List with Kitura $ curl http://127.0.0.1:5984/todolist/_design/tododesign \ /_views/all_todos To add a new item to the database, you make the call to the database with a UUID for the document ID: $ curl http://127.0.0.1:5984/todolist/ \ -d '{ "title": "Reticulate Splines" }' Now we can show how to make outbound network connections with Swift Connecting to the Database Because outbound network requests introduce a fair amount of complexity to your application, we recommend using a promise library You can add the promise library created in Chapter by adding the following dependency to Package.swift: Package(url: "https://github.com/davidungar/miniPromiseKit", majorVersion: 4, minor: 1) Now, you can extend URLSession to use a promise instead of using a callback: extension URLSession { func dataTaskPromise(with url: URL) -> Promise { return Promise { fulfill, reject in let dataTask = URLSession(configuration: default).dataTask( with: url) { data, response, error in if let d = data { fulfill(d) } else { reject(error!) } } dataTask.resume() } } } By default, the miniPromiseKit and PromiseKit libraries will use the main queue for dispatching the then, catch, and always blocks, so it is important to create a new concurrent queue and use it as the con‐ text for executing these blocks: let queue = DispatchQueue(label: "com.todolist.controller", qos: userInitiated, attributes: concurrent) Connecting to the Database | 71 The body of the firstly call returns a promise for the array of items In the examples below, url is the URL for the all_todos view Once the data is returned, we convert it to an array of items In the interest of space, we have omitted the dataToItems method, which does the JSON parsing Refer to it in the example code This method can throw an error if the data could not be parsed properly, and that error can percolate through the promise chain func getAllItems() -> Promise { return firstly { URLSession().dataTaskPromise(with: url) } then(on: queue) { dataResult in return try dataToItems(data: dataResult) } } You can add a task by sending a URLRequest with a PUT method Assume for the sake of this example that URL is the path to the data‐ base and the UUID of the item you want to insert—for example, "127.0.0.1:5984/todolist/E71233AD-01D2-430B-8708F7E2496AEFB2": func addItem(item: Item) -> Promise { return Promise { fulfill, reject in let session = URLSession(configuration: default) var request = URLRequest(url: url) request.httpMethod = "PUT" request.httpBody = try JSONSerialization.data( withJSONObject: item.dictionary, options: []) let dataTask = session.dataTask(with: request) { data, response, error in if let error = error { reject(error) } fulfill(item) } dataTask.resume() } } Next, you can write the handlers Promises help to improve the flow when responding to these error cases They help you write your error handling logic in a linear way The errors “short circuit” to the end of the handler where the code can serialize that error to the cli‐ ent Getting back a list of items takes the following steps: first, all of the items are retrieved from the database as a promise Once that 72 | Chapter 5: Writing a To-Do List with Kitura promise is fulfilled, the items can be sent back to the client But if there was an error with servicing the request, the error can be serial‐ ized back to the user In all cases, we want the next handler in the chain to be invoked: func handleGetCouchDBItems( request: RouterRequest, response: RouterResponse, callNextHandler: @escaping () -> Void ) throws { firstly { getAllItems() } then(on: queue) { response.send(json: JSON(items.dictionary)) } catch(on: queue) { response.status(.badRequest) response.send(error.localizedDescription) } always(on: queue) { callNextHandler() } } The add item handler also benefits from using promises A new item is parsed from the body, and the item is sent to the database to be persisted If there was an error either with the parsing or with the network connectivity, that error is handled and sent to the client: func handleAddCouchDBItem( request: RouterRequest, response: RouterResponse, callNextHandler: @escaping () -> Void ) { firstly { () -> Promise in guard case let json(jsonBody)? = request.body else { throw ItemError.malformedJSON } let item = try Item(json: jsonBody) return addItem(item: item) } then(on: queue) { item in response.send("Added \(item.title)") } catch(on: queue) { error in response.status(.badRequest) response.send(error.localizedDescription) } Connecting to the Database | 73 .always(on: queue) { callNextHandler() } } Register the handlers: router.get ( "/v1/couch/item", handler: handleGetCouchDBItems ) router.post( "/v1/couch/item", handler: handleAddCouchDBItem ) You can now test your application using the same aforementioned cURL statements $ curl -H "Content-Type: application/json" \ -X POST \ -d '{"title":"Finish book!"}' localhost:8090/v1/couch/item Added 'Item(id: 054879B8-B798-4462-AF0B-79B20F9617F4, title: "Finish book!")' $ curl localhost:8090/v1/couch/item [ { "id" : "054879B8-B798-4462-AF0B-79B20F9617F4", "title" : Finish book! } ] You have learned how to create a fully working to-do list application in Swift that uses a database and can be deployed to a server Scratch that off your bucket list 74 | Chapter 5: Writing a To-Do List with Kitura Conclusions Swift is a powerful programming language that supports both object-oriented and functional programming Its static type check‐ ing, type inferencing, optional types, value types, and closures allow you to write code that is clear, concise, and robust It catches more bugs at compile-time—such as accesses to nil values—than many other popular languages Swift’s facilities ease the implementation of constructs such as promises (a.k.a., futures) that greatly simplify asynchronous programming Its ahead-of-time compilation pro‐ vides predictable performance and plays nicely with libraries written in other languages such as C Swift is well suited for real applica‐ tions If you choose to implement your server-side code in Swift, you’ll find the necessary tools to help you The Swift Package Manager aids in importing other libraries into your project and building your application correctly The Kitura library helps get you started quickly building web apps by handling incoming web requests and routing them to your application code Bluemix and the IBM Cloud Tools for Swift provide for easy deployment We hope you consider writing the entire stack of your next applica‐ tion in Swift, from client to sensor to server Conclusions | 75 About the Authors David Ungar holds a Ph.D in Computer Science from U.C Berke‐ ley, taught at Stanford, and enjoys a research position at IBM in the Ubiquitous Platforms group in Cloud and Mobile Enterprise Research He loves programming and has enjoyed APL, C, C++, Smalltalk, Self (which he codesigned), Java, JavaScript, Objective-C, and Swift His interests have included UNIX system programming, microprocessors, object-oriented language design and implementa‐ tion, cartoon animation techniques for user interfaces, reflection APIs, IDEs, emergence for massive parallelism, and contextual pro‐ gramming Now he builds iOS and macOS applications Four of his papers have been honored by the Association for Com‐ puting Machinery for lasting impact In 2009, he was awarded the Dahl-Nygaard prize for outstanding career contributions to objectoriented language technology by the Association Internationale pour les Technologies Objets He blogs at http://blog.davidungar.net and tweets at @senderPath Robert F Dickerson is a software engineer in the Swift@IBM engi‐ neering group Having written many end-to-end applications in Java, JavaScript, and Swift (on iOS), he loves being able to write his server-side code in Swift! He was one of the original developers who made Kitura, a web-service middleware framework for Swift He leads a team that builds applications and libraries that use Kitura He is active in the open-source Swift community, where he has given talks about server-side Swift at AltConf 2016, Try! Swift NYC 2016, and the Server-side Swift Year-Long Conference 2016 Before joining IBM as a developer, he was on the faculty in the computer science departments at the College of William and Mary and then at the University of Texas at Austin He holds a Ph.D in Computer Sci‐ ence from the University of Virginia He blogs at https://developer.ibm.com/swift/ and tweets at @rfdicker‐ son ... init(city: String) { self.city = city } } After creating a request object: let request = TemperatureRequestClass(city: "Paris") Unless it is passed in-out, in which case the caller must mark it. .. Isolate Mutation | 19 init(city: String, state: String) { self.city = city self.state = state } var cityAndState: String { return city + ", " + state } } struct OzoneRequest let city: let state: var... Date? = nil init(city: String, state: String) { self.city = city self.state = state } var cityAndState: String { return city + ", " + state } } Both structures have identical cityAndState properties