Sistema de alquiler de libros orientado a objetos -- java campo con object-oriented camp codereview Relacionados El problema

Object-oriented book rental system


1
vote

problema

Español

En los últimos 2 días, he desarrollado una aplicación de la biblioteca simple, pero no estoy seguro de las relaciones entre las clases que diseñé y donde pueda usar la composición, agregar una interfaz o patrón de diseño. Me gustaría obtener sus comentarios sobre el diseño.

  package com.library.main;  import com.library.models.BookDirectory; import com.library.models.Rent; import com.library.service.Alert; import com.library.service.FileGenerator; import com.library.service.UserRegistration; import com.library.users.Customer; import com.library.users.User;  import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set;  public class RunApplication {      public static void main(String[] args) {         BookDirectory bookDirectory = new BookDirectory();         HashSet<User> userSet = new HashSet<User>();         HashSet<Customer> customerSet = new HashSet<Customer>();         FileGenerator.setBookDirectory(bookDirectory);         UserRegistration.setUsers(userSet);         UserRegistration.setCustomers(customerSet);         Alert.setCustomers(customerSet);     } }   
  package com.library.models;  public class Author {      private static int nextAuthorId = 0;      private String name;     private int id;      public Author(String name) {         this.name = name;         id = nextAuthorId;         nextAuthorId++;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     } }   
  package com.library.models;  public class Book {      private BookTitle bookTitle;     private int id;      public Book(BookTitle bookTitle, int id) {         this.bookTitle = bookTitle;         this.id = id;     }      public BookTitle getBookTitle() {         return bookTitle;     }      public String getTitle() {         return getBookTitle().getTitle();     }      public void setTitle(String title) {         this.getBookTitle().setTitle(title);     }      public Author getAuthor() {         return getBookTitle().getAuthor();     }      public void setAuthor(Author author) {         this.getBookTitle().setAuthor(author);     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     }  }   
  package com.library.models;  import com.library.users.Customer;  import java.io.FileWriter; import java.io.IOException; import java.time.LocalTime; import java.time.Period; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List;  public class BookDirectory {     private ArrayList<Book> books;     private HashSet<Author> authors;     private HashSet<BookTitle> bookTitles;      public void addBook(BookTitle bookTitle, int id) {         Book newBook = new Book(bookTitle, id);         books.add(newBook);     }      public boolean hasBook(Book book) {         return books.contains(book);     }      public void deleteBook(Book book) {         books.remove(book);     }      public void deleteAllBooks() {         books.clear();     }      public int getBookCount() {         return books.size();     }      public void addAuthor(String name) {         authors.add(new Author(name));     }      public void clearBookDirectory() {         books.clear();         authors.clear();     }      public void addBookTitle(String title, Author author, int id) {         bookTitles.add(new BookTitle(title, author, id));     }      public int getBookTitlesCount() {         return bookTitles.size();     }      public String toString() {         return books.toString();     }      public List<Book> getAllBooks() {         return books;     }      public HashSet<BookTitle> getAllBookTitles() {         return bookTitles;     }  }   
  package com.library.models;  public class BookTitle {     private String title;     private Author author;     private int id;      public BookTitle(String title, Author author, int id) {         this.title = title;         this.author = author;         this.id = id;     }      public String getTitle() {         return title;     }      public void setTitle(String title) {         this.title = title;     }      public Author getAuthor() {         return author;     }      public void setAuthor(Author author) {         this.author = author;     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     } }   
  package com.library.models;  import com.library.users.Customer;  import java.time.LocalDate; import java.time.Period;  public class Rent {     private Customer customer;     private Book book;     LocalDate dateOfRent;     Period period;      public Rent(Customer customer, Book book, Period period) {         this.customer = customer;         this.book = book;         this.period = period;         dateOfRent = LocalDate.now();     }      public Customer getCustomer() {         return customer;     }      public void setCustomer(Customer customer) {         this.customer = customer;     }      public Book getBook() {         return book;     }      public void setBook(Book book) {         this.book = book;     }      public LocalDate getDateOfRent() {         return dateOfRent;     }      public void setDateOfRent(LocalDate dateOfRent) {         this.dateOfRent = dateOfRent;     }      public Period getPeriod() {         return period;     }      public void setPeriod(Period period) {         this.period = period;     } }   
  package com.library.models;  public enum UserPrivilige {     USER, ADMIN, SUPERADMIN }  package com.library.service;  import com.library.models.Rent; import com.library.users.Customer; import com.library.users.User;  import java.time.LocalDate; import java.time.Period; import java.util.ArrayList; import java.util.HashSet; import java.util.Set;  public class Alert {      private static HashSet<Customer> customers;      public ArrayList<Rent> getOverdueRents() {         return getSoonOverdueRents(Period.ZERO);     }      public static HashSet<Customer> getCustomers() {         return customers;     }      public static void setCustomers(HashSet<Customer> customers) {         Alert.customers = customers;     }      public ArrayList<Rent> getSoonOverdueRents(Period period) {         ArrayList<Rent> result = new ArrayList<Rent>();         for (Customer customer : customers) {             for (Rent rent : customer.getRentedBooks()) {                 if (rent.getDateOfRent().plus(rent.getPeriod()).isAfter(LocalDate.now().minus(period))) {                     result.add(rent);                 }             }         }         return result;     }      public ArrayList<Rent> getAllRents() {         ArrayList<Rent> result = new ArrayList<Rent>();         for (Customer customer : customers) {             for (Rent rent : customer.getRentedBooks()) {                     result.add(rent);             }         }         return result;     } }   
  radix_sort0  
  radix_sort1  
  radix_sort2  
  radix_sort3  
  radix_sort4  
  radix_sort5  
  radix_sort6  
Original en ingles

Over the past 2 days I've developed a simple library application, but I'm not sure about relations between classes I designed and where I can use composition,add interface or design pattern. I would like to get your feedback on the design.

package com.library.main;  import com.library.models.BookDirectory; import com.library.models.Rent; import com.library.service.Alert; import com.library.service.FileGenerator; import com.library.service.UserRegistration; import com.library.users.Customer; import com.library.users.User;  import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set;  public class RunApplication {      public static void main(String[] args) {         BookDirectory bookDirectory = new BookDirectory();         HashSet<User> userSet = new HashSet<User>();         HashSet<Customer> customerSet = new HashSet<Customer>();         FileGenerator.setBookDirectory(bookDirectory);         UserRegistration.setUsers(userSet);         UserRegistration.setCustomers(customerSet);         Alert.setCustomers(customerSet);     } } 
package com.library.models;  public class Author {      private static int nextAuthorId = 0;      private String name;     private int id;      public Author(String name) {         this.name = name;         id = nextAuthorId;         nextAuthorId++;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     } } 
package com.library.models;  public class Book {      private BookTitle bookTitle;     private int id;      public Book(BookTitle bookTitle, int id) {         this.bookTitle = bookTitle;         this.id = id;     }      public BookTitle getBookTitle() {         return bookTitle;     }      public String getTitle() {         return getBookTitle().getTitle();     }      public void setTitle(String title) {         this.getBookTitle().setTitle(title);     }      public Author getAuthor() {         return getBookTitle().getAuthor();     }      public void setAuthor(Author author) {         this.getBookTitle().setAuthor(author);     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     }  } 
package com.library.models;  import com.library.users.Customer;  import java.io.FileWriter; import java.io.IOException; import java.time.LocalTime; import java.time.Period; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List;  public class BookDirectory {     private ArrayList<Book> books;     private HashSet<Author> authors;     private HashSet<BookTitle> bookTitles;      public void addBook(BookTitle bookTitle, int id) {         Book newBook = new Book(bookTitle, id);         books.add(newBook);     }      public boolean hasBook(Book book) {         return books.contains(book);     }      public void deleteBook(Book book) {         books.remove(book);     }      public void deleteAllBooks() {         books.clear();     }      public int getBookCount() {         return books.size();     }      public void addAuthor(String name) {         authors.add(new Author(name));     }      public void clearBookDirectory() {         books.clear();         authors.clear();     }      public void addBookTitle(String title, Author author, int id) {         bookTitles.add(new BookTitle(title, author, id));     }      public int getBookTitlesCount() {         return bookTitles.size();     }      public String toString() {         return books.toString();     }      public List<Book> getAllBooks() {         return books;     }      public HashSet<BookTitle> getAllBookTitles() {         return bookTitles;     }  } 
package com.library.models;  public class BookTitle {     private String title;     private Author author;     private int id;      public BookTitle(String title, Author author, int id) {         this.title = title;         this.author = author;         this.id = id;     }      public String getTitle() {         return title;     }      public void setTitle(String title) {         this.title = title;     }      public Author getAuthor() {         return author;     }      public void setAuthor(Author author) {         this.author = author;     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     } } 
package com.library.models;  import com.library.users.Customer;  import java.time.LocalDate; import java.time.Period;  public class Rent {     private Customer customer;     private Book book;     LocalDate dateOfRent;     Period period;      public Rent(Customer customer, Book book, Period period) {         this.customer = customer;         this.book = book;         this.period = period;         dateOfRent = LocalDate.now();     }      public Customer getCustomer() {         return customer;     }      public void setCustomer(Customer customer) {         this.customer = customer;     }      public Book getBook() {         return book;     }      public void setBook(Book book) {         this.book = book;     }      public LocalDate getDateOfRent() {         return dateOfRent;     }      public void setDateOfRent(LocalDate dateOfRent) {         this.dateOfRent = dateOfRent;     }      public Period getPeriod() {         return period;     }      public void setPeriod(Period period) {         this.period = period;     } } 
package com.library.models;  public enum UserPrivilige {     USER, ADMIN, SUPERADMIN }  package com.library.service;  import com.library.models.Rent; import com.library.users.Customer; import com.library.users.User;  import java.time.LocalDate; import java.time.Period; import java.util.ArrayList; import java.util.HashSet; import java.util.Set;  public class Alert {      private static HashSet<Customer> customers;      public ArrayList<Rent> getOverdueRents() {         return getSoonOverdueRents(Period.ZERO);     }      public static HashSet<Customer> getCustomers() {         return customers;     }      public static void setCustomers(HashSet<Customer> customers) {         Alert.customers = customers;     }      public ArrayList<Rent> getSoonOverdueRents(Period period) {         ArrayList<Rent> result = new ArrayList<Rent>();         for (Customer customer : customers) {             for (Rent rent : customer.getRentedBooks()) {                 if (rent.getDateOfRent().plus(rent.getPeriod()).isAfter(LocalDate.now().minus(period))) {                     result.add(rent);                 }             }         }         return result;     }      public ArrayList<Rent> getAllRents() {         ArrayList<Rent> result = new ArrayList<Rent>();         for (Customer customer : customers) {             for (Rent rent : customer.getRentedBooks()) {                     result.add(rent);             }         }         return result;     } } 
package com.library.service;  import com.library.models.UserPrivilige; import com.library.users.User;  import java.util.HashSet; import java.util.List; import java.util.Set;  public class Authentification {     private Set<User> userSet;     public Authentification(Set<User> userSet){         this.userSet = userSet;     }      public boolean isLoginValid(String name, String password) {         for (User user : userSet) {             if (user.getName().equals(name) && user.getPassword().equals(password)) {                 return true;             }         }         return false;     }      public boolean isAdmin(User user) {         return user.getPrivilige().compareTo(UserPrivilige.ADMIN) >= 0;     } } 
package com.library.service;  import com.library.models.Book; import com.library.models.BookDirectory; import com.library.models.BookTitle; import com.library.models.Rent; import com.library.users.Customer; import com.library.users.User;  import java.io.FileWriter; import java.io.IOException; import java.time.LocalTime; import java.util.HashSet;  public class FileGenerator {     private static BookDirectory bookDirectory = null;      public static BookDirectory getBookDirectory() {         return bookDirectory;     }      public static void setBookDirectory(BookDirectory bookDirectory) {         FileGenerator.bookDirectory = bookDirectory;     }      public static void createDirectoryBookListFile() {         try {             FileWriter fileWriter = new FileWriter("book_list_" + LocalTime.now().toString() + ".txt");             fileWriter.write("Title\tAuthor\tQuantity\n");             for (BookTitle bookTitle : bookDirectory.getAllBookTitles()) {                 Integer bookQuantity = 0;                 for (Book book : bookDirectory.getAllBooks()) {                     if (book.getBookTitle().equals(bookTitle))                         bookQuantity++;                 }                 fileWriter.write(bookTitle.getTitle() + "\t" + bookTitle.getAuthor() +                         "\t" + bookQuantity.toString() + "\n");             }             fileWriter.close();         } catch (IOException e) {             e.printStackTrace();         }     }      public void createCustomerBookListFile(Customer customer) {         try {             FileWriter fileWriter = new FileWriter("book_list_" + customer.getName() + "_" +                     LocalTime.now().toString() + ".txt");             fileWriter.write("Book\tDate of Rent\tRent Period\n");             for (Rent rent : customer.getRentedBooks()) {                 fileWriter.write(rent.getBook().getTitle() + "\t" + rent.getDateOfRent() +                         "\t" + rent.getPeriod() + "\n");             }             fileWriter.close();         } catch (IOException e) {             e.printStackTrace();         }     } } 
package com.library.service;  import com.library.models.Book; import com.library.models.BookDirectory;  import java.util.ArrayList; import java.util.List;  public class Search {     private BookDirectory dir;      public Search(BookDirectory dir) {         this.dir = dir;     }      public List<Book> search(String phrase) {         List<Book> results = new ArrayList<Book>();         for (Book b : dir.getAllBooks()) {             if (b.getAuthor().getName().equals(phrase) || b.getTitle().equals(phrase))                 results.add(b);         }         return results;     } } 
package com.library.service;  import com.library.users.Customer; import com.library.users.User;  import java.util.HashSet; import java.util.List; import java.util.Set;  public class UserRegistration {     private String name;     private String email;     private String password;      private static HashSet<User> users;     private static HashSet<Customer> customers;      public static HashSet<User> getUsers() {         return users;     }      public static void setUsers(HashSet<User> users) {         UserRegistration.users = users;     }      public static HashSet<Customer> getCustomers() {         return customers;     }      public static void setCustomers(HashSet<Customer> customers) {         UserRegistration.customers = customers;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public String getEmail() {         return email;     }      public void setEmail(String email) {         this.email = email;     }      public String getPassword() {         return password;     }      public void setPassword(String password) {         this.password = password;     }      public boolean isRegistrationValid() {         int nameLength = name.length();         int passwordLength = password.length();         boolean passwordHasDigit = password.matches("\\d+");         boolean isEmailValid = email.matches("^[a-zA-Z0-9._+-]+@[a-zA-Z._-]+.[a-zA-Z0-9]]$");         return nameLength > 3 && passwordLength > 6 && passwordHasDigit && isEmailValid;     }      public boolean registerUser() {         if (isRegistrationValid()) {             boolean isNameFree = true;             for (User user : users) {                 if (user.getName().equals(name)) {                     isNameFree = false;                     break;                 }             }             if (isNameFree) {                 users.add(new User(name, email, password));                 return true;             }         }         return false;     }      public boolean registerCustomer() {         if (!registerUser())             return false;         customers.add(new Customer(name, email, password));         return true;     }  } 
package com.library.users;  import com.library.models.Book; import com.library.models.UserPrivilige;  import java.util.ArrayList;  public class User {     protected String name;     protected String email;     protected String password;     private int id;     private UserPrivilige privilige = UserPrivilige.USER;     private static int nextUserId = 0;      public User(String name, String email, String password) {         this.name = name;         this.email = email;         this.password = password;         this.id = nextUserId;         nextUserId++;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public String getEmail() {         return email;     }      public void setEmail(String email) {         this.email = email;     }      public String getPassword() {         return password;     }      public void setPassword(String password) {         this.password = password;     }      public int getId() {         return id;     }      public void setId(int id) {         this.id = id;     }      public UserPrivilige getPrivilige() {         return privilige;     }      public void setPrivilige(UserPrivilige privilige) {         this.privilige = privilige;     } } 
package com.library.users;  import com.library.models.Book; import com.library.models.BookDirectory; import com.library.models.Rent;  import java.io.FileWriter; import java.io.IOException; import java.time.LocalTime; import java.time.Period; import java.util.ArrayList;  public class Customer extends User {      private ArrayList<Rent> rentedBooks;     private static BookDirectory bookDirectory;      public Customer(String name, String email, String password) {         super(name, email, password);         rentedBooks = new ArrayList<Rent>();     }      public static BookDirectory getBookDirectory() {         return bookDirectory;     }      public static void setBookDirectory(BookDirectory bookDirectory) {         Customer.bookDirectory = bookDirectory;     }      public ArrayList<Rent> getRentedBooks() {         return rentedBooks;     }      public boolean rentBook(Book book, Period period) {         if (bookDirectory.hasBook(book)) {             getRentedBooks().add(new Rent(this, book, period));             return true;         }         return false;     }      public void returnBook(Rent rent) {         rentedBooks.remove(rent);     } } 
package com.library.users;  import com.library.models.Author; import com.library.models.Book;  public class Admin extends User {     public Admin(String name, String email, String password) {         super(name, email, password);     } } 
     
     
     

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

Permítanme primero señalar que casi siempre debe elegir la interfaz sobre una implementación concreta . La implementación concreta debe usarse solo en 1 lugar. Ahí es donde se crea una instancia. Hiciste esto correcto en algunos lugares como:

  arr3  

Usted crea un arr4 / Código>. Esto es bueno. Pero debe hacer esto para todo su arr8 's, arr9 ' s y posiblemente otras cosas.

ejemplos donde lo hiciste mal:
end0 - & gt; end1
end2 - & gt; end3
end4 - & gt; end5
...
para nombrar unos pocos. (También incluye los Getters / Setters).

En casos como este end6 tiene sentido usar end7 en lugar de end8 porque está hablando específicamente de la subclase. Otros tipos de end9 No nos interesan en ese bucle. Así que eso está bien.


inmutable es mejor que mutable . Para algunas clases, no tiene sentido cambiar uno de los campos. Tome un %0 por ejemplo. Nunca he conocido un título de libro de repente cambie. Así que cambie esos campos a la final y elimine los colonos:

  %1  

Lo mismo se puede hacer para %2 , %33 , %34 , 998877665554433335 , ...

Sin embargo, tiene algunas implicaciones. Al igual que si realiza una alquiler de inmutable, cada vez que desee "actualizar" un alquiler (como extender la fecha de regreso a la semana), tendrá que crear un nuevo alquiler para reemplazar el anterior. Alternativamente, podría mantener la variable del período de alquiler, o proporcionar un método especial 9988777655555443336

A veces es más lógico que cambien las variables. Al igual que el período de un %7 o el correo electrónico y los aDRes de un usuario (las personas tienden a pasar de vez en cuando, o cambiar sus administradores de correo electrónico). Algunos puristas aún harían que los objetos sean inmutables, siempre creando una nueva instancia con el valor actualizado y reemplazando todas las instancias. Pero creo que eso es demasiado de una molestia. Comenzaría con objetos inmutables y siempre que tenga más sentido tener un cambio de valor (como cuando un usuario se mueve), proporcione el programa o otro método de actualización.


Otro principio útil es yagni . Que significa "no lo necesitarás". Dado que su programa no hace nada útil todavía, es difícil decir cuál de estas estructuras de datos necesitará, y que no lo es. Es por eso que las respuestas iniciales a su pregunta aquí en CR.SE son: ¿Para qué es?

Mientras no sepa lo que necesita, aún no debe implementarlo. ¿Está seguro de que necesitará ese %8 ? Qué, si decide, más adelante, el programa solo será utilizado por los administradores, y todo lo que necesita es su nombre de inicio de sesión (y contraseña para asegurarse de que sean ellos). Luego, eso significa que no necesitaba la separación en administrador / cliente / usuario en primer lugar. Solo tendrías a los usuarios (del programa) y los clientes, que son 2 cosas completamente diferentes, cada una con su propia información.

Solo para su información: un %9 en su programa actual no tiene el 99887776655443340 . Entonces, ¿qué hacen esos protectores de usuario por usted?



En cuanto a su elección de clases. Para mí, no es lógico que un usuario sea responsable de realizar un seguimiento de los libros alquilados. Su programa actual aún no hace mucho, por lo que es difícil decir cuál es el mejor lugar para realizar un seguimiento de los alquileres. Entonces, dependiendo de lo que planee hacer junto con su programa, podría entrar en conflicto con lo que voy a proponer aquí. Así que no tomes esto como un "debes hacerlo de esta manera". En su lugar, mira cómo y por qué elijo ciertas cosas, y deja que te inspire a mejorar su propio programa.


Usted ha dividido libros específicos con una librería general. No es inusual que una biblioteca tenga múltiples de la misma libreta, y no le importa cuál de los que alquila. Por lo tanto, tiene sentido buscar un libro de libros y alquilar una copia específica del libro.

Una alternativa sería solo tener 99887776655443341 (su código std::numeric_limits<int>::max() / 102 ) y haga un seguimiento de cuántos de aquellos que tiene o que ha pertenecido a copia del libro. Prefiero ligeramente esta alternativa Ve porque no le importa las copias individuales.


El cambio más grande que estoy pensando es quién realiza un seguimiento de qué libro se alquila?

Actualmente tiene un cliente que realiza un seguimiento de los libros que tiene. TIENE UN 9988777766555443343 std::numeric_limits<int>::max() / 104 a un std::numeric_limits<int>::max() / 105 y un período para cuando el libro debe devolverse. Hay un 998877766555443346 que podría haber sido un 9988777666555443347 ya que no agrega ningún valor adicional en este momento. Y algunas otras clases que se sienten ligeramente fuera de lugar.

Lo que no tiene es una clase de biblioteca que contiene la lista de todos los libros que son propiedad de la biblioteca. Así que actualmente su método principal realiza un seguimiento de los.

Mi idea es crear primero esa clase de la biblioteca. Tiene un mapa que realiza un seguimiento de los libros que están en alquiler y cuántos de esos están disponibles. (Alternativamente, si desea seguir con su libro + BookTitle, este sería un 998877765555443348 que asigna un título a las copias concretas disponibles).

Además de los libros disponibles, esta clase también mantiene una lista de todo el std::numeric_limits<int>::max() / 109 's (lista). De esa manera, tenemos un lugar central para buscar qué libros deben devolverse pronto (en lugar de pasar torpemente a todos los usuarios del sistema para encontrarlos), y también podemos usar esto para encontrar qué usuarios tienen una copia de un libro si No hay ninguno disponible. Podría ser útil decirle a un cliente: regrese a Tomorow, John Smith habrá devuelto su copia para entonces.

La clase de búsqueda (que tiene un nombre bastante malo) se vuelve obsoleto si agregamos su num / radix0 a nuestra nueva clase de biblioteca. Alternativamente, podríamos cambiar el nombre del num / radix1 clase a algo más significativo como num / radix2 y haga que la clase de la biblioteca use esto para buscar un libro en su lista. De esa manera, la biblioteca no recibe una nueva responsabilidad (que, según los principios de diseño sólidos es mejor). (O incluso mejor, tenga la clase responsable de manejar la solicitud de búsqueda del usuario primero obtener la lista de libros en la biblioteca, y luego use la nueva clase de libros de libros para buscar los libros correspondientes. Así que la biblioteca ni siquiera necesita saber que hay tal cosa como "buscar un libro".

Ahora, la clase de cliente ya no necesita realizar un seguimiento de los libros que este cliente tiene actualmente. Si devuelve un libro, el bibliotecario suele escanearlo para averiguar qué libro está regresando (con la ID correcta en el sistema, etc.). Esto debería ahora ser manejado en la clase de la biblioteca con un método como num / radix3 que eliminará el num / radix4 con esa combinación de usuario y libro y aumenta el conteo de libros en el mapa de su disposición. libros. Alternativamente, también podría mantener esta lista en el cliente. Y al devolver un libro, la lógica es que lo sacas del cliente y lo agrega de nuevo en la biblioteca. Esto hace que sea más fácil averiguar "¿Qué libros tiene actualmente este cliente"? (Así que, nuevamente, la elección aquí depende de lo que se supone que debe hacer su programa).


como se indica en la parte yagni. Probablemente no necesite el num / radix5 o num / radix6 Clases. Comience con solo num / radix7 con los campos requeridos. Y luego en ver si desea combinar tanto 99887776655443358 y num / radix9 en un general for0 . Pero luego también mira dónde desea reemplazar la subclase ( for1 ) a la Super Clase ( for2 ). Dudo que esto suceda en muchos lugares desde el interior del programa, siempre manejará for3 's que alquila libros.

Esto también afecta a su clase for4 . En realidad, esta clase en sí se implementa realmente rara. Esto es lo que esperaría que esta clase se vea:

  for5  

más notable es que no tiene campos para el nombre / correo electrónico / contraseña. La implementación exacta podría cambiar (como si quisiera la contraseña) dependiendo de lo que quieras hacer con un cliente.

Mi pensamiento inicial es no dejarlos usar el sistema ellos mismos. Solo tenga una entrada de entrada de bibliotecario que regrese / revise de los libros.


Espero que mi explicación le ayude a decidir cuál debería hacer su programa y no debe hacerlo. Es difícil dar consejos sobre un programa sin tener su intención, ya sabes;)

 

Let me first point out that you should almost always choose the Interface over a concrete implementation. The concrete implementation should be used in 1 place only. That is where an instance is actally created. You did this correct in a few places like:

public List<Book> search(String phrase) {     List<Book> results = new ArrayList<Book>(); 

You create an ArrayList and store it in a List, return it as a List and handle it like a List. This is good. But you should do this for all your List's, Set's and possibly other things.

Examples where you did it wrong:
private ArrayList<Rent> rentedBooks; -> private List<Rent> rentedBooks
private static HashSet<User> users; -> Set<User>
private static HashSet<Customer> customers; -> Set<Customer>
...
to name a few. (also includes the getters/setters).

In cases like this for (Customer customer : customers) { it makes sense to use Customer instead of User because you're specifically talking about the subclass. Other types of User's don't interest us in that loop. So that's OK.


Immutable is better than mutable. For some classes it makes no sense to ever change one of the fields. Take a BookTitle for example. I've never known a book title suddenly change. So change those fields to final and remove the setters:

public class BookTitle {     private final String title;     private final Author author;     private final int id;      public BookTitle(String title, Author author, int id) {         this.title = title;         this.author = author;         this.id = id;     }      public String getTitle() {         return title;     }      public Author getAuthor() {         return author;     }      public int getId() {         return id;     } } 

The same can be done for Book, Author, Rent, UserRegistration, ...

It does have some implications though. Like if you make a Rent immutable, each time you want to "update" a rent (like extending the return date by a week) you'll have to create a new rent to replace the old one. Alternatively you could keep the renting period variable, or provide a special extendByAWeek() method to do just that.

Sometimes it's more logical that variables change. Like the period of a Rent or the email and adres of a user (people tend to move from time to time, or change their email adres). Some purists would still make the objects immutable, always creating a new instance with the updated value and replacing all instances. But I think that's too much of a hassle. I would start with immutable objects and whenever it makes more sense to have a value change (like when a user moves) provide the setter or other update method.


Another useful principle is YAGNI. Which stands for "You Aren't Going to Need It". Since your program doesn't do anything useful yet, it's hard to say which of these data structures you are going to need, and which you are not. That's why the initial responses to your question here on cr.se are: what is it for?

As long as you don't know what you need, you shouldn't implement it yet. Are you sure you will need that Admin class? What if you decide later on that the program will only be used by admins, and all you need is their login name (and password to make sure it's them). Then that means you didn't need the separation into Admin/Customer/User in the first place. You would just have Users (of the program) and Customers, which are 2 completely different things, each with their own information.

Just for your information: an Admin in your current program doesn't have the UserPrivilige.ADMIN. So what do those UserPriviliges do for you?



As for your choice of classes. For me it's not logical that a user is responsible of keeping track of the rented books. Your current program doesn't do much yet so it's hard to say which is the best place to keep track of the rentals. So depending on what you plan to do next with your program might conflict with what I'm going to propose here. So don't take this as a "you must do it this way". Instead look at how and why I choose certain things, and let it inspire you to improve your own program.


You have split up specific books with a general booktitle. It's not unusual for a library to have multiple of the same booktitle, and you don't care which of those you rent. So it makes sense to look up a booktitle and rent a specific copy of the book.

An alternative would be to just have Books (your current BookTiltes) and keep track of how many of those you have or who has ranted a copy of the book. I slightly prefer this alternative because you don't care about the individual copies.


The biggest change I'm thinking off is who keeps track of which book is rented?

You currently have a Customer that keeps track of the books that it has. You have a Rent class which maps a Book to a Customer and a period for when the book should be returned. There's a BookDirectory that could have just as well been a List<Book since it doesn't add any extra value at the moment. And some other classes that feel slightly out of place.

What you don't have is a Library class that contains the list of all books that are owned by the library. So currently your main method keeps track of those.

My idea is to first create that Library class. It has a Map that keeps track of the books that are for rent and how many of those are available. (Alternatively if you want to stick with your Book+BookTitle, this would be a Map<BookTitle, Set<Book>> that maps a title to the concrete available copies.)

Besides the available books this class also keeps a list of all the open Rent's (List). That way we have a central place to look up which books should be returned soon (instead of awkwardly looping over all the users in the system to find these), and we can also use this to find which users have a copy of a book if there's none available. Could be useful to tell a Customer: come back tomorow, John Smith will have brought back his copy by then.

The Search class (which has a rather bad name) becomes obsolete if we add it's public List<Book> search(String phrase) { to our new Library class. Alternatively we could rename the Search class to something more meaningful like BookFinder and have the Library class use this to search for a book in it's list. That way the library doesn't get a new responsibility (which, according to SOLID design principles is better). (Or even better, have the class responsible for handling the user's search request first get the list of books in the library, and then use the new BookFinder class to search for the matching books. So Library doesn't even need to know there is such a thing as "searching for a book".

Now the Customer class no longer needs to keep track of the books that this customer currently has. If you return a book, the librarian usually scans it to find out which book you're returning (with correct ID in the system etc...). This should now be handled in the Library class with a method like returnBook(Customer customer, Book book) that will delete the Rent with that combination of user and book and increases the book count in it's map of available books. Alternatively you could also keep this list in Customer. And when returning a book, the logic is that you take it out of customer and add it back in the library. This makes it easier to find out "what books does this customer currently have". (So again, the choice here depends on what your program is supposed to do).


as stated in the YAGNI part. You probably don't need the Admin or User classes. Start out with just Customer with the required fields. And later on see if you want to combine both Customer and User into a general Person. But then also look at where you want to replace the subclass (Customer) to the super class (Person). I doubt this will happen in many places since inside the program you'll always handle Customer's that rent books.

This also affects your UserRegistration class. Actually this class itself is implemented really weird. Here's what I would expect this class to look like:

public class CustomerRegistration {     private Set<Customer> customers;      public UserRegistration() {         //load up the current existing users.         //from a file or database         //or hardcoded here for testing until actual loading is implemented     }      public Set<Customer> getAllCustomers(){         return customers;     }      public boolean registerCustomer(String name, String email) {         if(!isValidCustomerInfo(name, email){             return false;         }         Customer customer = new Customer(name, email);         customers.add(customer);         //save customer to file/database           return true;     }      private boolean isValidCustomerInfo(String name, String email) {         //check customer info here     } } 

Most noticable is that it doesn't have fields for the name/email/password. The exact implementation might change (like I removed the password) depending on what you want to do with a Customer.

My initial thought is to not let them use the system themselves. Just have a librarian input handle the returning/checking out of the books.


Hope my explanation helps you decide what your program should and shouldn't do. It's hard to give advice about a program without having it's intention you know ;)

 
 

Relacionados problema

6  Objetos de Java para un programa de sniffer de red  ( Java objects for a network sniffer program ) 
Estoy trabajando en un programa de sniffer de red, cuya estructura utiliza 3 clases principales: clase de marco - uno por marco monitoreado, sostiene la re...

1  Pasando un objeto a la vista en CodeIgner  ( Passing an object to the view in codeigniter ) 
Estoy tratando de usar un objeto y persistirlo en la base de datos. He creado una clase en la carpeta de la biblioteca. <?php if (!defined('BASEPATH'))...

8  Envoltura Libusb Library en C ++  ( Wrapping libusb library in c ) 
Quiero usar la biblioteca de Libusb en mi aplicación C ++. He creado clases que envuelven las funciones de Libusb. Puede ver que la API de Libusb se divide en...

0  Creación de múltiples objetos del extracto de SQL Server  ( Creating multiple objects from sql server extract ) 
He creado una solución prototipo simplificada como una especie de prueba de concepto antes de comenzar un programa más grande. Aquí están los datos de prueb...

8  Árbol fractal orientado a objetos  ( Object oriented fractal tree ) 
Hice un árbol fractal orientado a objetos en JavaScript utilizando la biblioteca P5, consta de tres archivos: fraternal tree.js sucursal.js flower.js ...

1  Clase de juego, escrito usando enums  ( Playing card class written using enums ) 
Escribí una clase de tarjeta A Mientras vuelvas a esta publicación aquí: Pregunta previa Sé que ha pasado mucho tiempo, pero recientemente regresé al proyec...

5  Solicitud de Tkinter para administrar las tareas escolares  ( Tkinter application to manage school tasks ) 
Soy un principiante en la programación de la OOP y me pregunto cuál es la mejor manera de poner todas las ventanas y funciones de una aplicación de ventana en...

10  "Stardust" Simulador 2D Gravity - Seguimiento 1: Los planetas  ( Stardust 2d gravity simulator follow up 1 the planets ) 
Este es un seguimiento para el juego de gravedad del simulador 2D pregunta. Desde entonces, he desarrollado mis habilidades de JavaScript, y ahora esto...

5  ¿Podría mejorarse este sistema de profundidad para un juego?  ( Could this depth system for a game be improved ) 
Todavía soy nuevo en C ++ y no tengo una gran idea de mi codificación, así que estaría muy agradecido a cualquiera y todos los que le otorgan consejos. Ade...

3  General Pathfinder en Python  ( General pathfinder in python ) 
Recientemente trabajé en un proyecto donde tuve la siguiente configuración: $_{456}$6 Ninguno del Código es relevante, no tendrá que poder ejecutar nada...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos