Repository navigation
[Syntax Review] Additional types of SampleGen code samples - #7051
beccasaurus wants to merge 1 commit into
Conversation
Note: this is using the same sample .snip templates as with the previous PR #6543
|
Hello Java friends ☕️ Follow-up PR, as promised! @kurtisvg @averikitsch @lesv @chingor13 @googleapis/samplegen |
|
| @@ -0,0 +1,59 @@ | |||
| /* | |||
There was a problem hiding this comment.
ℹ️ Note: this "no config" sample is different from the rest. Rather than demonstrating a feature, it shows what a sample looks like when not configured at all.
These samples could be generated for every API method without any manual configuration.
Review of the "no config" sample is not required, this is more of an FYI :)
| * Please include the following imports to run this sample. | ||
| * | ||
| * import com.google.cloud.vision.v1.CreateProductSetRequest; | ||
| * import com.google.cloud.vision.v1.LocationName; | ||
| * import com.google.cloud.vision.v1.ProductSearchClient; | ||
| * import com.google.cloud.vision.v1.ProductSet; |
There was a problem hiding this comment.
We've already provided feedback - strike the comments.
| * import com.google.cloud.vision.v1.ProductSet; | ||
| */ | ||
|
|
||
| public static void sampleCreateProductSet() { |
There was a problem hiding this comment.
This sample has a constructor, but most do not?
| // sample-metadata: | ||
| // title: This is the sample title | ||
| // description: This is the sample description | ||
| // usage: gradle run -PmainClass=com.google.cloud.examples.vision.v1.SamplegenBasics [--args='[--display_name "This is the default value of the display_name request field"]'] |
There was a problem hiding this comment.
I thought we typically used maven in samples?
There was a problem hiding this comment.
I think the goal is that we should support both - but since for Java we expect most users to run these from the IDE (instead of command line) these instructions should be something along the lines of "Update the values under the TODO(developer) line and execute the function to run this sample).
| /** | ||
| * This is the sample description | ||
| * | ||
| * @param displayName Description of the parameter | ||
| */ |
There was a problem hiding this comment.
Believe no javadocs.
Also since the constructor has the displayName variable this is redundant.
Codecov Report
@@ Coverage Diff @@
## master #7051 +/- ##
============================================
- Coverage 32.18% 32.18% -0.01%
+ Complexity 3698 3697 -1
============================================
Files 249 249
Lines 40371 40371
Branches 6134 6134
============================================
- Hits 12994 12992 -2
- Misses 26304 26305 +1
- Partials 1073 1074 +1
Continue to review full report at Codecov.
|
| * @param displayName Description of the parameter | ||
| */ | ||
| public static void sampleCreateProductSet(String displayName) { | ||
| try (ProductSearchClient productSearchClient = ProductSearchClient.create()) { |
There was a problem hiding this comment.
I believe we are also adding this comment to all client declarations:
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the "close" method on the client to safely clean up any remaining background resources.
There was a problem hiding this comment.
I love this! +💯 Thanks for providing the exact comment!
| try (ProductSearchClient productSearchClient = ProductSearchClient.create()) { | ||
|
|
||
| // The project and location in which the product set should be created. | ||
| LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); |
There was a problem hiding this comment.
Anything the user needs to set should be in the constructor
| import com.google.cloud.vision.v1.ProductSearchClient; | ||
| import com.google.cloud.vision.v1.ProductSetName; | ||
|
|
||
| public class SamplegenNoResponse { |
There was a problem hiding this comment.
No response or empty response?
| try (ProductSearchClient productSearchClient = ProductSearchClient.create()) { | ||
|
|
||
| // The project and location in which the product set should be created. | ||
| LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); |
There was a problem hiding this comment.
nit - I wish we used EnvVar's for this rather than user editing.
There was a problem hiding this comment.
There should probably be TODO(developer) here as well.
There was a problem hiding this comment.
These would be good to pass in as arguments, so we can test them.
|
|
||
| public static void sampleCreateProductSet() { | ||
| // TODO(developer): Replace these variables before running the sample. | ||
| String displayName = "This is the default value of the display_name request field"; |
There was a problem hiding this comment.
nit - wish this was an EnvVar
There was a problem hiding this comment.
I disagree on this one - if we expect users to copy/paste, it makes more sense that they would just update the values in the IDE after doing so.
It makes sense that the tests would look for EnvVars though.
| } catch (Exception exception) { | ||
| System.err.println("Failed to create the client due to: " + exception); | ||
| } |
There was a problem hiding this comment.
BLOCK - I think we've already provided feedback on this.
Exceptions should be as specific as possible and suggest what to do. Just printing the error isn't good form.
https://google.github.io/styleguide/javaguide.html#s6.2-caught-exceptions
| public static void main(String[] args) throws Exception { | ||
| Options options = new Options(); | ||
| options.addOption( | ||
| Option.builder("").required(false).hasArg(true).longOpt("display_name").build()); |
There was a problem hiding this comment.
BLOCK - "" ? This doesn't tell me much.
If I was reviewing, I'd certainly ask for a comment.
| } | ||
| // [END samplegen_basics] | ||
|
|
||
| public static void main(String[] args) throws Exception { |
There was a problem hiding this comment.
BLOCK - Exceptions should ideally be very specific if thrown to tell the user what to expect.
There was a problem hiding this comment.
Additionally - ArgParsing should be ideally outside the class (but at the very least excluded from the snippets).
| public static void sampleCreateProductSet(String project) { | ||
| try (ProductSearchClient productSearchClient = ProductSearchClient.create()) { | ||
| LocationName parent = LocationName.of(project, "us-central1"); | ||
| String displayName = "[DISPLAY NAME]"; |
There was a problem hiding this comment.
nit - would prefer EnvVar or as a passed param.
| } catch (Exception exception) { | ||
| System.err.println("Failed to create the client due to: " + exception); | ||
| } |
There was a problem hiding this comment.
BLOCK - should be specific exception(s).
|
|
||
| public static void main(String[] args) throws Exception { | ||
| Options options = new Options(); | ||
| options.addOption(Option.builder("").required(false).hasArg(true).longOpt("project").build()); |
| /* | ||
| * Please include the following imports to run this sample. | ||
| * | ||
| * import com.google.cloud.texttospeech.v1.AudioConfig; | ||
| * import com.google.cloud.texttospeech.v1.AudioEncoding; | ||
| * import com.google.cloud.texttospeech.v1.SynthesisInput; | ||
| * import com.google.cloud.texttospeech.v1.SynthesizeSpeechRequest; | ||
| * import com.google.cloud.texttospeech.v1.SynthesizeSpeechResponse; | ||
| * import com.google.cloud.texttospeech.v1.TextToSpeechClient; | ||
| * import com.google.cloud.texttospeech.v1.VoiceSelectionParams; | ||
| * import java.io.FileOutputStream; | ||
| * import java.io.OutputStream; | ||
| */ |
| } catch (Exception exception) { | ||
| System.err.println("Failed to create the client due to: " + exception); | ||
| } |
There was a problem hiding this comment.
BLOCK - needs to be the specific ERROR's so user knows to write code to deal with the situation, or don't catch them and add exception to the method defn.
| try (ProductSearchClient productSearchClient = ProductSearchClient.create()) { | ||
|
|
||
| // The project and location in which the product set should be created. | ||
| LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); |
There was a problem hiding this comment.
These would be good to pass in as arguments, so we can test them.
| ProductSet productSet = response; | ||
| System.out.printf("The full name of the created product set: %s\n", productSet.getName()); | ||
| } catch (Exception exception) { | ||
| System.err.println("Failed to create the client due to: " + exception); |
There was a problem hiding this comment.
Question to the Java DPEs: Should we be using a better logging library like slf4j?
There was a problem hiding this comment.
In the sample format, we already suggest using java.util.logging for web applications - slf4j matches this interface I think?
Maybe just expand this to suggesting for all samples?
| String language = "en"; | ||
|
|
||
| // The text content to analyze | ||
| String content = "Googleplex is at 1600 Amphitheatre Parkway, Mountain View, CA."; |
There was a problem hiding this comment.
Question for DPEs: a lot of the code in these samples feel squished together. Is that because of the formatting of builders?
There was a problem hiding this comment.
IMO - there should be a breaks between building, sending/receiving, and acting on the response (Arrange, Act, Assert)
There was a problem hiding this comment.
@beccasaurus, does samplegen support adding empty lines yet?
| // sample-metadata: | ||
| // title: This is the sample title | ||
| // description: This is the sample description | ||
| // usage: gradle run -PmainClass=com.google.cloud.examples.vision.v1.SamplegenBasics [--args='[--display_name "This is the default value of the display_name request field"]'] |
There was a problem hiding this comment.
I think the goal is that we should support both - but since for Java we expect most users to run these from the IDE (instead of command line) these instructions should be something along the lines of "Update the values under the TODO(developer) line and execute the function to run this sample).
|
|
||
| public static void sampleCreateProductSet() { | ||
| // TODO(developer): Replace these variables before running the sample. | ||
| String displayName = "This is the default value of the display_name request field"; |
There was a problem hiding this comment.
I disagree on this one - if we expect users to copy/paste, it makes more sense that they would just update the values in the IDE after doing so.
It makes sense that the tests would look for EnvVars though.
| // The API response represents the created product set | ||
| ProductSet productSet = response; | ||
| System.out.printf("The full name of the created product set: %s\n", productSet.getName()); | ||
| } catch (Exception exception) { |
There was a problem hiding this comment.
Should catch a more specific Exception - See Exception Handling
| ProductSet productSet = response; | ||
| System.out.printf("The full name of the created product set: %s\n", productSet.getName()); | ||
| } catch (Exception exception) { | ||
| System.err.println("Failed to create the client due to: " + exception); |
There was a problem hiding this comment.
In the sample format, we already suggest using java.util.logging for web applications - slf4j matches this interface I think?
Maybe just expand this to suggesting for all samples?
| } | ||
| // [END samplegen_basics] | ||
|
|
||
| public static void main(String[] args) throws Exception { |
There was a problem hiding this comment.
Additionally - ArgParsing should be ideally outside the class (but at the very least excluded from the snippets).
| RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(uri).build(); | ||
| LongRunningRecognizeRequest request = | ||
| LongRunningRecognizeRequest.newBuilder().setConfig(config).setAudio(audio).build(); | ||
| OperationFuture<LongRunningRecognizeResponse, LongRunningRecognizeMetadata> future = |
There was a problem hiding this comment.
nit: Ideally there would be a break between the section that builds the request and the section that sends the request - See Arrange, Act, Assert
Additionally, I think it would be helpful to include a comment explaining that the request is only to start the operation, which is why the future.get is called later.
| /** This sample reads and loops over a map field in the response */ | ||
| public static void sampleAnalyzeEntities() { | ||
| try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) { | ||
| Document.Type type = Document.Type.PLAIN_TEXT; |
There was a problem hiding this comment.
Similar to my comment in Python, we should provide links to docs or page on what values are supported.
| String language = "en"; | ||
|
|
||
| // The text content to analyze | ||
| String content = "Googleplex is at 1600 Amphitheatre Parkway, Mountain View, CA."; |
There was a problem hiding this comment.
IMO - there should be a breaks between building, sending/receiving, and acting on the response (Arrange, Act, Assert)
| for (Map.Entry<String, String> entry : entity.getMetadataMap().entrySet()) { | ||
| String key = entry.getKey(); | ||
| String value = entry.getValue(); | ||
| System.out.printf("%s: %s\n", key, value); |
There was a problem hiding this comment.
nit: inline single use variables
| System.out.printf("%s: %s\n", key, value); | |
| System.out.printf("%s: %s\n", entry.getKey(), entry.getValue()); |
| } | ||
|
|
||
| // Loop over just keys: | ||
| for (String theKey : entity.getMetadataMap().keySet()) { |
There was a problem hiding this comment.
Similar to python - these two loops don't show any API interaction with the library, they are only showing basic Java syntax. Since we've already established it's a map in the first loop, these two feel unnecessary.
To evaluate the readiness of ☕️ Java's GAPIC sample generator for use on cloud.google.com,
this provides a full set of samples which demonstrate the basic features of generated samples.
The first review Pull Request contained samples to show the basic structure as well as LRO samples.
This contains samples demonstrating those features and a few more use-cases for review –
SamplegenBasics.javaSamplegenNoConfig.javaSamplegenNoResponse.javaSamplegenPaged.javaSamplegenResourcePath.javaSamplegenMapFieldAccess.javaSamplegenReadAndWriteFiles.javaSamplegenRepeatedFields.javaSamplegenWriteBytesToFile.javaSamplegenLro.javaThis Pull Request is focused on feedback collection & a similar PR is being sent to all languages.
Once you've completed your review and left comments, you may feel free to close the PR!
🙏 Thanks in advance for your review!
P.S. Nits welcome! We'd like to get these as polished as possible for usage on cloud.google.com.
🔍 Known Issues
🔍 Tool for review: Java SAMPLE_FORMAT