minor refactor

This commit is contained in:
Mguy13 2023-01-06 16:08:26 +01:00
parent 5366b11f55
commit 0ee2be969f
6 changed files with 138 additions and 136 deletions

View File

@ -1,6 +1,5 @@
using Configuration; using DTO;
using DTO; using static Configuration.ApplicationConfigurationService;
using static Configuration.DemoApplicationConfiguration;
namespace OrderParser namespace OrderParser
{ {
@ -10,11 +9,12 @@ namespace OrderParser
{ {
try try
{ {
var filesInfoConfig = DemoApplicationConfiguration.InitializeFrom(args); var filesInfoConfig = Configuration.ApplicationConfigurationService.InitializeFrom(args);
var csvFileWriter = new CsvFileWriter(filesInfoConfig.OutputFile); var csvFileWriter = new CsvFileWriterService(filesInfoConfig.OutputFile);
foreach (var jsonFile in filesInfoConfig.JsonFilesInfo) foreach (var jsonFile in filesInfoConfig.JsonFilesInfo)
{ {
// Could have easily been another service, but only do that when it needs to be scaled.
var orderDTO = Newtonsoft.Json.JsonConvert.DeserializeObject<OrderDto>(File.ReadAllText(jsonFile.FullName)); var orderDTO = Newtonsoft.Json.JsonConvert.DeserializeObject<OrderDto>(File.ReadAllText(jsonFile.FullName));
var orderModel = new OrderModel(orderDTO); var orderModel = new OrderModel(orderDTO);

View File

@ -9,6 +9,8 @@
## Infrastructure disclaimer ## Infrastructure disclaimer
I come from a background of developing mobile applications in Dart/Flutter, with a different set of conventions (such for file naming etc). I have done some research into doing it and tried sticking to it. But in the end, the architecture is still heavily influenced by practices in mobile development. I come from a background of developing mobile applications in Dart/Flutter, with a different set of conventions (such for file naming etc). I have done some research into doing it and tried sticking to it. But in the end, the architecture is still heavily influenced by practices in mobile development.
Additionally, I haven't focussed too much on Exception handling, since I feel that the scope of this assignment, is just a simple PoC. I do have some basic safeguards for input validation, and basic exception printing.
### Structure ### Structure
#### Assets #### Assets
@ -19,8 +21,8 @@ There ae 2 JSON files in the `assets` directory. These can be used as input as c
2. [OrderModel](models/OrderModel.cs): Captures the usable part of the `OrderDTO` that will be written out to the CSV. 2. [OrderModel](models/OrderModel.cs): Captures the usable part of the `OrderDTO` that will be written out to the CSV.
#### Services #### Services
1. [DemoApplicationConfiguration](services/DemoApplicationConfiguration.cs): Stores the configuration that the program ran with. Such as the command-line args passed (and hence the mode), the actual input data, and the ouput destination. Along with the file-existnece checks 1. [ApplicationConfigurationService](services/ApplicationConfigurationService.cs): Stores the configuration that the program ran with. Such as the command-line args passed (and hence the mode), the actual input data, and the ouput destination. Along with the file-existnece checks
2. [CsvWriter](services/CsvWriter.cs): Writes an order to a file. 2. [CsvWriterService](services/CsvWriterService.cs): Writes an order to a file.
3. Deserializing the JSON was handled by a package. Could have made this into a service ideally, for better scaling up. 3. Deserializing the JSON was handled by a package. Could have made this into a service ideally, for better scaling up.
#### Packages used #### Packages used

View File

@ -12,7 +12,7 @@
"ProductId": "PID4", "ProductId": "PID4",
"Description": "pid4 description", "Description": "pid4 description",
"Amount": 2.5, "Amount": 2.5,
"price": 169.0 "price": 69.0
} }
] ]
} }

244
review.cs
View File

@ -1,144 +1,144 @@
using SollicitantReview.Models; // using SollicitantReview.Models;
using SollicitantReview.Services; // using SollicitantReview.Services;
using Microsoft.Extensions.Options; // using Microsoft.Extensions.Options;
using System; // using System;
using System.Collections.Generic; // using System.Collections.Generic;
using System.IO; // using System.IO;
using System.Linq; // using System.Linq;
using System.Text; // using System.Text;
using System.Threading; // using System.Threading;
using System.Threading.Tasks; // using System.Threading.Tasks;
namespace SollicitantReview // namespace SollicitantReview
{ // {
public class SollicitantReview // public class SollicitantReview
{ // {
private SollicitantReviewSettings options; // private SollicitantReviewSettings options;
private IWriter writer; // private IWriter writer;
private Queue<List<ReviewExportLine>> exportLineQueue; // private Queue<List<ReviewExportLine>> exportLineQueue;
public SollicitantReview(IOptions<SollicitantReviewSettings> options, IWriter writer) // public SollicitantReview(IOptions<SollicitantReviewSettings> options, IWriter writer)
{ // {
this.options = options.Value; // this.options = options.Value;
this.writer = writer; // this.writer = writer;
this.exportLineQueue = new Queue<List<ReviewExportLine>>(); // this.exportLineQueue = new Queue<List<ReviewExportLine>>();
var processExportLinesThread = new Thread(new ThreadStart(ProcessReviewExportLines)); // var processExportLinesThread = new Thread(new ThreadStart(ProcessReviewExportLines));
processExportLinesThread.Start(); // processExportLinesThread.Start();
} // }
public void RegisterOrder(Order order) // public void RegisterOrder(Order order)
{ // {
DeleteOrder(order); // DeleteOrder(order);
exportLineQueue.Enqueue(ConvertOrderToExportLines(order)); // exportLineQueue.Enqueue(ConvertOrderToExportLines(order));
} // }
private string FilterString(string value) // private string FilterString(string value)
{ // {
return value.Replace(";", ":"); // return value.Replace(";", ":");
} // }
private void DeleteOrder(Order order) // private void DeleteOrder(Order order)
{ // {
var exportLines = new List<ReviewExportLine>() // var exportLines = new List<ReviewExportLine>()
{ // {
new ReviewExportLine() // new ReviewExportLine()
{ // {
Type = "9", // Type = "9",
OrderNumber = FilterString(order.OrderNumber), // OrderNumber = FilterString(order.OrderNumber),
Amount = "1", // Amount = "1",
UserId = FilterString(order.User), // UserId = FilterString(order.User),
JournalPostIndication = "Y" // JournalPostIndication = "Y"
} // }
}; // };
exportLineQueue.Enqueue(exportLines); // exportLineQueue.Enqueue(exportLines);
} // }
private List<ReviewExportLine> ConvertOrderToExportLines(Order order, string userId = null) // private List<ReviewExportLine> ConvertOrderToExportLines(Order order, string userId = null)
{ // {
var exportLines = new List<ReviewExportLine>(); // var exportLines = new List<ReviewExportLine>();
foreach (var orderLine in order.OrderLines) // foreach (var orderLine in order.OrderLines)
{ // {
exportLines.Add(new ReviewExportLine() // exportLines.Add(new ReviewExportLine()
{ // {
OrderNumber = FilterString(order.OrderNumber), // OrderNumber = FilterString(order.OrderNumber),
Name = FilterString(orderLine.Name), // Name = FilterString(orderLine.Name),
Amount = FilterString(orderLine.Amount), // Amount = FilterString(orderLine.Amount),
ProductNumber = FilterString(orderLine.Number), // ProductNumber = FilterString(orderLine.Number),
ProductDescription = FilterString(orderLine.Description), // ProductDescription = FilterString(orderLine.Description),
UserId = userId == null ? FilterString(order.User) : userId, // UserId = userId == null ? FilterString(order.User) : userId,
Location = FilterString(orderLine.Location), // Location = FilterString(orderLine.Location),
JournalPostIndication = "Y" // JournalPostIndication = "Y"
}); // });
} // }
return exportLines; // return exportLines;
} // }
private void ProcessReviewExportLines() // private void ProcessReviewExportLines()
{ // {
while(true) // while(true)
{ // {
if (exportLineQueue.Any() && IsFolderEmpty(options.ReviewFolderPath)) // if (exportLineQueue.Any() && IsFolderEmpty(options.ReviewFolderPath))
{ // {
var exportLines = exportLineQueue.Dequeue(); // var exportLines = exportLineQueue.Dequeue();
var randomStringLength = 7; // var randomStringLength = 7;
writer.OpenFile($"{options.ReviewFolderPath}\\{GenerateRandomString(randomStringLength)}.txt"); // writer.OpenFile($"{options.ReviewFolderPath}\\{GenerateRandomString(randomStringLength)}.txt");
foreach (var exportLine in exportLines) // foreach (var exportLine in exportLines)
{ // {
writer.WriteLine($"{exportLine.Type};" + // writer.WriteLine($"{exportLine.Type};" +
$"{exportLine.OrderNumber};" + // $"{exportLine.OrderNumber};" +
$"{exportLine.Name};" + // $"{exportLine.Name};" +
$"{exportLine.Amount};" + // $"{exportLine.Amount};" +
$"{exportLine.ProductNumber};" + // $"{exportLine.ProductNumber};" +
$"{exportLine.ProductDescription};" + // $"{exportLine.ProductDescription};" +
$"{exportLine.UserId};" + // $"{exportLine.UserId};" +
$"{exportLine.Location};" + // $"{exportLine.Location};" +
$"{exportLine.JournalPostIndication};" + // $"{exportLine.JournalPostIndication};" +
$"{exportLine.Info2}"); // $"{exportLine.Info2}");
} // }
writer.CloseFile(); // writer.CloseFile();
} // }
Thread.Sleep(2000); // Thread.Sleep(2000);
} // }
} // }
private bool IsFolderEmpty(string path) // private bool IsFolderEmpty(string path)
{ // {
DirectoryInfo dirInfo = new DirectoryInfo(path); // DirectoryInfo dirInfo = new DirectoryInfo(path);
if (!dirInfo.Exists) // if (!dirInfo.Exists)
{ // {
throw new CouldNotFindReviewDirectory(); // throw new CouldNotFindReviewDirectory();
} // }
return !dirInfo.GetFiles("*.txt").Any(); // return !dirInfo.GetFiles("*.txt").Any();
} // }
private string GenerateRandomString(int length) // private string GenerateRandomString(int length)
{ // {
StringBuilder stringBuilder = new StringBuilder(); // StringBuilder stringBuilder = new StringBuilder();
Random random = new Random(); // Random random = new Random();
var ASCIIOffset = 65; // var ASCIIOffset = 65;
var ASCIIRange = 25; // var ASCIIRange = 25;
char letter; // char letter;
for (int i = 0; i < length; i++) // for (int i = 0; i < length; i++)
{ // {
double randomDouble = random.NextDouble(); // double randomDouble = random.NextDouble();
int shift = Convert.ToInt32(Math.Floor(ASCIIRange * randomDouble)); // int shift = Convert.ToInt32(Math.Floor(ASCIIRange * randomDouble));
letter = Convert.ToChar(shift + ASCIIOffset); // letter = Convert.ToChar(shift + ASCIIOffset);
stringBuilder.Append(letter); // stringBuilder.Append(letter);
} // }
return stringBuilder.ToString(); // return stringBuilder.ToString();
} // }
} // }
} // }

View File

@ -1,6 +1,6 @@
namespace Configuration namespace Configuration
{ {
public sealed class DemoApplicationConfiguration public sealed class ApplicationConfigurationService
{ {
private FileInfo[] jsonFiles; private FileInfo[] jsonFiles;
public FileInfo[] JsonFilesInfo public FileInfo[] JsonFilesInfo
@ -22,7 +22,7 @@ namespace Configuration
} }
} }
public static DemoApplicationConfiguration InitializeFrom(string[] args) public static ApplicationConfigurationService InitializeFrom(string[] args)
{ {
if (args.Length < 3) if (args.Length < 3)
throw new DemoApplicationConfigurationException("Must have atleast: 1 flag, 1 path, 1 output filename"); throw new DemoApplicationConfigurationException("Must have atleast: 1 flag, 1 path, 1 output filename");
@ -41,14 +41,14 @@ namespace Configuration
// Assert only a single 'd' was passed // Assert only a single 'd' was passed
if ( givenFlags.Length == 1 && givenFlags[0].Equals("-d") ) { if ( givenFlags.Length == 1 && givenFlags[0].Equals("-d") ) {
string[] filesInDirectory = Directory.GetFiles(givenFilePaths[0]); string[] filesInDirectory = Directory.GetFiles(givenFilePaths[0]);
return new DemoApplicationConfiguration { return new ApplicationConfigurationService {
OutputFile = outputFileName, OutputFile = outputFileName,
JsonFilesInfo = filesInDirectory.Select(name => new FileInfo(name)).ToArray(), JsonFilesInfo = filesInDirectory.Select(name => new FileInfo(name)).ToArray(),
}; };
} }
// Assert only '-f' were passed // Assert only '-f' were passed
else if (givenFlags.All((string flag) => flag.Equals("-f"))) { else if (givenFlags.All((string flag) => flag.Equals("-f"))) {
return new DemoApplicationConfiguration { return new ApplicationConfigurationService {
OutputFile = outputFileName, OutputFile = outputFileName,
JsonFilesInfo = givenFilePaths.Select(name => new FileInfo(name)).ToArray(), JsonFilesInfo = givenFilePaths.Select(name => new FileInfo(name)).ToArray(),
}; };

View File

@ -1,12 +1,12 @@
using System.Globalization; using System.Globalization;
using CsvHelper; using CsvHelper;
class CsvFileWriter class CsvFileWriterService
{ {
private TextWriter textWriter; private TextWriter textWriter;
private CsvWriter csvWriter; private CsvWriter csvWriter;
public CsvFileWriter(FileInfo fileInfo) { public CsvFileWriterService(FileInfo fileInfo) {
textWriter = new StreamWriter(fileInfo.FullName); textWriter = new StreamWriter(fileInfo.FullName);
csvWriter = new CsvWriter(textWriter, CultureInfo.InvariantCulture); csvWriter = new CsvWriter(textWriter, CultureInfo.InvariantCulture);