Skip to main content

TOMS - Inside the Group Model: Membership, Shared Contact Data and Seating Context

After looking in detail at the Guest model, the next logical object in my C++ event-planning reconstruction is the Group.

At first, a Group appears simpler than a Guest. And in terms of stored state, it genuinely is.

The reconstructed Group contains only three pieces of group-specific state: a collection of Guests, a Group name and a separate object containing shared contact information.

But the simplicity of those fields is deceptive.

The Group sits at an important junction in the application. It connects individual Guests into meaningful units, provides shared contact information, contributes presentation and sorting behaviour, and even participates in seating-related calculations.

The Group is not merely a label attached to several Guests. It is an independent domain object with its own identity, contact data, membership and behaviour.

The Group is itself an Event Object

Like the Guest, the Group derives from the common Event Object foundation.

It therefore inherits two concepts that are deliberately not duplicated in the Group itself:

  • a persistent object identifier;
  • free-form notes.

This is architecturally significant.

A Group is not simply an attribute stored inside a Guest. It has its own independent identity and lifetime.

Conceptually:

Event Object
│
├── Persistent identity
├── Notes
│
└── Group
    │
    ├── Group name
    ├── Group contact information
    └── Guest membership

That distinction becomes increasingly valuable as the application grows. If a Group were only a string inside each Guest, changing a group name would potentially require updating every Guest independently. Shared contact information would have to be duplicated. There would be no obvious place for group-level behaviour.

Making the Group an object avoids that entire category of problems.

Only three Group-specific fields

One of the things I like about this reconstructed class is how little persistent state it actually requires.

Ignoring the identity and notes inherited from the common Event Object, the Group stores:

  • a collection of references to the Guests belonging to the Group;
  • a complete Group Contact value;
  • the Group's name.

There is no duplicated Guest information inside the Group.

The Group does not contain copies of Guest names, RSVP statuses, meal choices or table assignments. It holds references to the actual Guest objects.

That makes the basic relationship straightforward:

Group
│
├── Name
├── Contact information
│
└── Members
    ├── Guest
    ├── Guest
    ├── Guest
    └── Guest

The Guest model contains the corresponding relationship back to its Group. This means Group membership is visible from both sides of the domain relationship.

Why Groups need to be independent objects

A Group could represent a family, but the architecture does not force that interpretation.

It could equally represent colleagues from the same company, a delegation, a wedding party, a club, a school group or another collection of people that should be treated together for some aspects of event planning.

The important idea is that the relationship has meaning beyond a textual tag.

For example, suppose four Guests are members of the same family. Their individual names, RSVP statuses, meal preferences and seating positions remain personal. But they may share:

  • a household address;
  • a common telephone number;
  • a common email contact;
  • a preferred grouping during seating;
  • a collective label used in reports or invitations.

That shared information belongs naturally to the Group rather than being copied four times.

A Group represents shared context. Guests remain individual objects, but the Group gives the application somewhere to store and reason about information that belongs to them collectively.

Group contact information is much richer than Guest contact information

The contact model associated with a Group is considerably more extensive than the individual Guest contact model I described previously.

The reconstructed Group Contact object contains ten textual fields:

  • primary address line;
  • secondary address line;
  • city;
  • state, province or region;
  • postal code;
  • country;
  • work telephone number;
  • home telephone number;
  • mobile telephone number;
  • email address.

This difference between Guest contact information and Group contact information is revealing.

The individual Guest model mainly needs direct communication channels. The Group model can represent something closer to a household or organisational contact record, including a full postal address.

Group Contact
│
├── Postal address
│   ├── Address line 1
│   ├── Address line 2
│   ├── City
│   ├── State / region
│   ├── Postal code
│   └── Country
│
└── Communications
    ├── Work phone
    ├── Home phone
    ├── Mobile phone
    └── Email

The Group itself can retrieve and replace this complete Contact object rather than manipulating ten unrelated pieces of state directly.

That is another example of composition being preferable to flattening every field into one enormous domain class.

Contact availability is part of Group behaviour

The Group does not simply store contact information. It can answer questions about it.

There is explicit behaviour for determining whether the Group has an email address and whether any telephone number is available.

That may sound minor, but it keeps callers from repeatedly implementing logic such as:

if work phone exists
   or home phone exists
   or mobile phone exists
then
   group is contactable by phone

The object itself understands what “has a phone number” means.

There is also an accessor associated with the first address line, showing that selected contact information can be exposed directly where the application frequently needs it.

The Guest collection is a relationship, not ownership evidence

The Group maintains a collection of pointers to Guests.

That tells me the Group knows which Guests belong to it. It does not, by itself, prove that the Group owns the lifetime of those Guest objects.

This distinction matters when reconstructing C++.

A raw pointer can represent ownership, borrowing, observation or simply an old implementation style. I do not want to infer ownership semantics from syntax alone.

The current call references show that the wider Event Document participates directly in adding Guests and retrieving Guests belonging to Groups. That strongly suggests that membership management belongs to the broader document model rather than being treated as a completely isolated Group operation.

So, for now, the safest architectural description is:

Event Document
      │
      ├── manages Guests
      ├── manages Groups
      │
      └── maintains relationships
              │
              ▼
             Group
              │
              └── references its Guests

That is more precise than claiming ownership before the remaining lifetime behaviour has been fully reconstructed.

The Group knows how many Guests it contains

The Group exposes its collection of Guest references and can report the number of Guests currently associated with it.

This is straightforward functionality, but it turns membership into a first-class part of the domain model.

Other parts of the application can therefore reason about a Group without manually inspecting implementation details.

A report can ask for the number of members. A presentation layer can retrieve the members. Seating logic can evaluate the Group as a unit. The Event Document can resolve references after loading persistent data.

The generated call relationships show exactly this sort of reuse: the member collection is referenced by Guest creation, Group queries, document-level Group lookups, reference resolution and seating-related logic.

Formatting a Group means formatting its members too

The Group contains several methods dedicated to producing human-readable descriptions of its Guest membership.

It can generate a complete formatted Guest list, optionally sorted.

It can produce a string containing the first names of the non-anonymous Guests.

It can also construct display-name lists using a supplied separator, again with optional sorting.

This tells me that Groups are intended to appear in more places than a simple Group-management screen.

They are likely to need compact descriptions suitable for tables, reports, lists or printed material.

Conceptually, the same Group might be represented as:

The Smith Family

Jane, John, Emily and Peter

Jane Smith; John Smith; Emily Smith; Peter Smith

The exact formatting depends on context, but the architectural point is that the Group understands how to turn its membership into meaningful presentation text.

Anonymous Guests affect Group presentation

The first-name-list behaviour explicitly excludes anonymous Guests.

This links directly back to the anonymous-Guest concept discussed in the previous article.

An unnamed placeholder Guest still participates in the Group and still counts as a member, but it should not necessarily appear in a human-readable list of people's names.

That demonstrates why anonymous status was modelled semantically rather than represented merely by an empty name string.

The interaction between Guest and Group behaviour is becoming visible: membership includes anonymous Guests, while some presentation functions deliberately exclude them.

Group names have sorting semantics

The Group also contains behaviour for producing a normalised version of its name specifically for sorting.

The method accepts an option controlling whether name particles should be ignored during that process.

This is another small but revealing detail.

Human names and organisational names do not always sort correctly using a simple byte-for-byte or character-for-character comparison. Prefixes, particles and presentation conventions can change where a name should appear in an alphabetical list.

The reconstructed application therefore distinguishes:

Displayed Group name
          │
          ▼
Sorting normalisation
          │
          ▼
Comparable sorting key

Again, this is the sort of detail that would be very easy to overlook if I recreated the software only by copying what was visible on screen.

The Group has a seating-related responsibility

The most interesting Group behaviour from the wider application perspective is a method that determines the seating compatibility status of the Guests belonging to the Group.

The generated documentation explicitly describes that operation in those terms.

This is an important clue about how Group membership influences seating.

The Group is therefore not simply administrative metadata. Its membership is meaningful to the seating domain.

The implementation uses the Group's Guest collection when calculating this status.

I am deliberately not assigning a stronger interpretation to the integer result yet. The documentation confirms that it represents a seating compatibility status, but I still need the surrounding solver and affinity logic before I can safely describe every possible value and how it affects optimisation.

The recovered code proves that Group membership participates in a seating-compatibility calculation. It does not yet justify inventing the exact business meaning of every returned status value.

Groups also participate in affinity processing

The generated call graph provides another useful connection.

The Event Document accesses the Group's Guest list while determining whether any Guest in the Group has a non-neutral affinity relationship.

This means Group membership becomes a useful boundary for querying interpersonal seating constraints.

Conceptually:

Group
  │
  ├── Guest A ── affinity relationships
  ├── Guest B ── affinity relationships
  ├── Guest C ── affinity relationships
  └── Guest D ── affinity relationships
          │
          ▼
 Group-level query by
 the Event Document

This reinforces a pattern I am starting to see in the architecture: the Group stores membership, while higher-level document logic can use that membership to perform broader relationship analysis.

The Group also has a visual identity

The reconstructed class includes static behaviour for producing a Group icon.

This does not mean that the Group itself is a graphical floor-plan object. It is not.

Instead, it means that the application has a standard visual representation for Groups in lists, dialogs or other interface components.

This distinction is worth preserving:

Group
│
├── Domain object
├── Not a floor-plan object
│
└── Can still have
    a UI icon

Having an icon does not automatically make something part of the graphical scene hierarchy.

The Group and Guest form a bidirectional relationship

Looking at the Guest and Group together makes the domain structure much clearer.

The Group maintains its collection of Guests.

Each Guest can also refer to the Group to which it belongs.

So conceptually the architecture contains a bidirectional association:

          belongs to
Guest ─────────────────────► Group
  ▲                           │
  │                           │
  └──────── contains ─────────┘

Bidirectional relationships need careful handling because both sides must remain consistent.

If a Guest moves from one Group to another, the Guest's relationship and both Group membership collections potentially need updating as one logical operation.

The current documentation suggests that the Event Document plays an important coordinating role here. That is an architecture point I expect to examine more closely when I document the Event Document itself.

What the Group does not contain is equally important

The Group class is useful partly because it does not try to duplicate the Guest model.

It contains no meal preference of its own, no RSVP status, no age category, no gender category, no table pointer and no custom Guest fields.

Those remain Guest responsibilities.

Likewise, the Group itself does not store affinity relationships. Higher-level logic can inspect its members when affinity information is required.

This keeps the boundary relatively clean:

Guest owns individual state
        │
        ▼
Group owns shared context
        │
        ▼
Document coordinates
cross-object relationships

Putting the complete Group together

The reconstructed Group can now be summarised conceptually as follows:

Group
│
├── inherited
│   ├── persistent identity
│   └── notes
│
├── identity / presentation
│   ├── Group name
│   ├── formatted display name
│   ├── normalised sorting name
│   └── Group icon
│
├── membership
│   ├── Guest references
│   ├── Guest count
│   ├── formatted member list
│   ├── first-name list
│   └── display-name list
│
├── shared contact information
│   ├── address line 1
│   ├── address line 2
│   ├── city
│   ├── state / region
│   ├── postal code
│   ├── country
│   ├── work phone
│   ├── home phone
│   ├── mobile phone
│   └── email
│
├── contact queries
│   ├── has email?
│   └── has any phone number?
│
└── seating context
    └── Group seating compatibility

A compact class with a large architectural role

The most interesting thing about this class is the contrast between its data size and its architectural importance.

The Group itself stores only three Group-specific members.

Yet through those three members it connects identity, shared contact information, Guest membership, formatting, sorting, affinity queries and seating compatibility.

That is a useful object-oriented design lesson.

A class does not need dozens of fields to represent an important domain concept. Often the value lies in the relationships and invariants surrounding a relatively small amount of state.

The Guest describes an individual participant. The Group describes the shared context around several participants. The Event Document then coordinates the relationships between both.

The reconstruction is beginning to expose a fairly coherent object model: identity at the bottom, individual Guests and Groups above it, and a document-level model responsible for assembling those objects into a complete event.

The next interesting step will be to move further into the physical side of the problem: tables, seats and the relationship between people and the seating plan.

AI Assistance Disclosure: This article was developed from my original software reconstruction, generated technical documentation and personal professional experience with the assistance of generative AI. AI was used to help organise, expand and refine the text and clarify certain technical distinctions. The reconstruction work, engineering decisions, experience, opinions and conclusions remain my own. Identifying implementation details and internal naming conventions have been omitted.

Comments

Popular posts from this blog

Movies - The Bubble (2022)

  Back to Evolution (2001) .

IT - Fixing Windows Error 1327: Account Restrictions Are Preventing This User from Signing In

Fixing Windows Error 1327: Account Restrictions Are Preventing This User from Signing In Introduction Error 1327, “Account restrictions are preventing this user from signing in,” is a perplexing and disruptive issue that occurs on some Windows 10 and Windows 11 machines. The message typically appears at login or while connecting to remote resources, like shared folders, network drives, or remote desktops. Table of Contents Symptoms of Error 1327 Common Causes Step-by-Step Troubleshooting Advanced Fixes Automation via PowerShell Prevention Tips Further Reading Symptoms of Error 1327 Users experiencing this error may encounter one or more of the following: Login screen fails after credentials are entered. Error message appears when accessing mapped drives or network resources. Remote Desktop Connection (RDP) is rejected with the 1327 message. Group Policy logon restrictions silently block access. Co...

IT - Troubleshooting Kodi DLNA Visibility Issues After Windows Updates: A Deep Dive Into Conflicts, Fixes, and Lessons Learned

Title: Troubleshooting Kodi DLNA Visibility Issues After Windows Updates: A Deep Dive Into Conflicts, Fixes, and Lessons Learned Subtitle: How I Diagnosed and Solved Intermittent Kodi Visibility Problems on a Samsung Smart TV After Windows OS Updates and Media Server Conflicts Introduction Home media streaming should be seamless, but anyone who has integrated Kodi into a smart home setup knows that stability isn't always guaranteed. Recently, I encountered a frustrating issue: Kodi, running perfectly on my Windows 10 Pro desktop, suddenly became invisible to my Samsung Smart TV via DLNA. The journey to resolve this seemingly simple visibility issue turned into a deep technical rabbit hole involving Windows Media Server, Universal Media Server, Jellyfin, NordVPN, and the very internals o... The System Setup Before diving into the problem, it's essential to understand my hardware and software setup: Operating System: Windows 10 Pro (build 2009) Media Server: Kodi (...