DEV Community

Cover image for A believable person, and making it honest
Ernesto Herrera Salinas
Ernesto Herrera Salinas

Posted on • Edited on

A believable person, and making it honest

Two things were still missing before the persona was presentable. It had to be fully believable, not half-coherent, and it had to be honest about what it had done. Three decisions covered both.

Correlate fully, or not at all

The first fork was how deep the correlation goes. Name-coherence only (first, last, full, email, username agree) is cheaper. But half-coherence is its own kind of broken: a FirstName of "Maria" next to a Salutation of "Mr.," or an Age that contradicts the BirthDate, looks as wrong as fully random data, and the seed/demo reader is exactly the person who notices.

So the persona is a full bundle. Some facets are drawn, the rest derive with no extra randomness:

drawn:   gender, firstName (conditioned on gender), lastName,
         birthDate (adult-aged, off the operation's reference time),
         phone (locale format), emailDomain
derived: fullName, initials, email, username, salutation (from gender),
         age (from birthDate + reference time)
Enter fullscreen mode Exit fullscreen mode

This is not free: it adds a dataset dependency, first names tagged by gender. I accepted that, because the alternative is data that fails the two-second believability test.

Gender, without shipping a gender enum

The persona needs an internal gender axis to pick a coherent name and salutation.
That raised a question I wanted to handle carefully: does Munchausen now ship a public gender enum? I decided no.

The fork was whether to leave a model's own gender field alone (and risk it contradicting the name) or bind it. I bind it, by adapting to whatever type the model already declares:

class Account { string FirstName; string Gender; }                 // string -> "Female"
class Profile { string FirstName; Sex Sex; } enum Sex { Female, Male, Unspecified }
                                                                    // enum -> Sex.Female
class Contact { string FirstName; }                                // no gender field
                                                                    // axis still drives the name
Enter fullscreen mode Exit fullscreen mode

A string member gets "Female" or "Male". An enum member gets the value whose name matches the internal axis, falling back to ordinary inference when nothing matches. Munchausen never defines the categories itself; it mirrors the type the model declares, and the explicit d.Person.Gender is a plain string for the same
reason. The internal-axis-only option lost because it leaves the gender field free to contradict the name, which is the exact incoherence I was removing, just moved one field over.

Make it inspectable

Explainability is a differentiator on the rigor axis, so coherence cannot be a silent behavior. Each persona-bound member reports a new source, InferenceSource.CoherentEntity, and Explain() shows it plainly:

Contact.FirstName  -> Person.First     [coherent entity]
Contact.LastName   -> Person.Last      [coherent entity]
Contact.Email      -> Person.Email     [coherent entity]   (fulfills [EmailAddress])
Contact.Gender     -> Person.Gender    [coherent entity]
Enter fullscreen mode Exit fullscreen mode

You can see which members share one identity (they all say Person.*), and the compose decision from the last post shows up inline on Email. The same report is what makes the two-people collapse diagnosable.

Takeaway

Correlate fully or not at all, because partial coherence reads as broken. Adapt to the types your users declare instead of legislating your own. And never let an automatic behavior be opaque: inference you can read is inference you can trust.

What's next

A persona engine that only does Person is just a Person feature with extra steps. The real test of the abstraction was a second entity. Next post: proving it generalizes, from Person to Address.

Top comments (0)