-
cctv
stands for Credit Card Transactions Vanta -
cctv
is a RESTful Web service -
The service enables us to Register Customer Accounts
-
And issue credit cards to those customers
* Java : 8
* Spring Boot: 2.2.2.RELEASE
* Gradle : 6.0.1
* Kotlin : 1.3.50
* Target-JVM : 1.8
$ git clone https://github.com/swapab/cctv.git
$ cd cctv
$ ./gradlew clean build
$ java -jar build/libs/cctv-0.0.1-SNAPSHOT.jar
-
Domain Centric Design: Inspired by Uncle Bob Martin's Clean Architecture.
-
What is Clean Architecture?
- Just another design architecture to better manage layers and embrace SOLID principles.
-
Domains defined:
User
: This domain deals with register-user, add-money, get-userCreditCard
: Validate and Issue credit-cards to usersTransaction
: Perform transactions per credit-card
-
The datastore have been designed to mimic a relational datastore with indexing. The indexes are the primary keys. Example
userId
inUser
domain -
Why Spring Boot?
- Quick and easy to bootstrap new Java applications. Easy to test.
-
Why Kotlin for testing?
- To expedite writing tests since Kotlin is concise and allows functional approach of writing code,
- Java requires a little more of boilerplate code for testing compared to Kotlin
- And I have been writing Kotlin for over a year now so I am efficient and fast
-
The API naming is resourceful per domain.
-
The first challenge was to design data-store(s) to enable simple and efficient data storage and retrieval. This could have been made possible with various collections(namely: Map, Set, List etc). I chose
HashMap
,Set
andArray
. -
The choice has been made purely on the basis of: a. KISS - keep is short and simple(simple and stupid) b. Facilitate easy write and read of data
-
Try to keep objects/data immutable. Avoid in place update.
- immutable objects are easy to construct and test
- they are free of any side effects
- and are thread safe
-
2nd challenge Atomic and Concurrent Transactions.
-
Choice of collection for User data-store. I initially kept it as
HashMap
but later replaced theHashMap
withConcurrentHashMap
reason, HashMap is non-synchronized and not thread-safe leading toConcurrentModificationException
. WhereasConcurrentHashMap
is synchronized on writes. -
ConcurrentHashMap
could lead to stale balance reads because concurrent reads are non-blocking. -
The counter in
TransactionStoreProvider
was also a Critical Section since there can't be more than 100 transactions in the store. How to makeTransaction
happy then?AtomicInteger
to the rescue. Java 8AtomicInteger
is implemented using Fetch-and-add as opposed to Compare-and-swap
-
- Change GET Transactions API to per user instead of all transactions
- Deploy to GCP