Saturday, 30 January 2016

Documenting your software

TL/DR:Document your code now, your colleagues and your future self would thank you for.
When it comes down to documenting any software I write, I focus on a good README file and well documented interfaces within the codebase. Most of it will be obvious to developers but I believe it is still worth mentioning.

README File

I find this file to be very important as this will be the starting point to onboard someone onto your code. The more concise and relevant the better since nobody reads long README files. Naturally, it'll grow with the size of the project but as my history teacher used to say, "don't waffle!".
Generally speaking I'll include these topics (if relevant) in a README file :
  • A basic summary of the project containing it's purpose
  • The relevant environments and/or configurations
  • Screenshots of the software component in actions (a picture is worth a thousand words)
  • Architecture diagrams for larger projects
  • For libraries, an installation guide that explain how to integrate the library to your project
  • Project specific examples
For example, the README file of JSONUtilities contains all the relevant information to get started.

Documenting code (Interface Documentation)

As developers we like to write self-documenting code. This way it's easy to understand what our code does. We only add comments explaining "why" something is done and not "how". However, the interfaces should be documented to explain and define the intention of a class or a method for example. This allows for explanation of intent of what a software component should do while going through the code. For example, to understand why a class was created or what the purpose of a function is. By documenting the interfaces the contracts between software components are clearer and less prone to ambiguity when used or changed in the future. In the context of iOS/Mac development the interfaces and properties can be documented using HeaderDoc-style comments. VVDocumenter is great Xcode plugin to help with this as it prefills all the boilerplate part of the comment.
For example a code snippet of JSONDecoder.swift from JSONUtilities clearly explains what the purpose of Decodable protocol is:
/**
 *  Use the Decodable protocol to support nested JSON objects
 */
public protocol Decodable {
  /**
   Creates a instance of struct or class from a JSONDictionary
   
   - parameter jsonDictionary: The JSON dictionary to parse
   
   - throws: Throws a decoding error if decoding failed
   
   - returns: A decoded instance of the type conforming to the protocol
   */
  init(jsonDictionary: JSONDictionary) throws
}
These comments can then be translated into documentation if you need to by using for example appledoc for Objective-C or Jazzy for both Swift and Objective-C.

Sunday, 24 January 2016

5 tips when using Core Data in Swift 2

1. Don't use optionals for required types

When you generate your NSManagedObject subclasses, Xcode will declare all your properties as optionals, even those that you've marked required. This means that when you instantiate a class with required properties in Core Data, everything will work fine until that entity is validated by Core Data, either by saving that entity or when you call validateForInsert(). It's therefore better to remove the optional marker (?) on properties that are required in the Core Data model.

2. When using relationships, remember not to use Swift sets

While you can use Swift data types in most cases, one exception (this might change in the future) are relationships. You must still use NSSet for relationships, so you won't get the same level of type checking. If you attempt to use a Swift Set, the relationship won't be persisted nor will it be seen by Core Data as a relationship. I would suggest you use the method validateForInsert() mentioned before to validate your relationships instead.

3. Use Swift number types, but be careful with the requirements

You don't need to use NSNumber for number types in Core Data, you can use Swift's own internal data types. What you need to bear in mind is that you must specify the exact type you've used in Core Data. So for example, if you've selected "Integer 32", you must use Int 32 on your Core Data class.

4. Use a simple Core Data stack as possible

As you've probably seen, there are plenty of articles telling you how Core Data can be used in a multi-threaded environment; how it is possible to have multiple NSManagedContext objects that are synchronised and so on. I would suggest that you start with a simple Core Data stack that does all of its operations in a single thread. If later on you find that you need a more complex setup, by all means expand your Core Data stack at that point.

5. Don't use inheritance in Core Data Entities

Strictly speaking, this is not a Swift-specific tip. While Core Data is not a mere object relationship mapper, it does tend to be used to persist data using a sqlite database. If your entities inherit from other entities, they will end up sharing a table in the sqllite database. This can lead to serious performance issues once you your database grows to a few thousand entries. It's best to have some duplicated fields, or use inheritance in your NSManagedObject classes but not on the actual Core Data model.