Every time I google instanceof and casting I will always see answers saying to avoid it and use X pattern.
I have an example where I can't see any pattern I think I could use.
We have 2 classes: Order and Payment (CashPayment and CardPayment).
CashPayment has 1 property called amount and and an implemented method pay.
CardPayment has 1 property called cardNumber and an implemented pay that calls 3rd party API.
Now say you would like to compose a view about an Order, how would someone avoid using instanceof or casting here to show the payment details?
With instanceof I can do this:
order = new Order(...);
order.checkout(aPayment);
Payment Details (Cash):
Type: (instanceof CashPayment ? "Cash") or order.payment().type();
Amount: ((CashPayment) order.payment()).amount();
Payment Details (Card):
Type: (instanceof CardPayment ? "Card") or order.payment().type();
Card Number: ((CardPayment) order.payment()).cardNumber();
Question: can we really avoid instanceof and casting? If yes, how can we achieve this the "OO-way"? If no, I assume this is one of the valid cases?
IMO, we can avoid instanceof/casting and favor use of overridden methods however if you want to know about a concrete object it can't be avoided.
Edit:
I am trying to write my Domain Models which means it is agnostic of infrastructure and application specific stuff.
Imagine we would need to save the Order thru OrderRepository and the Payment has their own tables. Wouldn't it be ugly if it was like:
class OrderRepository {
public function save(Order order) {
// Insert into order query here...
// Insert into orderItems query here...
// Insert payment into its table
queryBuilder
.table(order.payment().tableName())
.insert([
order.payment().columnName() => order.payment().value()
]);
}
}
If you absolutely want to segregate the operation from the object itself (e.g. to maintain separation of concerns), but the operation is strongly coupled to subclass details then you only have two choices.
You either need to rethink the model and find an homogeneous abstraction, which could be any approach that allows you to treat the various types the same way.
e.g.
Payment Details:
Type: {{payment.type}}
{{for attr in payment.attributes}}
{{attr.name}}: {{attr.value}}
{{/}}
or you need to perform some kind of type matching, whether you are using the visitor pattern, pattern matching, instanceof, etc.
e.g. with the Visitor Pattern
interface IPaymentVisitor {
public void visit(CashPayment payment);
public void visit(CardPayment payment);
}
class PaymentRenderer implements IPaymentVisitor ...
class CashPayment extends Payment {
...
public void visit(IPaymentVisitor visitor) {
visitor.visit(this);
}
}
var renderer = new PaymentRenderer(outputStream);
payment.accept(renderer);
The obvious object-oriented solution is to add a display() method to the Payment.
In general instanceof/casting is frowned upon, because it usually indicates a less then optimal design. The only time where it is allowed is when the type-system is not powerful enough to express something. I encountered a few situations in Java where there is no better solution (mostly because there are no read-only collections in Java, therefore the generic parameter is invariant), none in Scala or Haskell yet.
You could go with composition over inheritance.
Perhaps something along the lines of:
public class Payment
{
private CardPaymentDetail _cardPaymentDetail;
public PaymentType Type { get; private set; }
public decimal Amount { get; }
private Payment(decimal amount)
{
// > 0 guard
Amount = amount;
}
private Payment(decimal amount, CardPaymentDetail cardPayment)
: this(amout)
{
// null guard
CardPayment = cardPayment;
}
public CardPaymentDetail CardPayment
{
get
{
if (Type != PaymentType.Card)
{
throw new InvalidOperationException("This is not a card payment.");
}
return _cardPaymentDetail;
}
}
}
IMHO persistence may also be easier. Along the same lines I have also used what equates to an Unknown payment type as the default and then have a method to specify the type: AsCard(CardPaymentDetail cardPayment) { }.
Related
Let's say I have a class Order. An Order can be finished by calling Order.finish() method. Internally, when an Order is finished, a finishing date is set:
Order.java
public void finish() {
finishingDate = new Date();
}
In the application's business logic, there is no need to expose an Order's finishingDate, so it is a private field without a getter.
Imagine that after finishing an Order, I want to update it in a database. For instance, I could have a DAO with an update method:
OrderDao.java
public void update(Order order) {
//UPDATE FROM ORDERS SET ...
}
In that method, I need the internal state of the Order, in order to update the table fields. But I said before that there is no need in my business logic to expose Order's finishingDate field.
If I add a Order.getFinishingDate() method:
I'm changing the contract of Order class without adding business value, ubt for "technical" reasons (an UPDATE in a database)
I'm violating the principle of encapsulation of object oriented programming, since I'm exposing internal state.
How do you solve this? Do you consider adding getters (like "entity" classes in ORM do) is acceptable?
I have seen a different approach where class itself (implementation) knows even how to persist itself. Something like this (very naive example, it's just for the question):
public interface Order {
void finish();
boolean isFinished();
}
public class DbOrder implements Order {
private final int id;
private final Database db;
//ctor. An implementation of Database is injected
#Override
public void finish() {
db.update("ORDERS", "FINISHING_DATE", new Date(), "ID=" + id);
}
#Override
public boolean isFinished() {
Date finishingDate = db.select("ORDERS", "FINISHING_DATE", "ID=" + id);
return finishingDate != null;
}
}
public interface Database {
void update(String table, String columnName, Object newValue, String whereClause);
void select(String table, String columnName, String whereClause);
}
Apart from the performance issues (actually, it can be cached or something), I like this approach but it forces us to mock many things when testing, since all the logic is not "in-memory". I mean, the required data to "execute" the logic under test is not just a field in memory, but it's provided by an external component: in this case, the Database.
This is an excellent observation in my opinion. No, I don't consider adding any methods just for technical reasons acceptable, especially getters. I must admit however, that the majority of people I've worked with would just add the getters and would not think about it in detail as you do.
Ok, so how do we solve the problem of persisting something we can't get access to? Well, just ask the object to persist itself.
You can have a persist() (or whatever) method on the object itself. This is ok, since it is part of the business. If it is not, think about what is. Is it sendToBackend() maybe? This does not mean you have to put the details of persistence into the object!
The method itself can be as removed from actual persistence as you like. You can give it interfaces as parameters, or it can return some other object that can be used further down the line.
See these other answers about the same problems for presentation:
Returning a Data Structure to Display information
Encapsulation and Getters
A Model object which has some private internal state. A component of this state is exposed to the clients. But one of the clients wants a different component of the internal state to be exposed. How should this be dealt with?An example
public GarageModel {
private Vehicle car;
private Vehicle truck;
public Vehicle getMostInterestingVehicle() {
//exposes car as the most interesting vehicle but
//one of the client wants this to return a truck
return car;
}
}
It is hard to say given your sample, you could apply a strategy pattern on your GarageModel class for each different client and override that single method to cater to each of their needs. This only works if you can provide different garage models to your clients though.
Polymorphism is always the answer as a teacher of mine used to say
An example would be
public TruckGarageModel: GarageModel {
public override Vehicle getMostInterestingVehicle(){
return truck;
}
}
public CarGarageModel: GarageModel {
public override Vehicle getMostInterestingVehicle(){
return car;
}
}
Then you would pass the appropriate decorated version of your GarageModel to each different client
You could provide method with parameters which will define criteria by which your client sees most interesting vehicle.
public Vehicle getMostInterestingVehicleByCriteria(VehicleCriteria vehicleCriteria){
// logic which selects correct vehicle in simple way it will be just
if(vehicleCriteria.getMostInterestingVehicleType().equals(VehicleType.TRUCK){
//do your logic
}
// In case of multiple objects you should refactor it with simple inheritance/polymorphism or maybe use some structural pattern
}
public class VehicleCriteria{
VehicleType mostInterestingVehicle; // enum with desired vehicle type
public VehicleCriteria(VehicleType mostInterestingVehicle){
this.mostInterestingVehicle = mostInterestingVehicle;
}
}
If the client knows what type it wants, then let the client say so with a generic argument (C# assumed):
public T getMostInterestingVehicle<T>() where T : Vehicle { }
You can then use a dictionary of 'things' (factories maybe?) that will get a vehicle, keyed by the type they return. This could be a static collection created on construction or resolved by IoC:
private Dictionary<T, Vehicle> _things;
You can then use this to do the work:
public T getMostInterestingVehicle<T>() where T : Vehicle
{
FactoryThing thing;
if (_things.TryGetValue(T, out thing))
{
return thing.GetVehicle();
}
}
Apologies if it's not C# you're working with and if the syntax/usage is incorrect, but I think you'll get my point...
You might have to consider quite a few things before making a decision about the implementation, some questions are these-
Do you expect newer implementations of Vehicle to be added later?: If yes, you might have to provide a factory that could register newer types without you making changes in the factory again and again. This provides an example. That way you avoid many if-else as well.
Do you want to decide what Vehicle to return at runtime?: Then Strategy Pattern helps as pointed in other answers.
Hope this helps a little bit.
As input I have a list of Books. As output I expect a SimilarBookCollection.
A SimilarBookCollection has an author, publishYear and list of Books. The SimilarBookCollection can't be created if the author of the books is different or if the publishYear is different.
The solution so far in PHP:
client.php
----
$arrBook = array(...); // array of books
$objValidator = new SimilarBookCollectionValidator($arrBook);
if ($objValidator->IsValid()) {
$objSimilarBookCollection = new SimilarBookCollection($arrBook);
echo $objSimilarBookCollection->GetAuthor();
}
else {
echo 'Invalid input';
}
SimilarBookCollection.php
---
class SimilarBookCollection() {
public function SimilarBookCollection(array $arrBook) {
$objValidator = new SimilarBookCollectionValidator($arrBook);
if ($objValidator->IsValid()) {
throw new Exception('Invalid books to create collection');
}
$this->author = $arrBook[0]->GetAuthor();
$this->publishYear = $arrBook[0]->GetPublishYear();
$this->books = $arrBook;
}
public function GetAuthor() {
return $this->author;
}
public function GetPublishYear() {
return $this->publishYear;
}
public function GetBooks() {
return $this->books;
}
}
SimilarBookCollectionValidator.php
---
class SimilarBookCollectionValidator() {
public function IsValid() {
$this->ValidateAtLeastOneBook();
$this->ValidateSameAuthor();
$this->ValidateSameYear();
return $this->blnValid;
}
... //actual validation routines
}
The goal is to have a "special" collection with only books that have the same author and publishYear. The idea is to easily access the repeating information like author or year from the object.
How would you name the SimilarBookCollection? The current name is to
generic. Using a name like SameYearAuthorBookCollection looks a bit
long and strange(if more conditions will be added then name will increase)
Would you use a Validator in SimilarBookCollection constructor using a
defensive programming style?
Would you change the design of the code? If yes how?
It all depends ;)
So if I were to aim for a generic adaptable solution I would do the following:
Validator in constructor
On one hand you are validating twice; that is informative in case of a broken precondition/contract (not giving a valid list), but is double the code to run - for what purpose exactly?
If you want to use this in a system depends on its size, how critical it is, product phase, and likely more criterias.
But then it also is controller logic fitted into a model meaning you are spreading your code around.
I would not put it in the constructor.
Name / Design
I would say keep the BookCollection generic as it is, and have any validation strictly in the controller space, instead of bloating the collection which essentially seems to be an array with the extra field of author.
If you want to differentiate between different collection types use either (multiple) inheritance or some sort of additional field "collectionType"; the former if you expect many derivatives or varying functionality to come (also keeps the logic where different nicely separated).
You could also consider your collection as a set on which you perform queries and for convenience's sake you could maintain some sort of meta data like $AuthorCount = N, $publicationDates = array(...) from which you can quickly derive the collection's nature. This approach would also keep your validator-code minimal (or non-existent), as it'd be implicitly in the collection and you could just do the validation in the controller keeping the effective logic behind it clearly visible.
That would also make it more comfortable for you in the future. But the question really is what you want and need it for, and what changes you expect, because you are supposed to fit your design to your requirements and likely changes.
For your very particular problem the constraints as I understand are as follows:
There is only one collection type class in the system at any given
point in time.
The class's items have several attributes, and for a particular, possibly changing subset of these (called identical attributes), the collection only accepts item lists where the chosen attributes of all items are identical.
The class provides getters for all identical attributes
The class must not be usable in any other way than the intended way.
If not for point 1 I would use a generic base class that is either parametrized (ie you tell it upon instantiation which is the set of identical attributes) or uses multiple inheritance (or in php traits) to compose arbitrary combinations with the needed interfaces. Children might rely on the base class but use a predefined subset of the identical attributes.
The parametrized variant might look something as follows:
class BookCollection {
public function __construct($book_list, $identical_fields=array())
{
if (empty($book_list))
{
throw new EmptyCollectionException("Empty book list");
}
$default = $book_list[0];
$this->ia = array();
foreach($identical_fields as $f)
{
$this->ia[$f] = $default->$f;
}
foreach($book_list as $book)
{
foreach($identical_fields as $f)
{
if ($this->ia[$f] !== $book->$f)
{
throw new NotIdenticalFieldException("Field $f is not identical for all");
}
}
}
$this->book_list = $book_list;
}
public function getIdentical($key)
{
$this->ia[$key];
}
}
final class BC_by_Author extends BookCollection{
public function __construct($book_list)
{
parent::__construct($book_list,array('author'));
}
public function getAuthor(){ $this->ia['author']; }
}
or fooling around with abstract and final types (not sure if it's valid like this)
abstract class BookCollection{
public final function __construct($book_list){...}
abstract public function getIdenticalAttributes();
}
final class BC_by_Author {
public function getIdenticalAttributes(){ return array('author'); }
public function getAuthor(){ return $this->ia['author']; }
}
If you rely on getters that do not necessarily match the field names I would go for multiple inheritance/traits.
The naming then would be something like BC_Field1Field2Field3.
Alternatively or additionally, you could also use exactly the same classname but develop your solutions in different namespaces, which would mean you wouldn't have to change your code when you change the namespace, plus you can keep it short in the controllers.
But because there will only ever be one class, I would name it BookCollection and not unnecessarily discuss it any further.
Because of constraint 4, the white box constraint, the given book list must be validated by the class itself, ie in the constructor.
Let's say you need to build an application that manages cheques. Each cheque contains data about the amount of money, the date, the payee and an additional payment date which may or may not be present. Additionally, each cheque must be related to a current account which belongs to a certain bank.
Now, our application should allow cheques printing under these conditions:
Each bank managed by the app has a different cheque layout (i.e. each field has a different x,y position).
The cheque layout changes slightly if the payment date is present, even with the same related bank object. But, from bank to bank these changes may not be the same (e.g. bank A may vary position for the date field, while bank B changes position for the payee field)
With these restrictions in place, it's difficult to come up with a simple inheritance schema as there is no consistent behavior to factor out accross the different types of cheques there are. One possible solution would be to avoid inheritance and create a class for every cheque - bank combination:
class ChequeNoPaymentDateForBankA
class ChequeWithPaymentDateForBankA
class ChequeNoPaymentDateForBankB
class ChequeWithPaymentDateForBankB, etc.
Each of these classes implement the print() method which takes the fields positions from a Bank object and builds up the cheque layout. So far so good, but this approach leaves me with a strange feeling as there is no room for code reuse. I wonder if I'm misinterpreting the problem and perhaps there is a better way. As this is not a new problem domain at all, I'm sure this is a reinvent-the-wheel effort. Any insights will be kindly appreciated.
Usually in these situations I move from inheritance to delegation. That is, instead of putting the common code in a superclass (which, as you say, is problematic becuase there are two dimensions), I put the common in a field (one field per dimension) and delegate to that field.
Assuming you're speaking about Java:
public interface Bank {
public void print();
}
public class BankA implements Bank {
public void print() { ... }
}
public class BankB implements Bank {
public void print() { ... }
}
public interface PaymentSchedule {
public void print();
}
public class WithPaymentDate implements PaymentSchedule {
public void print() { ... }
}
public class NoPaymentDate implements PaymentSchedule {
public void print() { ... }
}
public class Cheque {
private final Bank bank;
private final PaymentSchedule schedule;
public Cheque(Bank b, PaymentSchedule s) {
bank = b;
schedule = s;
}
public void print() {
bank.print();
schedule.print();
}
}
That's the general structure of the solution.
Depending on the exact details of your print() algorithm you may need to pass some more data into the print methods and/or to pass this data into the constructors of the classes (of the Bank or PaymentSchedule subclasses) and store it in fields.
I would start by separating the domain model (cheques, banks, etc) from the view (the way the cheques are printed). This is the basic idea behind the MVC pattern and one of its aims is to allow the same domain model to be displayed in different ways (which seems to be your case). So, I would first create the domain classes, something like:
class Cheque
{
protected $bank;
protected $money;
...
}
class Bank {...}
Note that these classes are the "M" of the MVC triad and implement the logic of your domain model, not the behavior related to the rendering process. The next step would be to implement the View classes used to render a cheque. Which approach to take heavily depends on how complex your rendering is, but I would start by having a ChequeView class that renders the common parts and that delegates to other sub-view the specific parts that can change (in this case the date):
abstract class ChequeView
{
protected $cheque;
protected $dateView;
public function __construct($cheque)
{
$this->cheque = $cheque;
$this->dateView = //Whatever process you use to decide if the payment date is shown or not
}
public function render()
{
$this->coreRender();
$this->dateView->render();
}
abstract protected function coreRender();
}
class BankACheckView extends ChequeView
{
protected function coreRender() {...}
}
class BankBCheckView extends ChequeView
{
protected function coreRender() {...}
}
abstract class DateView
{
abstract function render()
}
class ShowDateView extends DateView
{
function render() {...}
}
class NullDateView extends DateView
{
function render() {...}
}
And, if there is code to reuse across subclasses, you can of course factor them in ChequeView and make coreRender() call them.
In case your rendering turns to be too complex, this design may not scale. In that case I would go for splitting your view in meaningful subparts (e.g. HeaderView, AmountView, etc) so that rendering a cheque becomes basically rendering its different sub-parts. In this case the ChequeView may end basically working as a Composite. Finally, if you reach this case and setting up the ChequeView turns out to be a complex task you may want to use a Builder.
Edit based on the OP comments
The Builder is mostly used when the instantiation of the final object is a complex process (e.g. there are many things to sync between the sub-parts in order to get a consistent whole). There is generally one builder class and different clients, that send messages (potentially in different orders and with different arguments) to create a variety of final objects. So, while not prohibited, it is not usual to have one builder per type of object that you want to build.
If you are looking for a class that represents the creation of a particular instance you may want to check the Factory family of patterns (maybe the Abstract Factory resembles closely to what you had in mind).
HTH
OOP interfaces.
In my own experience I find interfaces very useful when it comes to design and implement multiple inter-operating modules with multiple developers. For example, if there are two developers, one working on backend and other on frontend (UI) then they can start working in parallel once they have interfaces finalized. Thus, if everyone follows the defined contract then the integration later becomes painless. And thats what interfaces precisely do - define the contract!
Basically it avoids this situation :
Interfaces are very useful when you need a class to operate on generic methods implemented by subclasses.
public class Person
{
public void Eat(IFruit fruit)
{
Console.WriteLine("The {0} is delicious!",fruit.Name);
}
}
public interface IFruit
{
string Name { get; }
}
public class Apple : IFruit
{
public string Name
{
get { return "Apple"; }
}
}
public class Strawberry : IFruit
{
public string Name
{
get { return "Strawberry"; }
}
}
Interfaces are very useful, in case of multiple inheritance.
An Interface totally abstracts away the implementation knowledge from the client.
It allows us to change their behavior dynamically. This means how it will act depends on dynamic specialization (or substitution).
It prevents the client from being broken if the developer made some changes
to implementation or added new specialization/implementation.
It gives an open way to extend an implementation.
Programming language (C#, java )
These languages do not support multiple inheritance from classes, however, they do support multiple inheritance from interfaces; this is yet another advantage of an interface.
Basically Interfaces allow a Program to change the Implementation without having to tell all clients that they now need a "Bar" Object instead of a "Foo" Object. It tells the users of this class what it does, not what it is.
Example:
A Method you wrote wants to loop through the values given to it. Now there are several things you can iterate over, like Lists, Arrays and Collections.
Without Interfaces you would have to write:
public class Foo<T>
{
public void DoSomething(T items[])
{
}
public void DoSomething(List<T> items)
{
}
public void DoSomething(SomeCollectionType<T> items)
{
}
}
And for every new iteratable type you'd have to add another method or the user of your class would have to cast his data. For example with this solution if he has a Collection of FooCollectionType he has to cast it to an Array, List or SomeOtherCollectionType.
With interfaces you only need:
public class Foo<T>
{
public void DoSomething(IEnumerable<T> items)
{
}
}
This means your class only has to know that, whatever the user passes to it can be iterated over. If the user changes his SomeCollectionType to AnotherCollectionType he neither has to cast nor change your class.
Take note that abstract base classes allow for the same sort of abstraction but have some slight differences in usage.