Code Structure and Readability Part 4 — Project Structure

Bob Roebling
Swift2Go
Published in
9 min readAug 5, 2018
Photo by rawpixel on Unsplash

In the previous article we talked about file structure, today we are moving on to talk about project structure.

Like file structure, we still have to adhere to the single responsibility principle and separation of concerns, but not so much in the sense that it will affect our code. We do this to help us navigate the project and make changes later.

First, let’s look at your typical starting layout of an Xcode project (really any project).

That’s great, isn’t it? We have the main project folder, we have the app that it will create at the end, and we have everything so nice and easy to find in there. If this were a small project, that would be just fine. However, many times this is not the case and you end up with some ugly projects looking like this…

Let’s see, we have two more view controllers, SettingsViewController.swift and LoginViewController.swift we have User.swift whatever that is. We also have LoginForm.swift, another Settings.storyboard and then HTML? JS? CSS? Hey, those aren’t Swift files!

This is why a clean project structure is so important. It prevents you from having to click in each file to figure out what it’s supposed to be used for.

In Xcode you use groups, in Visual Studio you would use folders, in Python you’d use modules, and so on and so on…. However, in Xcode, you are provided some flexibility. Either a group with a folder or a group without a folder.

If we create one without a folder we end up with the files left in place, but in your project, they appear to be buried in a folder.

If we create one with a folder, the files in the project are moved to that folder on disk. We can tell by the folder on whether or not it is a group with or without a folder by looking at the bottom left corner. Products above is a group without a folder, while MyAwesomeProject is a group with a folder.

So when do you use them?

You’d use a group with a folder when you want any new file to automatically be created under this folder, or when it makes sense to group similar things within the same directory. You’d use a group without a folder when you don’t care where the files are stored or you want to use a folder to hold similar files that are already in a directory and shouldn’t change directories on disk.

Another reason I use groups without a folder is to keep the AppDelegate.swift and Info.plist at the root of my project but limit their visibility in my project structure.

Normally I create a Storyboards group without a folder so I can store all of my storyboards in that directory. Then I can use the default storyboard directory to hold my storyboards.

I also move View controllers to their own Controllers group and my Assets to a group both with a folder.

Let’s see how this looks on disk.

We can still see AppDelegate.swift and Info.plist are at the root of the project, my Storyboards appear inside of Base.lproj, all view controllers are inside of a Controllers folder, and my Assets all reside under Resources.

With Storyboards, we want to ensure they make it into the Base.lproj folder so we can ensure they get reviewed by the Autolayout inspections. We can right-click on the Storyboards group and add a new file, when we do this we can select Base.lproj in the Create dialog box that appears, and save the new storyboard to this folder while still adding it to the Storyboards group as selected in the second half of the screen.

Later on, as we add more and more items to our project, we can create new folders to keep our project structure looking good. Let’s say MyAwesomeProject is a web app that requires the user to log in. We can add a few more files to our project. Notably, a User model to describe a user in the database, a LoginForm so they can actually log in through a web view, and LoginViewController to actually handle the login. Of course, this means we might need to dress it up with some HTML, some fancy CSS, and ever-present javascript.

So now things get a little messy. But we can think back on how we should set up our project, and we realize we can make this less of a nightmare.

Our User is a model, so we’ll create a new group with a folder called Models.

Our LoginForm is a View, so we’ll create a new group with a folder called Views.

Our web stuff is self-contained so we can throw it all in a web folder and place that under our Resources group.

Awesome! That wasn’t hard, it just took a little bit of thinking about what is and isn’t related then grouping all of it together. Even if you aren’t using Xcode, you can still do all of this with folders in most languages. I’d definitely consult project structure documentation for your language before diving right in.

Now we have all of these groups but with Views at the top, Models at the bottom, and Controllers somewhere in between, it’s going to get difficult to find these files, so we sort our sidebar so we can quickly find what we are looking for.

Easy enough, now we know where everything is and we just need to drill down for exactly what we were looking for.

This may seem like overkill for smaller projects, trust me it is. But when you start getting into larger projects, it can really save you a lot of time. Just look at one of my previous projects:

If I asked you to find the section of code that deals with displaying search results from the map’s search view controller how long would it take you? What if I asked you to change the color of the map’s table view controller background?

Or what about finding the new user registration function? Just a quick glance and it’s easy to spot.

This project is over 7,000 lines of code and I’m not finished with it yet, fortunately/unfortunately, I’m also the only one working on it. Fortunately, because I don’t have to bend to other coding styles or figure out what’s left to do. I just know. Unfortunately, because I’m the only one writing these 7,000 lines of code, if I were to hire someone else to work on it with me, they could get up and running relatively shortly.

This is why the project structure is important. This is why you should always be mindful of how your project structure appears even from the very start.

By placing all of our models under a single group, any time we need to make a modification to that model, we know exactly where to find it, we can make the change, and because we’ve been abiding by the loose coupling principles and DRY and SRP, these changes are guaranteed not to screw up our code somewhere else, right?!

Finally, there is one more thing that I don’t have screenshots for but if you’ve ever used Carthage or Cocoapods, or the MapKit framework in Xcode, or even imports or includes, you’ll have an understanding of libraries.

Libraries are self-contained pieces of code that you can use in more than one project. They can help take the complexity out of your applications while providing a common interface for doing stuff in all of your applications. For example, a login screen that can be created by passing a title and a background image would be a good library that you could distribute to the world since the login screen has literally been made hundreds of thousands of times, if not millions.

If we had a login screen library included in this application, we wouldn’t need the LoginViewController or the LoginForm. Instead, we’d just call methods inside of the already existing LoginViewController and LoginForm inside of the library. Because of that, we don’t have 2 files, we just have one. We don’t have to worry about if the code inside of the library still works after this one change because it has no dependency on any other part of our code.

Here’s an example from a AAA title developer. EA/Dice has a Frostbyte engine. This engine is responsible for how characters move on the screen, it contains the physics logic, the bullet logic, the weapon functions logic such as reload and fire, it contains weather logic, reflections, etc…. It’s just one big massive library that can be reused in Mirror’s Edge, Battlefield, Star Wars: Battlefront, Need for Speed. The Frostbyte engine isn’t the only engine available, there are others such as CryEngine, Havok, Source, and Unity.

Imagine, thousands of files belong to this engine, all with their own roles, but when these developers create a new game, they use the library and that provides these thousands of files under one library. There is a lot of power and flexibility in that, it’s also the reason why development is sped up. Imagine if they had to write this engine over and over and over again every time they wanted to make a new game. It would take a very long time.

Summary

Here we learned about good project structure, but I want to leave you with a challenge. Find one of your old projects that could benefit from better structure and make a copy of it!

Then in your copy, improve the structure in its entirety, code comments and all. Write it as if you were going to sell this project off to someone else to maintain. Write it as if someone sold you this project and what questions you’d have about it if you had never seen the code base before.

You don’t have to post it anywhere or give it to anyone, just see if you can make it better. Do it for yourself, because the next time you have a bug in your code that needs to be fixed, it will be a lot easier to maintain.

In the last article of this series, I’ll provide a few links on where you can go for information on structuring your code and keeping it readable.

--

--

Bob Roebling
Swift2Go

Bob is a Senior Infrastructure Administrator and tech evangelist with a background in multiple programming languages.