Since around 2020, I have been looking for the right personal software project.
I did not want another small programming exercise, a collection of disconnected experiments or something that existed only to demonstrate a particular C++ feature. I wanted a real application: something sufficiently large to force me to think about architecture, object modelling, persistence, user interfaces, data manipulation, portability, security, testing and eventually packaging and distribution.
Most importantly, I wanted to return to something I have always enjoyed: developing software in C++.
After considering different possibilities, and partly because of circumstances in my personal life, I eventually settled on an application for table and seating organisation.
The concept sounds simple. Organise an event, define the available tables, enter the guests and determine where everybody should sit.
From a software-engineering perspective, however, it quickly becomes much more interesting.
A surprisingly useful problem domain
Consider what happens when the apparently simple idea of assigning people to tables becomes an actual application.
There are guests. Guests may belong to families or other groups. There are relationships between people. Some people should preferably sit together; others perhaps should not. Tables have capacities, shapes and positions. Seats belong to tables. Venues have physical layouts. Some assignments may be fixed while others can potentially be calculated.
Even before introducing any sophisticated optimisation, there is already a meaningful domain model:
Event
│
├── Guests
│ ├── Groups
│ └── Relationships
│
├── Venue / floor plan
│ └── Tables
│ └── Seats
│
└── Seating assignments
├── Constraints
└── Preferences
Then come the processes around those objects: creating and modifying them, validating them, assigning guests, saving and loading events, printing information and eventually exchanging data with external systems.
That gives me exactly what I was looking for: a bounded application whose complexity can grow gradually rather than an artificial programming exercise with no real destination.
Deliberately not SaaS
Before deciding to proceed, I spent some time looking at the market. There are many event-planning and seating products, and unsurprisingly a significant proportion of modern offerings are delivered as SaaS.
I decided that I do not want to follow that model for this project.
This is not a criticism of SaaS. I have spent enough of my professional career around distributed systems, infrastructure and enterprise applications to understand its advantages.
But those are not the engineering problems I want this particular project to concentrate on.
I want to develop an application that I can compile, package and ship.
I want the user to install it on a computer and use it locally. I want application versions, installation packages, local files, backwards compatibility and operating-system differences to be part of the engineering problem.
A local application also changes some architectural assumptions. There is no server that I control continuously. Upgrades cannot be assumed to happen immediately. Files created by an older version may need to remain readable years later. The customer's data exists outside infrastructure that I operate.
Those are useful constraints rather than inconveniences.
C++17, Qt and a cross-platform architecture
The technical foundation is C++17.
I have worked with C and C++ for many years, and part of the purpose of this project is to spend serious time with modern C++ again. I want to use the language for an application large enough that decisions about ownership, object lifetime, interfaces, const-correctness, containers, algorithms and separation of responsibilities actually matter.
For the application framework and graphical interface, I am using Qt.
The principal reason is portability. I want the same application architecture to run on Windows, Linux and macOS without maintaining three unrelated user interfaces.
My intended structure is broadly:
C++17 domain model
│
┌──────────┼──────────┐
│ │ │
Qt GUI Persistence Import /
Export
│
┌─────┼─────┐
│ │ │
Windows Linux macOS
An important architectural objective is to avoid making the GUI the application.
The concepts of guests, tables, seats, groups and assignments belong to the domain. They should not exist merely as properties of windows and widgets. Qt should provide the application framework and presentation mechanisms, while the core model remains understandable as a model in its own right.
I expect that boundary to evolve as the software grows, but establishing it early should make later work considerably easier.
An intentionally old-fashioned development environment
My development environment is going to be relatively uncomplicated.
I will use Visual Studio Code for editing, with the actual compilation and related operations available from the command line.
Perhaps this is the old-fashioned programmer in me, but I still like being able to see exactly how software is built.
I have nothing against sophisticated IDEs. They can provide excellent debugging, navigation and development facilities. What I do not particularly like is reaching a point where the build works only because an IDE knows about a configuration that I no longer completely understand.
If I can build the project from a terminal, the build process is explicit. It is also much easier to reproduce and automate later.
Windows 11 makes the platform situation particularly convenient because I can also use its Linux environment. That gives me Windows and Linux development and compilation facilities on the same main machine.
I also have a Mac notebook.
Between the three environments, I should therefore have a practical way of continuously checking that the application remains portable rather than discovering platform dependencies at the end of development.
Where I am today
The project is still at an early stage.
At the moment, much of my work is concentrated on the general class design: identifying the objects, their attributes, their responsibilities and the processes connecting them.
I am deliberately spending time here because I do not want to begin by constructing screens and then allow the widgets to determine what the application model becomes.
I would rather establish a reasonably coherent domain model and then let the user interface expose and manipulate it.
That does not mean trying to design the entire application perfectly before writing it. I fully expect the model to change as implementation exposes assumptions that looked good on paper but do not work particularly well in code.
For a personal project, that is part of the attraction. I have the freedom to revisit a decision because I have learned something rather than preserving it simply because a delivery date has arrived.
The persistence question is still open
One architectural question I have deliberately not finalised is how the application's own data should be stored.
I have been investigating what Qt can provide directly, including its facilities for structured and document-oriented data. HTML-based representation is one possibility I am considering, particularly because Qt already provides useful support around HTML and rich text.
However, I do not regard that decision as settled.
There is an important distinction between representing a document and representing application state. As the object model becomes clearer, I will be in a better position to decide whether HTML remains appropriate or whether another structured representation provides a cleaner persistence model.
For now, I prefer to keep that architectural decision open rather than select a format merely because it is convenient during the first implementation.
From persistence to data integration
Once the core application is sufficiently stable, there is another area I want to explore in considerably more depth: data import and export.
This is where the project becomes particularly useful as a learning environment.
A real event does not necessarily begin with somebody manually entering every person into my application. Guest information may already exist somewhere else. Likewise, information produced by the application may need to be consumed by another tool.
That introduces a different class of engineering problem:
External data
│
▼
Parse
│
▼
Validate
│
▼
Transform
│
▼
Domain model
│
▼
Application
And in reverse:
Domain model → Transform → Export
I want to deal with mapping, validation, malformed input, missing fields, type conversion and the distinction between an external representation and the application's internal objects.
Exactly which formats I support can come later. The interesting part for me is the integration architecture and the manipulation of data as it crosses that boundary.
Security without destroying usability
One area that still needs considerably more thought is security.
This type of application can potentially contain personal information about guests. That means I cannot treat security as something to add after the rest of the application has been completed.
At the same time, this is a desktop productivity application. Security controls that continually interfere with ordinary operation can make a theoretically secure product unpleasant to use.
The challenge is therefore not simply to ask, “How can I secure this?”
The better questions are: What information requires protection? Against which threats? What does the customer reasonably expect? What should the application protect automatically? Which controls should be optional? And how much operational complexity is justified by the actual risk?
I do not yet have all of those answers, and I think it would be a mistake to pretend otherwise. Security will have to evolve alongside the architecture rather than being represented by a single feature called “encryption” added near the end.
The project itself is part of the result
I recently moved to a new country, and one consequence of that change is that I now have more opportunity to dedicate some of my free time to projects of my own.
This is the project I have chosen.
I do not yet know how far it will go or whether it will eventually become something I want to distribute commercially. I do not need to decide that now.
At this stage, success means building something coherent and using the process to explore areas of software engineering that interest me: C++17, Qt, object modelling, GUI architecture, persistence, data transformation, portability, security, testing and software distribution.
It also means having the freedom to investigate why something works rather than merely making it work.
After several years of thinking about what my next substantial personal programming project should be, I finally have an answer.
Now I need to build it.
Where relevant, factual and regulatory references were checked against the sources cited in the article. AI assistance does not replace professional legal, regulatory, financial or technical advice, and the final selection, interpretation, opinions and conclusions presented here remain my own.
Comments
Post a Comment