-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Support experimental/provisional APIs #1019
Comments
I think the first two options- Documentation Only and Namespace- are the best two options. Both the Experimental Branch and the Feature Flags methods will add additional work for both the development team and anyone who wants to contribute new features, with the Experimental Branch idea also making it difficult for people to use experimental features regularly. Out of the Documentation Only and Namespace ideas there's really one major question- should there be some sort of explicit notification (in this case, the package name) that the code is experimental, or is documenting it enough? Personally I think documentation is enough, but I understand the other argument as well. |
My thoughts on each, in order from favorite to least favorite.
|
|
@JordonPhillips - why would namespaces require two versions of the same code in one release? Would that be a solution to the problem @stealthycoin brought up regarding moving code out of the experimental namespace and into the core? If so another solution that doesn't involve duplicating code is to create a proxy object in the experimental namespace that just called the final code (basically run some |
The advantage of namespacing is hard isolation - you don't have to worry about mucking about with existing builtins. But if you do need to, then you still need to isolate everything. You could just internally handle it the same way you would handle feature flags, but at that point you may as well do feature flags because then it's not necessarily a breaking change when a feature moves out of experimental status. |
I would like a hybrid approach of a single opt-in flag and documentation:
Here is why I like this idea:
The one thing I am not sure about now is how we would go about doing the opt-in checks. I think for things that can be checked at deployment time it should not be difficult, but if the experimental feature is being used in the the runtime of a Lambda function that may be tricky. |
It seems to be a tradeoff between ease-of-use for maintainers, and users. Users disregarding documentation or copy-pasting from StackOverflow and thus relying on experimental features will happen whether feature flags, documentation, namespaces are used. Perhaps a big "deploy-time" warning that experimental features are being used? |
Thanks for the feedback so far, to summarize what I'm reading: It seems like the preferred options right now are feature flags and the experimental branch (with the caveats that @stealthycoin proposed, which I like). My main concern with feature flags is that I don't think it's a general solution, it seems like it would only work for specific types of APIs (for example we could probably do this for any new decorators we add). I'm not sure how this would work for more "invasive" API changes such as blueprints, websockets, and resources. I've also not seen this done before in a client side library/framework, only in web apps/apis, so I figure there's probably some reason no one's done this before. I can try to put together a POC for feature flags and see what we think about it. |
Ok, here's a simple POC I have for feature flags. There's three parts to it:
Pros:
Cons:
Examplefrom chalice import Chalice
from chalice import Blueprint
app = Chalice(app_name='test-features')
bp = Blueprint(__name__)
@bp.route('/')
def index():
return {'hello': 'world'}
app.register_blueprint(bp)
To opt in: from chalice import Chalice
from chalice import Blueprint
app = Chalice(app_name='test-features')
app.experimental_feature_flags.update([
'BLUEPRINTS'
])
bp = Blueprint(__name__)
@bp.route('/')
def index():
return {'hello': 'world'}
app.register_blueprint(bp) Now a |
I wanted to consolidate what @stealthycoin proposed
I don't think this would be that big of a burden on us because I'd expect the The main downside I can see is that I'm not sure if we'd get as much feedback |
Lets say the end of every even month (February, April, June, etc) you decide to merge the experimental back into master. Would this mean that you'd just delay/refuse pull requests if it was already close to the merge time, and then mass merge after a release? I do like your feature flags POC, I think that could work out well. |
@jamesls I like the feature flag design. I really like that to enable a feature you have to do so in your |
Cool, I haven't heard any feedback against using the feature flags so I'll go ahead and clean up the POC and send a PR. This will allow us to merge the blueprints PR. |
Implemented in #1053. Thanks everyone for the feedback. |
This is a follow up that originally came from a discussion on a PR.
Chalice is now GA (> 1.0) so we maintain backwards compatibility of our API. Specifically, chalice apps that are written against chalice 1.x will continue to work for all future versions of 1.x.
At the same time, Chalice has a lot of potential for new ideas and new APIs, many of which will take several iterations to get right. I suspect that in many cases we'll need to implement an initial idea, get customer feedback, try it out ourselves, and make corresponding adjustments. This may include anything from backwards incompatible changes to outright removal of a feature if it ends up not being a good idea.
There's been a few ideas on how to do this that I'll try to summarize here.
Ideas
Documentation only - Clearly document if an API is experimental vs. stable, but otherwise make no changes to the code itself. Features/PRs for experimental features get merged into master and treated like any other code. This is somewhat similar to how python handles provisional APIs (pep 411).
Namespace - Add an
experimental
subpackage in chalice, and add experimental features under that namespace. You'd then have to import explicitly form the experimental package. I'm not sure what exactly this would look like (haven't done this before), but maybe if we wanted to add a new decorator we might havefrom chalice import experimental; app = Chalice(__name__); experimental.inject_some_new_app_decorators(app)
. My concern with this is that when a feature graduates to a fully supported feature, that in itself would be a breaking change (we've move it out of experimental), and you'd have to modify your code.Experimental branch - This option proposes maintaining an
experimental
branch on Github. A PR would then either target themaster
branch for immediate inclusion or theexperimental
branch. After some period of time testing, we'd mergeexperimental
intomaster
after removing any features we want to drop fromexperimental
. The downside to this is that we (the maintainers) have a lot more repo maintenance and merging between branches could be problematic. It's also possible that not as many people would be willing to try out anexperimental
branch.Feature flags - The idea is to gate each feature behind a feature flag. You'd need an explicit opt in that you're using an experimental feature. After some period of time we'd either drop the feature entirely or support by default (no feature flag needed). This reminds me of how rust nightly works (https://doc.rust-lang.org/book/appendix-07-nightly-rust.html). The downside is I'm not sure how to actually implement this when it comes to APIs in a client side framework. It seems like we'd have to have conditional checks throughout our code to only support this feature if a given feature flag is enabled (or would the specific method not even exist unless you somehow enabled a feature flag?) I'm worried that this could clutter our code. If anyone has examples of a client framework doing this let me know.
Let us know what you'd prefer, or if you have any other ideas!
The text was updated successfully, but these errors were encountered: