Modeling with data.

Programs work with data. But where does that data come from? How do we decide what data to represent and how to represent it? This is modeling. Today we learn to translate real-world concepts into data structures.

Modeling is creating a representation. A map is a model of terrain. A blueprint is a model of a building. Data is a model of concepts.

When you build software, you must represent things from the real world. Users. Products. Orders. Messages. Each of these is a concept. You need data structures to capture them.

Modeling is the act of deciding: what data do I need? What types should that data have? How do pieces of data relate to each other?

A model is always a simplification. A map does not show every rock and tree. A data model does not capture every aspect of the real thing. You choose what matters for your purpose.

Start by listing what you need to know about a concept.

Consider a book. What matters about a book? Title. Author. Pages. Publication year. ISBN. Genre. Price.

But do you need all of these? If you are building a library catalog, you need title, author, ISBN. If you are building an e-commerce site, you need price. If you are building a reading tracker, you need pages.

The essential attributes depend on your purpose. A book in a library system is not the same as a book in a bookstore system. Same real-world thing, different models.

Ask: what questions will the code need to answer? What operations will it perform? Those questions reveal what attributes are essential.

Include only what you need. Every extra attribute is complexity. Every missing attribute limits functionality. Find the balance.

Once you know the attributes, choose types for each.

Title is text. Use a string.

Publication year is a number. Use an integer.

Price is money. Use a decimal type, not floating point. Floating point has rounding errors that cause problems with money.

ISBN is a string, not a number. It might have leading zeros. It is never used for arithmetic.

Each choice carries meaning. An integer says this value is numeric and can be compared and calculated. A string says this value is textual and might have any characters.

Wrong types cause problems. If you store a phone number as an integer, you lose leading zeros. If you store a price as a float, you get rounding errors. If you store a date as a string, sorting fails.

Think about what the data represents. Think about what operations you need. Choose the type that fits.

Most concepts are not single values. They are groups of values. A book has title and author and pages.

This is where composite types come in. You create a record or data class that groups the attributes together.

A Book type contains: title of type String, author of type String, pages of type Integer, published of type Integer.

Now Book is a type you can use. You can have a variable of type Book. You can have a list of Books. You can pass a Book to a function.

The composite type gives the concept a name and a structure. It defines what a book is in your system.

Concepts do not exist in isolation. They relate to each other.

A book has an author. But an author might write many books. This is a relationship.

An order contains products. A product belongs to a category. A user places orders. Relationships connect concepts.

How do you represent relationships? One approach: include one type inside another. A Book contains an Author object. This works for simple cases.

Another approach: use identifiers. A Book has an author ID. The Author exists separately. You look up the Author by ID when needed. This is more flexible.

The choice depends on your needs. Embedding is simpler but creates duplication if the same author appears in many books. IDs are more flexible but require lookups.

Consider the cardinality. One-to-one: embed or reference. One-to-many: the many side has a reference to the one. Many-to-many: use a separate structure to hold the relationships.

Some attributes are not just values. They are choices between alternatives.

A payment method might be credit card or bank transfer or cash.

A shipping status might be pending or shipped or delivered or returned.

These are enumerations or choice types. A value is exactly one of a fixed set of options.

Model these explicitly. Do not use strings like "credit_card" that can be misspelled. Do not use integers like 1, 2, 3 that are meaningless without documentation.

Use an enum or sealed type that names the options. The type system then ensures you only use valid options. The compiler catches mistakes.

When the options carry different data, use sealed types. CreditCardPayment contains card number. BankTransferPayment contains account number. Different shapes for different choices.

Some attributes are always present. Some are sometimes absent.

A user always has an ID. But a user might not have a phone number.

Model this distinction explicitly. Required attributes use non-nullable types. Optional attributes use nullable or optional types.

If an attribute is required but your model allows null, you have a bug waiting to happen. Something might set it to null. Code might crash when it tries to use it.

If an attribute is optional but your model requires a value, you will use placeholder values like empty strings or zeroes. These placeholders cause confusion. Is empty string a real value or a placeholder?

Be deliberate. For each attribute, decide: is this always present or sometimes absent? Then use the appropriate type.

Once you have a model, validate it against requirements.

Walk through the use cases. Can this model support user registration? Can it support checkout? Can it support reporting?

For each use case, check: does the model have the necessary data? Can you derive the needed information? Are the relationships correct?

You might find gaps. The model lacks something needed for a use case. Add it.

You might find excess. An attribute is never used. Consider removing it.

You might find inconsistency. Two use cases expect different structures. Resolve the conflict.

Modeling is iterative. You draft a model. You validate it. You revise it. You validate again. Repeat until the model fits the requirements.

Let us model an online bookstore.

We need: Books. Authors. Customers. Orders.

A Book has: id, title, price, publication year, author. We reference author by ID.

An Author has: id, name, biography.

A Customer has: id, name, email, shipping address. Address is a composite: street, city, postal code, country.

An Order has: id, customer id, order date, status, items. Status is a choice: pending, paid, shipped, delivered, cancelled. Items is a list of order lines.

An OrderLine has: book id, quantity, price at purchase time. We store price at purchase because book price might change later.

This model captures the essential entities and their relationships. Each type is focused. Each attribute has a purpose.

Let us summarize.

Modeling is translating real-world concepts into data structures.

Start by identifying essential attributes. Only what your use cases need.

Choose appropriate types for each attribute. Types carry meaning.

Compose types to represent concepts. Use records or data classes.

Represent relationships with embedding or references.

Use choice types for alternatives.

Distinguish required from optional attributes.

Validate the model against use cases. Iterate until it fits.

Good models are simple, complete, and match the domain.