Skip to content

Instantly share code, notes, and snippets.

@aannenko
Created June 4, 2024 14:00
Show Gist options
  • Save aannenko/620a21a0ae1421ecdff7bc615006c9aa to your computer and use it in GitHub Desktop.
Save aannenko/620a21a0ae1421ecdff7bc615006c9aa to your computer and use it in GitHub Desktop.
Library management OOP/SOLID
namespace LibraryManager;
public sealed record Book(string Name, bool CanBeBorrowed, int? AgeRating) : ILibraryItem;
namespace LibraryManager;
public interface IBorrowedItemsRepository<T> where T : ILibraryItem
{
public T[] GetBorrowedItems(Person person);
public void AddBorrowedItem(Person person, T item);
public void RemoveBorrowedItem(Person person, T item);
}
namespace LibraryManager;
public interface IBorrowedItemsRepositoryFactory
{
IBorrowedItemsRepository<T> CreateRepository<T>() where T : ILibraryItem;
}
namespace LibraryManager;
public interface IBorrowingPolicy<T> where T : ILibraryItem
{
int MaxBorrowedItemsPerPerson { get; }
}
namespace LibraryManager;
public interface IBorrowingPolicyProvider
{
IBorrowingPolicy<T> GetPolicy<T>() where T : ILibraryItem;
}
namespace LibraryManager;
public interface ILibraryItem
{
string Name { get; }
bool CanBeBorrowed { get; }
int? AgeRating { get; }
}
namespace LibraryManager;
public interface ILibraryItemsRepository<T> where T : ILibraryItem
{
public T? FindByName(string title);
public int GetCount(T item);
public void Remove(T item);
}
namespace LibraryManager;
public interface ILibraryItemsRepositoryFactory
{
ILibraryItemsRepository<T> CreateRepository<T>() where T : ILibraryItem;
}
namespace LibraryManager;
public interface IPeopleRepository
{
Person? FindByName(string name);
}
namespace LibraryManager;
public class Library(
ILibraryItemsRepositoryFactory libraryItemsRepositoryFactory,
IBorrowedItemsRepositoryFactory borrowedItemsRepositoryFactory,
IBorrowingPolicyProvider borrowingPolicyFactory,
IPeopleRepository peopleRepository)
{
public void BorrowItem<T>(string personName, string itemName) where T : ILibraryItem
{
var person = peopleRepository.FindByName(personName)
?? throw new ArgumentException("Person not found", nameof(personName));
var libraryItemsRepository = libraryItemsRepositoryFactory.CreateRepository<T>();
var item = libraryItemsRepository.FindByName(itemName)
?? throw new ArgumentException("Item not found", nameof(itemName));
var borrowedItemsRepository = borrowedItemsRepositoryFactory.CreateRepository<T>();
var borrowingPolicy = borrowingPolicyFactory.GetPolicy<T>();
if (person.CanBorrowLibraryItem(item, borrowingPolicy, libraryItemsRepository, borrowedItemsRepository))
{
libraryItemsRepository.Remove(item);
borrowedItemsRepository.AddBorrowedItem(person, item);
}
}
}
namespace LibraryManager;
public sealed class Person(string name, DateTime dateOfBirth)
{
public string Name { get; } = name;
public DateTime DateOfBirth { get; } = dateOfBirth;
}
namespace LibraryManager;
public static class PersonExtensions
{
public static bool CanBorrowLibraryItem<T>(
this Person person,
T item,
IBorrowingPolicy<T> borrowingPolicy,
ILibraryItemsRepository<T> libraryItemsRepository,
IBorrowedItemsRepository<T> borrowedItemsRepository)
where T : ILibraryItem
{
return item is not null
&& item.CanBeBorrowed
&& person.GetAge() >= (item.AgeRating ?? 0)
&& libraryItemsRepository.GetCount(item) > 0
&& borrowingPolicy.MaxBorrowedItemsPerPerson > borrowedItemsRepository.GetBorrowedItems(person).Length;
}
public static int GetAge(this Person person)
{
var today = DateTime.Today;
var age = today.Year - person.DateOfBirth.Year;
return age - Convert.ToInt32(today.Date - person.DateOfBirth.AddYears(age));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment