A language agnostic approach since I see this problem in both compiled and interpreted languages with the builder pattern.
Let's say I have a Model that has 10 required fields and 5 optional fields. Of course, adding all these fields to the constructor would be a mess, but the constructor would allow us to easily check for failure because it can verify the types of the fields and that all the fields are provided.
Using the Builder pattern, we can make this code much cleaner to read and write, but as far as I see, it'd be hard for the compiler or IDE to know that a required field hasn't been provided.
For instance, let's say
instance = new Model(firstName, lastName, phoneNumber);
The compiler, or other forms of checks, can see
instance = new ModelBuilder() ->withName(firstName, lastName) ->withPhoneNumber(phoneNumber) ->build();
Here, the compiler, as far as I know, cannot tell that
withEmail() should have been called in order to define the email which can lead to a runtime exception if you have one instance of the Builder that is missing a required field.
Is this unavoidable? Is there some pattern that can be used to solve this problem?
Beyond making sure every instance that uses Builder has test coverage, I haven't been able to come up with a solution to the runtime exceptions. This problem seems to present itself more when the model has a new required field added after the builder instances have been implemented across the application.