Philosophy

Core design principles and architectural decisions behind the Entity System

The Vyuh Entity System is built on a foundation of carefully considered design principles that prioritize consistency, modularity, and developer productivity. This document explores the core philosophy behind the system and the architectural decisions that shape its implementation.

Fundamental Design Thinking

The Entity System addresses a fundamental challenge in enterprise applications: how do we bring data from various backend sources to the client side for viewing, interaction, and manipulation in a consistent, maintainable way?

The Architecture

Core Principles

1. Entity-First Architecture

At the heart of the Vyuh Entity System is the belief that business logic should be modeled as entities. An entity represents any business object that has:

  • A unique identity
  • A defined lifecycle
  • Relationships with other entities
  • Business rules and behaviors

By treating everything as an entity - from users and products to locations and equipment - we create a consistent mental model that scales across the entire application.

// Everything is an entity
class Area extends VersionedEntity { ... }
class Equipment extends VersionedEntity { ... }
class LogTemplate extends VersionedEntity { ... }
class User extends EntityBase { ... }

2. Configuration Over Code

The system embraces declarative configuration over imperative programming. Instead of writing repetitive CRUD controllers, UI screens, and API endpoints, developers define a single configuration that generates all necessary components:

final areaConfig = EntityConfiguration<Area>(
  metadata: EntityMetadata(
    identifier: 'areas',
    name: 'Area',
    pluralName: 'Areas',
    category: EntityCategory.elog,
    icon: Icons.location_on,
    priority: 1,
  ),
  api: AreaApi(), // Implements EntityApi<Area>
  routing: EntityRoutingDescriptor(
    path: NavigationPathBuilder.collection('areas', prefix: '/elog'),
    builder: StandardRouteBuilder<Area>(),
    mode: EntityNavigationMode.navigate,
    permissions: EntityRoutePermissions(
      list: ['elog.areas.view'],
      create: ['elog.areas.registration'],
      edit: ['elog.areas.modification'],
    ),
  ),
  layouts: EntityLayoutDescriptor<Area>(
    list: [tableLayout, gridLayout],
    details: [detailsTab, equipmentTab, versionsTab, auditTab],
    analytics: [usageDistribution, topUsedAreas, usageHeatMap],
  ),
  form: EntityFormDescriptor<Area>(
    getForm: (entityId) => buildAreaForm(entityId),
    transformer: DefaultEntityTransformer<Area>(
      fromJson: Area.fromJson,
    ),
  ),
  actions: EntityActionsDescriptor<Area>(
    inline: VersionedEntityActions.defaults<Area>(),
  ),
);

This approach:

  • Reduces boilerplate code by 80-90%
  • Ensures consistency across all entities
  • Makes it easy to add new features system-wide
  • Simplifies maintenance and updates
  • Automatically generates routes, permissions, and UI components

3. Separation of Concerns

The entity system enforces clear boundaries between:

  • Data Models - Pure entity definitions with JSON serialization
  • Business Logic - API implementations and validation rules
  • Presentation - Layouts, forms, and UI components
  • Infrastructure - Routing, permissions, and services

This separation allows teams to work independently and makes the codebase more maintainable.

4. Composability and Extensibility

Every component is designed to be:

  • Composable - Mix and match layouts, forms, and actions
  • Extensible - Override default behavior when needed
  • Pluggable - Add custom implementations without modifying core
// Multiple layouts for different use cases
layouts: EntityLayoutDescriptor(
  list: [
    TableListLayout(...),    // Default table view
    GridListLayout(...),      // Card-based grid
    CustomMapLayout(...),     // Custom implementation
  ],
  details: [
    StandardDetailLayout(...),
    CompactDetailLayout(...),
  ],
);

5. Convention Over Configuration

While highly configurable, the system provides sensible defaults:

  • Standard CRUD routes (/users, /users/new, /users/:id)
  • Common UI patterns (tables, forms, detail views)
  • Default permissions (CRUD actions)
  • Standard API endpoints

Developers only need to specify deviations from these conventions.

Architectural Patterns

The Entity Configuration Pattern

Each entity is fully described by a single EntityConfiguration object that serves as the source of truth:

EntityConfiguration<T> {
  metadata,    // What is this entity?
  api,         // How do we interact with it?
  layouts,     // How do we display it?
  form,        // How do we edit it?
  actions,     // What can we do with it?
}

This pattern ensures that all entity-related code is co-located and discoverable.

The Provider Pattern

The entity system integrates seamlessly with Flutter's InheritedWidget pattern via the EntityProvider widget:

EntityProvider.of<User>(context).list();
EntityProvider.of<User>(context).byId(userId);

This provides:

  • Type-safe access to entity operations
  • Automatic dependency injection
  • Reactive updates based context changes
  • Easy testing

The Layout System

Layouts are first-class citizens, not afterthoughts. There are two main types:

List Layouts - for tables, cards, and grids:

abstract class ListLayoutConfiguration<T extends EntityBase> {
  // Renders the list of entities
  Widget build(BuildContext context, List<T> items);

  // Configuration
  bool get enableSearch => true;
  bool get enableMultiSelect => false;
  List<ListAction<List<T>>> get batchActions => [];
}

Detail/Summary/Dashboard Layouts - using Vyuh's layout system:

class EntityLayoutConfiguration<T extends EntityBase> {
  final LayoutConfiguration<T> layout;
  final Widget Function(BuildContext)? headerActionsBuilder;
  // ... metadata like title, icon, priority, permissions
}

This allows:

  • Multiple views of the same data (table, grid, card layouts)
  • Permission-based layout visibility
  • Priority-based ordering
  • Easy addition of new visualizations

The Permission System

Security is built into every layer with the PermissionService:

// Declarative permission checks with PermissionGuard
PermissionGuard(
  entityType: 'users',
  action: PermissionAction.view,
  permissionService: permissionService,
  child: UserListView(),
  fallback: Text('Access denied'),
)

// Programmatic permission checks
final permissionService = context.read<PermissionService>();

if (await permissionService.canEdit('users', userId)) {
  // Show edit UI
}

// Available permission checks:
// canView(), canCreate(), canEdit(), canDelete()
// canApprove(), canReject()

// User group membership checks
if (await permissionService.isMemberOf('admin-group')) {
  // Show admin features
}

Future Evolution

The entity system philosophy is designed to accommodate future needs:

  • AI Integration - Entities provide structured data for AI operations
  • Real-time Sync - Entity pattern works well with real-time databases
  • Offline Support - Clear entity boundaries simplify offline strategies
  • Multi-platform - Same entity model across mobile, web, and desktop

Conclusion

The Vyuh Entity System represents a paradigm shift in how we build Flutter applications. By embracing entity-driven design, we create applications that are:

  • Easier to build
  • Simpler to maintain
  • More consistent for users
  • Faster to extend

The philosophy is simple: treat your business objects as first-class citizens, and the framework handles the rest. This approach has proven successful across multiple production applications and continues to evolve based on real-world usage.

On this page