I was editing my interview with Orta Therox yesterday when I realized I mentioned asking my boss Brad Larson what an object was.
I realized when listening to this that I hadn’t given any context because I wasn’t anticipating talking about that during the interview and I come off being rather ignorant in the course of this question. So, to avoid having to turn in my nerd card, I am going to give some context and give a more nuanced explanation behind that question.
My Personal Background with Object-Oriented Programming
I started going to school in 2010 for computer programming. I was 28 and I had almost no experience whatsoever with computer programming. My background was writing HTML when I was in high school and learning how to compile “Hello, world!” in Perl. At the time I enrolled I was working at Target because I failed to find a journalism job after I graduated and I really didn’t want to work at Target for the rest of my life. Programming seemed like it would be a good fit and it didn’t seem like it was going anywhere for a while.
I got through my first semester of introductory programming okay. Starting in your second semester, you had to pick a language to study for the next three semesters. At the time I was making this decision, there were three languages to pick from: Java, PHP, and VB.Net. I decided I would pick whichever one fit into my work schedule. The one that fit was VB.Net.
Our introductory class kept getting further and further behind. By the time we got to the end of the semester, we had never spoking about object-oriented programming. It was something we were supposed to do, but we just never got around to it.
The following fall, I took the advanced class. It was a night class, which I don’t really do well with anyway. The first class period, my teacher showed me object-oriented programming for the first time. I had no idea what the fuck he was talking about.
A bunch of code was in other files! How did it work together? How does the computer know to look in these other files?? Wait, what the hell is polymorphism? Am I having a bad acid trip??
After three hours of this, the teacher said since this was all review he was never going to go over any of this ever again. That was when I realized I was kind of screwed.
I decided to drop out after I asked what a constructor was and the teacher asked me if I learned anything the previous semester. At this point I had a decent job with people that I liked. I figured I was too stupid to learn programming because I wasn’t born with an intuitive sense for it and I was tired of feeling stupid all the time.
Six months after this, I took a new job that was the most miserable job I have ever had. The plus side to this job was that I taught myself programming while I was there. I realized I hadn’t put enough effort into it and if I just programmed forty hours a week I could learn it. So I went back to school.
I finally grokked OOP when I took the Intro to Java class. They introduced objects immediately and forced you to use them throughout the whole semester so you could get used to them. I started to understand about file paths and how the program knew how to find your other classes and how you imported them and how you constructed them. I felt like after I understood this for the first time that I was a “real” programmer. I hadn’t felt that way before grasping object orientation.
OOP is Not the Only Paradigm
I went from Java to iOS/Cocoa/Objective-C programming. I had a few vague issues when I was learning Objective-C with trying to pass around things that weren’t objects. Rather than really think about it at the time, I just got annoyed and turned all of my ints and floats into NSNumber objects to shut up the compiler.
Here is a sample header file you might commonly make if you were creating an Objective-C project:
@interface MyViewController ()
@property (nonatomic, strong) UIImageView *backgroundImageView;
@property (nonatomic, strong) UIImageView *blurredImageView;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, assign) CGFloat screenHeight;@end
In my experience with Objective-C, everything was an object. You created classes, which were objects, and you populated them with instances of other objects and in turn instantiated your new object in instances of UIViewController objects.
You had header and implementation files. The name of your class was the same as the name of your implementation file. Every file has a class. This is what programming is. It’s objects all the way down.
My first experience with understanding that this wasn’t the only way of doing things came several months ago. I was working on translating a plug-in we were using to a piece of code we kept internally. I had a weird method I was dealing with that wouldn’t compile.
After fighting with it for a while, I took it to Brad and asked him what I was doing wrong. He told me I was treating the function like a method. This statement kind of blew my mind because I thought that methods and functions were the same thing. I thought we called functions methods in Objective-C the same way that Java interfaces were the same thing as Objective-C protocols. (Yes, I am aware I am probably wrong about this as well. I am still learning.)
I didn’t know that there was a difference in Objective-C between functions and methods. Functions exist outside of classes and methods are functions that are embedded in a class. I hadn’t really thought about this or why anyone would want to do that. I simply assumed that all functions were methods and everything had to be encapsulated in a class.
This was only the tip of the iceberg.
Becoming Functional
Back in November, Brad went away for a week for a trade show. We were planning to rewrite all of our control software in Swift and he wanted me to take a look at the code he had written so far to make sure that I understood it.
What I saw completely broke my reality.
He has posted a sample project on GitHub including some of the code I looked at initially. Here is a small sample of what I saw that changed the way I think about programming:
import Foundation // MARK: - // MARK: Error protocols public protocol ErrorType {} protocol PresentableError { var errorTitle: String { get } var errorInfo: String { get } } // MARK: - // MARK: Error types enum CommunicationsError: ErrorType, Printable, Equatable { case ReadWriteTimeout case WrongByteCount(expectedByteCount:UInt, receivedByteCount:UInt) case CorruptedResponse(expectedResponse:[UInt8], receivedResponse:[UInt8]) var description : String { get { switch (self) { case .ReadWriteTimeout: return ".ReadWriteTimeout" case let .WrongByteCount(expectedByteCount, receivedByteCount): return ".WrongByteCount(expectedByteCount:(expectedByteCount), receivedByteCount:(receivedByteCount)" case let .CorruptedResponse(expectedResponse, receivedResponse): return ".CorruptedResponse(expectedResponse:(expectedResponse), receivedResponse:(receivedResponse)" } } } } enum ElectronicsError: ErrorType, Printable, Equatable { case ElectronicsDisconnected case UnrecoverableCommunicationNoise var description : String { get { switch (self) { case .ElectronicsDisconnected: return ".ElectronicsDisconnected" case .UnrecoverableCommunicationNoise: return ".UnrecoverableCommunicationNoise" } } } } // MARK: - // MARK: Equatable protocol compliance for these errors func == (lhs: CommunicationsError, rhs: CommunicationsError) -> Bool { switch (lhs, rhs) { case let (.ReadWriteTimeout, .ReadWriteTimeout): return true case let (.ReadWriteTimeout, _): return false case let (.WrongByteCount(expectedByteCount, receivedByteCount), .WrongByteCount(expectedByteCount2, receivedByteCount2)): return ((expectedByteCount == expectedByteCount2) && (receivedByteCount == receivedByteCount2)) case let (.WrongByteCount, _): return false case let (.CorruptedResponse(expectedResponse, receivedResponse), .CorruptedResponse(expectedResponse2, receivedResponse2)): return (equal(expectedResponse, expectedResponse2) && equal(receivedResponse, receivedResponse2)) case let (.CorruptedResponse, _): return false } } func == (lhs: ElectronicsError, rhs: ElectronicsError) -> Bool { switch (lhs, rhs) { case (.ElectronicsDisconnected, .ElectronicsDisconnected): return true case (.ElectronicsDisconnected, _): return false case (.UnrecoverableCommunicationNoise, .UnrecoverableCommunicationNoise): return true case (.UnrecoverableCommunicationNoise, _): return false } }
The name of this file is ErrorTypes.swift. There is no ErrorTypes class. There is nothing in this file named ErrorTypes.
NOTHING IN THIS FILE IS AN OBJECT!!
We have several enums, which are not objects, that we are references for type conformity. We have UInts, which are not objects. We also have functions. Lots and lots of functions. That aren’t associated with a class. They’re just out there like llamas roaming free.
When I tried to understand this I felt like I went to a party and someone asked if I wanted to use another person’s liver. I didn’t know if was possible to call functions that were not associated with a class instance. I had never seen anything like this before. I couldn’t believe this would build and run and compile just fine. I felt like I fell down a rabbit hole and nothing made sense anymore.
Reorienting Myself with Reality
I, like many people, learned programming in the age of Imperative Programming. Java has been around for twenty years and many people learned programming with Java. A lot of us don’t know anything except the Object Oriented way of doing things. To many of us, this is what programming is.
It doesn’t have to be.
One reason I am so vocal in my defense of Swift is because this realization has completely changed my reality. I used to think there was only one way of doing things. Well, I won’t say that. There was one right way of doing things and then there was the “Dear god, what is this person thinking by having this property controlled in four different places?!” way of doing things.
Being exposed to Swift and seeing that you don’t have to put everything in a class has been a revelatory experience for me. It is forcing me to reevaluate everything I know about programming.
I never thought about what an object was before because there was no point because everything was an object. Now, I am trying to get a better understanding of what an object actually is. I wrote about the difference between structs and classes and at the time I really didn’t understand why you would want to use a struct instead of a class if they essentially do the same things. I now understand that you want to try to use structs when possible because they aren’t objects. Objects come with a lot of overhead. They let you do some more powerful things like subclassing through polymorphism, but you don’t always need to do those things. Looking at how powerful the enums are that Brad uses in his code, I am fascinated by how confined my own view was when I thought everything had to be an object and exist in a class.
So yes, I did ask what an object is. I know most programmers worth their salt can tell you the definition of what an object is, but I don’t think many of them stop to think about why we use them and if they are the best way of doing things. Or if they bother to wonder if objects are the only way of doing things.