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

Library Modularization via Specialization #172

Closed
JakeWharton opened this issue Jun 9, 2015 · 13 comments
Closed

Library Modularization via Specialization #172

JakeWharton opened this issue Jun 9, 2015 · 13 comments

Comments

@JakeWharton
Copy link
Contributor

In an effort to stave off becoming either obsolete or a dumping ground (or both), a few of us have been talking through other channels about how best to approach the future of this library.

Everyone agrees that the current project is a dumping ground of utilities, operators, and helpers that were once useful to one or more people when working with RxJava on Android. These were contributed by a wide variety of people with little thought to what this library's identity would be—they just wanted to share useful code.

Android is an entire platform with vast APIs. Adapting or shimming all of its APIs with RxJava will result in a large, slow moving monolithic library. It would be very hard to dictate policy on naming, reference holding, and behavior across such a large adaptation. And finally, the ways with which developers interact with this large API surface area differs based on use-case, history, and opinion.

It is infeasible to build a single RxAndroid library.

This should come as no surprise as the repo currently doesn't even house a single RxAndroid library. The ill-defined 'framework' module splits functionality in an pre-emptive realization of all the points from above.

I am proposing a from-scratch, modularization of the library into re-usable and composeable modules. A few other notable contributors are in support of this and I'll let them voice their support, suggestions, and/or issues individually.

The APIs in RxAndroid which are fundamental to all RxJava use on the platform deals with threading. Android's hallowed main thread and the related handler-scheduler adapter are fundamental to all RxJava use in a non-trivial capacity. These will be part of the 'core' module.

The newly added plugin hooks are also something foundational with which other modules would leverage functionality. They will also be present in the 'core' module.

Finally, internal static helpers which will be used in all modules (such as the current preconditions/assertions classes) will be in the 'core' to reduce needless duplication.

The second subject on which I want to dedicate a module is binding to and from the UI controls which make up the android.view.* and android.widget.* packages. This 'ui' module will feature observable factories for listening to UI changes and action factories for subscribing UI properties.

The scope of this second module is too large for this issue as there are a lot of considerations to be made around naming, threading, reference keeping, etc. so I will create another issue for that once consensus is reached.

I'll try to preempt answers to some questions below:

This seems drastic. Is this really needed?

It has become very clear to the few of us that have been having conversations that this project is dying. If we do not undertake an effort to make drastic changes such that applications and libraries can confidently depend on it in a way that's useful to everyone then it will simply stagnate into uselessness.

The current offering covers Android APIs randomly, has varying implementations of correctness and efficient, and without a strong idea of an identity no one know what should go in.

Will this be done in an API-compatible way?

No. This will be invasive and destructive. Things will be moving.

What about deprecations?

No. There is no point. We can release master as a v0.25 which can be considered an instant deprecation of every API.

Why from scratch?

This will allow front-loading discussions about naming conventions, implementation patterns, and nuances of things like references. It's much easier to evolve an approach used by all APIs than try to unify 10 different approaches. This does not mean that the existing code will be ignored. It might even be copied verbatim in places, just that it will be all new modules with consistency.

What about activity/fragment lifecycle binding?

That'll potentially be a third module. I personally don't use these so while they are not included in this issue, they will likely be scoped to the same effort.

What about (insert API not mentioned)?

Plan for it to disappear. Copy/paste its implementation into your source tree for continued use after modularization happens. There are plenty of APIs from this library that are used which are useful but have questionable applicability to the masses. If it's specialized enough, consider making a separate library on your personal or corporate GitHub account and depend on one of the modules we will be creating. The point of having small, composeable modules is for a la carte re-use across many libraries.

When will this happen?

If no compelling, well-reasoned, and majorly agreed-upon counter-argument to this approach is to be had we would like to start figuring out the 'core' module in one week. The final current-form release of the library as-is will happen in approximately the same timeline. Once the 'core' module is mostly agreed upon, implementation will start and discussion around the 'ui' module will begin (and will likely be a longer process to flesh out).

How can I help?

Get on board with the effort. Constructive comments, criticisms, and suggestions are welcome. Don't "+1" this issue (we'll see how many read this far). The easiest way to think about this effort is as a new, opinionated, well-designed library driven by a few people who really want it to succeed both in terms of usability to developers but also in being clear in what's appropriate and what's not appropriate for inclusion.

@erickok
Copy link

erickok commented Jun 9, 2015

I strongly agree with the separation into modules, as developers can pick themselves which parts to use. The only counter-argument can can think of is that most developers would use most modules anyway, in which case the split might not be as useful, but it wouldn't do much harm (code duplication) either.

I foresee a (4th?) separate module for compat-ui, which contains bindings like the ui module, yet for AppCompat classes. This would actually be another argument FOR the separation of code, as its dependency on appcompat could be restricted to actual users of it. (The same goes perhaps for the Android Design Support Library.)

I have been following the NotRxAndroid project and like the stronger consistency of the API and implementation. For future contributions I would hope to have an even stronger guideline. I have wanted to contribute but as every implementation seems to differ it is hard to fall in line with the correct style. For example, some view bindings allow broadcasting of the initial value and some not. Some allow multiple bindings (via an internal list of listeners) and some not. Would a binding emit the raw events or perhaps the objects that are affected?

@mttkay
Copy link
Collaborator

mttkay commented Jun 9, 2015

+1 all of what Jake said. From my personal standpoint, the project had
already derailed just a few weeks after it broke out of RxJava, hence my
early withdrawal from it. The vast majority of contributions that had
happened since were dealing with bringing RxJava into Android presentation
land, and at SoundCloud we neither do or want to use RxJava anywhere in the
presentation layer other than presenters being downstream subscribers to
the business logic. So I’m very strongly +1 on having a core module that
sheds off all of this stuff and puts it in a separate module.

I would also vote for not having things like LifeCycleObservable in the
core module. That to me is framework territory, and here we deliberately
decided to solve the same problem in a much simpler and straight forward
way (our presenters attach/detach the model via subscriptions, but the
orchestration is done automatically via an annotation based life-cycle
dispatcher for less brittleness). So I would prefer to see this as an
optional thing, too.

On Tue, Jun 9, 2015 at 10:28 AM, Eric Kok [email protected] wrote:

I strongly agree with the separation into modules, as developers can pick
themselves which parts to use. The only counter-argument can can think of
is that most developers would use most modules anyway, in which case the
split might not be as useful, but it wouldn't do much harm (code
duplication) either.

I foresee a (4th?) separate module for compat-ui, which contains bindings
like the ui module, yet for AppCompat classes. This would actually be
another argument FOR the separation of code, as its dependency on appcompat
could be restricted to actual users of it. (The same goes perhaps for the
Android Design Support Library.)

I have been following the NotRxAndroid project and like the stronger
consistency of the API and implementation. For future contributions I would
hope to have an even stronger guideline. I have wanted to contribute but as
every implementation seems to differ it is hard to fall in line with the
correct style. For example, some view bindings allow broadcasting of the
initial value and some not. Some allow multiple bindings (via an internal
list of listeners) and some not. Would a binding emit the raw events or
perhaps the objects that are affected?


Reply to this email directly or view it on GitHub
#172 (comment)
.

Matthias Käppler

Engineer

Twitter: https://twitter.com/mttkay

Skype: matthias-sc

SoundCloud Ltd. | Rheinsberger Str. 76/77, 10115 Berlin, Germany | +49
(0)172 2345679

Managing Director: Alexander Ljung | Incorporated in England & Wales
with Company
No. 6343600 | Local Branch Office | AG Charlottenburg | HRB 110657B

Capture and share your music & audio on SoundCloud
http://soundcloud.com/creators

@loganj
Copy link

loganj commented Jun 9, 2015

Ship a rev of the core first. Just schedulers, plugins, a few helpers. That opens up experimentation in UI and lifecycle libraries. It wouldn't be surprising to see multiple perfectly valid competing and complementary libraries in those spaces.

@zsiegel
Copy link

zsiegel commented Jun 9, 2015 via email

@dlew
Copy link
Collaborator

dlew commented Jun 9, 2015

I'm a big fan of this idea. There's no reason to have a single monolithic library when it's easy to add multiple dependencies. The current offerings are a scattershot of ideas with weak cohesion.

By creating a focused core library, we make it easier for others to build on top of RxAndroid. If someone, for example, wants to build an RxAndroidDialog, they could get started with core and build on top of it. This project could move separately from core RxAndroid, so it would have more freedom. In other words, there's no need for non-core functionality to be part of RxAndroid proper.

@f2prateek f2prateek mentioned this issue Jun 9, 2015
@ronshapiro
Copy link
Contributor

I think this makes a lot of sense, but I also think that it makes the startup cost of someone new to Rx incorporating the code in their project. Discovering what classes and options becomes harder, especially if you just start out with core and then never find out that their are other modules. I'm not sure the feasibility of this, but I think it would be good to export one combined artifact for people to depend on for debug (if they choose), which would allow for their IDE to index everything all at once. Then, for release they could only compile the modules they needed.

I'm also wary that just simply splitting everything up into modules will really solve the problem at hand. If there was one 'ui' module, that itself would probably become bloated itself since there are so many widgets in the sdk. So one option would be to go module crazy and let people depend on whichever ones they need, but I think this creates a lot of friction for developers to manage. This split does allow people to easily not use any of the ui module and all of core, but I think the same experience could happen in the 'ui' module as is currently happening.

If many worthwhile libraries spin up that all depend on core, but are external to this repo, it may get hard to keep everything in sync, but I think it's probably a problem worth solving. Just wanted to throw it out there.

@Takhion
Copy link

Takhion commented Jun 11, 2015

+1–oh wait

Seriously though, I approve and applaude the effort, I believe a well though foundation and "extension framework" will not only make everything more stable, but actually faster to move forward.

A list of all associated plugins could still be collected here to make them easily discoverable, maybe through some sort of wizard/configurator; at that point adding a few lines in Gradle won't be a big deal!

@frapontillo
Copy link

It goes without saying, this is the only way to make RxAndroid work.
About modules depending on core, you may create a RxAndroid organization and mirror all of the "unofficial-but-good" modules in order to advertise them, or even propose to take ownership of them in the org context.

@cantrowitz
Copy link

Happy to follow the lead on this. Just a question about this:

Finally, internal static helpers which will be used in all modules (such as the current preconditions/assertions classes) will be in the 'core' to reduce needless duplication.

If at all possible, I would prefer to standardize on Google's support annotations instead of Assertions.assertUiThread(). I realize this might not be possible in all cases, but the annotations (e.g., @UiThread) make it faster and easier to do the right thing for most developers. If you don't think this is the appropriate or is too much overhead to include the library, that's fine too!

@JakeWharton
Copy link
Contributor Author

I'm pretty certain that the static analysis tools are not going to be powerful enough to understand RxJava's scheduler mechanism for moving between threads to accurately prevent people from doing the wrong thing. The use of that helper method is for the thread on which subscription happens, not the thread on which the static factory method is called.

@austynmahoney
Copy link
Contributor

I like the idea of separating the functionality into modules. If the core module is designed well, someone should be able to create whatever they would like in their own repo as a another module. I'd love to see most of the work on RxAndroid to be done here, but as we have already experienced, everyone has different opinions on how to solve the non-core issues.

As someone else posted above, eventually I'd hope we can sort out what modules are useful/popular, and move them into an RxAndroid organization.

For those of us that would like to participate more closely, what other channels are being used for discussion?

@xorgate
Copy link

xorgate commented Aug 3, 2015

What's the status of this?

Should I get worried about this library falling out of date with RxJava and if so, how can I keep up-to-date?

Are new library projects already up?

@JakeWharton
Copy link
Contributor Author

This is done and will be released in the next two weeks. There is nothing to fall out-of-date with on RxJava.

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

No branches or pull requests