Skip to main content
← Blog

Refining the Preparation Section — From a Shared Model to Category-Specific Separation

VauDium ·

We were handling five categories with one PreparationItemModel. We split the models, screens, and components — and fixed a cache bug along the way.

Refining the Preparation Section

One Model Was Carrying Five Categories

The preparation section has five categories: materials, tools, venue, personnel, and qualification. At first, we handled all five with a single PreparationItemModel. Every possible field was on the model, and each category just used the ones it needed.

Materials have quantity and unit. Venue has address. Personnel has specialty. But the model had all of these fields mixed together. A venue item had a quantity field. A material item had an address field. They just happened to be unused.

Looking at the model alone, you couldn’t tell which fields belonged to which category.

We Decided to Split

MaterialItemModel, ToolItemModel, VenueItemModel, PersonnelItemModel, QualificationItemModel. Each category now owns only its fields.

The server response model, the client types, the serialization — all separated. No shared base class. Each model stands on its own.

We initially tried a base class with inheritance. The common fields (order, title, description, link, checked) were tempting to share. But independent models turned out to be clearer to read. Even with some repetition.

Screens Too

Once the models were split, having a single screen for all categories felt awkward.

create-preparation-item was taking a category parameter and conditionally showing fields. browse-preparation-item did the same. Five branches interleaved inside each component.

create-material-item, create-tool-item, create-venue-item, create-personnel-item, create-qualification-item. Each screen shows only its category’s fields. No conditional branches. Each file is simple.

The list components followed the same pattern. PreparationInput, which looped through all five categories, became MaterialsInput, ToolsInput, and so on.

More files, but each one is short and clear.

The Cache Bug

During the split, we found a bug. Quantity and unit weren’t persisting.

The server was returning 200 OK. MongoDB had the data. But reopen the app, and the values were gone.

The cause was in two places.

First, the server’s TaskResponseModelFactory wasn’t mapping category-specific fields (quantity, unit, address, specialty, issuer) when converting preparation items to the response. The server saved the data but didn’t include it in the response.

Second, the client’s toJSON() was missing the same fields. When saving to the SQLite cache, these fields were dropped. Reading from the cache returned null.

The same mistake on both sides. The base fields (order, title, description, link, checked) were mapped. The category-specific fields, added later, were forgotten.

List Display

We also started showing category-specific info in the list. Quantity and unit next to the name, for instance.

At first we concatenated everything into one text: “Ramen 2pcs”. But that looked different from the other categories. So we unified the style: name in dark color, supplementary info in lighter color, side by side.

Venue addresses can be long, so we skip those in the list. You can open the item to see it.

Looking Back

Starting with a single shared model is fast. But when each category develops its own fields, that one model grows awkward. You have to read the code to know which fields apply where, and it’s easy to miss them in serialization.

Splitting means more files, but each one is clear. And in clear code, bugs have fewer places to hide.