-
Notifications
You must be signed in to change notification settings - Fork 124
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
[SOAR-0013] Idiomatic naming strategy #683
base: main
Are you sure you want to change the base?
[SOAR-0013] Idiomatic naming strategy #683
Conversation
Thanks @czechboy0! Review started: https://forums.swift.org/t/proposal-soar-0013-idiomatic-naming-strategy/76242. |
I'm very happy to see that work is being done to improve the ease of use of the generator and like all changes described here. Personally I'd argue to make But I hope this proposal can go a bit further. For me, it would not fix the first experience I had with this generator: When I started using this generator: pretty much any config file that I was provided never contained I hope the proposal can be amended to have an idiomatic approach for naming operations with slashes in them, as I'm pretty sure this will have snagged others as well when they started. TLDR:
|
@hactar thanks for taking the time to provide your feedback.
If we were to release a new major version, that would be on the table, but we cannot do this in a SemVer minor release.
That's an interesting thought. This proposal currently doesn't do anything different to address operations without an operation ID.
OOI, what would you write by hand for an operation that did have an I'm wondering if it would be enough to just drop the leading slash, if present, either in the explicit or implicit operation ID. |
Hi @hactar, thanks so much for the thoughtful feedback. I'll get the first one out of the way - while I agree that for most people this will be the new default, and that it would be nice to not have to explicitly configure it, we're not ready to go through the ecosystem breakage that a 2.0 would cause right now. Plus, we might accumulate more feature flags over the next 6-12 months, so I think it's more likely that we'd ship a 2.0 once there are multiple highly valuable improvements that need to be enabled explicitly. I don't believe this proposal alone meets that bar, but again, in broad strokes I agree with your reasons to ship a new major. The second point you made, about slashes leading to suboptimal names, and those being very common when no Considering your case, and complicating it a bit to help us think up a solution, if no operationId is specified, and the method + path are something like:
what would you like the synthesized operationId to be? // Edit: Si just beat me to it 🙂 |
Default setting: I understand - then I think we should at least ensure it is in the default example of the tutorials so anyone starting out will see it and use it if they copy/paste. Operations: So I'm going to approach this from the other side, what would the perfect easy to read swift function be (assuming claimId is a String)? To me it would be
So what happened?
Now I do understand that my function is very idiomatic and makes assumptions on how things should be (I'm a SwiftUI guy, thats how we role 😄). If we want to be less idiomatic about it, some of the steps above could be removed:
As soon as we start adding any sol or lcub or double underscore I'd argue that things become difficult to read. Swift is a camel case and not a snake case language, so I'd try to prevent underscore usage whenever possible. Ss far as I understand the whole sol thing was done to prevent naming clashes - but could we make it so that it only triggers if really required - if an actual clash occurs? |
Question about name overrides in the config file: does that affect properties, types, or both, and is there a way to do it for only a specific property on a specific type? Use case would be fixing the occasional confusing name in the API I'm consuming. |
@hactar had some good ideas, but I wanted to address this one:
Inflections for plurals are very irregular, and many singular forms are also plurals. Rails gave up on providing comprehensive auto inflections for this reason (I contributed an inflection patch in the last version where they were being accepted), and instead allowed people to specify mappings. This will just chew up people points, especially once you get to things like correct inflections for octopus or correct singular for hooves. The folks who wrote the API specified |
I agree with this. Inflections are difficult. I was describing my perfect generated function name for the provided example. A generic version would be making a lot of assumptions, like the API being in english. If we could do this close to perfectly in most cases it would be awesome, but its not as simple as "remove an 's' if its at the end of a word. |
@hactar One possibility might be allowing a struct (or YAML file) to help with inflections e.g.:
When you get to languages with noun cases (e.g., many Eastern European languages), plural noun forms get more complex, but we're not generating plural forms, just trying to determine the singular from a given plural used in the I think it would be cool if we could generate the function names with a singular form for singular items like your |
Thanks again @hactar for bringing up the important topic of synthesized operationIds. I updated the proposal with a solution that's close to your generalized solution: by turning slashes into underscores, and dropping curly braces. In concrete terms, that means that an operation without an explicit operationId that looks like:
would get the method name:
It affects all strings from the OpenAPI document that the generator needs to turn into type/method/property names in the generated Swift code. So currently there isn't any way to only do it for one property in one type, but not for an identically named property in another type. You either use the original generated name, or you override it for all occurrences by using Also, thanks @hactar and @deirdresmtoo for the exploration of a more sophisticated automatic naming strategy, but as you correctly identified, that'd be much more complex due to the assumptions about the language and patterns used, and I'd consider that out-of-scope for now. |
@czechboy0 Awesome, thanks! Yes, this will make things without operationIDs much useable. I'd still argue that the resulting API should strive for camel case and not snake case - it is a Swift API guideline after all - it feels really weird to me that the Swift OpenAPI generator would generate API that does not comply to the guidelines: https://www.swift.org/documentation/api-design-guidelines/#conventions . The capitalization would still give away the separation between path components, so I don't see the added benefit of snake case? But, even if you guys do decide to stick to snake case, this will proposal will be a great improvement! |
I was thinking that if you have a path like What do you think, @simonjbeaumont? I'm actually fine with either now. |
IMO there's an important distinction here that I think has been missed: the goal of avoiding snake case is a good one but it should not be confused with avoiding underscores in all places. There is no snake case in the proposal—because snake-case and camel-case are about word separation. The goal is to generate the most idiomatic code we can, within reason, from a generalisable, opinionated strategy. That means we should aim to generate code that is most similar to what would be written by hand, even if that does have underscores. The clearest example is how to handle the translation of If we agree that we shouldn't remove the If the feedback is that |
I agree with you that we need to be careful not to mix up different aspects of the generator. In the case of an operation, the generator is taking the http method, a word, and the path components, also usually words - frequently even forming sentences if read together. For the example of GET /map/styles, this can be read as a sentence: "get map styles". These words now need to be joined in a way that makes them readable to a swift developer, because '/' and ' ' is not valid within a function name. So some options would be
As I see it the goal of the Swift OpenAPI Generator is to take an OpenAPI spec and turn it into an API that feels like a native Swift API. Swift APIs are camel case, so I'd pick the last option here. Now "version2.0" is a different pair of shoes. I'm assuming you're referring to something like |
Thanks @hactar for continuing to reason this one through with us.
If one views the slash separators in a path as equivalent to word separators, then it follows that substituting them with underscores results in snake case. My position was/is that the slashes held more semantic meaning than just word separation, so the use of underscores in their place felt as natural to me as in the However, I think for those that do see them as word separation, the use of underscores is quite an eye sore. So, I'm happy in this case to remove them and treat them like word separators as I think, averaging across the pool of users, this will cause the least surprise. What's your thinking on this one now @czechboy0? |
Yeah, I'm happy to change the proposal to reflect that. |
I agree with what @hactar and @simonjbeaumont have said about their slash and underscore comments. In particular, Si's comment about slashes holding more semantic meaning. An API that has Where an api that had Path component cleanup via _ seems sensible (e.g., the Version2.0 -> version2_0 example). |
I think in the most recent comments, we seem to have landed on just dropping the slashes rather than replacing them with underscores. Is that still okay with you, @deirdresmtoo? |
Absolutely, apologies for leaving that unclear. |
Ok folks, here's the diff of the latest proposal changes (version 1.2): e1f5e42 |
Motivation
See proposal
Modifications
N/A
Result
N/A
Test Plan
N/A