From 1bb39ecaf2cd76b1cc140987d2d97799586995db Mon Sep 17 00:00:00 2001 From: Cyril Jacquet Date: Sat, 2 Mar 2024 16:16:14 +0100 Subject: [PATCH] update Readme --- README.md | 72 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 28318a74..ab5565b5 100755 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ It's important to note that this conceptual representation needs to be tailored - **Persistence**: Manages internal data persistence. It includes a 'repository' wrapper for SQLite database interactions, with each entity having its repository in the `RepositoryProvider` class. - **Contracts**: A common library for most other components, housing all interfaces from `persistence`, `gateway`, and `infrastructure`. This design minimizes tight coupling and circular dependencies. - **DTO Libraries**: Each functionality has its DTO library, facilitating communication with the `application` layer. DTOs are used for both input and output in interactions with the outer layers, such as interactors. +- **CQRS Libraries** (Command Query Responsibility Segregation): The `application` layer is designed to support CQRS, with commands and queries being handled separately. This separation is achieved by using the `CommandHandler` and `QueryHandler` classes. Other classes, such as `CommandValidator` and `QueryValidator`, are used to validate commands and queries, respectively. They are stored away in a separate library called `cqrs`. - **Gateway**: Optional library for handling remote connections and services. It can be manually added by the developer and is used similarly to repositories in use cases. - **Infrastructure**: Optional. Handles actions like file management, local settings, and system queries. It's injected into use cases similar to repositories and gateways. - **Interactor**: Acts as an internal API to invoke use cases, streamlining the interaction between the user interface and application logic. @@ -76,6 +77,51 @@ sudo cmake --install . Qleany is building and examples are running well if you use Qt Creator or Visual Studio Code with the CMake Tools extension. +## Using Qleany + +To use Qleany, follow these steps: + +1. Write a `qleany.yaml` file for your project. You can use the `examples/simple/qleany.yaml` file as a reference. +2. Run the Qleany GUI interface and select the `qleany.yaml` file. +3. List and select the files you want to generate. +4. To avoid overwriting your current files: Preview the files, it will generate them in a "qleany_preview" folder. +5. If you are sure, generate the files directly. Qleany will generate them in the right place, but will never delete other files. +7. Create CMakelists.txt files to include the generated libraries in your project. You can use the `examples/simple/src/core/CMakeLists.txt` and `examples/simple/src/gui/CMakeLists.txt` files as a reference. +6. For custom commands and queries, you still have to fill the blanks in the generated files. You will find "Q_UNIMPLEMENTED();" in the generated files. + + +### For QWidgets GUI + +7. Create an UI project, not at the root of the project, but in a dedicated sub-folder, like with did with `examples/simple/src/gui/desktop_application`. +8. You can now start to implement your GUI and use cases. A GUI made with QWidgets will only use the interactors and models in presenter. Refer to the example for guidance at `examples/simple/src/gui/desktop_application/main.cpp` + +### For QML GUI + +*Note*: For now, the QML file generation is tailor-made to be used after a project is created using Qt Design Studio, but only subltle changes are needed to use it with a project created manually. You can use the `examples/simple/src/gui/qml_application` as a reference of what is running fine, this project uses Qt Design Studio's generated CMakeLists.txt. At the minimum, you only have to include the generated `realqmlmodules.cmake` file in your project's CMakeLists.txt file and mofify your main.cpp to register the other libraries. + +7. Create a QML project using Qt Design Studio, not at the root of the project, but in a dedicated sub-folder, like with did with `examples/simple/src/gui/qml_application`. +8. You can now start to implement your GUI and use cases. A GUI made with QML will use **not** the interactors and models directly from the interactor and presenter libraries. Wrappers around them all are generated in the QML `real_imports` folder in the QML folder to be made available from QML. Also, QML mocks are generated in `mock_imports`, to be filled by the developer. Refer to the example for guidance at `examples/simple/src/gui/qml_application/src/main.cpp` and `examples/simple/src/gui/qml_application/CMakelists.txt` + +### For both QWidgets and QML GUI + +You can use both QWidgets and QML GUIs in the same project. You can use the `examples/simple/` as a reference. The QML and QWidgets GUIs are in their own sub-folders, and the main.cpp file is in the root of the project. The CMakeLists.txt file is in the root of the project and includes the QML and QWidgets GUIs. + +### Gateway and Infrastructure + +The gateway and infrastructure are not generated by Qleany. You have to create them manually. You can use the `examples/simple/src/core/contracts` and `examples/simple/src/core/persistence` as a reference. The `contracts` folder contains the interfaces for the gateway and infrastructure, similar to what is done with the repositories of `persistence`. + +So, if I wnated to add a `gateway`, I would create a `gateway` folder in the `src/core/contracts` folder, and add the interfaces for the gateway. Then, I would create a `gateway` folder in the `src/core` folder, and add the implementation of the gateway. Each use case (handler) in `application` would have a `gateway` parameter using the interface, like what is already one with the repositories, and the `gateway` would be instanciated and injected into `interactor` in the `main.cpp` file. + +Finally, do not forget a `gateway_registration.cpp` file in the `src/core/gateway` folder to register the gateway classes. + +In a Gateway, we would find connections to remote services like REST APIs and remote datbases, and in Infrastructure, we would find connections to local services, like file management, local settings, and system queries. A "loadFile" method in a `FileLoader` class would be an example of an infrastructure service. Same for a `Settings` class or "exportToPdf" method in a `PdfExporter` class. + +The names Gateway and Infrastructure are not mandatory, you can use other names, like Remote and Local, or whatever you want. + +### Custom Commands and Queries + +You can add custom commands and queries for each feature in the `application.features` of the `qleany.yaml`. You can use the `examples/simple/qleany.yaml` and `examples/simple/src/core/application` as references. Search for the Q_UNIMPLEMENTED(); macro in the generated files to find the places to fill with your custom code. Be careful ot not overwrite your custom code when you regenerate the files. + ## Installing the Qleany GUI Interface Qleany tooling can be installed using `pip install qleany`. Alternatively, for an easier installation, you can install it using `pipx run qleany` if you have pipx installed. @@ -302,29 +348,3 @@ qml: folder_path: path/to/qml/folder ``` - -## Using Qleany - -To use Qleany, follow these steps: - -1. Write a `qleany.yaml` file for your project. You can use the `examples/simple/qleany.yaml` file as a reference. -2. Run the Qleany GUI interface and select the `qleany.yaml` file. -3. List and select the files you want to generate. -4. To avoid overwriting your current files: Preview the files, it will generate them in a "qleany_preview" folder. -5. If you are sure, generate the files directly. Qleany will generate them in the right place, but will never delete other files. -7. Create CMakelists.txt files to include the generated libraries in your project. You can use the `examples/simple/src/core/CMakeLists.txt` and `examples/simple/src/gui/CMakeLists.txt` files as a reference. -6. For custom commands and queries, you still have to fill the blanks in the generated files. You will find "Q_UNIMPLEMENTED();" in the generated files. - - -### For QWidgets GUI - -7. Create an UI project, not at the root of the project, but in a dedicated sub-folder, like with did with `examples/simple/src/gui/desktop_application`. -8. You can now start to implement your GUI and use cases. A GUI made with QWidgets will only use the interactors and models in presenter. Refer to the example for guidance at `examples/simple/src/gui/desktop_application/main.cpp` - -### For QML GUI - -*Note*: For now, the file generation is tailor-made to be used after a project is created using Qt Design Studio, but only subltle changes are needed to use it with a project created manually. You can use the `examples/simple/src/gui/qml_application` as a reference of what is running fine, this project uses Qt Design Studio's generated CMakeLists.txt. At the minimum, you only have to include the generated `realqmlmodules.cmake` file in your project's CMakeLists.txt file and mofify your main.cpp to register the other libraries. - -7. Create a QML project using Qt Design Studio, not at the root of the project, but in a dedicated sub-folder, like with did with `examples/simple/src/gui/qml_application`. -8. You can now start to implement your GUI and use cases. A GUI made with QML will use **not** the interactors and models directly from the interactor and presenter libraries. Wrappers around them all are generated in the QML `real_imports` folder in the QML folder to be made available from QML. Also, QML mocks are generated in `mock_imports`, to be filled by the developer. Refer to the example for guidance at `examples/simple/src/gui/qml_application/src/main.cpp` and `examples/simple/src/gui/qml_application/CMakelists.txt` -