DEV Community

Why I Stopped Letting Screens Talk to the Database

Most of us start a new front-end project the same way: open the template, rename MainPage, and start dropping controls. It feels productive. It is also how a lot of apps end up with business logic living inside XAML (or React, or whatever) and database calls scattered across pages.

I recently spent a focused session on the Management side of a real system. We deliberately did almost no feature work. Instead we decided where every future responsibility would live and how the pieces would be allowed to talk to each other. The result is a small set of rules I now treat as non-negotiable.

1. The front office is not the records department

The Management application is the place staff actually work. The API and the database are a different building. The only legal communication between them is HTTP + JSON.

That single rule has three practical consequences:

  • The Management project never references the infrastructure or data-access projects.
  • If the database later moves from SQLite to PostgreSQL (or anything else), the Management app does not care.
  • Every piece of data that reaches a screen has already passed through an explicit service boundary.

In other words, this is forbidden:

ChildRegistrationPage → AtipDbContext → SQLite

This is required:

ChildRegistrationPage
→ ChildRegistrationViewModel
→ AtipApiClient
→ HTTP
→ ATIP.Api
→ ChildService
→ AtipDbContext
→ Database

Enter fullscreen mode Exit fullscreen mode

2. Screens are rooms; ViewModels are the people who run them

A page (View) decides what the room looks like. The corresponding ViewModel decides what happens when someone presses a button, what data is valid, and when the UI should show a spinner or an error.

Keeping the two separate is classic MVVM, but the discipline is easy to abandon once a deadline appears. The test I now use is simple:

If I cannot unit-test the decision logic without spinning up a real page, the logic is in the wrong place.

3. Not every data shape belongs in the domain

Domain entities live in a shared Core library. They represent the truth of the business. The Management UI often needs thinner or differently shaped objects — a list item that only shows four fields, a dashboard summary, a search filter. Those belong in the Management project’s own Models folder.

Mixing the two creates either leaky abstractions or awkward mapping code later.

4. Navigation is architecture, not an afterthought

We made the application open into a Shell whose first content is a Dashboard, not a registration form. That forces an explicit user journey:

Dashboard
└── Children
├── List
├── Register
└── Profile
Enter fullscreen mode Exit fullscreen mode

Creating the navigation skeleton before the individual rooms is one of the highest-leverage early decisions you can make. In MAUI terms it looked like this:

<!-- AppShell.xaml -->
<Shell ...>
  <ShellContent
      Title="Dashboard"
      ContentTemplate="{DataTemplate views:DashboardPage}"
      Route="dashboard" />
</Shell>
Enter fullscreen mode Exit fullscreen mode

And the startup chain is simply:

App → CreateWindow() → new AppShell() → DashboardPage

5. Create the rooms you need, not the ones that look professional

We created six folders:

Views
ViewModels
Services
Models
Components
Converters
Enter fullscreen mode Exit fullscreen mode

We did not create empty classes inside them “just in case.” Architecture is not the number of folders; it is the consistent placement of responsibility. Empty scaffolding that never gets used is noise.
The real payoff
When the first real feature arrives, the only new code that needs to be written is:

a page in Views
its ViewModel
the calls inside the already-planned API client

Everything else already has a home. That is the quiet win of spending a session on architecture before the first line of feature code.
I still have to prove the empty Shell actually launches. After that, the next phase is the concrete AtipApiClient. But the hard part — deciding who is allowed to talk to whom — is already done.
Three questions before you write the first page
If you are about to start a new client application, try forcing yourself to answer these three questions first:

  • What is the single entry point the user will see?
  • Which project is allowed to know about the database?
  • Where will UI-specific shapes live, and how will they stay separate from domain entities?

The answers tend to save more time than any amount of clever code later.

  • What rules do you refuse to break on the client side? I’m curious what others have settled on after a few projects.

Top comments (0)