I have the finance application where we can have different types of transactions, like balance enquiry, funds transfer, and pin change etc. Now the Transaction
is a base class, and there are specific child classes implementing it as per above use cases.
Class Transaction
{
int txnId;
String sourceAccountNumber;
}
Class PinChange extends Transaction
{
int pin;
}
Class FundsTransfer extends Transaction
{
int amount;
String destAccountNumber;
}
Now I have a BankService
object which takes transaction and executes it.
Class BankService
{
executeTransaction(Transaction transaction)
}
I want to know:
How will
BankService
knows what is the type of transaction? Do I need to wrap it up in a new Enum likeTransactionType
and put it in transaction base class?When the
BankService
comes to know type of transaction, how will it access specific class details? I think it needs to type cast transaction to specific child class, which seems bad to me. Thoughts?
3 Answers 3
If you have execute()
method overridden in each child class, you can just call transaction.execute()
inside executeTransaction()
, so BankService
does not have to know the transaction type.
However, I don't see the necessity of using inheritance here --- you can just have fundsTransfer
, pinChange
,... methods inside BankService
class and implement them separately:
Class BankService
{
executeFundsTransfer(BankAccount source, BankAccount target, int amount);
executePinChange(BankAccount source, int pin);
}
Update:
You can have TransactionType
enum class and make it a member field in Transaction
: DEPOSIT
, and WITHDRAW
, but I don't think pin update or other methods are transactions, and they don't have a common (single) responsibility in executeTransAction
method, so yes enum work but I don't see a strong reason that you have to use that.
-
adding execute in transaction is not the ways i want to go.as it is just metadata and it does not know how to execute.Only bank knows how to execute it.So i would rather add separate api for each transactionrahul sharma– rahul sharma2020年12月31日 14:45:28 +00:00Commented Dec 31, 2020 at 14:45
-
@rahulsharma yeah that's what I was suggesting in the 2nd paragraphlennon310– lennon3102020年12月31日 15:46:45 +00:00Commented Dec 31, 2020 at 15:46
-
is it bad to add ENUM named transactionType in transaction and then can read that enum and decide what to do?rahul sharma– rahul sharma2020年12月31日 16:30:36 +00:00Commented Dec 31, 2020 at 16:30
-
@rahulsharma updated the answerlennon310– lennon3102020年12月31日 16:42:39 +00:00Commented Dec 31, 2020 at 16:42
You don't want BankService
to know what the true type of the transaction
parameter is. It can find out by doing instanceof
, but that is a red flag indicating OOP problems.
However, the transaction
parameter variable knows what kind of object was passed in.
So, the idea is to tell the transaction
object to do something for you, instead of inspecting it to see what to do.
The principle is called "Tell, don't Ask."
We don't have to use this approach, but using Ask instead of Tell is "contrary" to OOP.
-
so you are also suggesting to have separate api for each transaction,right?or what if I add an Enum with TransactionType in transaction object, and then the bank execute can see if what type of transaction is actually passed?Is it a suggested way?rahul sharma– rahul sharma2020年12月31日 16:31:17 +00:00Commented Dec 31, 2020 at 16:31
-
Ok, you want to use Ask not Tell. That's contrary to OOP but there's no OOP police or jail, so you can do that if you like. If you go that route, don't duplicate the type of transaction in an enum (assuming it is already explicit in hierarchy), just use
instanceof
.Erik Eidt– Erik Eidt2020年12月31日 16:36:00 +00:00Commented Dec 31, 2020 at 16:36 -
this is first time i heard of this principle,tell not ask,I just read about it.Now i am confused that if I use ENUM,will i be violating it? it says we should not get state from object and then act on it.But to handle this thing we move everything to object, so it has only tell and not ask.Now let us say i tried to use ENUM and if it violate tell dont ask, then i should be able to handle this by moving asking logic to object class.but here for me it is not possible to move that logic to transaction class.I am not able to convince myself that using ENUM is actually a violation of tell dont ask?rahul sharma– rahul sharma2020年12月31日 17:59:34 +00:00Commented Dec 31, 2020 at 17:59
-
or may be i will not keep ENUM in trasaction object. I can keep transaction object as it is and then pass two parameters to execute(Transaction transaction, TransactionType type). In that way i will not be reading object state but something else sent along object.Just trying to know pro and con of different approaches?rahul sharma– rahul sharma2020年12月31日 18:01:49 +00:00Commented Dec 31, 2020 at 18:01
There have been some good answers, but I would like to add to them.
- Transaction is a terrible choice of base class name as it already has meaning, especially in financial and database-centric applications.
- Model the real world. When I front up to an ATM I know that I want to deposit, withdraw or transfer between accounts. I don't think along the lines "let's do a transaction - what type?". So rather than inheritance the service you call should reflect reallity and have separate entry points for each operation. This will aid maintenance in the future. But full marks for asking. Hopefully the community can help improve your design.
-
2It does not strike me as odd to have a transaction class in a banking application, neither do I think the name is bad. Because performing transactions is core business to a bank. I do wonder why pin change or balance inquiry are considered transactions though. The point of a transaction is to make sure multiple steps are performed as one and this does not apply here. Anyway, the customer may not think in terms of transactions but what ultimately happens are transactions and this is the core logic. There will be a UI that caters to the user's model but that is not what we are talking about.Martin Maat– Martin Maat2021年01月01日 08:24:37 +00:00Commented Jan 1, 2021 at 8:24
Explore related questions
See similar questions with these tags.
executeTransaction
has a single responsibility?