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 ## 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 ## Explanation
Real world example 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 In plain words
> Transaction Script organizes business logic into transactions that the system needs to carry out. > 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 { public class Hotel {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class); private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
private HotelDaoImpl hotelDao; private final HotelDaoImpl hotelDao;
public Hotel(HotelDaoImpl hotelDao) { public Hotel(HotelDaoImpl hotelDao) {
this.hotelDao = 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); public void bookRoom(int roomNumber);
``` ```
The book room method consolidates all the needed steps like checking if the room is already booked The `bookRoom` 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. or not, if not booked then books the room and updates the database by using the DAO.
``` ```
public void cancelRoomBooking(int roomNumber) 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. if booked then calculates the refund amount and updates the database using the DAO.
## Class diagram ## Class diagram
![alt text](./etc/transaction-script.png "Transaction script model") ![alt text](./etc/transaction-script.png "Transaction script model")
## Applicability ## 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 ## Consequences
* As the business logic gets more complicated, * As the business logic gets more complicated,
it gets progressively harder to keep the transaction script it gets progressively harder to keep the transaction script
in a well-designed state. in a well-designed state.
@ -101,11 +111,13 @@ in a well-designed state.
patterns. patterns.
## Related patterns ## Related patterns
* Domain Model * Domain Model
* Table Module * Table Module
* Service Layer * Service Layer
## Credits ## 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 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) * [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> <configuration>
<archive> <archive>
<manifest> <manifest>
<mainClass>com.ashishtrivedi16.transactionscript.App</mainClass> <mainClass>com.iluwatar.transactionscript.App</mainClass>
</manifest> </manifest>
</archive> </archive>
</configuration> </configuration>

View File

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

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@
* THE SOFTWARE. * 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. * A room POJO that represents the data that will be read from the data source.

View File

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

View File

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

View File

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

View File

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

View File

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