# Habit engine interface
- HTTP handler
- Receives http requests and delegate the request to service for the response. Doesn't know much about the business logic
- Service
- Does buisness level logic like creating cohorts, inviting memebrs, sending welcome emails etc....
- Datastore
- Used by the service to fetch and retrieve persistent data from sql DB
## Interfaces
```go=
// engine/datastore.go
// Datastore defines a set of functions to the persistent layer
// each function will accept a dstore interface which it will use
// to persist data. Reason we want to pass it explicitly is due to
// the transactions on DB. User of datastore interface should pass this which would be Service
type CohortStore interface {
// This will just create the cohort into db
CreateCohort(dstore, cohort *engine.Cohort) (cohort, error)
// fetch the cohort
GetCohort(dstore, id string) (cohort, error)
}
// Datastore is the main interface embedding multiple small datastores
type DataStore interface{
CohortStore
}
// engine/service.go
// Service defines a set of functions http or any other handler can use
type Service interface {
// Creates a cohort, invote members, and send emails etc....
CreateCohort(cohort *engine.Cohort) (cohort, error)
// fetches cohorts and its sessions etc...
GetCohort(id string) (cohort, error)
}
// service implements Service
type service struct{
datastore engine.Datastore
}
func(s service)CreateCohort(cohort *engine.Cohort) (cohort, error){
dstore := s.datastore.txn()
within-txn{
s.datstore.CreateCohort(dstore, cohort)
s.datastore.SetCohortAdmins(dstore,cohort)
s.sendEmails(cohort)
}
}
// Handler functions are http handlers
type Handler struct{
service engine.Service // interfce
}
// createcohort handler interacts with service to create cohort
func(h Handler) CreateCohort(w http.ResponseWriter, r *http.Request){
cohort := cohortFrom(r)
return h.service.CreateCohort(cohort)
}
```
## Testing
These defined interfaces above would be make it easy to write unit tests for each level i.e
- datastore tests will use postgres for testing
- service tests will use datastore default implementation with postgres to run tests
- HTTP tests would be done through API mocks