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

Add Parameter Grouping to AutoRest for Azure.CSharp, Azure.NodeJS #381

Merged
merged 1 commit into from
Oct 23, 2015

Conversation

matthchr
Copy link
Member

@matthchr matthchr commented Oct 8, 2015

A "Parameter group" is just a nicer way to bundle parameters so that methods don't get horribly long. It is controlled by an extension to the Swagger specification.

Left out Ruby/Java for now, as Java doesn't have an "Azure.Java" yet and cut Ruby in the name of time (if/when somebody wants the feature in Ruby they should be able to follow the implementation from NodeJS/C#/Java since the metadata is in the client model now)

@azuresdkci
Copy link

Can one of the admins verify this patch?

1 similar comment
@azuresdkci
Copy link

Can one of the admins verify this patch?

@azurecla
Copy link

azurecla commented Oct 8, 2015

Hi @matthchr, I'm your friendly neighborhood Azure Pull Request Bot (You can call me AZPRBOT). Thanks for your contribution!


It looks like you're working at Microsoft (matthchr). If you're full-time, we DON'T require a contribution license agreement.



If you are a vendor, or work for Microsoft Open Technologies, DO please sign the electronic contribution license agreement. It will take 2 minutes and there's no faxing! https://cla.azure.com.

TTYL, AZPRBOT;

@matthchr matthchr force-pushed the feature/parameter-grouping branch from 18230d7 to 105ea6a Compare October 8, 2015 18:08
@amarzavery
Copy link
Contributor

@matthchr - It is a nice concept. As per the current implementation, the user can group parameters in 1 bucket. What if the user wants to group them into more than 1 bucket? Would it be a better idea if the extension takes a key value pair instead of a Boolean, something like this:

"x-ms-parameter-grouping" : {"groupName" : "group1" }

In this way the user can put parameters into different buckets if required. It also provides a flexibility to name the parameter group as per their requirement.

What do you think?

@matthchr
Copy link
Member Author

matthchr commented Oct 8, 2015

@amarzavery Yes, allowing more than one parameter group was something I thought about (if you see in the implementation the "groups" is actually a collection and everywhere when I generate the code I treat it as such), so the only thing currently stopping us from having multiple groups is the extension piece...

With that said are some additional complications with allowing multiple parameter groups which is why I leaned against it initially:

  1. You must allow swagger to specify "type" names then (which only apply to some languages?)
  2. You must allow swagger to specify "parameter" names (instead of just hardcoding the string "parameter") - maybe this could be sourced off of the same string as the "type" names issue mentioned above
  3. You have to handle type-collisions better then, which I wasn't really sure how to do. Since right now the type of the parameter group class is based on the OperationId (which I believe is unique) we're protected from that naturally.

I agree it would be good to have, but maybe leave it for a V2 implementation?
I know that my team at least is happy with even just 1 parameter group (i.e. 1 is better than 0 for us, but N is not much better than 1)

edit: Okay I tried this and it turns out it was pretty easy to do (I thought it would be harder), so I added support for this right out of the box (and added some tests to make sure it works). Let me know what you think.

@brjohnstmsft
Copy link
Member

Have you considered a more general approach? Rather than indirectly define a model type by grouping parameters, it would be really handy if we could bind some parameter values to others. For example, for PUT operations, it would be really nice to be able to bind the URL parameter for the resource ID to the corresponding property on the resource itself. See this issue for a concrete example: #382

@matthchr
Copy link
Member Author

matthchr commented Oct 8, 2015

@brjohnstmsft David Justice had discussed something similar to what you're asking for - he colloquially called it "parameter factories" or something. My team has a similar request, but instead of a "duplicate" parameter like in your example (where there is Model.Id and id), we want to set certain parameters to be automatically generated instead of including them in the signature.

For example: parameter "string requestId" (required: true) could instead be optional or omitted entirely and automatically generated as a Guid (or in your case automatically generated from an existing model field).

I do see the two things being different features though: this is about how to structure the parameters we do want, what you're asking for is a way to omit parameters which are "required" by the REST API but which you do not want.

@matthchr matthchr force-pushed the feature/parameter-grouping branch from af20e76 to 73e51d2 Compare October 12, 2015 16:36
@yugangw-msft
Copy link
Contributor

add to whitelist


foreach (Method method in serviceClient.Methods)
{
//TODO: Does this group name need to be normalized later, or does that already happen?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will be normalized by each code generator, so you are good

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yugangw-msft Updated comment to reflect that fact

@matthchr matthchr force-pushed the feature/parameter-grouping branch from 2acb4ee to 6a03ddf Compare October 15, 2015 21:29
@matthchr
Copy link
Member Author

Okay, I moved the Parameters objects into the models folder and namespace.

@matthchr
Copy link
Member Author

@yugangw-msft I am not sure why the "default" check failed in jenkins, can somebody help me take a look at that? Travis pass seems okay...

@yugangw-msft
Copy link
Contributor

@matthchr please merge with dev. The CI failure was caused by the java change made to the dev branch this afternoon

@matthchr matthchr force-pushed the feature/parameter-grouping branch from 6a03ddf to d09a149 Compare October 15, 2015 23:46
@matthchr
Copy link
Member Author

@yugangw-msft Merge with dev done

@matthchr matthchr force-pushed the feature/parameter-grouping branch from d09a149 to d21bea0 Compare October 16, 2015 00:18
@matthchr
Copy link
Member Author

@devigned @stankovski Should we use these comments to discuss proposed changes to this implementation?

One thing that @xingwu1 pointed out to me is that this PR is pretty critical to our adoption, so I don't really want to have to re-design/re-do everything (especially if it's significantly more complicated to do an alternate way) because it will delay our swagger adoption (after this PR, we can actually generate a real client).

If we can align on:

  1. The Swagger representation (tentatively, I think what I have now is fine).
  2. The generated code structure (I think what I have now is fine).
  3. A model structure which is generic enough for now.

If we change the internals of AutoRest (the model structure) in the future to be more generic or cater to more scenarios, that change is fine because it's hidden from clients generated code and their swagger specifications.

I'll start with my suggestion:

  1. Swagger extension format stays as it is in this PR (a piece of metadata on the Parameter object in the swagger spec).
  2. Client model is updated to have some sort of "mapped" parameter notion. Basically, there can be parameters in the ParameterList, and there will be a dictionary mapping ParameterList parameters to "real" parameters, and there will be some generic methods which will transform the parameters in the list to parameters in the internals of the method. At the end of the day the generated method code will still look almost exactly like I have it in the PR today (top of the method will extract stuff out of the object into a set of named local variables, other pieces of the method will consume the local variables).

I think that the part which might be reusable is the stuff for the client model, but even that is maybe not totally code-reuse but rather just concept re-use... what I mean is this:

  • For input parameters, there is this notion of a ParameterList, and a dictionary or something which describes the mapping of Parameters -> UnwrappedParameters.
  • For output parameters, there is the reverse notion - you have a set of parameters and a mapping collapsing them into a new type, so it's UnwrappedParameters -> OutputParameters.

Let me know what you think.

@@ -59,6 +59,27 @@ public Method()
public List<Parameter> Parameters { get; private set; }

/// <summary>
/// Gets the parameter groups.
/// </summary>
public IEnumerable<string> ParameterGroups
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be replaced with two "Mapping" properties - one for input and one for output.

@stankovski
Copy link
Member

@matthchr I agree with the approach. Let's leave swagger extension as-is. I also think that the generated code will stay almost the same. An output block of similar structure will be needed and you may need to convert terniary expression to an if block for mapping from primitives to a class.

As far as mapping, I would leave current ParameterList as is and add a new data structure (either just a dictionanry or a class to work with output mapping) that matches an existing parameter or parameter property to a new parameter or parameter property.

@matthchr
Copy link
Member Author

@stankovski I've created an issue #395 to discuss the structure of the returned object for the return header -> object path. Can we delay the implementation of that until we've decided on what the output object should look like (is it a union of the returned headers and the body, a <T, K> double-generic (in C#) or something else?).

Until then, I think I won't be able to write any test cases or samples for the "re-grouping" case (since there will be no place to put the returned header seeing as the body is already populated by the JSON deserialization), so I will hold off on writing it. When we get there, we can follow the exact same pattern as the un-grouping case in this PR.

Does that sound okay?

@matthchr matthchr force-pushed the feature/parameter-grouping branch from d21bea0 to e9d74c3 Compare October 20, 2015 17:07
@matthchr
Copy link
Member Author

@stankovski This has the changes to ParameterGrouping to move to the "Mapping" idea -- the CI is failing due to an issue in dev branch -- once that is fixed I'll merge and update.

@@ -59,6 +60,22 @@ public Method()
public List<Parameter> Parameters { get; private set; }

/// <summary>
/// Gets the list of Parameter Expansions
/// </summary>
public Dictionary<string, Dictionary<Property, Parameter>> ParameterExpansions { get; private set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make it more generic and support parameter groups as well primitive to object mapping can we do the following:

  1. Rename this to ParameterMappings
  2. Add new type to ClientModel called ParameterMapping with the following properties
  • Parameter InputParameter {get; set;}
  • string InputParameterProperty {get; set;} (either null, which will map the parameter itself, or dot separated string to match properties)
  • Parameter OutputParameter {get; set;}
  • string OutputParameterProperty {get; set;} (either null, which will map the parameter itself, or dot separated string to match properties)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add a public Parameter Body {get;} to get easier access to the body parameter

@matthchr matthchr force-pushed the feature/parameter-grouping branch 2 times, most recently from dde26e6 to 357d061 Compare October 22, 2015 22:06
 - Support in C#, NodeJS, and partially in Java.
@matthchr matthchr force-pushed the feature/parameter-grouping branch from 357d061 to 3791d93 Compare October 22, 2015 23:54
stankovski added a commit that referenced this pull request Oct 23, 2015
Add Parameter Grouping to AutoRest for Azure.CSharp, Azure.NodeJS
@stankovski stankovski merged commit 21dfdca into Azure:dev Oct 23, 2015
@matthchr matthchr deleted the feature/parameter-grouping branch November 3, 2015 19:05
timayabi2020 pushed a commit to timayabi2020/autorest that referenced this pull request Jan 22, 2025
* Add examples in body-string

* Update examples

* Update examples

* Update package lock version

* Update format
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

Successfully merging this pull request may close these issues.

7 participants