Skip to content

Commit

Permalink
Refactor FeatureFactory public API using Params. (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
Laimiux authored Sep 25, 2024
1 parent 98b71fb commit 3ddba2a
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- **Breaking**: Removed `FlowFactory` and `Flow`
- **Breaking**: Replace `FragmentStoreBuilder` with `FeaturesBuilder`
- **Breaking**: Rename `FragmentFlowStore` to `FragmentStore`, `FragmentState` to `FragmentOutput`, `FragmentFlowState` to `FragmentState`
- **Breaking**: Making `FeatureFactory` into an abstract class and modifying the `initialize` API to use `Params` wrapper type

## [0.7.1] - June 28, 2022
- **Breaking**: Rename `FragmentBindingBuilder` to `FragmentStoreBuilder`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import io.reactivex.rxjava3.core.Observable
class TestFeatureFactory<Key : FragmentKey>(
private val render: (FragmentKey, Any) -> Unit = { _, _ -> },
private val state: (Key) -> Observable<Any>,

) : FeatureFactory<Unit, Key> {
override fun initialize(dependencies: Unit, key: Key): Feature {
) : FeatureFactory<Unit, Key>() {
override fun Params.initialize(): Feature {
return Feature(
state = state(key),
viewFactory = TestViewFactory { _, value ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,22 @@ package com.instacart.formula.android
* @param Key a type of fragment key that is used to identify this feature.
*
*/
interface FeatureFactory<in Dependencies, in Key : FragmentKey> {
abstract class FeatureFactory<in Dependencies, in Key : FragmentKey> {

inner class Params(
val dependencies: @UnsafeVariance Dependencies,
val key: @UnsafeVariance Key,
)

/**
* Initializes the [Feature] using [Params] provided.
*/
abstract fun Params.initialize(): Feature

/**
* Initializes state observable and a view factory for a specific [key].
*/
fun initialize(dependencies: Dependencies, key: Key): Feature
fun initialize(dependencies: Dependencies, key: Key): Feature {
return Params(dependencies, key).initialize()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import com.instacart.formula.android.FragmentKey
internal class MappedFeatureFactory<Component, Dependencies, Key : FragmentKey>(
private val delegate: FeatureFactory<Dependencies, Key>,
private val toDependencies: (Component) -> Dependencies,
) : FeatureFactory<Component, Key> {
override fun initialize(dependencies: Component, key: Key): Feature {
) : FeatureFactory<Component, Key>() {
override fun Params.initialize(): Feature {
return delegate.initialize(
dependencies = toDependencies(dependencies),
key = key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ class FragmentStoreTest {
}

@Test fun `bind feature factory with to dependencies defined`() {
val myFeatureFactory = object : FeatureFactory<String, MainKey> {
override fun initialize(dependencies: String, key: MainKey): Feature {
val myFeatureFactory = object : FeatureFactory<String, MainKey>() {
override fun Params.initialize(): Feature {
return TestUtils.feature(
stateValue = dependencies
)
Expand Down Expand Up @@ -182,8 +182,8 @@ class FragmentStoreTest {
@Test fun `store returns failure event when feature factory initialization throws an error`() {
val expectedError = RuntimeException("something happened")
val store = FragmentStore.init(FakeComponent()) {
val featureFactory = object : FeatureFactory<FakeComponent, MainKey> {
override fun initialize(dependencies: FakeComponent, key: MainKey): Feature {
val featureFactory = object : FeatureFactory<FakeComponent, MainKey>() {
override fun Params.initialize(): Feature {
throw expectedError
}
}
Expand All @@ -209,8 +209,8 @@ class FragmentStoreTest {
val stateSubject = PublishSubject.create<Any>()

val store = FragmentStore.init {
val featureFactory = object : FeatureFactory<Any, MainKey> {
override fun initialize(dependencies: Any, key: MainKey): Feature {
val featureFactory = object : FeatureFactory<Any, MainKey>() {
override fun Params.initialize(): Feature {
return Feature(
state = stateSubject,
viewFactory = TestViewFactory(),
Expand Down Expand Up @@ -248,8 +248,8 @@ class FragmentStoreTest {
val stateSubject = PublishSubject.create<Any>()

val store = FragmentStore.init {
val featureFactory = object : FeatureFactory<Any, MainKey> {
override fun initialize(dependencies: Any, key: MainKey): Feature {
val featureFactory = object : FeatureFactory<Any, MainKey>() {
override fun Params.initialize(): Feature {
return Feature(
state = stateSubject,
viewFactory = TestViewFactory(),
Expand Down Expand Up @@ -293,8 +293,8 @@ class FragmentStoreTest {

@Test fun `fragment store visible output`() {
val store = FragmentStore.init {
val featureFactory = object : FeatureFactory<Any, MainKey> {
override fun initialize(dependencies: Any, key: MainKey): Feature {
val featureFactory = object : FeatureFactory<Any, MainKey>() {
override fun Params.initialize(): Feature {
return Feature(
state = Observable.just("value"),
viewFactory = TestViewFactory(),
Expand Down Expand Up @@ -360,8 +360,8 @@ class FragmentStoreTest {
private fun FragmentKey.asAddedEvent() = FragmentLifecycleEvent.Added(FragmentId("", this))
private fun FragmentKey.asRemovedEvent() = FragmentLifecycleEvent.Removed(FragmentId("", this))

class TestFeatureFactory<FragmentKeyT : FragmentKey>: FeatureFactory<FakeComponent, FragmentKeyT> {
override fun initialize(dependencies: FakeComponent, key: FragmentKeyT): Feature {
class TestFeatureFactory<FragmentKeyT : FragmentKey>: FeatureFactory<FakeComponent, FragmentKeyT>() {
override fun Params.initialize(): Feature {
return Feature(
state = dependencies.state(key),
viewFactory = TestViewFactory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import com.instacart.formula.android.compose.ComposeViewFactory
import com.instacart.formula.invoke
import com.instacart.formula.rxjava3.toObservable

class StopwatchFeatureFactory : FeatureFactory<Any, StopwatchKey> {
override fun initialize(dependencies: Any, key: StopwatchKey): Feature {
class StopwatchFeatureFactory : FeatureFactory<Any, StopwatchKey>() {
override fun Params.initialize(): Feature {
return Feature(
state = StopwatchFormula().toObservable(),
viewFactory = StopwatchViewFactory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import com.instacart.formula.android.LayoutViewFactory
import com.instacart.formula.android.ViewInstance
import com.instacart.formula.rxjava3.toObservable

class TaskListFeatureFactory : FeatureFactory<TaskListFeatureFactory.Dependencies, TaskListKey> {
class TaskListFeatureFactory : FeatureFactory<TaskListFeatureFactory.Dependencies, TaskListKey>() {
interface Dependencies {
fun taskRepo(): TaskRepo
fun taskListInput(): TaskListFormula.Input
}

override fun initialize(dependencies: Dependencies, key: TaskListKey): Feature {
override fun Params.initialize(): Feature {
// Note: we could create our own internal dagger component here using the dependencies.
val formula = TaskListFormula(dependencies.taskRepo())
return Feature(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import io.reactivex.rxjava3.core.Observable

class NoOpFeatureFactory<FragmentKeyT : FragmentKey>(
private val viewFactory: ViewFactory<FragmentKeyT> = TestViewFactory(),
) : FeatureFactory<Unit, FragmentKeyT> {
override fun initialize(dependencies: Unit, key: FragmentKeyT): Feature {
) : FeatureFactory<Unit, FragmentKeyT>() {
override fun Params.initialize(): Feature {
return Feature(
state = Observable.empty(),
viewFactory = viewFactory,
Expand Down

0 comments on commit 3ddba2a

Please sign in to comment.