Skip to content

Instantly share code, notes, and snippets.

@reidcooper
Last active October 13, 2023 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reidcooper/0337591d8a5ce9af23f00d64ed395e83 to your computer and use it in GitHub Desktop.
Save reidcooper/0337591d8a5ce9af23f00d64ed395e83 to your computer and use it in GitHub Desktop.
functional_composition.go
package main
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
type DatabaseFetcher struct {
databaseRepo string
}
func (idr *DatabaseFetcher) GetListOfIds(ids []string) []string {
return []string{"1", "2", "3"}
}
// ====
type RedisFetcher struct {
databaseRepo string
}
func (idr *RedisFetcher) GetListOfIds(ids []string) []string {
return []string{"1", "2", "3"}
}
// ====
type IdFetcher interface {
GetListOfIds(ids []string) []string
}
type CalculateCountOfIds struct {
idFetcher IdFetcher
}
func (cci *CalculateCountOfIds) CountIds(ids []string) int {
return len(cci.idFetcher.GetListOfIds(ids))
}
// ====
type Calculator interface {
CountIds(ids []string) int
}
type SomeController struct {
calculator Calculator
}
func (controller *SomeController) MakeItAString() string {
count := controller.calculator.CountIds([]string{"1", "2", "3"})
return fmt.Sprint(count)
}
func BuildSomeController() SomeController {
idDBFetcher := DatabaseFetcher{}
calculator := &CalculateCountOfIds{
idFetcher: &idDBFetcher,
}
controller := SomeController{
calculator: calculator,
}
return controller
}
// ====
type mockCalculator struct {
countIds func(ids []string) int
}
func (mc *mockCalculator) CountIds(ids []string) int {
return mc.countIds(ids)
}
func TestSomeControllerMakeItAString(t *testing.T) {
mc := mockCalculator{}
mc.countIds = func(ids []string) int {
return 4
}
controller := SomeController{
calculator: &mc,
}
assert.Equal(t, "4", controller.MakeItAString())
}
// ====
// Now for the Functional Side (Below)
// ====
type CountIdsFunc func(ids []string) int
func NewCountIdsFromDatabaseFunc(databaseFetcher *DatabaseFetcher) CountIdsFunc {
return func(ids []string) int {
return CountIdsFromDatabase(ids, databaseFetcher)
}
}
func CountIdsFromDatabase(ids []string, databaseFetcher *DatabaseFetcher) int {
return len(databaseFetcher.GetListOfIds(ids))
}
func NewCountIdsFromRedisFunc(redisFetcher *RedisFetcher) CountIdsFunc {
return func(ids []string) int {
return CountIdsFromRedis(ids, redisFetcher)
}
}
func CountIdsFromRedis(ids []string, redisFetcher *RedisFetcher) int {
return len(redisFetcher.GetListOfIds(ids))
}
// ====
type SomeFuncController struct {
calculator CountIdsFunc
}
func (controller *SomeFuncController) MakeItAString() string {
result := controller.calculator([]string{"1", "2", "3"})
return fmt.Sprint(result)
}
func BuildSomeFuncController() SomeFuncController {
idRedisFetcher := RedisFetcher{}
countFunc := NewCountIdsFromRedisFunc(&idRedisFetcher)
controller := SomeFuncController{
calculator: countFunc,
}
return controller
}
// ====
func TestSomeFuncControllerMakeItAString(t *testing.T) {
calcFunc := func(ids []string) int {
return 4
}
controller := SomeFuncController{
calculator: calcFunc,
}
assert.Equal(t, "4", controller.MakeItAString())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment