Git Product home page Git Product logo

goddd's Issues

Examples using SQL and relational models.

First off, thanks so much for creating this repository. As a relative newcomer to Go, orienting myself in a landscape without established or strictly enforced best practices has been the toughest part of starting and this repository has been a godsend in terms of strategizing about project structure.

I've been having some trouble applying some of the principles here to my real-world services, however. Primarily, I have been having difficulty figuring out how to structure my models in a relational way, or rather where it is appropriate to load related models (repository, service, etc)? I'm using jmoiron/sqlx and also dealing with how to expand the repository interface to cover some more relational semantics that are not covered by the No-SQL example given in the repository.

For instance, only Store(obj *Object) is covered by the repository, but what if I'd like to handle the case of persisting a new object independently of persisting an existing object? In my case, I need to assign a custom ID to the new object and perhaps hash a user's password or something to that effect. Where would this best be handled and how?

Database transactions

Where should I put database transactions. Let's say I am building an e-commerce website, and I want to create a feature to order an item with a third-party payment. The simplified flow:

  1. Deduct item stock in database
  2. Charge to Paypal
  3. Create invoice in database

Where should I put the transaction implementation? It should not be in the repository layer no?

Improve test suites

  • gocheck helped when recreating the test cases from the original Java application but now's the time revisit, and rewrite them as stdlib tests instead.
  • Many of the tests are using in-memory repositories. The tests should (where sense is made) instead be using the mock repositories from the mock package.

improving package names

Thanks for creating this repository. Now, I am studying with this.
Especially, I felt interested in wrapping service.

var bs booking.Service
bs = booking.NewService(..)
bs = booking.NewLoggingService(...)

As far as I know, DDD has layerd architecture, but packages on this code is placed in flat.
When I develop golang web application, for example, I often write as below:

interfaces/booking/
interfaces/routing/
application/booking/
domain/cargo/
infrastructure/inmem/
infrastructure/mongo/
...

I think this is better, but what do you think?
I am happy if you check it out ๐Ÿ˜„

Idiomatic way of attaching authentication

What's an idiomatic way to add authentication to goddd?

I think I should perform following operation for each request:

  • extract and validate jwt token,
  • check if user exists in repository,
  • attach user object to context and
  • load user info from context when needed.

After that each endpoint can have different middleware for authorization such RequireAdmin, RequireLogin, RequireRole etc.
Should this functionality be added as another application service? Or as infrastructure service like logging? Maybe another way? How can I add a middleware that handle every request?

Returning interfaces?

Hi, Very new to GO/Programming here, very interested in implementing DDD. Having a look over your code and just have a question.

Why did you choose to return/export interfaces rather than structs/concrete types? Was it to keep from having to retype the same interface in each service?

Haven't quite figured everything out yet, maybe there is something else I'm missing?

For example the CargoRepository interface is declared in in cargo.go rather then where it is consumed?

type CargoRepository interface {
	Store(cargo *Cargo) error
	Find(id TrackingID) (*Cargo, error)
	FindAll() []*Cargo
}

Why not do something like this in your service.go?

type cargoRepository interface {
	Store(cargo *shipping.Cargo) error
	Find(id shipping.TrackingID) (*shipping.Cargo, error)
	FindAll() []*shipping.Cargo
}

type Service struct {
	cargos         cargoRepository
}

func (s *Service) Track() {
//...
}

func NewService(cargos cargoRepository) *Service {
	return &Service{
		cargos:         cargos,
	}
}

Reference:
https://github.com/golang/go/wiki/CodeReviewComments#interfaces
https://mycodesmells.com/post/accept-interfaces-return-struct-in-go
https://stackoverflow.com/questions/37181597/go-should-i-use-an-interface-to-allow-for-mocking

invalid memory address or nil pointer dereference

/inspection/inspection.go

	if c.Delivery.IsMisdirected {
		s.handler.CargoWasMisdirected(c)      //<-- s.handle is nil
	}

	if c.Delivery.IsUnloadedAtDestination {
		s.handler.CargoHasArrived(c).               //<-- s.handle is nil
	}

Extract server package

The middleware package has too much responsibility. Extract a new package server with subpackages for each endpoint.

First reported here

Application services use both DTOs and domain objects

In the original Java version, the application services are divided into a service using domain objects and a facade that accepts DTOs, converts them to domain objects and dispatches them.

Should request/response structs contain DTOs or domain objects?.
If request contains DTOs, where should translation occur?

I'm reluctant to place translation in application service since it should focus on fulfilling the use case.

Alternatives?

Docker example failure to start.

I'm having an issue testing Goddd demo app, after watching presentation https://www.youtube.com/watch?v=twcDf_Y2gXY.

Any idea what can possibly be the issue? Thanks in advance for your time.

# Start routing service - in terminal 1 pass

> docker run --name some-pathfinder marcusolsson/pathfinder 
Unable to find image 'marcusolsson/pathfinder:latest' locally
latest: Pulling from marcusolsson/pathfinder
911c6d0c7995: Pull complete 
1edb6ba6b964: Pull complete 
fad95b9d855a: Pull complete 
0dd6a60995af: Pull complete 
Digest: sha256:1829ebcaf75240aec855f43e87b6d4f6214493a509c7ab0a2cc03da40788761f
Status: Downloaded newer image for marcusolsson/pathfinder:latest
ts=2018-09-16T14:13:24.3559957Z transport=http address=:8080 msg=listening

# Start application - in terminal 2 fail

>  docker run --name some-goddd \
>  --link some-pathfinder:pathfinder \
>  -p 8080:8080 \
>   -e ROUTINGSERVICE_URL=http://pathfinder:8080 \
>   marcusolsson/goddd /goddd -inmem
Unable to find image 'marcusolsson/goddd:latest' locally
latest: Pulling from marcusolsson/goddd
911c6d0c7995: Already exists 
bf860b7c31a6: Pull complete 
7e1a6e706574: Pull complete 
9b451e13c5e3: Pull complete 
51256e166ac3: Pull complete 
2035a10c322a: Pull complete 
Digest: sha256:7665533494bf93ea512ec7e6fda4618c319c71013d0a663235df745c940354be
Status: Downloaded newer image for marcusolsson/goddd:latest
panic: no reachable servers

goroutine 1 [running]:
main.main()
	/go/src/github.com/marcusolsson/goddd/cmd/shippingsvc/main.go:74 +0x1dc2

Changing port 8080 -e ROUTINGSERVICE_URL=http://pathfinder:8080 to -e ROUTINGSERVICE_URL=http://pathfinder:7878 still have the same result.

RequestPossibleRoutesForCargo returns domain objects

The booking service method RequestPossibleRoutesForCargo returns []cargo.Itinerary which causes a DTO to be created in the makeRequestRoutesEndpoint function. It should be assembled in the application service the way it's currently done for Cargo.

Consolidate time formats

Currently, when booking a cargo using the REST API the arrival deadline requires to be of UNIX timestamp format. It should be changed to use ISO 8601.

Moving source code to src/pkg/app directory

Its just my opinion, but I think it will be much cleaner if you would take all the code that
is connected to the project itself and put it into an additional directory.
I have red that you want it to be as flat as possible, and it will be still flat, the code that matters, the way you implement DDD, all that is related somehow to the domain, application and infrastructure layers will all be in the same level as it is right now, but only inside another directory, separated from the other files that have a different purpose.
And then at the first level of the folder tree you would have the cmd directory, pkg (or src or app or whatever you want to call it) and all the other remaining files that are related to setting up the application itself, like docker files etc...

Adopt a package management tool / makefile

Hello! Participated at Goconf2016, awesome talk :-)
So I've forked this repo but run into trouble when trying to run it. Essentially the compiler first looks into the /vendor folder, but since in the code the imports are specified as github.com/marcusolsson/ it doesn't work when I clone the project in the local folder github.com/edoardo849.

My suggestion could be to use a package management tool like glide to fix the problems OR to specify in the README to create the folder GOPATH/src/github.com/marcusolsson and to git clone there.

Sample output:

./main.go:86: cannot use session (type *"github.com/edoardo849/goddd/vendor/gopkg.in/mgo.v2".Session) as type *"github.com/marcusolsson/goddd/vendor/gopkg.in/mgo.v2".Session in argument to mongo.NewCargoRepository
./main.go:87: cannot use session (type *"github.com/edoardo849/goddd/vendor/gopkg.in/mgo.v2".Session) as type *"github.com/marcusolsson/goddd/vendor/gopkg.in/mgo.v2".Session in argument to mongo.NewLocationRepository
./main.go:88: cannot use session (type *"github.com/edoardo849/goddd/vendor/gopkg.in/mgo.v2".Session) as type *"github.com/marcusolsson/goddd/vendor/gopkg.in/mgo.v2".Session in argument to mongo.NewVoyageRepository
./main.go:89: cannot use session (type *"github.com/edoardo849/goddd/vendor/gopkg.in/mgo.v2".Session) as type *"github.com/marcusolsson/goddd/vendor/gopkg.in/mgo.v2".Session in argument to mongo.NewHandlingEventRepository

I was also thinking that maybe it will be easier to just have a makefile to make run and make docker-run to do everything. If you agree I can create it myself and create a pull request. Let me know!

Does the implementation of routing service really belong to booking?

The routing service is a domain service that may be used by multiple application services. Even so, currently it resides in the booking package.

Discussion:

Where should the implementation of domain services be placed?

Alternatives:

  • Keep implementation in the routing domain package. This mixes infrastructure with domain logic though.
  • Place the implementation in a separate package, middleware, impl, infrastructure etc.
  • Other alternative?

Question about aggregates

Hello Marcus,

New ddd guy here, and I wanted to ask you if the cargo struct is considered to be an aggregate.

If possible labeling of tactical type in the comments would help as a reference example.

Flatten directory structure

The Clean Architecture structure feels out of place. Bring packages to root directory instead of hiding them in domain, infrastructure etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.