cemolcay / MusicTheory

Universal music theory library for iOS, iPadOS, macOS, tvOS and watchOS in Swift
MIT License
442 stars 50 forks source link

Change ScaleType and ChordProgression from enum to struct to realize … #28

Closed DJBen closed 5 years ago

DJBen commented 6 years ago

…semantic equality between custom created objects and predefined options.

Rationale

It might be tempting to define these types as enum for predefined options due to its succinct syntax. However, the existence of .custom(value) options challenges the use of enum.

We design every case in the enum to be unique and mutually exclusive with other cases. In the current code, multiple representations using more than one case with the same semantic can exist, violating the principle.

For example, ChordProgression.i_v_vi_iv != ChordProgression.custom([.i, .v, .vi, .iv]) but they are semantically the same. An author can write I-V-VI-IV progressions in both ways and treat them as the same. However when determining equality between I-V-VI-IV representations, we may get either true or false depending if the same representations are being compared. This is undesirable.

With minimum API change I changed the enum types to struct and make every case a static let, so ChordProgression.i_v_vi_iv == ChordProgression.init([.i, .v, .vi, .iv]). This also eliminate the separate implementation of description and combine the initializer with the declaration (so we don't need patterns like public var intervals: [Interval] { switch(self} { ... } }).

This change should be transparent to the outside API except the typo correction of Romanian Minor.