Reputation: 858
Apologies if this has been answered elsewhere, my search didn't yield quite the answer I was looking for.
Hypothetically speaking, let us say I am building an application for a bookshop.
I have a class that handles all my database transactions. I also have a 'Book' class which extends the Database class, calling the Database constructor from it's own constructor, removing the need to instantiate the Database class first:
class Book extends Database {
__construct($book_id){
parent::__construct();
$this->databaseGet("SELECT * FROM..."); // method in Database class
etc...
}
}
I can pass a reference id to the 'Book' class constructor and create an object containing information pulled from the database about that book along with several methods relevant to a given book.
But I also want to list all the books in the database. My question is, where do I put this method and other methods that simply don't have a context such as 'Book'?
I could create a single "GetStuff" or 'Bookshop' class that extends the Database class, which would contain all these single-use methods. But that requires it to be loaded all the time as these orphan methods would be used all over the program.
I could create lots of classes that house a single method but that would require instantiating the class to an object in order to call the method, seems like overkill.
They aren't general utilities, they have a place in the business model. Just where should I put these orphan methods?
Upvotes: 1
Views: 177
Reputation: 3454
Seems your design is seriously flawed. You have to separate three concerns:
A simplified example:
// Model Object
class Book {
title;
author:
isbn;
constructor(title, author, isbn) {// ...}
// other methods ...
}
// DAL class
class BookDataMapper {
// constructors ...
save(Book book) {}
Book getById(id) {
String query = get from book table where book_id = id;
execute query;
parse the result;
Book book = new Book(parsed result);
return book;
}
Book getByTitle(title) {}
...
getAll(){} // returns all books
}
//Service class
class BookService {
BookDataMapper bookMapper;
buyBook(title) {
// check user account
// check if book is available
Book book = bookMapper.getBytitle(title);
if book available
charge customer
send the book to ship etc.
}
}
Upvotes: 0
Reputation: 20320
Book is a book, Books is collection of books. Database is one thing you could use to persist a lot of books so you don't have to type them all in again.
It could be an xml file, an excel spreadsheet, even a webservice.
So write Book and Books, then write something like
BookDatabase extends database with methods like Books GetBooks(); and void SaveBook(Book argBook); The real trick is to make Book and Books work no matter what / how they are stored.
There's lot more to learn around that, but first thing to do is start again and not make your data objects dependant on a particular "database".
Upvotes: 2
Reputation: 2173
If I understand it, you're asking where should code go that relates to a specific type but doesn't implement a behaviour of the type itself. There is no single answer. According to the overall design of the system, it could be part of the type - Smalltalk classes have 'class fields' and 'instance fields', and there is nothing wrong with that - or it could end up anywhere it makes sense. If it relates to something external to the type itself - that is, it's not merely a matter of not being the behaviour of an instance, but a matter of being an interaction with something extraneous - it may make sense to put it outside. For instance, you may have Book
, BookDatabase
, BookForm
, BookWebService
, etc. There's no harm in some of those classes having few members, you never know when you'll want to add some more.
Upvotes: 2