We grew up as nerds in school and learned to expect people would think we’re lame for the things we loved. We kept the things we loved to ourselves and looked for the few people on Earth who also loved those things as much as we did so we could share with them.
Community is really not just about sharing with other people who are as deep into what you love. It’s also about opening up what you love to teach it and make it accessible to people who are interested.
Community is about helping and getting help from those around you. With one hand we each should reach out for help and with the other we should reach back to help those behind us. Together, we all pull each other up and the community thrives.
The fact that the Objective-C community is still growing at a crazy rate and is already huge does not mean our community can’t be the one some of us know from before the iPhone. There’s just more of us to help each other out now, this is a good thing. We should all be reaching out so we can collectively lift the whole community up.
When I was in college for electrical engineering, I learned to program objective-C for the Mac and that has now become my full-time job instead of engineering. The primary reason for pursuing a life of software development instead of engineering was the community. The developers I read about like Mike Lee, Daniel Jalkut, Gus Mueller, and so on made me so very excited to write software for a living. When I had the chance to meet them in person, along with other developers, I was even more excited. It was a community, a group of people who gave a shit about each other.
When you choose to take shortcuts in your freelance projects, consider the effect on the community. When you whip out that singleton because it’s quick and easy (and we all know it’s a bad idea), think of the community. Think of the other developer who has to add features and fix bugs on the project once you’re done. That poor guy (or gal) has children to feed, expenses to pay, and needs to take this project to make the money to take care of that. They have to add features onto that project full of your shortcuts. They have to pay the technical debt you acquired to get the job done. Like all clients, the client is hassling them to get it done as quickly as possible for as little money as possible.
Your shortcuts have made life harder for that person. That person can’t afford to tell the client it can’t be done because they have bills to pay. The client won’t listen when that person says the app needs to be re-written because of the mess you left bend.
Think of the children when you choose to take those quick, easy, delicious shortcuts. The children the next guy has to feed by adding features and fixing bugs in your code. Don’t just try to write better code for yourself, do it for the community. Sure, no one is perfect, but do your best to learn how to write things so that you can be nice to your fellow developers.
It is becoming popular, especially in American tech culture, to encourage failure as a natural part of learning and a key to success. Humans fail in many casual ways to learn basically anything, even basic skills like walking.
Failure in software is often expected on a very minor level. Maybe I’ll release this software and it will have a bug in it. Maybe I won’t get that job at that big tech company I applied for.
The real failure in software is when all the work you have done falls apart so badly, largely from your own mistakes, that you lose everything you have spent years working for and have to beg for a place to sleep with your tail between your legs barely able to afford the shirt on your back.
It’s the kind of failure they joked about in engineering school when discussing friends who were artists and musicians and maybe even dropped out of school. We felt safe studying engineering, a profession so obviously useful that surely we will all have jobs and be paid well.
We were wrong. Horribly wrong. If it wasn’t for software like Rails and iOS and my fortune in having a skill to work with them, I would have been unemployed indefinitely after college. Many of my friends spent years living with their parents maybe working at the local grocery store or mall. They had engineering degrees from a serious school with way better GPAs and qualifications than I did. The truth is everyone who is working a job they enjoy and getting paid, a job they actually wanted to work, is incredibly lucky.
I have spent most of my life reaching out further than I should, often a breath away from failure. The day I received my rejection letter from MIT, I locked myself in my room and didn’t sleep. I refused to get out of bed in the morning, I just wanted to be left alone to cry. My mother (a decently smaller person than me) literally dragged me out of bed and would have slapped me if necessary to get me to put on clothes and go to school. She believed in me when I no longer did and refused to allow me to quit. I had people like her who saw something in me and helped me to continue and do the awesome things I have been able to do. Without them I would be the failure I’m afraid of.
I was incredibly lucky to have a job before I graduated working on Rails and iOS projects. I was incredibly lucky that I didn’t fall flat on my face when I decided to leave that job with no plans and no savings. I was lucky to get a well-paying job in NYC. I was lucky to be in a position to even consider leaving that job to go to Amsterdam.
I had no plan when I got to Amsterdam, I just foolishly thought it would magically work out. Turns out it didn’t work out completely. I neglected important details like having any savings, paying off my college loans (which are expensive because I failed to keep my scholarships), and the business development necessary to keep contract work coming. Now true complete failure is entirely a possibility. Not just a failed feature or a failed project. A failed, broken, person.
Fortunately for me, my lifetime of reaching further than I should has left behind dear friends and family members who would accept that broken shell of a man, desperate and hungry, back from Europe, and they would make sure Blynken and I weren’t out on the street. Even in absolute failure I am incredibly lucky to have these people.
This is what keeps me up at night.
NSLog is a fun debug tool, but it has no place living in your version control history. Those of you who came from other languages and platforms might be used to a world where NSLog’s cousins, console.log, print, puts, and the sort were all you had to try to figure out what was wrong with your code.
In Objective-C we have something much better: breakpoints. I think you get them in Python or Ruby or some such depending on the platform, but I don’t know about those, so I’m not talking about them.
Here’s why the breakpoint is far superior to NSLog for your OS X and iPhone projects:
Sounds powerful, huh? It certainly is. You can even do much fancier things with breakpoints like tell the computer to make noise when your code gets to that spot. If you know python at all, you can have it execute arbitrary scripts to capture any info you like and record it any way you like. If you have an account with Apple, you can check out this video where they spend an hour or so talking about all the god-like power you have — all without tainting up your source code with lines that don’t directly contribute to your customer’s happiness.
There are some times where you need legit logging. You need your app to keep a record of what it was doing. That’s fine, server-based systems do this all the time. Your own computer does it. For logging like this, you need a better solution than NSLog. People have built things like this. Try having a look here for some ideas.
Now you might be thinking “Wow, that sounds so much better, why would I bother with NSLog?” To which I would respond, “Exactly! Glad you liked my article.”
You might also be thinking “dude, I love my NSLogs so much, shame on you for talking bad about them.” To which I’d reply, “sure, sure, use your NSLogs all you like, just don’t commit them and share them with the team.”
I would like to explain my hatred for commented-out code. Some might call this hatred extreme. They’re probably right.
When I look at code interspersed with commented-out lines, I think of my own home which is often covered in dog hair. Now my dog is adorable, but he does in fact shed quite a bit.
Now for me, in my home, by myself, this dog hair bothers me maybe 2% of the time I am there. Most of the time I don’t even notice it. For everyone else who comes over, however, they notice it all of the time. It’s on the floor, it’s collecting in corners, it gets in your shoes. They notice it and most of the time it bothers them. I don’t vacuum for myself, I vacuum for them.
Now back to your code. Comments collect in files, sometimes in big ugly piles, and you don’t even notice. You don’t care, you know why those lines are commented out. “Big deal,” you might say. “I might need to use those lines later if someone changes their mind.” Meanwhile, everyone else who looks at that code sees those lines and it bothers them. “Is a feature broken because that line is commented out? Was that just to debug something?” We don’t vacuum for ourselves, we do it for them. We clean up our code and delete those lines so that the next person can read our code without having a panic attack.
Now code isn’t entirely the same as dog hair. Commented-out code could actually be useful in the future. Fortunately, for code, we have an easy solution: version control. I don’t care which one you use, just pick one and use it. You’re probably already using one. If that code you just deleted instead of commenting out really does need to be resurrected, version control will do it.
So take a deep breath, relax, and delete those lines. Trust your version control system, it’s there to make life easier. It’s going to be ok.
We have a new rule here at Roundwall Software: switches get stitches.
Switches and if statements can easily pile up in a method and make it difficult for someone to understand what a method does. They also makes testing harder because tests that cover a method need to cover every possible branch path one might take through the code. Combining ifs and switches in the same method can quickly turn into madness. They’re not very object oriented either and we’re mostly writing code in Objective-C.
We began with a challenge — can we write our code without switch statements? Turns out most of it could be replaced with clearer switch-free implementations without too much effort.
A common use case for switches appears in a table view’s data source. When the table needs to support multiple section, some of these sections are static information or perhaps each section is made of different kinds of dynamic data, the mixed-section requirement means you cannot simply depend on NSFetchedResultsController’s support for sections to do this for free. You might try to accomplish this with something like this:
It works, sure, and you can even try to eliminate magic numbers and such using enums like this:
This way at least gives some meaning to all the switches and makes it harder to ruin everything by accidentally typing a 4 when you meant to type a 2. The compiler will even remind you when you add a new section and forget to add it to one of your switches.
We could take it a step further and move the stuff in each case into its own method like so:
Now you might say, “dude, that’s so easy to read now and I don’t think we need to do anything more,” to which I would reply, “certainly not, we have a switch to eliminate!” Much like mobster movies, we begin to plot a way to make sure these switch statements “sleep with the fishes”.
A fun place to get inspiration for architecting your Objective-C stuff is to look at Apple’s own frameworks. NSFetchedResultsController handles multiple sections without switches. Maybe we should model our solution to the way that works? NSFetchedResultsController has an array of section objects that adhere to NSFetchedResultsSectionInfo. We don’t even know specifically what type they are, but we do know that we can ask for -numberOfObjects and -indexTitle and such to get the info we need to answer a table view’s data source questions. These objects let’s us write our data source methods without any switch statements (yay!). NSFetchedResultsController allows us to do nifty, object-oriented, switchless things like this:
Let’s do the same huh? Let’s make classes that can contain the information we need for each section and push the datasource responsibilities of our theoretical datasource into the appropriate section. Let’s take a quick stab at a solution. Perhaps something like this?
Now we have a static section that works in a similar fashion to the NSFetchedResultsController style. No more switches, yay! We can easily make use of the section like this:
Look at that! No switches, just objects. If you were writing unit tests, you could feed the controller a mock section to test that the view controller sends expected messages to your fake section. You could then test sections individually as you added them. Easier testing. Easier reading. Easier maintenance. Happy days are here again.
The point of sample code is to show you just enough code to communicate a concept. Sometimes code for a given demonstration (such as showing how to use parts CoreData or CoreText) requires a bit of boilerplate in order to show the concept.
For example, let’s consider a sample project to demonstrate how to draw text in a spiral using CoreText. You would need code to allow you to actually display your CoreText example code. This code has nothing to do with what you’re trying to demonstrate, but it is necessary for the project to function. Now you don’t want to bundle your sample project with an entire production-ready, functioning app because that would be way more code than a developer wants to look at to learn about CoreText’s ability to draw in a spiral. This is a super cool feature, we want to make sure people know how to make this happen. In an effort to reduce the amount of code included in your sample project, you might chose to do things that you would never do in a production app. You might violate all kinds of development principles and have one object handle 45 different jobs. You might put all kinds of functionality into only a few methods. This means a few things for the person reading your sample code:
So kids, never copy-paste code out of an example into your app blindly. It is for educational purposes and not to save you the thought and time needed to write your app.
New since iOS 5.0, we have a new weapon at our disposal for Core Data. External Storage lets you tell Core Data that you’re going to jam large data blocks (mp3s, pngs, whatever) into a property on your Managed Object. Normally you might say “Oh no! Why would you do that? Everyone knows you shouldn’t give large data blobs to Core Data! You should write them out as a separate file you idiot!” iOS 5.0 changed everything, it’s ok. Now you can let Core Data handle those large files and stop bothering to write all kinds of files and handling deleting them yourselves. Yay less code!
If you check the Google or Apple’s docs, you’ll see articles explaining how to get things running, but what you won’t find is an explanation for how Core Data deletes those files. I setup a test application to find out for myself. You can find it here. My tests show that the external files get deleted when you simply nil out the property and save your context. It will also delete the file if you delete the whole entity. Since all you need to do is nil out the property, you don’t need to make separate entities for your data blob properties. Whooo!