Clean up Transaction Script

This commit is contained in:
Ilkka Seppälä 2020-08-11 17:17:25 +03:00
parent d091e369ec
commit 1683fbdf9c
12 changed files with 40 additions and 27 deletions

View File

@ -9,11 +9,15 @@ tags:
---
## Intent
Transaction Script organizes business logic by procedures where each procedure handles a single request from the presentation.
Transaction Script organizes business logic by procedures where each procedure handles a single
request from the presentation.
## Explanation
Real world example
> You need to create a hotel room booking system. Since the requirements are quite simple we intend to use the Transaction Script pattern here.
> You need to create a hotel room booking system. Since the requirements are quite simple we intend
> to use the Transaction Script pattern here.
In plain words
> Transaction Script organizes business logic into transactions that the system needs to carry out.
@ -26,7 +30,7 @@ The `Hotel` class takes care of booking and cancelling room reservations.
public class Hotel {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
private HotelDaoImpl hotelDao;
private final HotelDaoImpl hotelDao;
public Hotel(HotelDaoImpl hotelDao) {
this.hotelDao = hotelDao;
@ -72,27 +76,33 @@ public class Hotel {
}
```
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.
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.
```
public void bookRoom(int roomNumber);
```
The book room method consolidates all the needed steps like checking if the room is already booked
or not, if not booked then books the rooma nd updates the database by using the DAO.
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.
```
public void cancelRoomBooking(int roomNumber)
```
The cancel room method consolidates steps like checking if the room is booked or not,
The `cancelRoom` method consolidates steps like checking if the room is booked or not,
if booked then calculates the refund amount and updates the database using the DAO.
## Class diagram
![alt text](./etc/transaction-script.png "Transaction script model")
## Applicability
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.
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.
## Consequences
* As the business logic gets more complicated,
it gets progressively harder to keep the transaction script
in a well-designed state.
@ -101,11 +111,13 @@ in a well-designed state.
patterns.
## Related patterns
* Domain Model
* Table Module
* Service Layer
## Credits
* [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)
* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420?ie=UTF8&tag=gupesasnebl-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321127420)
* [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)

View File

@ -60,7 +60,7 @@
<configuration>
<archive>
<manifest>
<mainClass>com.ashishtrivedi16.transactionscript.App</mainClass>
<mainClass>com.iluwatar.transactionscript.App</mainClass>
</manifest>
</archive>
</configuration>

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import java.util.List;
import javax.sql.DataSource;

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import java.util.Optional;
import java.util.stream.Stream;

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import java.sql.Connection;
import java.sql.PreparedStatement;

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
/**
* A room POJO that represents the data that will be read from the data source.

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
/**
* Customer Schema SQL Class.

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import org.junit.jupiter.api.Test;

View File

@ -21,10 +21,11 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@ -79,7 +80,7 @@ public class HotelDaoImplTest {
dataSource.setURL(DB_URL);
dao = new HotelDaoImpl(dataSource);
var result = dao.add(existingRoom);
assertTrue(result);
Assertions.assertTrue(result);
}
/**
@ -96,7 +97,7 @@ public class HotelDaoImplTest {
final var nonExistingRoom = new Room(2, "Double", 80, false);
var result = dao.add(nonExistingRoom);
assertTrue(result);
Assertions.assertTrue(result);
assertRoomCountIs(2);
assertEquals(nonExistingRoom, dao.getById(nonExistingRoom.getId()).get());
@ -107,7 +108,7 @@ public class HotelDaoImplTest {
final var nonExistingRoom = new Room(2, "Double", 80, false);
var result = dao.delete(nonExistingRoom);
assertFalse(result);
Assertions.assertFalse(result);
assertRoomCountIs(1);
}
@ -119,7 +120,7 @@ public class HotelDaoImplTest {
final var room = new Room(nonExistingId, newRoomType, newPrice, false);
var result = dao.update(room);
assertFalse(result);
Assertions.assertFalse(result);
assertFalse(dao.getById(nonExistingId).isPresent());
}
@ -141,7 +142,7 @@ public class HotelDaoImplTest {
var existingRoom = new Room(1, "Single", 50, false);
var result = dao.add(existingRoom);
assertFalse(result);
Assertions.assertFalse(result);
assertRoomCountIs(1);
assertEquals(existingRoom, dao.getById(existingRoom.getId()).get());
}
@ -150,7 +151,7 @@ public class HotelDaoImplTest {
public void deletionShouldBeSuccessAndRoomShouldBeNonAccessible() throws Exception {
var result = dao.delete(existingRoom);
assertTrue(result);
Assertions.assertTrue(result);
assertRoomCountIs(0);
assertFalse(dao.getById(existingRoom.getId()).isPresent());
}
@ -164,7 +165,7 @@ public class HotelDaoImplTest {
final var Room = new Room(existingRoom.getId(), newRoomType, newPrice, newBookingStatus);
var result = dao.update(Room);
assertTrue(result);
Assertions.assertTrue(result);
final var room = dao.getById(existingRoom.getId()).get();
assertEquals(newRoomType, room.getRoomType());

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.jupiter.api.BeforeEach;

View File

@ -21,7 +21,7 @@
* THE SOFTWARE.
*/
package com.ashishtrivedi16.transactionscript;
package com.iluwatar.transactionscript;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;