Truths Universally Acknowledged: Swift Design Patterns as Jane Austen Heroes northofnormal Hey, welcome to this, hope this is what you want, where to find me, etc.
A presentation at Penguicon in May 2018 in Southfield, MI, USA by Anne Cahalan
Truths Universally Acknowledged: Swift Design Patterns as Jane Austen Heroes northofnormal Hey, welcome to this, hope this is what you want, where to find me, etc.
How to tell you are in a Jane Austen Novel • Someone disagreeable is trying to persuade you to take a trip to Bath Hi! I’m Anne Cahalan. I’m an application developer at Detroit Labs, working mainly in iOS. I’ve been doing that for about five years, and before that I was doing entirely different things.
How to tell you are in a Jane Austen Novel • A woman who hates you is playing the pianoforte I actually started learning Objective C just a few months before Swift was announced, so that was awesome use of my time. But I made the transition pretty quickly and started to dig into the language and learning how to think in Swift.
Code Crush Marketing made me do it. And I got better at it, and found a few things I particularly liked, and then the person who runs the blog at Labs strongarmed me into writing an article about one thing I particularly liked. And so I wrote about how I fell a little bit in love with Guard Statements, because they remind me of a romantic hero, charging in to save the day.
How to tell you are in a Jane Austen Novel • You once took a walk with a cad And actually, I started to realize that a lot of my experiences learning swift have felt like dealing with various romantic heroes. Specifically, those of my favorite author, Jane Austen.
Jane Austen If you’ve interacted with popular culture at all, ever, you are familiar with the works of Jane Austen. Her plots have been recycled in one way or another in every romantic comedy ever.In a nutshell, Jane Austen wrote 6 novels from 1787 to about 1811. She wrote mainly about the lives of women, how they navigated the social constraints and expectations of her particular time and place. She gets dismissed a lot as having written silly romantic novels, but although all of them end with the heroine marrying her beloved, they involve at lot more cutting social insight and commentary than they are given credit for. But we’re not here to talk about feminism and Jane Austen—I can do that later, if you want—we’re hear to talk swift and Jane Austen.
Delegates & Protocols Mr Darcy Pride and Prejudice Let’s start with Austen’s most famous work, and swift’s possibly most famous design pattern—Swift has been described as a protocol oriented programming language.
Pride And Prejudice • Mr. Fitzwilliam Darcy arrives at Netherfield Hall, immediately is horrified by the neighbors and makes a terrible impression on Ms. Elizabeth Bennet • Shortly thereafter, army officer Mr. Wickham arrives in town and makes a much better impression on the local ladies. • A series of events, Darcy eventually warms to Lizzie, while she’s seeing the appeal of Mr. Wickham. • So Darcy rushes to her side to tell her that, despite her appalling family and the fact that she is so terribly beneath him, he has, despite all his better judgment, fallen in love with her. I promised you there wouldn’t be any homework for this, so I’ll recap the plot for you very quickly. (Do that) I’m zipping over a lot here, but I’ll give you the important parts. Protip: if you are declaring undying love for and proposing marriage to someone, maybe don’t rattle on at length about how embarrassing they are and how you tried really hard not to love them, but it didn’t work out.
Pride And Prejudice • Meanwhile, Wickham disappears with Lizzie’s younger sister—without marrying her. • Everyone panics, Mr. Bennet goes looking for his lost daughter but returns without her—only to find that somehow, everything has worked out for the best. • Wickham has married Lydia in return for an annual income…paid for by Darcy! • Darcy returns, he and Lizzie take a walk in a garden and he proposes. this glosses over a lot, including some of my favorite characters, but the important part, the part you’ve seen over and over again, is that two people meet, hate each other, then fall slowly in love.
Protocols And Delegates “A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.” From the swift documentation Translation: it’s a contract that your class conforms to or a blueprint for its behavior. Each delegate has a set of default behaviors - protocols - and variable declarations, both required and optional, that it must conform to. It’s up to each delegate to actually implement this functionality, though.
public protocol WooingDelegate { func wooingAttempt() } struct gentleman: WooingDelegate { func wooingAttempt() { print(“You must allow me to tell you how ardently I admire and love you.”) } } struct scoundrel: WooingDelegate { func wooingAttempt() { print(“I know it’s not funny, but your perfume smells like your daddy’s got money.”) } } Let’s say we’ve got some scoundrels, and some gentlemen going a-courting. Both of them conform to the wooing delegate, which means that they promise to have a method called wooingAttempt. But as you can see, each one woos very differently.
class suitorTableViewCell: UITableViewCell { // some cell set up var wooingDelegate: WooingDelegate @IBAction func wooingButtonTapped(sender: UIButton) { wooingDelegate.wooingAttempt() } } Why does that matter? Well, let’s say that you are keeping track of your suitors in a tableView. That’s organized of you. And you want each tableViewCell to have a button that will show you each suitor’s best wooing. By using a protocol and setting a wooing delegate, your tableViewCells don’t need to know or care if any particular suitor is a gentlemen or a scoundrel.
extension SuitorListViewController: UITableViewDelegate, UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 2 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0 { return gentlemen.count } else if section == 1 { return scoundrels.count } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: “SuitorListTableViewCell”) as! SuitorListTableViewCell let suitor = suitorList[indexPath.row] cell.setupCell(with: suitor) } return cell } In fact, a tableview is a great example of the power of delegates and protocols because a lot of the tedious work of setting up a tableview happens in protocols. If you want your view controller to conform to the protocols of UITableViewDelegate and UITableViewDataSource—and you do want that, if you want to use a tableview—you need to define the number of sections and rows you will have, and define a cell for each index path. Under the hood, some math happens to layout all these sections and rows and that math is consistent across all tableviews. When you set up a tableview, you know what you are going to get. Because the work happens in the protocol, and by making these methods required, the whole mess won’t run unless you give it all the info it needs to layout the screen.
extension WooingDelegate { func sendLoveLetter() { print(“You pierce my soul. I am half agony, half hope. Tell me not that I am too late, that such precious feelings are gone for ever. I offer myself to you again with a heart even more your own than when you almost broke it, eight years and a half ago. Dare not say that man forgets sooner than woman, that his love has an earlier death. I have loved none but you. Unjust I may have been, weak and resentful I have been, but never inconstant.”) } } That’s one use of protocols, and it’s pretty handy. But protocols can be extended to include some default implementation. So, for instance, if all your suitors send the same love letters—and if you need to send a love letter, Wentworth’s letter to Anne is a good choice. You can set up a default implementation of a love letter, and all that conform to this wooing delegate can send the exact same letter.
class suitorTableViewCell: UITableViewCell { // some cell set up var wooingDelegate: WooingDelegate? @IBAction func wooingButtonTapped(sender: UIButton) { if let wooingDelegate = wooingDelegate { wooingDelegate.wooingAttempt() } } @IBAction func sendLoveLetterButtonTapped() { wooingDelegate.sendLoveLetter() } } Persuch.
How are Protocols & Delegates like Mr. Darcy? • They seem smug Because P&D feels like titled nobility coding practice. This is some fancy pants business, the first time I encountered it, and I felt like this code thought it knew something I didn’t. Why couldn’t I do this with inheritance? Or by coupling together the tableViewCell with the data it contains? Why not create a separate type of tableViewCell for scoundrels as opposed to gentlemen? Well, where does that road end—do we make a different cell for social climbers? cads? well meaning dolts? Because, as it turns out, those things can lead to Wickhamlevel disgrace. Bad, indiscreet code, tightly and inappropriately coupled together can only bring shame on you and your entire family.
How are Protocols & Delegates like Mr. Darcy? • They seem smug • They can be inscrutable Mr. Darcy, it turns out, was just a kind of awkward guy with resting bitch face. Which can, if you don’t know, feels like silent judginess. When I first encountered them, they felt inscrutable. Why was there this wall in between the code I was looking at and what it was actually doing? It puts another layer of complexity on things, another place where I had to look to see what was going on.
How are Protocols & Delegates like Mr. Darcy? • They seem smug • They can be inscrutable • They will save the day, behind the scenes But in the end, cleanly separated code following a defined contract is not only perfectly upstanding and respectable, but it will quietly rescue you from all manner of disaster. We won’t need a thousand types of tableViewCells, we won’t need to couple together each instance of a suitor to a unique cell. We can share code that’s common.
How to tell you are in a Jane Austen Novel • You develop a resentment at a public dance So that’s Mr. Darcy and Protocols and maybe also a lesson about snap judgments and letting your own pride blind you to the possibilities of something.
Enums Capt. Wentworth Persuasion And here we have what is not necessarily my favorite swift feature, but definitely my favorite Austen hero. True story—I used to have a copy of Persuasion in my car, and if I was stuck in traffic or stopped by a train, I’d open it to the end and read my favorite part.
Persuasion • 7 years ago, Anne Elliot broke an engagement to a young naval officer, Frederick Wentworth. • He was confident and ambitious, but not of a particularly noteworthy family—her father and sisters convinced her that she would be marrying beneath her station. The Elliot family is old, titled, landed. • But time passes, and Freddie Wentworth becomes the decorated Capt. Wentworth, but as for Anne, “her bloom had vanished early…she was faded and thin.” • And the proud Elliot family has fallen into debt and been reduced to renting out their manor to another naval officer Persuasion is one of those novels that opens several years after a bunch of things happen, in this case… Anne’s father has been spending beyond his means for years, and it’s starting to catch up to them. They rent the hall, and because this is a novel, they end up renting it to friends of Capt. Wentworth
Persuasion • One day, on a walk with Capt. Wentworth and some friends, one of the women falls and is terribly injured. Everyone freaks out, Anne is calm and level-headed • Wentworth starts to reconsider his resentment of Anne, but he’s still pretty upset over the whole getting dumped thing • In a drawing room, Anne has a conversation with a gentlemen over wether women or men fall out of love quicker • Capt. Wentworth overhears and hides a letter to Anne declaring his love. Anne and Capt. Wentworth reconnect, but he’s kind of bitter about the whole getting dumped thing and she’s quietly pining away for him It’s the Napoleonic Wars, England is lousy with naval officers Wentworth starts reconsidering…
func setupCell(for setting: String, suitor: String) { let cell = SettingCell() if setting == “Netherfield Hall” { cell.backgroundColor = .blue } else if setting == “Cleveland Park” { cell.backgroundColor = .yellow } else if setting == “Kellynch Hall” { cell.backgroundColor = .green } } if suitor == “Darcy” { suitorLabel.text = “Insufferable, but maybe not?” } else if suitor == “Wickham” { suitorLabel.text = “Immoral con-man” } else if suitor == “Willoughby” { //you know what, this is exhausting logic and I got tired } Let’s go back to our sorting of suitors. Let’s say we want to change our background color and some label text based on our setting and the suitor in question. We can pass in which setting and which suitor each cell is for and do a huge chain of if/else’s, and our setup method will be 900 lines long. And even if we pull some of this out into smaller methods, we’re still doing a lot of work here that maybe we don’t need to do.
func cellSetup(for setting: String, suitor: String) { let cell = SettingCell() switch setting { case “Netherfield Hall”: cell.backgroundColor = .blue case “Cleveland Park”: cell.backgroundColor = .yellow case “Kellynch Hall”: cell.backgroundColor = .green } switch suitor { case “Darcy”: suitorLabel.text = “Insufferable, but maybe not?” default: // you know what, I’m still tired } } What if we tried this a different way, and switched on the settings and suitors instead? Okay, this is a little easier to scan. Kinda. Feels a little more big-girl-pants developer to do it this way but I’m not sure what it gains us in terms of cleanliness or readability. What if we thought more directly about what we know, and what we need?
What do we know? • We know we have a limited number of settings • We want to associate a background color with each setting • Each setting has certain associated suitors What do we know? We know we have a limited number of settings and that we want to associate a background color to each of them. We know that certain suitors are only found in certain settings. Why don’t we make a thing that holds our discrete settings, the colors we want, and the suitors?
enum Setting { case netherfieldHall case clevelandPark case kellynchHall var backgroundColor: UIColor { switch self { case .netherfieldHall: return .blue case .clevelandPark: return .yellow case .kellynchHall: return .green } } } Like maybe an enum, with some computed properties?
enum Setting { … var suitors: [Suitor] { switch self { case .netherfieldHall: return [.wickham, .darcy] case .clevelandPark: return [.willoughby, .brandon] case .kellynchHall: return [.wentworth] } } } enum Suitor { case wickham case darcy case willoughby case brandon case wentworth var name:String { switch self { case .wickham: //…etc } var description: String { switch self { case .wickham: // …etc } And maybe some of those computed properties will be enums of their own with their own computed properties? Now we’ve got our set of suitors, with their names and descriptions, and our settings, with their discrete suitors associated with them directly.
func doSomeSettingUIBusiness() { backgroundColor = setting.backgroundColor for suitor in setting.suitors { print(“(suitor.name): (suitor.description)”) // maybe do something useful in the UI, like set some labels } } And if we want to, for example, set up a screen with a background color and some labels about our suitors…
How do we get from enums to dreamy sea captains? • If blocks are expensive, spendthrift with your attention — like Anne’s father, blowing through the family fortune if… blocks are expensive, spendthrift with your attention & brainpower. I won’t bore you with my entire work history, but my new swift project was a foodordering app and I was working on UI styling and we had a lot of tableViews whose structure and appearance depended heavily on other things—was it a delivery or a pickup order? which of five or so menus was this screen building? And I was coding that in increasingly dense if-blocks that were starting to get very mentally expensive.
How do we get from enums to dreamy sea captains? • If blocks are expensive, spendthrift with your attention — like Anne’s father, blowing through the family fortune • Enums & Switches in Swift have more opportunity, now — like Capt. Wentworth prospering from the Napoleonic Wars Like Wentworth, both the switch and the enum constructions have been around for a while. In ObjC, switch statements were kind of limited. You could only switch on integral types. But Swift has given the switch statement broader horizons. We can switch on strings, now, or on types, or on ranges, or on tuples. And Swift lends itself more to using enums and structs than Objective C did.
How do we get from enums to dreamy sea captains? • If blocks are expensive, spendthrift with your attention — like Anne’s father, blowing through the family fortune • Enums & Switches in Swift have more opportunity, now — like Capt. Wentworth prospering from the Napoleonic Wars • New times and new languages require new ways of thinking Anne’s father was hung up on the old rules and old approaches. In his day, the naval service Wentworth had entered was not seen as a road to great wealth and advancement. Then the wars started and suddenly things changed. Getting in on the ground floor of development with Swift has been super interesting, because it’s been a chance for me to experience the entire iOS community learning—deciding, in a way—how to THINK in Swift. What is the “swifty” approach. I spent some time last year on a project that we started in Swift 1, before a lot of the Swift idioms and approaches had been worked out, and it reads like ObjC google-translated into Swift. Old tools and old ideas have come out in front in unexpected ways, like Wentworth finding his fortune. I think that’s kinda cool.
How to tell you are in a Jane Austen Novel • You have five hundred a year. From who? Five hundred what? No one knows. No one cares. You have it. It’s yours. All five hundred of it. So we’ve got the thing that I kind of hated but eventually won me over, and the thing that I finally saw the value of after a while. But we all know where my heart truly lies with swift, so let’s get to maybe my second-favorite Austen hero and far and away my favorite thing in swift.
Guard Statements Col. Brandon Sense and Sensibility
Sense And Sensibility • Marianne Dashwood meets the charming Mr. Willoughby when she sprains her ankle on a walk and he gallantly carries her home • The two are inseparable and deeply in love, but suddenly Mr. Willoughby departs for London and stops answering Marianne’s letters • Meanwhile, Col. Brandon shows up and is obviously taken with Marianne. She’s not interested. Here we’re going to talk about the B Plot of S&S. The A plot revolves around regency era inheritance law and the kinds of wacky hijinks that ensue when you have four brothers all called “Mr. Ferrars.” MD is a very romantic and sensitive soul It’s raining, she’s out walking on the moors, he gallops up on his mighty steed, there is not a single romance novel cliche left out.
Sense And Sensibility • Marianne is invited to London, where she hopes to meet Mr. Willoughby again • And she does, at dance where he is incredibly rude to her— and announces his engagement to a wealthy heiress • Distraught, Marianne falls ill and Col. Brandon helps care for her, reading her sonnets • And Col. Brandon and Marianne get married Again, story you’ve heard a million times: woman falls for a confusing jerk, gets her heart broken by him, sees the value of the good guy who was there all along.
Guard Statements “A guard statement is used to transfer program control out of a scope if one or more conditions aren’t met” The mind turns naturally to guard statements. Again, from the docs. Basically, it’s an improvement upon the if x = !y { do a thing } construction.
func createSuitor() { if let name = caller.name{ if let hatType = caller.hat() { if let incomeLevel = caller.income { if let horseName = caller.horse() { sendToServer(name, hat: hatType, income: incomeLevel, horse: horseName) } else { print(“No horse”) } } else { print(“No income”) } } else { print(“No hat”) } } else { print(“No name”) } } Want to add a suitor? Need to know name, income, hat, and horse. Standards! This? This is confusing. This looks like it’s your friend, it cuddles up to you and makes all kinds of promises, you think it’s lining up all your expectations… But when you have to debug this code in a hurry because you need to a get a build to the client by the end of the day, that’s just when this code is going to fuck off to London and stops taking your calls. The most important part of this code, the thing it actually does, is buried in the deepest part of the indentation. You have to be careful with this kind of code, because it’s super easy to get ahead of yourself and misunderstand what’s happening. To make assumptions about where you are going and get your heart broken. As far as MD was concerned, the most important thing to know about Willoughby—that he was kind of a jerk, and kind of already engaged—was hidden.
func createSuitor() { guard let name = caller.name else { print(“No name”) return } guard let hasHat = caller.hasHat else { print(“No hat”) return } guard let income = caller.income else { print(“No income”) return } guard let hasHorse = caller.hasHorse else { print(“No horse”) return } } sendToServer(name, hasHat: hasHat, income:income, hasHorse: hasHorse) This, on the other hand is very straightforward, and a little poetic. You can see immediately where the path exits, and the actual work of the function, the most important part, is right up front for everyone to see. There’s no mystery here. Like Brandon, it has it’s heart on it’s sleeve. And it’s kind of lovely, isn’t it? There’s some artfulness here, but not at the expense of readability. I like it.
How is a guard statement like Col. Brandon? • Was Marianne settling for the boring guy—or finding romance where she wasn’t looking for it? Sam didn’t like it, etc. Settling vs. finding what you are looking for in an unexpected place—Marianne was looking for the man who would sweep her off her feet when she needed him, and who would read her poetry—like Col. Brandon did when she was ill. For me, the power of a guard statement is in finding something I’ve been looking for in an unexpected place.
How is a guard statement like Col. Brandon? • Was Marianne settling for the boring guy—or finding romance where she wasn’t looking for it? • Elegant in both the scientific and aesthetic sense Guard statements are elegant scientifically and artistically, both in what it is doing, and how it does it. I mean, listen to it: Guard Let… it starts with a perfect iamb, the cadence of poetry and of the English language. There’s an gracefulness of language—what we call syntax—at work here, it’s beautiful in a way you don’t really expect code to be I know code can be a creative endeavor, but I don’t think people expect to see actual poetry, and for me, a guard statement is like poetry.
How is a guard statement like Col. Brandon? • Was Marianne settling for the boring guy—or finding romance where she wasn’t looking for it? • Elegant in both the scientific and aesthetic sense • truth vs. Truth It’s the difference between talking at length about meeting people where they are, loving them entirely and saying, “Love is not love…” It’s the same thing, but one speaks truth with a small t and T, truth in a universal sense. And that lead me to an interesting and kind of sobering thought—>
If you can find capital-T-truth in your code… that means you can put capital-T-truth in your code. This is a powerful realization, and a big responsibility. Code can be creative, but how often do we spend thinking of ourselves as creators in the same manner as poets and playwrights? If programming is the new literacy, what are we writing?
What are the Truths in your code? We have control over huge parts of our user’s lives—their financial information, their personal information, (dating apps) hopes & dreams, (social app) their own self-expression. What greater truths are we revealing about privacy, security, safety, social interaction with our code?
How to tell you are in a Jane Austen Novel • You are in a garden, and you are astonished In general, I spend a lot of time feeling like the code I am looking at is a garden, and I am constantly astonished by it. By the powerful things we can do, by the interesting ways we can do them, by the ways we can use syntax to express an idea. Well written code should tell a story as clearly as any novel does. Hopefully, I’ve given you another way of thinking about your code, whether it’s in swift or not, so you can go off and write code stories as universally truthful as Austen’s.
northofnormal You can reach me at northofnormal on pretty much all the things, and I’d love to hear about your code heroes and your code stories.