How to create a common interface for various implementations? - c#

I'm doing small exercise project to have more practice with programming in general.
The project is a program that takes content of CSV file and puts it in some database.
I started from creating a database-access interface IDatabaseClient, which made me think about a few things:
How should my Connect(...) method look like? Various databases might have a different set of credentials that are needed for connection, i.e. one might need a conenction string, another might need: URL, username, password, etc. One way to solve this could be to have Connect method like this:
Task Connect(IConnectionCredentials credentials);
IConnectionCredentials interface would be empty and each database would have its own implementation of it, like this for example:
public class DatabaseNo1Credentials : IConnectionCredentials
{
public Uri Uri { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
The thing that I don't like about such solution is that the user of IDatabaseClient implementation does not have any information which credentials class should be used. The code will throw an exception if wrong credentials class is provided. Is there a better solution?
My CSV files could contain data for different database tables. One CSV could contain Cars data, another could contain People data, etc. How do I make my IDatabaseClient usable for many kids of data?
I could do this:
public interface IDatabaseClient
{
Task Connect(IConnectionCredentials credentials);
Task WriteCars(string model, int productionYear);
Task WritePeople(string firstName, string lastName, int age);
}
However, what if one day I want to write data to Phones table, or any other table?

Your interface is too specific, in terms of methods and especially in terms of method parameters.
You should not have a Connect method with parameters, rather you would do something like this:
interface IDatabaseClient
{
Task ConnectAsync();
Task AddDataAsync<T>(string databaseName, T data);
}
class DatabaseClient1 : IDatabaseClient
{
public DatabaseClient1(string username, string password)
{
Username = username;
Password = password;
}
public string Username { get; }
public string Password { get; }
public async Task ConnectAsync()
{
// connect using Username and Password
}
public async Task AddDataAsync<T>(string databaseName, T data)
{
// Not sure if you can work with a generic method for inserting data
// into your database, but given that you didn't specify your
// requirements further, I'm just going to go with this
}
}
Having multiple database table specific operations in one interface defeats the purpose of having an interface in my opinion, so you should delegate the specific work to other classes, which only depend on the IDatabaseClient:
class CarManager
{
public CarManager(IDatabaseClient databaseClient)
{
_databaseClient = databaseClient;
}
public async Task AddCarAsync(string model, int productionYear)
{
var car = new Car(model, productionYear);
_databaseClient.AddDataAsync("cars", car);
}
private readonly IDatabaseClient _databaseClient;
}

Related

Dependency Injection with static methods in DTOs

emphasized textMy project has as series of DTOs that we use in one of our Function Apps, which takes in a JSON "message" from a service bus, like so:
public class Account
{
public string Id { get; set; }
public string Name{ get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country{ get; set; }
public static Account Parse(string messageFromQueue)
{
Message message = new Message(messageFromQueue);
return Parse(message.Id, message.Content);
}
public static Account Parse(Guid Id, dynamic content)
{
var account = new Account(){ Command = content.MessageName, AccountId = id };
account.AccountNumber = StaticClass.GetValue("AccountNumber");
account.AccountName = StaticClass.GetValue("AccountName");
etc...
return account;
}
}
We have several like this that follow a similar format in that they are being used to create a readable, useful object from our JSON message. These DTOs don't all have the same fields in them; I need to be able to properly set the fields dynamically based on the object that is being instantiated.
Now before anyone asks, yes, based on the JSON message format, we have a reason for calling out to the static classes to assign the values. Many of our service bus messages are scheduled messages, meaning they're initially processed and scheduled for sometime in the future (due to business rules outside of our control). When the scheduled message is finally processed, we call out to the third-party platform to get the current data from where the message data originated. We do this to prevent us from having to put service bus triggers on every single field in this third-party platform and constantly having to cancel and reschedule messages whenever a data field is updated on the given record between the time the message is scheduled and the time the scheduled message is processed.
I've been working on trying to get out project implementing dependency injection wherever possible. However, it makes it difficult to implement DI in some of these static helper classes since they are being called within the DTOs and the DTOs cannot implement DI because they need to be instantiated. So there's no way for us to inject those dependencies into the DTOs if the helpers were made into DI classes.
Does anyone know a clean, proper way to architect these DTOs so we can still somehow get the proper values from the static classes that we want to convert to using DI?

How to access CRUD operations of single db class instance without static methods

I'm new to NoSql and MongoDB. I'm using the MongoDB C# driver inside Visual Studio.
I've read in different places that it's preferable to have a single instance of your database class that maintains the connection(s) to keep everything thread safe and that it's generally a bad idea to use static classes for database CRUD operations.
At the start of my program I instantiate my database class which opens a connection. Within that class and also in derived classes I can perform CRUD operations. But now I'm in a different part of my solution (same namespace, different class) and I need to do read operations to check if a user exists. I also need to compose a new document that I then want to insert.
Now I'm in a situation where that's only possible by creating a new instance of the database class to access its CRUD methods. I want to avoid static CRUD methods (that could be accessed from other classes) because then the base class of my database connection also needs to be static. I cannot figure out how to approach this and what would be the recommended way.
From the MongoDB website:
The MongoClient instance actually represents a pool of connections to the database; you will only need one instance of class MongoClient even with multiple threads.
http://mongodb.github.io/mongo-csharp-driver/2.2/getting_started/quick_tour/
Does this mean I should create a new MongoClient everytime I need to acces the database in others parts of my program?
UPDATE
It seems I was a bit mistaken about the static properties and how they can be used. I now have it setup like this:
class Database
{
const string MongoConnection = "mongodb+srv://user:password#cluster.mongodb.net";
public static MongoClient Client { get; set; }
public static IMongoDatabase Directory { get; set; }
public static IMongoCollection<User> Collection { get; set; }
public Database()
{
Client = new MongoClient(MongoConnection);
Directory= Client.GetDatabase("studentDB");
Collection = Directory.GetCollection<User>("users");
}
public static void InsertNewUser(User user)
{
Collection.InsertOne(user);
}
public static bool EmailHasAccount(string email)
{
return Collection.Find(x => x.Email == email).FirstOrDefault() == null ? false : true;
}
public static User RetrieveUserAccount(string email)
{
return Collection.Find(x => x.Email == email).FirstOrDefault();
}
}
public class User
{
public Guid Id { get; private set; }
public string Name { get; set; }
public string Email { get; set; }
public User(string name, string email)
{
Id = Guid.NewGuid();
Name = name;
Email = email;
}
}
And in my main program I can use it like this:
var db = new Database();
var user = new User("myName", "email#address");
Database.InsertNewUser(user);
Console.WriteLine(Database.EmailHasAccount("email#address")); // returns true
Console.WriteLine(Database.RetrieveUserAccount("email#address").Name); // returns "myName"
That's exactly what I was looking for. What would be the best way to handle multiple collections? Would it be safe to change the Collection property or is it better to create separate properties? Is a Generic even possible?

Creation of domain objects

I'm creating an application with employee and employer as a domain objects.
Both of them have a reference to User object where I store password and other account related stuff.
Example:
public class Employee
{
public Guid EmployeeId { get; set; }
public User User { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string About { get; set; }
...
//other properties
}
public class Employer
{
public Guid EmployerId { get; set; }
public User User { get; set; }
public string CompanyName { get; set; }
public string CompanyDescription { get; set; }
public string FoundedYear { get; set; }
...
//other properties
}
public class User
public Guid UserId { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
...
//other properties
}
I'm also using application services where a method represents a single use case.
Let's say I have RegisterEmpolyee method that should save employee to database set his role to "Employee" and send verification email.
This is my code right now. I'm using AspNet.Core.Idenity.UserManager to create user account:
public async Task<EmployeeDto> RegisterEmployee(RegisterEmployeeDto employee)
{
var validateResult = _validatorService.Validate(employee);
if (!validateResult.IsValid)
throw new ServerException
("RegisterEmployeeDto is not valid", validateResult.GetErrors());
await _db.BeginTransactionAsync();
var newUser = new User { UserName = employee.Email, Email = employee.Email };
var userCreationResult = await _userManager.CreateAsync(newUser, employee.Password);
if (!userCreationResult.Succeeded)
{
var userCreationErrors = userCreationResult.GetIdentityResultErrors();
throw new ServerException("Error during create User account.", userCreationErrors);
}
await _roleService.AddUserToRoleAsync(newUser.Id, ApplicationRoles.Employee);
var verificationCode = await _userManager.GenerateEmailConfirmationTokenAsync(newUser);
newUser.VerificationCode = verificationCode;
await _emailService.SendActivationEmail(newUser.Email, newUser.Id, verificationCode);
var newEmployee = new Employee(employee.Name, employee.Surname, newUser);
await _db.Employees.AddAsync(newEmployee);
await _db.CompleteAsync();
var employeeDto = _mapper.Map<Employee, EmployeeDto>(newEmployee);
_db.CommitTransaction();
return employeeDto;
}
And here are my questions:
Does this code and my approach are fine according to DDD?
Should I extract creation of employee to domain service? Or maybe factory? And if so should I call repository method from there? (I mean service of course)
Let's say should extract creation of employee to domain service. Should I create User internally then?
Like this:
public async Task<Employee> CreateEmployee(RegisterEmployeeDto employee)
{
var newUser = new User { UserName = employee.Email, Email = employee.Email };
var userCreationResult = await _userManager.CreateAsync(newUser, employee.Password);
if (!userCreationResult.Succeeded)
{
var userCreationErrors = userCreationResult.GetIdentityResultErrors();
throw new ServerException("Error during create User account.", userCreationErrors);
}
var newEmployee = new Employee(employee.Name, employee.Surname, newUser);
//Should I call repository here?
await _db.Employees.AddAsync(newEmployee);
await _db.CompleteAsync();
return newEmployee;
}
Or maybe pass User as a parameter?
And last question: Where is a right place to checking if user I want to create exist or not? Is Application service appropriate place to do so?
Thank you in advance for answers.
From what I see, User, Employee and Employer are Aggregate roots (AR).
Does this code and my approach are fine according to DDD?
In DDD it's not recommended that an Aggregate have references to other Aggregates other than by ID. Your Employee and Employer AR have such a bad reference so it is not OK. Instead Employee and Employer should contain only a UserId field.
Should I extract creation of employee to domain service? Or maybe factory? And if so should I call repository method from there? (I mean service of course)
From what I can see you have a complex process of creating multiple Aggregates. In DDD you cannot do this atomically, inside a single transaction. Instead, every Aggregate is created/mutated in its own transaction. There is however a tactical pattern of coordinating a long process: Saga/Process manager.
You should define a process of registering an employee as a Saga: RegisterEmployee. This process should have an interface with these methods: create, start, continue. The create method receive all the data it needs to start process. The start method tries to run the individual steps (like createEmployee, createUser etc); if the start method is run again, it should continue from where has stopped, so the Saga should record its status.
The architecture can be made better by making the command on Aggregates as idempotent. In this way, when a Saga restarts it can send again all the commands to the Aggregates; this effectively makes the Saga very simple.
Let's say should extract creation of employee to domain service. Should I create User internally then?
That domain service is in fact the Saga from the previous step. The Saga however should not contain logic that belongs to the Aggregates! Be carefully to not make your domain model anaemic. The Saga should contain only coordinating logic!
And last question: Where is a right place to checking if user I want to create exist or not? Is Application service appropriate place to do so?
What means that an User already exists? There is already an user with that username? If yes, then the simplest solution is to have an unique index on the username column, if possible. If it's not possible (i.e. you have sharding enabled) then you can have another Saga that checks for duplicates and reports to an Admin or something.

Improve design with IOC/DI

I'm currently trying to find a better design for my multi-module solution using DI/IOC, but now I'm somehow lost. I have a solution where different kind of entities can be distributed to recipients via different channels.
This is a simplified version of my classes:
#region FTP Module
public interface IFtpService
{
void Upload(FtpAccount account, byte[] data);
}
public class FtpService : IFtpService
{
public void Upload(FtpAccount account, byte[] data)
{
}
}
#endregion
#region Email Module
public interface IEmailService :IDistributionService
{
void Send(IEnumerable<string> recipients, byte[] data);
}
public class EmailService : IEmailService
{
public void Send(IEnumerable<string> recipients, byte[] data)
{
}
}
#endregion
public interface IDistributionService { }
#region GenericDistributionModule
public interface IDistributionChannel
{
void Distribute();
}
public interface IDistribution
{
byte[] Data { get; }
IDistributionChannel DistributionChannel { get; }
void Distribute();
}
#endregion
#region EmailDistributionModule
public class EmailDistributionChannel : IDistributionChannel
{
public void Distribute()
{
// Set some properties
// Call EmailService???
}
public List<string> Recipients { get; set; }
}
#endregion
#region FtpDistributionModule
public class FtpDistributionChannel : IDistributionChannel
{
public void Distribute()
{
// Set some properties
// Call FtpService???
}
public FtpAccount ftpAccount { get; set; }
}
#endregion
#region Program
public class Report
{
public List<ReportDistribution> DistributionList { get; private set; }
public byte[] reportData{get; set; }
}
public class ReportDistribution : IDistribution
{
public Report Report { get; set; }
public byte[] Data { get { return Report.reportData; } }
public IDistributionChannel DistributionChannel { get; private set; }
public void Distribute()
{
DistributionChannel.Distribute();
}
}
class Program
{
static void Main(string[] args)
{
EmailService emailService = new EmailService();
FtpService ftpService = new FtpService();
FtpAccount aAccount;
Report report;
ReportDistribution[] distributions =
{
new ReportDistribution(new EmailDistributionChannel(new List<string>("test#abc.xyz", "foo#bar.xyz"))),
new ReportDistribution(new FtpDistributionChannel(aAccount))
};
report.DistributionList.AddRange(distributions);
foreach (var distribution in distributions)
{
// Old code:
// if (distribution.DistributionChannel is EmailDistributionChannel)
// {
// emailService.Send(...);
// }else if (distribution.DistributionChannel is FtpDistributionChannel)
// {
// ftpService.Upload(...);
// }else{ throw new NotImplementedException();}
// New code:
distribution.Distribute();
}
}
}
#endregion
In my current solution it is possible to create and store persistent IDistribution POCOs (I'am using a ReportDistribution here) and attach them to the distributable entity (a Report in this example).
E.g. someone wants to distribute an existing Report via Email to a set of recipients. Therefore he creates a new ReportDistribution' with anEmailDistributionChannel'. Later he decides to distribute the same Report via FTP to a specified FtpServer. Therefore he creates another ReportDistribution with an FtpDistributionChannel.
It is possible to distribute the same Report multiple times on the same or different channels.
An Azure Webjob picks up stored IDistribution instances and distributes them. The current, ugly implementation uses if-else to distribute Distributions with a FtpDistributionChannel via a (low-level) FtpService and EmailDistributionChannels with an EmailService.
I'm now trying to implement the interface method Distribute() on FtpDistributionChannel and EmailDistributionChannel. But for this to work the entities need a reference to the services. Injecting the Services into the entities via ConstructorInjection seems to be considered bad style.
Mike Hadlow comes up with three other solutions:
Creating Domain Services. I could e.g. create a FtpDistributionService, inject a FtpService and write a Distribute(FtpDistributionChannel distribution) method (and also a EmailDistributionService). Apart from the drawback mentioned by Mike, how can I select a matching DistributionService based on the IDistribution instance? Replacing my old if-else with another one does not feel right
Inject IFtpService/EMailService into the Distribute() method. But how should I define the Distribute() method in the IDistribution interface? EmailDistributionChannel needs an IEmailService while FtpDistributionChannel need an IFtpService.
Domain events pattern. I'm not sure how this can solve my problem.
Let me try to explain why I came up with this quite complicated solution:
It started with a simple list of Reports. Soon someone asked me to send reports to some recipients (and store the list of recipients). Easy!
Later, someone else added the requirement to send a report to a FtpAccount. Different FtpAccounts are managed in the application, therefore the selected account should also be stored.
This was to the point where I added the IDistributionChannel abstraction. Everything was still fine.
Then someone needed the possibility to also send some kind of persistent Logfiles via Email. This lead to my solution with IDistribution/IDistributionChannel.
If now someone needs to distribute some other kind of data, I can just implement another IDistribution for this data. If another DistributionChannel (e.g. Fax) is required, I implement it and it is available for all distributable entities.
I would really appreciate any help/ideas.
First of all, why do yo create interfaces for the FtpAccount? The class is isolated and provide no behavior that need to be abstracted away.
Let's start with your original problem and build from there. The problem as I interpret it as that you want to send something to a client using a different set of mediums.
By expressing it in code it can be done like this instead:
public void SendFileToUser(string userName, byte[] file)
{
var distributions = new []{new EmailDistribution(), new FtpDistribution() };
foreach (var distribution in distributions)
{
distribution.Distribute(userName, file);
}
}
See what I did? I added a bit of context. Because your original use case was way to generic. It's not often that you want to distribute some arbitrary data to an arbitrary distribution service.
The change that I made introduces a domain and a real problem.
With that change we can also model the rest of the classes a bit different.
public class FtpDistributor : IDistributor
{
private FtpAccountRepository _repository = new FtpAccountRepository();
private FtpClient _client = new FtpClient();
public void Distribute(string userName, byte[] file)
{
var ftpAccount = _repository.GetAccount(userName);
_client.Connect(ftpAccount.Host);
_client.Authenticate(ftpAccount.userName, ftpAccount.Password);
_Client.Send(file);
}
}
See what I did? I moved the responsibility of keeping track of the FTP account to the actual service. In reality you probably have an administration web or similar where the account can be mapped to a specific user.
By doing so I also isolated all handling regarding FTP to within the service and therefore reduced the complexity in the calling code.
The email distributor would work in the same way.
When you start to code problems like this, try to go from top->down. It's otherwise easy to create an architecture that seems to be SOLID while it doesn't really solve the actual business problem.
Update
I've read your update and I don't see why you must use the same classes for the new requirements?
Then someone needed the possibility to also send some kind of persistent Logfiles via Email
That's an entirely different use case and should be separated from the original use case. Create new code for it. The SmtpClient in .NET is quite easy to us and do not need to be abstracted away.
If now someone needs to distribute some other kind of data, I can just implement another IDistribution for this data.
Why? what complexity are you trying to hide?
If another DistributionChannel (e.g. Fax) is required, I implement it and it is available for all distributable entities
No. Distributing thing A is not the same as distributing thing B. You can't for instance transport parts of a large bridge on an airpane, either a freight ship or a truck is required.
What I'm trying to say is that creating too generic abstractions/contracts to promote code reuse seems like a good idea, but it usually just make your application more complex or less readable.
Create abstractions when there is real complexity issues and not on before hand.

Should I use static method (C#)

Should I use static in the following 2 cases:
Case 1)
public class RequestHeader
{
private string Username { get; set; }
private string Password { get; set; }
private string AccessKey { get; set; }
public string url { get; set; }
public string pageid { get; set; }
public string organizationid { get; set; }
private RequestHeader()
{
}
public static RequestHeader GetRequestHeader(string url, string pageid, string organizationid)
{
return new RequestHeader()
{
Username = "Some logic to fetch username",
Password = "Some logic to fetch password",
AccessKey = "Some access key",
url = url,
pageid = pageid,
organizationid = organizationid,
};
}
}
Case 2)
public class HttpClientHelper
{
public static HttpClient GetHttpClient(RequestHeader header)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
foreach (var property in header.GetType().GetProperties())
{
client.DefaultRequestHeaders.Add(property.Name, property.GetValue(header).ToString());
}
return client;
}
}
I know that static is not used where state is maintained. I believe I am not maintaining any state here. I will be using this in a class library and I will be using these for calling a rest service.
The only thing which makes me want to use static here is not to initialize these class.(I know this is a very baaad reason).
Please let me know your thoughts. Is there something which I am not seeing in this.
Note: 1) I am aware of the small casing for some of the properties. It is in sync with the rest service on which I have absolutely no control.
2) If I have multiple RequestHeader in future, I might create an IRequestHeader which has a method GetRequestHeader. So the different RequestHeaders will implement this. In this case I know I cant keep a static method in interface.
Please Keep these 2 conditions away and let me know your thoughts.
What you have here seems to be a version of the Static Factory Pattern. This is a well-known pattern and is perfectly fine to use.
You might also be interested in the non-static version of the Factory Pattern.
I assume HttpClient is not "your class", in which case you of course can't add a method inside the class itself.
The only thing which makes me want to use static here is not to initialize these class.(I know this is a very baaad reason).
Technically you're instantiating and initializing these classes no matter how you do it (factory method or no factory method), the only question is if you are going to use a factory method to do the instantiation and initialization for you.
If you have to use same values for each call you should use static fields, because static fields are used when only one copy of the variable is required. The same static field will share the copy across all the instances.

Categories