Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constants Grouping #12

Open
diegoreymendez opened this issue Oct 5, 2017 · 7 comments
Open

Constants Grouping #12

diegoreymendez opened this issue Oct 5, 2017 · 7 comments
Labels

Comments

@diegoreymendez
Copy link
Contributor

diegoreymendez commented Oct 5, 2017

When grouping constants use enums, and select descriptive names.

Examples

// Correct:
class MyView {
    enum Dimensions {
        let defaultHeight = 24
        let defaultWidth = 24
    }
}
// Correct: also correct, but when not using any grouping
class MyView {
    let defaultViewHeight = 24
    let defaultViewWidth = 24
}
// Wrong: the name of the enum is not descriptive enough
class MyView {
    enum Constants {
        let defaultHeight = 24
        let defaultWidth = 24
    }
}
// Wrong: use an enum instead of a struct
class MyView {
    struct Dimensions {
        let defaultHeight = 24
        let defaultWidth = 24
    }
}

Rationale

Why enums and not structs?

The reason why we should avoid structs is simply because they are going to show up more frequently in autocompletion suggestions (both when declaring a variable's type and assigning it a value).

Why descriptive names?

Descriptive names make groups more focused and, well, descriptive.

Naming the group just Constants would promote storing completely unrelated values inside of it, making it not too generic:

class MyView {
    enum Constants {
        let titleViewHeight = 20
        let titleViewWidth = 50
        let buttonHeight = 10
        let buttonWidth = 30
        let buttonTitle = "Best Button"
        let viewTitle = "Amazing!"
    }

    // The rest of the code would be here...
}

Whereas more descriptive naming would encourage more atomic and logical groups:

class MyView {
    enum Dimensions {
        let titleViewHeight = 20
        let titleViewWidth = 50
        let buttonHeight = 10
        let buttonWidth = 30
    }

    enum Titles {
        let buttonTitle = "Best Button"
        let viewTitle = "Amazing!"
    }
}

Enforcing the rule

Manual peer reviews, but we can try to spot the most common mistakes through Swift lint rules.

@diegoreymendez diegoreymendez changed the title Group Constants Constants Grouping Oct 5, 2017
@diegoreymendez
Copy link
Contributor Author

I'm not really convinced using either enums or structs is a good practice, because quite frankly Swift doesn't really support namespaces. But since I'm seeing a trend in using these as namespaces in our more recent PRs I wanted to try and get the discussion going.

Just to make it clear: not using / discouraging the use of any of these is an option as well.

@koke
Copy link
Member

koke commented Oct 6, 2017

I somehow like grouping constants sometimes, but I confess that I'm not sure why. A recent example:

    private enum Animation {
        static let shortDuration = 0.1
        static let longDuration = 0.4
        static let visibleAlpha = CGFloat(1.0)
        static let hiddenAlhpa = CGFloat(0.0)
    }

I'm not sure how Animation.shortDuration is better than animationShortDuration. As long as all the constants are near each other in the file, it's good enough for me.

That said, if we do group them I like the idea of more descriptive names. Which I think also means that if you can't come up with a name better than Constants, maybe they should not be grouped.

Addendum 1, don't repeat the group in the constant name:

    // Wrong: Titles.buttonTitle has two titles
    enum Titles {
        let buttonTitle = "Best Button"
        let viewTitle = "Amazing!"
    }

    // Better: Titles.button
    enum Titles {
        let button = "Best Button"
        let view = "Amazing!"
    }

Addendum 2: keep the group names singular (Title instead of Titles).

Although the more I look at the examples, the more I think I would not group those in particular.

@koke
Copy link
Member

koke commented Oct 6, 2017

Also noting that the most common usage I've found for this are dictionary keys. I've played with this in the past and my ideal solution was something that wasn't possible until Swift 4 introduced generic subscripts. I'd make dictionary keys an actual enum and extend Dictionary (or UserDefaults) to take those as keys (to avoid dealing with too much rawValue noise).

My playground is freezing with this test code, but here's the main idea:

// Existing
enum KeysA {
    static let monitorEnabled = "monitor"
    static let blockMaliciousLoginAttempts  = "protect"
    // ...
}

// Proposed
enum KeysB: String, DictionaryKey {
    case monitorEnabled = "monitor"
    case blockMaliciousLoginAttempts  = "protect"
    // ...
}

// The Dictionary subscript can take any RawRepresentable whose RawValue matches
// the Key type. Which in this case means it will take any `enum X: String` for
// a `[String: Y]` Dictionary
extension Dictionary {
    subscript<T: RawRepresentable>(key: T) -> Value where T.RawValue == Key.Type {
        get {
            return self[key.rawValue]
        }
        set {
            self[key.rawValue] = newValue
        }
    }
}

var dictionary = [String: String]()
dictionary[KeysA.monitorEnabled] = "true"
dictionary[KeysB.monitorEnabled] = "false"

@diegoreymendez
Copy link
Contributor Author

That last example is something I’ve been expecting / wishing would work right out of the box in Swift.

To be honest I believe it could even be a good candidate for a new official Swift proposal.

In terms of this proposal, though I feel like it goes a bit beyond the scope. But I would try shaping it into a new one.

@koke
Copy link
Member

koke commented Oct 6, 2017

It's definitely beyond scope, but I brought it up just because if we got rid of the Key enums-as-namespace, maybe there's not much of a case to keep grouping constants 🤷‍♂️

@diegoreymendez
Copy link
Contributor Author

diegoreymendez commented Oct 19, 2017

Here's an example of why I think more specific naming is important.

@nheagy
Copy link
Contributor

nheagy commented Oct 19, 2017

I like this a lot.

Can you clarify why structs are going to show up more frequently in autocompletion suggestions? Is that just the way Xcode works?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants