C++/Qt database desktop applications: Questions about implementation details (DTO, DAO, etc.)
-
Hi,
I want to develop a desktop application to handle port scan results (e.g. hosts IP addresses and the network services they provide). The actual data will be imported and aggregated by nmap XML output. I consider SQLite as database backend.
I have been looking into the concepts of DTO and DAO. Altough most of the stuff was Java related I think I have understood the basic concepts. But I have some questions how to implement and use them.
So, my database tables could be something like this:
Host: PK(HostId) |HostId|IP-Address| MAC |vendor | 1 |10.0.0.1 |11:...|vmware Service: PK(HostId,Port,Protocol) |HostId|Port|Protocol|service_name|description | 1 | 80 | TCP | http | apache | 1 |443 | TCP | https | apache
Since the term "model" seems a bit ambiguous within Qt, I'd like to clarify the following terms, as I think I have understood them:
Domain model: Objects that represents the data the application is using.
DTO: A more or less "stripped down" version of the model, for transfering plain data between layers (e.g. back- & frontend, application & database).
Qt Item Model: An "adaptor" between the domain model and the Qt views.As my data is pretty simple, I have an anemic domain model. I've read that in this case, one could refrain from using separate DTO classes. So I would think of following domain model classes (for compactness I ommit unnessecary syntax overhead):
class Project { void loadDatabase(); QList<QSharedPointer<Host>> m_hosts; QMap<QString,QSharedPointer<Host>> m_hostbyIp; }; class Host { int id; QString ip; QString mac; QString vendor; QList<QSharedPointer<NetService>> services; }; class NetService { int port; QString procotol; QString serviceName; QString description; QWeakPointer<Host> host; };
Now, if I start the application and open a project I want a list view of all hosts in the database. If I select a host, I want to show all services of that host. So my DAO logic could look something like this:
Project::loadDatabase() { m_hosts = HostDAO::fetchAll(); } QList<> HostDAO::fetchAll() { // SELECT * FROM host // for each host: ServiceDAO::fetchServicesForHost(hostId); } QList<> ServiceDAO::fetchServicesForHost(int hostId) { // SELECT * FROM service WHERE HostId = hostId }
My first question now is: Does it make sense that
HostDAO::fetchAll()
creates fully filled Host objects from the start (e.g. loading all services in advance)?
Obviously it depends on the size of the database (in a big shop system it wouldn't make sense to load all orders with all details into memory).
But what do you think, does it make sense in this case? I'm also planning to extend the related data (add tags, documents). Is there a rough rule of thumb that you can use as a guide?Now, my next uncertainty: Does it make sense to fetch all services for each host individually? I could also use a JOIN query, to get all data in one table and split the data in the application logic. But this would contradict the DAO separation. When should I make which trade-off?
Now cosinder I want to display the services of all hosts on one specific port: Since I have all data already in memory, I could iterate over all hosts and services and collect all relevant services. Wouldn't that contradict the query character of SQL? Would it make more sense to implement
fetchServicesForPort(int)
and use a SQL WHERE statement to select the relevant services?I would appreciate any advice.