# Project Analysis: rexx-address-book ## Tech Stack & Layout - Object Rexx serves as the core language, blending procedural scripting with OOP for modular, extensible code; key extensions include Unix for system interactions (e.g., file handling, environment vars), SQLite for lightweight persistent storage, and ncurses for building a terminal-based UI (TUI); configuration uses JSON for flexibility, chosen to leverage Rexx's strengths in scripting while adding modern data and UI capabilities without heavy dependencies. - High-level directory structure includes `app/` for core application modules and classes (e.g., database and UI logic), `db/` for database-related scripts or schemas (though integrated into `app/` in this setup), `tests/` for unit tests (e.g., database functionality), `addrbook.rex` as the main entry point script, `install.rex` for setup and configuration, and `default-config.json` for default settings like DB paths and UI themes, ensuring easy customization and portability. ## Module & Function Relationships - The main script `addrbook.rex` acts as the orchestrator, loading classes from `app/` and invoking `install.rex` for initial setup; `install.rex` handles environment checks, DB initialization, and config loading to prepare the app for runtime. - The SQLite backend (via `app/appdb.cls`) manages data persistence for contacts, while the ncurses frontend (via `app/appui.cls`) handles user interactions like menus and forms, separating concerns for maintainability. - Configuration in `default-config.json` ties pieces together by defining paths (e.g., DB file), UI settings (e.g., colors), and defaults, which are parsed in `install.rex` and propagated to classes in `app/` for a unified, configurable experience. ## Function & Method Reference ### addrbook.rex (Main Entry Point) - **main()**: Orchestrates app startup by loading configs, initializing DB and UI objects, and entering the main event loop; uses `::requires` to import classes, creates instances like `AppDB` and `AppUI`, and calls UI methods for user interaction; exists to centralize control flow, promoting a clean separation between setup and runtime. - **handleExit()**: Cleans up resources like closing DB connections and ncurses sessions on exit; employs Object Rexx's `guard off` for safe object destruction and Unix extensions for any file cleanup; designed for graceful shutdown, ensuring data integrity and resource management. ### install.rex (Setup Script) - **install()**: Checks system dependencies, parses `default-config.json` using Rexx stems for JSON data, sets up SQLite DB schema if needed; leverages Unix extensions for path validation and file creation; exists to make the app portable and user-friendly, handling one-time setup without cluttering the main script. - **configLoad()**: Reads and validates JSON config into a Rexx directory object; uses classic Rexx parsing with stems to convert JSON to accessible structures; rationale is to enable dynamic configuration, allowing easy tweaks without code changes. ### app/appdb.cls (Database Class) - **init()**: Initializes SQLite connection using extension calls like `sqlite_open`; sets up stems for contact records (e.g., `contacts.name`, `contacts.email`); uses Object Rexx classes for encapsulation, ensuring DB ops are object-oriented; exists to abstract storage, separating data logic from UI. - **addContact()**: Inserts a new contact via SQLite execute with parameterized queries to prevent injection; maps input stems to SQL, handles transactions; designed for safety and efficiency, demonstrating Rexx's stem usage for flexible data handling. - **queryContacts()**: Retrieves contacts with SQL select, populates Rexx arrays or stems; integrates SQLite results into objects; rationale is query optimization and easy data flow to UI, using OOP methods for reusability. ### app/appui.cls (UI Class) - **init()**: Starts ncurses session with `initscr()` and sets up windows/menus; uses Object Rexx methods to manage UI state objects; exists to encapsulate TUI logic, leveraging ncurses for interactive terminal apps without GUI overhead. - **displayMenu()**: Renders main menu using ncurses panels and handles key inputs via `getch()`; employs loops with conditionals for navigation, updating UI objects dynamically; designed for usability, separating input handling from business logic. - **editContactForm()**: Creates form fields for contact editing, validates input, and calls DB methods; uses ncurses forms extension and Rexx stems for form data; rationale is intuitive user experience, with error handling built into methods. ### app/utils.rex (Utility Functions) - **parseJson()**: Converts JSON strings to Rexx directories using procedural parsing; classic Rexx string functions like `pos()` and `substr()`; exists as a helper to avoid external libs, supporting config-driven design. - **logError()**: Logs errors to file or console using Unix extensions; simple procedural function with condition signals; designed for debugging and robustness, keeping utils lightweight. ### tests/test_appdb.rexx (Test Suite) - **testAddContact()**: Mocks DB insert and asserts results using Rexx's `assert` equivalents; calls class methods and checks stems; exists for TDD, ensuring DB reliability through isolated testing. - **testQuery()**: Simulates queries and validates output structures; uses Object Rexx's testing patterns; rationale is to catch issues early, demonstrating separation of tests from production code. ## Object & Data Flow - Main data structures include contact records as Rexx stems (e.g., `contact.1.name = "John"`) for flexible storage, and configuration as directory objects (e.g., `config~dbPath`) for easy access. - Data flows from user input via ncurses UI methods (e.g., form submissions) to business logic in `addrbook.rex` (validation), then to SQLite backend for storage/retrieval (e.g., `appdb~addContact(stem)`); reverse flow pulls DB data into stems, formats via utils, and displays in UI windows. - Error handling uses Object Rexx's `signal on` for conditions like `syntax` or `novalue`, with try-catch patterns in methods; safety includes parameterized SQLite queries and ncurses refresh checks to prevent crashes or data corruption. ## Learning Path & Gotchas - Start with `addrbook.rex` for overall flow, then `install.rex` for setup, followed by `app/appdb.cls` and `app/appui.cls` to grasp OOP integration, utils for helpers, and tests for validation; this order builds from high-level to details. - Common pitfalls for Object Rexx newcomers include confusing classic Rexx procedural code with OOP (e.g., overusing globals instead of methods), improper `::requires` for class loading, and mixing stems (dynamic arrays) with true objects—treat stems as lightweight data holders. - Gotchas with ncurses include handling terminal resizes or key mappings across platforms (use `resizeterm()`), SQLite in Rexx requires careful extension loading and error codes, and Unix differences (e.g., paths on Windows vs. Linux) may need conditionals. - Design decisions like UI-DB separation enhance modularity, JSON config allows extensibility without recompiles, and minimal dependencies showcase Object Rexx's power for self-contained CLI/TUI apps, making it ideal for hobbyists building real tools.