Update README.md

This commit is contained in:
LahaLuhem 2023-01-13 17:02:14 +01:00
parent 792d293dd4
commit 6ee2c5a715
6 changed files with 31 additions and 29 deletions

2
.gitignore vendored
View File

@ -104,7 +104,7 @@ fabric.properties
# Package Files #
*.jar
!libs/postgresql-42.5.1.jar
!libs/
*.war
*.nar
*.ear

View File

@ -12,35 +12,44 @@ Classes and packages
--------------------
The application's main class is `Main` class, it runs the entire application. It's composed of three services: `AppConfigService`, `DatabaseService`, and `ReportGenerationService`.
### AppConfigService
### Services
#### AppConfigService
`AppConfigService` is a service class that prompts and stores the configuration that the app needs to be run with. It prompts the user for input for the country name and date, and stores them as class members.
### DatabaseService
#### DatabaseService
`DatabaseService` class is responsible for maintaining the active connection between the app and the SQL Server. It also communicates with the `DatabaseApi` class to perform final CRUD operations and return any results.
### ReportGenerationService
#### ReportGenerationService
`ReportGenerationService` generates a report from results. Since only a std-out is the only strategy, composition is preferred. It provides a single method `reportBaseResults(QueryResultsRepository queryResultsRepository)` that takes a `QueryResultsRepository` object as input and prints the results to the console. The method prints the `toString()` representation of the `QueryResultsRepository` object. It provides a basic printer and more members can be added in the future to use different strategies for printing out the received results.
### data.dtos
### Data
#### DTOs
`data.dtos` package contains the `QueryDTO` class. This class serves as a container for storing SQL statements to be executed, along with their arguments.
### data.enums
#### Enums
`data.enums` package contains the `CustomPreparedStatementsRead` enum. This enum contains all the read-only prepared statements that are used throughout the application.
### data.repos
#### Repos
`data.repos` package contains the `QueryResultsRepository` class. This class stores the results of the executed queries, and can be used to generate a report.
### data.models
#### Models
`data.models` package contains the `PersistentResultSetModel` class. This class adapts a given `ResultSet` to a `PersistentResultModel`.
### apis
### APIs
`apis` package contains the `DatabaseApi` class. This class communicates with the database to perform final CRUD operations, returning any results. This class is responsible for executing SQL statements, which are passed to it in the form of a QueryDTO class. It receives a QueryDTO object and a JDBC connection, then it processes the query and returns a PreparedStatement object. This class is designed to handle any exception that may occur during the execution of the query and it can be extended in the future to handle other types of queries if needed.
### Improvements
Here are some points that I could have improved upon, but did not go through with it because of either time constraints, or because it might be too much for the scope of this assignment.
+ The DatabaseService class is tightly coupling the DatabaseApi class. It's better to make the DatabaseApi class a singleton and inject it into the DatabaseService class.
+ The DatabaseApi class is doing more than just communicating with the database, it's also handling error handling. It would be better to extract the error handling logic into a separate class.
+ The QueryResultsRepository class is tightly coupled to the PersistentResultSetModel class. It would be better to extract the PersistentResultSetModel class into a separate package, and use a factory pattern to create instances of it.
+ The App class is doing too much. It would be better to extract the logic for each endpoint into separate classes, and use a factory pattern to create instances of them.
+ The Main class should be refactored to use dependency injection, so that the dependencies can be easily swapped out for testing.
+ The AppConfigService class should be refactored to use a more robust input validation library, to handle more edge cases.
+ The ReportGenerationService class should be refactored to support more output formats, such as HTML, CSV and PDF.
+ The Main class is using exceptions for flow control, it would be better to use specific exception classes for different error conditions, and handle them accordingly.
+ The Main class is catching a general SQLException and rethrowing it as a runtime exception, but it would be better to handle specific SQLException subclasses and provide more informative error messages.

View File

@ -7,15 +7,6 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" exported="">
<library>
<CLASSES>
<root url="file://$MODULE_DIR$/libs" />
</CLASSES>
<JAVADOC />
<SOURCES />
<jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" />
</library>
</orderEntry>
<orderEntry type="library" name="postgresql-42.5.1" level="project" />
</component>
</module>

View File

@ -76,6 +76,8 @@ public class PersistentResultSetModel {
@Override
public String toString() {
if (resultRowEntries.length == 0) return "--------No results--------";
final int rowLengthEstimate = resultRowEntries[0].toString().replaceAll("\t", " ").length();
final String outerHorizontalLine = new String(new char[rowLengthEstimate]).replace("\0", "_");
final String innerHorizontalLine = new String(new char[rowLengthEstimate]).replace("\0", "-");

View File

@ -1,6 +1,6 @@
package services;
import utils.ConstFormatters;
import utils.Formatters;
import utils.ConstValues;
import java.text.ParseException;
@ -28,7 +28,7 @@ public class AppConfigService {
System.out.println(ConstValues.inputDate);
while (true) {
try {
date = ConstFormatters.APPLICATION_DATE_FORMATTER.parse(scanner.nextLine());
date = Formatters.APPLICATION_DATE_FORMATTER.parse(scanner.nextLine());
// Always using exact current date. Otherwise, different day possible at the start of the run.
if (date.after(new Date())) {
System.out.println("There is no data available for the future yet... Try again:");
@ -39,7 +39,7 @@ public class AppConfigService {
break;
} catch (ParseException e) {
System.out.printf("Unable to parse date. Should be in format '%s'.\nTry again:%n", ConstFormatters.APPLICATION_DATE_FORMATTER.toPattern());
System.out.printf("Unable to parse date. Should be in format '%s'.\nTry again:%n", Formatters.APPLICATION_DATE_FORMATTER.toPattern());
}
}

View File

@ -2,6 +2,6 @@ package utils;
import java.text.SimpleDateFormat;
public class ConstFormatters{
public class Formatters {
final public static SimpleDateFormat APPLICATION_DATE_FORMATTER = new SimpleDateFormat("dd-MM-yyyy");
}