<div dir="ltr">Indeed that might solve the problem (as it would also solve the issues JEP 468 tries to address btw) but it's not the actual matter i wanted to point out. This matter is more about data modeling and the use-case is just a personal example for explanation. The real issue is currently records are the java construct to model data but they lack the ergonomics and semantics  to tell which fields are strictly mandatory and necessary other than creating static methods that acts like custom constructors, they assume all fields are mandatory and must be set manually (even to null). Maybe they should have those ergonomics and semantics or maybe they shouldn't and are much less important than I assume.<div><br></div><div>I am not a language designer so I am not going to discuss further since I am very confident the amber team members know best. </div><div><br></div><div>Best regards and always yours. <br><div><br></div><div><br></div></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">El mar, 11 mar 2025 a la(s) 10:29 a.m., Anatoly Kupriyanov (<a href="mailto:kan.izh@gmail.com">kan.izh@gmail.com</a>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">Does the stuff like <a href="https://github.com/Randgalt/record-builder" target="_blank">https://github.com/Randgalt/record-builder</a> solve the problem? It doesn't sound as it needs changes in the language.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 11 Mar 2025, 14:48 david Grajales, <<a href="mailto:david.1993grajales@gmail.com" target="_blank">david.1993grajales@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><p><span>Hi Amber team. I would like to share some thoughts based on real use cases I am dealing with at work.</span></p><p><span><br></span></p><pre><span>I know</span> is very<span style="font-family:Arial,Helvetica,sans-serif"> likely you have already thought about something like this and I don't know if this would be the best solution for the use case presented. </span></pre><pre><span style="font-family:Arial,Helvetica,sans-serif">My intention is not to propose this as "the solution" but instead just present a personal use-case based on my actual job and a naive solution that crossed my mind in the first 15 minutes. </span></pre><pre><span style="font-family:Arial,Helvetica,sans-serif">So please pay more attention to the use case and "the problem" rather than the proposed "solution" which is actually just a mean to explain the problem</span></pre><p dir="ltr"><br></p><p dir="ltr"><span>Nowadays to create a new record object we must set the value to all it fields, even the ones that might be null.</span></p><pre><span>record User (String name, String email){}</span><br><span>var userWithoutEmail = new User ("name", null)</span></pre><p dir="ltr"><span>This is good since it forces us to set all fields to a valid state and null can be a valid state. This is useful for things like JSON serialization; null fields in JSON are usually not serialized, which saves some bandwidth, in very large JSON structures that only have an small set of mandatory fields, this is very common in banks that happens to be international, since they usually use the same Core for all countries but each country may have different requirements (for example in some countries it's mandatory for people to provide 2 lastnames but in other countries usually you only have one lastname).</span></p><p dir="ltr"><span>To achieve this I usually do the opposite of withers, let me introduce you to the "withouts"</span></p><pre><span>record User (String name, String email){</span><br><span>  </span><br><span>   public static withoutEmail(String name){</span><br><span>     </span><br><span>      return new User(name, null);</span><br><span>   }</span><br><span>}</span><br><span>var userWithoutEmail = User.withoutEmail(name);</span></pre><p dir="ltr"><span>The example is very basic for explanatory purposes and for a record with only 2 fields this can be an overkill, but for bigger records it makes a lot of sense, specially if only few fields between dozens are actually mandatory.</span></p><p dir="ltr"><span>Why not use a class instead? Serialization. records' serialization uses the record constructor, which means it's safer since you can make format and safety validations in the data before the record is built.</span></p><p dir="ltr"><span>nowadays to make sure all the mandatory fields are set, I do something like this.</span></p><p dir="ltr"><span>record User (String name, String email){</span><br><span>  User{</span><br><span>     if(name == null) </span><br><span>        throw new IllegalArgumentException("name field it's mandatory");</span><br><span>   }</span><br><span>}</span><span></span></p><p dir="ltr"><span><br></span></p><p dir="ltr"><span>With derived record creation (or something equivalent but for direct creation) and nullability it would be possible and very handy to be able to declare optional  fields that would compile to null (or zero in case of primitives)</span></p><p dir="ltr"><br><b><strong>Please ignore the straw man syntax from here.</strong></b></p><pre><span>record User (String name!, String email? ){}</span><br><span>User userWithoutEmail with { name : "name"}</span></pre><p dir="ltr"><span>This would make this feature in java to behave similar to TypeScript's interfaces, which are used to model data</span></p><pre><span>export interface User {</span><br><span>   name: String!</span><br><span>   email: String?</span><br><span>}</span></pre><p dir="ltr"><br><span>To me one of the most useful use cases of this would be for writing unitary tests and mocks. </span></p><p dir="ltr"><span>when writing tests sometimes you want to test the behaviour of your contracts (the domain objects) when they carry only the bare required fields, if one has very large json objects to try out but only a small set of mandatory fields usually it's easier to write down the json string and pass it to jackson or gson, with this we could use the domain object directly.</span></p><p dir="ltr"><br><span>Regular test if the domain object has many optional fields</span></p><pre><br><span>record Message (String id, String document, String name, String lastname, String email.... (another 20 fields)){}</span><br><br><br><span>var request = </span><br><span>"""{</span><br><span>  id: "XXXXXXX",</span><br><span>  document: "NNN-NNNNN"</span><br><span>}"""</span></pre><pre><br></pre><pre><span>var message = gson.fromJson(request, Message.class);</span><br><span>var res = method2Test(message);</span><br><span>// put your favorite assertion here//</span></pre><pre><span><br></span></pre><pre><pre>this has the issue you don't have help from the compiler in case you want to represent different scenarios (formatting data, invalid fields, etc)</pre><pre>this is why I usually do "whitouts" for this kind of records.</pre><pre><br></pre><pre>record Message (String id, String document, String name, String lastname, String email.... (another 20 fields)){</pre><pre>  public Static Message minimalRequest(String id, String document){</pre><pre>     return new Message (id, document, lastname, email, null, null...);</pre><pre>   // so I have to write all those nulls once</pre><pre>   }</pre><pre>}</pre><pre>var request = Message.minimalRequest(.....);</pre><pre>var res = method2Test<span style="font-family:Arial,Helvetica,sans-serif">(message);</span></pre><pre>// put your favorite assertion here//</pre></pre><p dir="ltr"><br><span>With optional fields in records there could be changed for something like this.</span></p><pre><span>record Message (String id, String document, String name?, String lastname?, String email? .... (another 20 nullable fields)){}</span><br><br><span>Message request  with {id: "XXXXXXXX"; document: "NNN-NNNNNN"}</span><br><span>var res = method2Test(message);</span><br><span>// put your favorite assertion here//</span></pre><pre>I hope this presented use-case it's useful</pre><pre>Best regards!</pre><p dir="ltr"><span></span></p></div>
</div>
</div>
</blockquote></div>
</blockquote></div>