In a small project that I am writing, I have a package models
that exposes a type Transaction
. In another package controllers
, I make frequent reference to models.Transaction
.
From a a purely software engineering perspective, what would be the advantages and disadvantages of using the new Go 1.9 type alias language feature to alias models.Transaction
as Transaction
in the controllers
package (type Transaction = models.Transaction
) so that I don't need to type models.
at every reference, setting aside the arguments about how easy it is to type models.Transaction
using a modern editor?
I'm not saying that I am going to do this. I just thinking about the implications.
评论:
ChristophBerger:
Maybe it helps if considering the original use case for type aliases: To support gradual code repair, as outlined here.
The goal is to move a type from one package to another without breaking client code that still refers to the type in the old package. Then, after all client packages have been refactored to refer to the new package only, the alias can be removed and the old package can be retired.
So the original intent was to use type aliases only temporarily during phases of refactoring. (Which IMHO does not exclude any other use that seems justifiable.)
For your use case (of using a type alias permanently as a shortcut to a type in another package), I see two main consequences:
- Easier to write (as you said, this saves some typing)
- But maybe harder to comprehend when reading the code (as the reader loses the mental reference to the
models
package.)
shovelpost:If it is simply for reducing keystrokes, why type aliases over 'dot' imports? The latter only requires two extra characters per package.
From a software engineering perspective, based on your description, I find myself asking if Transaction is actually a separate concern that warrants a separate package in the first place? To pick a random example from the standard library, the
http.Client
type is controller-like and thehttp.Request
type is model-like, but they live in the same package as they are of the same concern.I would suggest that if you have good reason to think of these as a separate concerns, I think it warrants letting the reader of your code explicitly see it as a separate concern. Aliasing the type makes it a local package concern, in which case, in your case, you may as well ditch the alias entirely and move the entire type into that package. In fact, your example exports the
controllers.Transaction
type, which may be unintended for consumers of your package.
grkuntzmd:
models.Transaction
Models is a not a very good package name. Same goes with
controllers
. They don't tell anything about the package. Use better package names and you won't even think about aliases anymore.
@skidooer and @shovelpost: I agree with separating
Transactions
into its own package as a separate concern, and when I first started writing Go about 2 years ago, that is what I would have done, but now tend toward fewer, larger packages. In Ben Johnson's blog Structuring Applications in Go, in section 4, he talks about sub-packages. Because Go does not allow cyclic dependencies, it is easy to get into trouble with packageA
depending onB
andB
depending onA
. I found that I had to combineA
andB
into some artificial packageAB
to accommodate the inter-dependency, so I stopped making so many sub-packages.As far as using the type alias feature to pull a type into another package, I agree that it is not a great choice, and I was really only doing a "thought experiment". I also shy away from "." imports because they pollute the namespace unnecessarily.
