-
Notifications
You must be signed in to change notification settings - Fork 3
Access Control
Pablo Villar edited this page Mar 20, 2017
·
2 revisions
Always set the most restrictive access level that is possible for any given entity (variables, classes, structs, protocols, etc).
struct User {
let name: String
let email: String
func save() {
User.Defaults.setObject(self.dictionaryValue(), forKey: Keys.SavedUser)
User.Defaults.synchronize()
}
static var savedUser: User? {
guard let dictionary = User.Defaults.objectForKey(Keys.SavedUser) as? [String: AnyObject] else {
return nil
}
return User(dictionary: dictionary)
}
// MARK: - Private
private static let Defaults = NSUserDefaults.standardUserDefaults()
private struct Keys {
static let SavedUser = "saved_user"
static let Name = "name"
static let Email = "email"
}
}
// MARK: - Conversion
private extension User {
init(dictionary: [String: AnyObject]) {
let name = dictionary[Keys.Name] as! String
let email = dictionary[Keys.Email] as! String
self.init(name: name, email: email)
}
func dictionaryValue() -> [String: AnyObject] {
return [
User.Keys.Name: self.name,
User.Keys.Email: self.email
]
}
}
Notice:
- The usage of a
private struct
to define a group of static strings that should only be known internally. - The usage of a
private extension
to group relevant methods that are only used internally within the file. - Observe how, by this way,
User
ends up exposing a concise API:-
init(name: String, email: String)
, the default implicit initializer as a consequence of being astruct
. -
name
andemail
as read-only properties. -
save()
method for saving a user. -
savedUser
static variable to get the saved user. - That's all you can do with it. Anything else is internal, and not exposed to other classes.
-
- More robust code architecture thanks to achieved encapsulation.
- Clearness: Your classes end up exposing minimal and clear APIs; therefore, they become easier to use and understand for other developers.
- It helps tracking bugs, given that we gain a stronger separation of concerns:
- A public member can be accessed from outside the class, which for practical considerations means potentially anywhere. If something goes wrong with a public field, the culprit can be anywhere, and so in order to track down the bug, you may have to look at quite a lot of code.
- A private member, by contrast, can only be accessed from inside the same class, so if something goes wrong with that, there is usually only one source file to look at. If you have a million lines of code in your project, but your classes are kept small, this can reduce your bug tracking effort by a factor of 1000.