Skip to content

Commit

Permalink
Refactored the DDD-hex example to define own structs for each of the …
Browse files Browse the repository at this point in the history
…operations available.
  • Loading branch information
katzien committed Aug 11, 2018
1 parent 402ab2d commit 10b0057
Show file tree
Hide file tree
Showing 30 changed files with 690 additions and 575 deletions.
57 changes: 57 additions & 0 deletions domain-driven-hex/cmd/beer-server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"fmt"
"log"
"net/http"

"github.com/katzien/go-structure-examples/domain-driven-hex/http/rest"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/listing"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/adding"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/reviewing"
"github.com/katzien/go-structure-examples/domain-driven-hex/storage/memory"
"github.com/katzien/go-structure-examples/domain-driven-hex/storage/json"
)

// StorageType defines available storage types
type Type int

const (
// JSON will store data in JSON files saved on disk
JSON Type = iota
// Memory will store data in memory
Memory
)

func main() {

// set up storage
storageType := JSON // this could be a flag; hardcoded here for simplicity

var adder adding.Service
var lister listing.Service
var reviewer reviewing.Service

switch storageType {
case Memory:
s := new(memory.Storage)

adder = adding.NewService(s)
lister = listing.NewService(s)
reviewer = reviewing.NewService(s)

case JSON:
// error handling omitted for simplicity
s, _ := json.NewStorage()

adder = adding.NewService(s)
lister = listing.NewService(s)
reviewer = reviewing.NewService(s)
}

// set up the HTTP server
router := rest.Handler(adder, lister, reviewer)

fmt.Println("The beer server is on tap now: http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", router))
}
26 changes: 0 additions & 26 deletions domain-driven-hex/cmd/data/main.go

This file was deleted.

26 changes: 26 additions & 0 deletions domain-driven-hex/cmd/sample-data/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import (
"fmt"
"github.com/katzien/go-structure-examples/domain-driven-hex/storage/json"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/adding"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/reviewing"
)

func main() {

var adder adding.Service
var reviewer reviewing.Service

// error handling omitted for simplicity
s, _ := json.NewStorage()

adder = adding.NewService(s)
reviewer = reviewing.NewService(s)

// add some sample data
adder.AddSampleBeers()
reviewer.AddSampleReviews()

fmt.Println("Finished adding sample data.")
}
52 changes: 0 additions & 52 deletions domain-driven-hex/cmd/server/main.go

This file was deleted.

114 changes: 114 additions & 0 deletions domain-driven-hex/http/rest/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package rest

import (
"net/http"
"github.com/julienschmidt/httprouter"
"encoding/json"
"strconv"
"fmt"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/listing"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/adding"
"github.com/katzien/go-structure-examples/domain-driven-hex/pkg/reviewing"
)

func Handler(a adding.Service, l listing.Service, r reviewing.Service) http.Handler {
router := httprouter.New()

router.GET("/beers", getBeers(l))
router.GET("/beers/:id", getBeer(l))
router.GET("/beers/:id/reviews", getBeerReviews(l))

router.POST("/beers", addBeer(a))
router.POST("/beers/:id/reviews", addBeerReview(r))

return router
}

// addBeer returns a handler for POST /beers requests
func addBeer(s adding.Service) func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
decoder := json.NewDecoder(r.Body)

var newBeer adding.Beer
err := decoder.Decode(&newBeer)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

s.AddBeer(newBeer)

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode("New beer added.")
}
}

// addBeerReview returns a handler for POST /beers/:id/reviews requests
func addBeerReview(s reviewing.Service) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
ID, err := strconv.Atoi(p.ByName("id"))
if err != nil {
http.Error(w, fmt.Sprintf("%s is not a valid Beer ID, it must be a number.", p.ByName("id")), http.StatusBadRequest)
return
}

var newReview reviewing.Review
decoder := json.NewDecoder(r.Body)

if err := decoder.Decode(&newReview); err != nil {
http.Error(w, "Failed to parse review", http.StatusBadRequest)
}

newReview.BeerID = ID

s.AddBeerReview(newReview)

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode("New beer review added.")
}
}

// getBeers returns a handler for GET /beers requests
func getBeers(s listing.Service) func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
w.Header().Set("Content-Type", "application/json")
list := s.GetBeers()
json.NewEncoder(w).Encode(list)
}
}

// getBeer returns a handler for GET /beers/:id requests
func getBeer(s listing.Service) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
ID, err := strconv.Atoi(p.ByName("id"))
if err != nil {
http.Error(w, fmt.Sprintf("%s is not a valid beer ID, it must be a number.", p.ByName("id")), http.StatusBadRequest)
return
}

beer, err := s.GetBeer(ID)
if err == listing.ErrNotFound {
http.Error(w, "The beer you requested does not exist.", http.StatusNotFound)
return
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(beer)
}
}

// getBeerReviews returns a handler for GET /beers/:id/reviews requests
func getBeerReviews(s listing.Service) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
ID, err := strconv.Atoi(p.ByName("id"))
if err != nil {
http.Error(w, fmt.Sprintf("%s is not a valid beer ID, it must be a number.", p.ByName("id")), http.StatusBadRequest)
return
}

reviews := s.GetBeerReviews(ID)

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(reviews)
}
}
9 changes: 9 additions & 0 deletions domain-driven-hex/pkg/adding/beer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package adding

// Beer defines the properties of a beer to be added
type Beer struct {
Name string `json:"name"`
Brewery string `json:"brewery"`
Abv float32 `json:"abv"`
ShortDesc string `json:"short_description"`
}
27 changes: 0 additions & 27 deletions domain-driven-hex/pkg/adding/endpoint.go

This file was deleted.

Loading

0 comments on commit 10b0057

Please sign in to comment.