Go to file
LahaLuhem a8687095c2 rebase conflicts 2023-01-16 10:26:11 +01:00
.github Initial commit 2023-01-10 14:15:29 +01:00
.idea rebase conflicts 2023-01-16 10:26:11 +01:00
database-init Initial commit 2023-01-10 14:15:29 +01:00
docs rebase conflicts 2023-01-16 10:26:11 +01:00
libs Initial commit 2023-01-13 20:33:09 +01:00
src rebase conflicts 2023-01-16 10:26:11 +01:00
.DS_Store rebase conflicts 2023-01-16 10:26:11 +01:00
.gitattributes Initial commit 2023-01-13 20:33:09 +01:00
.gitignore Update README.md 2023-01-13 21:07:37 +01:00
INSTRUCTIONS.md Initial commit 2023-01-10 14:15:29 +01:00
README.md rebase conflicts 2023-01-16 10:26:11 +01:00
covid_10012023_MehulAhal_covid-reports.iml Update README.md 2023-01-13 21:07:37 +01:00
docker-compose.yaml Initial commit 2023-01-10 14:15:29 +01:00

README.md

Lunatech COVID Assessment

Please use this readme as your projects readme. You can find instructions for the assignment in the INSTRUCTIONS.md file.

Table of contents

Setup instructions

  1. Add the postgresql-42.5.1.jar as a library dependency in your IDE.
  2. Follow the Docker-setup instruction in INSTRUCTIONS.md.

Overview

This project is a simple command-line application that communicates with a PostgreSQL database to retrieve data and generate reports based on that data. It's composed of several classes and packages that work together to accomplish this task.

Class UML

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.

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 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 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 package contains the QueryDTO class. This class serves as a container for storing SQL statements to be executed, along with their arguments.

Enums

data.enums package contains the CustomPreparedStatementsRead enum. This enum contains all the read-only prepared statements that are used throughout the application.

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.

Models

data.models package contains the PersistentResultSetModel class. This class adapts a given ResultSet to a PersistentResultModel.

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.

  • Ideally all the services, and inner services and APIs being used, should be injected in by dependency injection. In Dart, get_it, is makes this very easy with a Locator file. But for Java, I was not able to find something that was as easy.
  • Ideally the AppConfigService should be more generalized to acecpt N number of user inputs, for the scalability.
    • That would have also helped with making the pipeline in run() better, as the list of config vars could be supplied directly, instead of manually specifying.
  • 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.
    • Could be rectified by using lots of custom Exceptions in general, but overkill for this scope.
  • 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.
    • But then till it is needed, composition was preferred over inheritance.
  • 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.