##Example 2##
In this example we will look at a part of a web application that manages stock items. The decision was made to start with using an embedded database, something like SQLite or BoltDB, with the idea to scale out to a more distributed database like Cassandra as the business scale.
Let's define the domain type:
package domain
//StockItem domain type model
type StockItem struct {
Name string
Description string
Price int
}
The SQLite implementation package will look like this:
type StockItemRepository struct {
Db *sql.DB
}
//Add puts a new StockItem into the warehouse
func (s *StockItemRepository) Add(new *StockItem) error {
//
}
//Update StockItem identified by given id with updated
func UpdateById(id int, updated *StockItem) error {
//
}
//Find StockItem identified by given id
func FindById(id int) (*StockItem, error) {
//
}
//List all StockItems in the warehouse
func ListAll() ([]*StockItem, error) {
//
}
From the calling code we create a StockItemRepository
object
and assign the opened DB handler to it's Db
field:
db, err := sql.Open("sqlite3", "./app.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
inventoryStore := &sqlite.StockItemRepository {
Db: db,
//....
}
The web handler type embeds the concrete sqlite.StockItemRepository
type:
type webHandler struct {
sqlite.StockItemRepository
}
This will work for a while until our application need to scale and
the need for a database like Cassandra is needed.
We can decouple the webHandler
from the concrete sqlite type and rather
define an interface type that the webHandler
can use.
That way the webHandler
is not concerned and decoupled with the underlying database that is used.
The interface type will look like this:
type StockItemRepository interface {
Add(*StockItem) error
Update(int, *StockItem) error
Get(int) (*TerStockItemminal, error)
ListAll() ([]*StockItem, error)
}
It will be a good idea to put the interface part of the domain
package
where our StockItem
type is defined.
The webHandler
type can now be changed to use the new interface type instead:
type webHandler struct {
domain.StockItemRepository
}
The sqlite concrete type implementation will still work as it satisfies the new interface type.
But more importantly if a new Cassandra implementation (or any other implementation that satisfies the interface) is created later on it can easily be swopped in and used by the webHandler
without making any changes to the webHandler
type.