2020-07-19 16:19:01 +05:30
|
|
|
---
|
2020-07-27 00:39:53 +05:30
|
|
|
layout: pattern
|
2020-08-09 00:51:28 +05:30
|
|
|
title: Transaction Script
|
2020-07-27 00:39:53 +05:30
|
|
|
folder: transaction-script
|
|
|
|
permalink: /patterns/transaction-script/
|
2020-08-09 00:51:36 +05:30
|
|
|
categories: Behavioral
|
2021-05-19 10:49:05 -06:00
|
|
|
language: en
|
2020-07-27 00:39:53 +05:30
|
|
|
tags:
|
|
|
|
- Data access
|
|
|
|
---
|
|
|
|
|
|
|
|
## Intent
|
2020-08-11 17:17:25 +03:00
|
|
|
|
|
|
|
Transaction Script organizes business logic by procedures where each procedure handles a single
|
|
|
|
request from the presentation.
|
2020-07-19 16:19:01 +05:30
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
## Explanation
|
2020-08-11 17:17:25 +03:00
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
Real world example
|
2020-08-11 17:25:38 +03:00
|
|
|
|
2020-08-11 17:17:25 +03:00
|
|
|
> You need to create a hotel room booking system. Since the requirements are quite simple we intend
|
|
|
|
> to use the Transaction Script pattern here.
|
2020-07-19 16:19:01 +05:30
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
In plain words
|
2020-08-11 17:25:38 +03:00
|
|
|
|
2020-08-10 00:25:43 +05:30
|
|
|
> Transaction Script organizes business logic into transactions that the system needs to carry out.
|
2020-07-19 16:19:01 +05:30
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
Programmatic example
|
2020-07-19 16:19:01 +05:30
|
|
|
|
2020-08-10 00:24:44 +05:30
|
|
|
The `Hotel` class takes care of booking and cancelling room reservations.
|
2020-08-08 15:49:14 +05:30
|
|
|
|
|
|
|
```java
|
2021-03-13 13:19:21 +01:00
|
|
|
@Slf4j
|
2020-08-08 15:49:14 +05:30
|
|
|
public class Hotel {
|
|
|
|
|
2020-08-11 17:17:25 +03:00
|
|
|
private final HotelDaoImpl hotelDao;
|
2020-08-08 15:49:14 +05:30
|
|
|
|
|
|
|
public Hotel(HotelDaoImpl hotelDao) {
|
|
|
|
this.hotelDao = hotelDao;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void bookRoom(int roomNumber) throws Exception {
|
|
|
|
|
|
|
|
Optional<Room> room = hotelDao.getById(roomNumber);
|
|
|
|
|
|
|
|
if (room.isEmpty()) {
|
|
|
|
throw new Exception("Room number: " + roomNumber + " does not exist");
|
|
|
|
} else {
|
|
|
|
if (room.get().isBooked()) {
|
|
|
|
throw new Exception("Room already booked!");
|
|
|
|
} else {
|
|
|
|
Room updateRoomBooking = room.get();
|
|
|
|
updateRoomBooking.setBooked(true);
|
|
|
|
hotelDao.update(updateRoomBooking);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelRoomBooking(int roomNumber) throws Exception {
|
|
|
|
|
|
|
|
Optional<Room> room = hotelDao.getById(roomNumber);
|
|
|
|
|
|
|
|
if (room.isEmpty()) {
|
|
|
|
throw new Exception("Room number: " + roomNumber + " does not exist");
|
|
|
|
} else {
|
|
|
|
if (room.get().isBooked()) {
|
|
|
|
Room updateRoomBooking = room.get();
|
|
|
|
updateRoomBooking.setBooked(false);
|
|
|
|
int refundAmount = updateRoomBooking.getPrice();
|
|
|
|
hotelDao.update(updateRoomBooking);
|
|
|
|
|
|
|
|
LOGGER.info("Booking cancelled for room number: " + roomNumber);
|
|
|
|
LOGGER.info(refundAmount + " is refunded");
|
|
|
|
} else {
|
|
|
|
throw new Exception("No booking for the room exists");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-08-11 17:17:25 +03:00
|
|
|
The `Hotel` class has two methods, one for booking and cancelling a room respectively. Each one of
|
|
|
|
them handles a single transaction in the system, making `Hotel` implement the Transaction Script
|
|
|
|
pattern.
|
2020-08-08 15:49:14 +05:30
|
|
|
|
2020-08-11 17:17:25 +03:00
|
|
|
The `bookRoom` method consolidates all the needed steps like checking if the room is already booked
|
|
|
|
or not, if not booked then books the room and updates the database by using the DAO.
|
2020-08-08 15:49:14 +05:30
|
|
|
|
2020-08-11 17:17:25 +03:00
|
|
|
The `cancelRoom` method consolidates steps like checking if the room is booked or not,
|
2020-08-08 15:49:14 +05:30
|
|
|
if booked then calculates the refund amount and updates the database using the DAO.
|
2020-07-19 16:19:01 +05:30
|
|
|
|
|
|
|
## Class diagram
|
2020-08-11 17:17:25 +03:00
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|

|
2020-07-19 16:19:01 +05:30
|
|
|
|
|
|
|
## Applicability
|
2020-08-11 17:17:25 +03:00
|
|
|
|
|
|
|
Use the Transaction Script pattern when the application has only a small amount of logic and that
|
|
|
|
logic won't be extended in the future.
|
2020-07-19 16:19:01 +05:30
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
## Consequences
|
2020-08-11 17:17:25 +03:00
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
* As the business logic gets more complicated,
|
|
|
|
it gets progressively harder to keep the transaction script
|
|
|
|
in a well-designed state.
|
|
|
|
* Code duplication between transaction scripts can occur.
|
|
|
|
* Normally not easy to refactor transactions script to other domain logic
|
|
|
|
patterns.
|
2020-07-19 16:19:01 +05:30
|
|
|
|
|
|
|
## Related patterns
|
2020-08-11 17:17:25 +03:00
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
* Domain Model
|
|
|
|
* Table Module
|
|
|
|
* Service Layer
|
2020-07-19 16:19:01 +05:30
|
|
|
|
|
|
|
## Credits
|
2020-08-11 17:17:25 +03:00
|
|
|
|
2020-08-08 15:49:14 +05:30
|
|
|
* [Transaction Script Pattern](https://dzone.com/articles/transaction-script-pattern#:~:text=Transaction%20Script%20(TS)%20is%20the,need%20big%20architecture%20behind%20them.)
|
|
|
|
* [Transaction Script](https://www.informit.com/articles/article.aspx?p=1398617)
|
2020-08-11 17:17:25 +03:00
|
|
|
* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=18acc13ba60d66690009505577c45c04)
|