[#85] Updated Documentation for v3.0 (#87)

* Illustrated the use of feature flag value transformation
* Updated phrasing and formatting in `README`
* Updated code documentation
* Updated version numbers
This commit is contained in:
Yakov Manshin 2022-02-20 01:29:23 +03:00 committed by GitHub
parent 4205ce7dc8
commit 4704bcff97
3 changed files with 51 additions and 17 deletions

View File

@ -1,12 +1,12 @@
# YMFF: Feature management made easy
Every company I worked for needed a way to manage availability of features in the apps already shipped to users. Surprisingly enough, [feature flags](https://en.wikipedia.org/wiki/Feature_toggle) (a.k.a. feature toggles a.k.a. feature switches) tend to cause a lot of struggle.
Every company I worked for needed a way to manage availability of features in the apps already shipped to users. Surprisingly enough, [*feature flags*](https://en.wikipedia.org/wiki/Feature_toggle) (a.k.a. *feature toggles* a.k.a. *feature switches*) tend to cause a lot of struggle.
I aspire to change that.
**I aspire to change that.**
YMFF is a nice little library that makes management of features with feature flags—and management of the feature flags themselves—a bliss, thanks to the power of Swifts [property wrappers](https://docs.swift.org/swift-book/LanguageGuide/Properties.html#ID617).
YMFF is a nice little library that makes managing features with feature flags—and managing feature flags themselves—a bliss, thanks mainly to the power of Swifts [property wrappers](https://docs.swift.org/swift-book/LanguageGuide/Properties.html#ID617).
YMFF ships completely ready for use, right out of the box: you get everything you need to start in just a few minutes. But you can also replace nearly any component of the system with your own, customized implementation. The supplied implementation and the protocols are kept in two separate targets (YMFF and YMFFProtocols, respectively).
YMFF ships completely ready for use, right out of the box: you get everything you need to get started in just a few minutes. But you can also replace nearly any component of the system with your own, customized implementation. The supplied implementation and the protocols are kept in two separate targets (YMFF and YMFFProtocols, respectively).
## Installation
@ -19,28 +19,26 @@ https://github.com/yakovmanshin/YMFF
Youre then prompted to select the version to install and indicate the desired update policy. I recommend starting with the latest version (its selected automatically), and choosing “up to next major” as the preferred update rule. Once you click Next, the package is fetched. Then select the target youre going to use YMFF in. Click Finish, and youre ready to go.
If you need to use YMFF in another Swift package, add it as a dependency:
If you need to use YMFF in another Swift package, add it to the `Package.swift` file as a dependency:
```swift
.package(url: "https://github.com/yakovmanshin/YMFF", .upToNextMajor(from: "2.0.0"))
.package(url: "https://github.com/yakovmanshin/YMFF", .upToNextMajor(from: "3.0.0"))
```
### CocoaPods
YMFF now supports installation via [CocoaPods](https://youtu.be/iEAjvNRdZa0).
YMFF alternatively supports installation via [CocoaPods](https://youtu.be/iEAjvNRdZa0).
Add the following to your Podfile:
```ruby
pod 'YMFF', '~> 2.1'
pod 'YMFF', '~> 3.0'
```
## Setup
All you need to start managing features with YMFF is at least one feature flag *store*—an object which conforms to `FeatureFlagStoreProtocol` and provides values that correspond to feature flag keys.
`FeatureFlagStoreProtocol` has two required methods: `containsValue(forKey:)` and `value(forKey:)`.
All you need to start managing features with YMFF is at least one *feature flag store*—an object which conforms to `FeatureFlagStoreProtocol` and provides values that correspond to feature flag keys.
### Firebase Remote Config
Firebases Remote Config is one of the most popular tools to manage feature flags on the back-end side. Remote Configs `RemoteConfigValue` requires use of different methods to retrieve values of different types. Integration of YMFF with Remote Config, although doesnt look very pretty, is quite simple.
Firebases Remote Config is one of the most popular tools to manage feature flags on the server side. Remote Configs `RemoteConfigValue` requires the use of different methods to retrieve values of different types. Integration of YMFF with Remote Config, although doesnt look very pretty, is quite straightforward.
```swift
import FirebaseRemoteConfig
@ -80,9 +78,9 @@ extension RemoteConfig: FeatureFlagStoreProtocol {
}
```
Now `RemoteConfig` is a valid feature flag store.
Now, `RemoteConfig` is a valid *feature flag store*.
Alternatively, you can create a custom wrapper object instead of extending `RemoteConfig`. Thats what I prefer to do in my projects for better flexibility.
Alternatively, you can create a custom wrapper object. Thats what I tend to do in my projects to achieve greater flexibility and avoid tight coupling.
## Usage
Heres the most basic way to use YMFF:
@ -111,6 +109,29 @@ enum FeatureFlags {
@FeatureFlag("number_of_banners", default: 3, resolver: resolver)
static var numberOfBanners
// Sometimes it may be convenient to transform the raw value—the one you receive from the store—
// to the native value—the one used in your app.
// In the following example, `MyFeatureFlagStore` stores values as strings, but the app uses an enum.
// To switch between the types, you use a `FeatureFlagValueTransformer`.
@FeatureFlag(
"promo_unit_kind",
FeatureFlagValueTransformer { string in
PromoUnitKind(rawValue: string)
} rawValueFromValue: { kind in
kind.rawValue
},
default: .image,
resolver: resolver
)
static var promoUnitKind
}
// You can create feature flags of any type.
enum PromoUnitKind: String {
case text
case image
case video
}
```
@ -118,7 +139,14 @@ To the code that makes use of a feature flag, the flag acts just like the type o
```swift
if FeatureFlags.promoEnabled {
displayPromoBanners(count: FeatureFlags.numberOfBanners)
switch FeatureFlags.promoUnitKind {
case .text:
displayPromoText()
case .image:
displayPromoBanners(count: FeatureFlags.numberOfBanners)
case .video:
playPromoVideo()
}
}
```
@ -161,9 +189,9 @@ Contributions are welcome!
Have a look at [issues](https://github.com/yakovmanshin/YMFF/issues) to see the projects current needs. Dont hesitate to create new issues, especially if you intend to work on them yourself.
If youd like to discuss something else regarding YMFF (or not), contact [me](https://github.com/yakovmanshin) via email (the address is in the profile).
If youd like to discuss something else, contact [me](https://github.com/yakovmanshin) via email (the address is in the profile).
## License and Copyright
YMFF is available under the terms of the Apache License, version 2.0. See the [LICENSE file](https://github.com/yakovmanshin/YMFF/blob/main/LICENSE) for details.
© 20202021 Yakov Manshin
© 20202022 Yakov Manshin

View File

@ -15,6 +15,10 @@ public struct FeatureFlagValueTransformer<RawValue, Value> {
let rawValueFromValue: (Value) -> RawValue
/// Creates a new instance of transformer using the specified transformation closures.
///
/// - Parameters:
/// - valueFromRawValue: *Required.* The closure which attempts to transform a raw value into a value.
/// - rawValueFromValue: *Required.* The closure which transforms a value into a raw value.
public init(
valueFromRawValue: @escaping (RawValue) -> Value?,
rawValueFromValue: @escaping (Value) -> RawValue
@ -29,6 +33,7 @@ public struct FeatureFlagValueTransformer<RawValue, Value> {
extension FeatureFlagValueTransformer where RawValue == Value {
/// The transformer which converts between values of the same type.
static var identity: FeatureFlagValueTransformer {
.init(valueFromRawValue: { $0 }, rawValueFromValue: { $0 })
}

View File

@ -17,6 +17,7 @@ final public class FeatureFlagResolverConfiguration {
public var stores: [FeatureFlagStore]
/// Initializes a new configuration with the given array of feature flag stores.
public init(stores: [FeatureFlagStore]) {
self.stores = stores
}