Correct me if I'm wrong, but for my understanding of an API is that it is something that allows me to modify and request data through an interface, which is what I want to do in Go. For example I have a user interface:
interface IUser {
GetId() int
GetName() string
GetSignupDate() time
GetPermissions() []IPermission
Delete()
}
This already looks to me like active record and if I want to create a new user with a new id I would have to use new since Go doesn't support static functions as far as I know. This means I would also need a commit function in my interface, which makes it even worse for me. What am I doing wrong here?
In Go, interfaces are behavioural. That is, they describe what a thing does more than what it is. Your example looks like you're trying to write C# in Go, with your heavy use of I in front of interface classes. However, an interface that is only implemented by one type is a bit of a waste of time.
Instead, consider:
interface Deleteable { // You'd probably be tempted to call this IDeleteable
// Effective go suggests Deleter, but the grammar
// sounds weird
Delete() err
}
Now you can create a function to perform batch deletes:
func BatchDelete(victims []Deleteable) {
// Do some cool things for batching, connect to db, start a transaction
for _, victim := range(victims) {
victim.Delete() // Or arrange for this function to be called somehow.
}
}
You'd probably get started faster by creating an interface for Update, Serialize and so on, and storing your actual users/permissions/etc in concrete structs that implement those methods. (Note in Go you don't have to say that a type implements an interface, it happens "automatically"). You also don't have to have a single interface for each method (Updater, Serializable), but you can bundle them all into one interface:
type DBObject interface {
Update()
Serialize() RowType
Delete()
}
type User struct {
Id int
Name string
// ... etc
}
Remember, your model can always "Fill in" a User object to return from your API, even if the actual representation of the User object is something much more diffuse, e.g. RDF triples.
I agree with #ZanLynx comments. Go’s standard library seems to favour the interface way for APIs.
package main
import "fmt"
type S string
type I interface{ M() S }
func (s S) M() S { return s }
func API(i I) I { return i.M() }
func main() {
s := S("interface way")
fmt.Println(API(s))
}
It may be worth noting that APIs that take in a one-method interface could be re-written as taking a function type.
package main
import "fmt"
func API(f func() string) string { return f() }
func main() {
f := func() string { return "higher-order way" }
fmt.Println(API(f))
}
As an API author, one could provide both mechanisms and let the API consumer decide the style of invocation. See http://aquaraga.github.io/functional-programming/golang/2016/11/19/golang-interfaces-vs-functions.html.
Related
I'm new to Golang and have been taking a TDD approach while learning the language. I've been getting along okay yet I find testing third party packages quite clunky, which leads me to believe that I've been taking the wrong approach.
The specific case I'm having trouble with is mocking a Redis client for error handling. The approach I've taken is to create my own interface, and the implementation wraps the clients methods that I want to use.
type Redis interface {
Get(key string) (string, error)
}
type RedisClient struct {
client *redis.Client
}
func (redisClient *RedisClient) New(client *redis.Client) *RedisClient {
redisClient.client = client
return redisClient
}
func (redisClient *RedisClient) Get(key string) (string, error) {
return redisClient.client.Get(key).Result()
}
I can then create a mock which implements that same interface to return whichever values I specify, particularly for testing error handling.
I've hit a roadblock where a specific method on the client to perform transactions (MULTI) returns another interface belonging to that package. What would I do in this scenario? Implementing that interface myself seems out of the question.
Similarly, as usage of this client grows, my own implementation can grow to the point that it implements the whole interface to Redis - this seems to go against the whole idea of delegating this out to an external dependency.
Is there a better way to test third-party packages like this, for things such as error handling?
One approach would be to create a type that focuses on what you want to accomplish instead on what methods of the client you are using.
Let's say all you want is a storage to save and fetch users, you could imagine an interface like this:
type UserStore interface {
SaveUser(*User) error
GetUserByID(id string) (*User, error)
SearchUsers(query string) ([]User, error)
}
You could then implement a Redis version of this storage and call whatever client methods you want inside, it doesn't matter. You can even implement one in PostgreSQL or whatever.
Also, mocking is way easier with this approach since you all you need to do is to implement this interface instead of the Redis one.
Here is an example of a mock version of this interface:
type UserStoreMock struct {
SaveUserFn func (*User) error
SaveUserInvoked bool
...
}
func (m *UserStoreMock) SaveUser(u *User) error {
m.SaveUserInvoked = true
if m.SaveUserFn != nil {
return m.SaveUserFn(u)
}
return nil
}
...
You can then use this mock in tests like this:
var m UserStoreMock
m.SaveUserFn = func(u *User) error {
if u.ID != "123" {
t.Fail("Bad ID")
}
return ErrDuplicateError
}
...
I wrote a lot PHP with the OOP frameworks before, and I'm learning Golang,
When I was using PHP, The class is useful that I could pass a $model in to my class then share it between functions:
class User {
function __construct(UserModel $model) {
$this->model = $model
}
function delete($id) {
$this->model->delete($id);
}
function update($id) {
$this->model->update($id);
}
}
$UserModel = new UserModel();
$User = new User($UserModel);
$User->delete(1);
But there's no class in Golang, I knew that I could treat structs like a class:
type User struct {
model *models.User
}
func (u *User) Delete(id int) {
u.model.Delete(id)
}
func (u *User) Update(id int) {
u.model.Update(id)
}
userModel := &models.User{}
user := User{model: userModel}
user.Delete(1)
I felt like the struct is used to store the information, and the method of the struct should be used to modify the value of the struct.
But right now I made a struct just because I want to treat it like a class and solve the dependency problem, is it bad to use such approach in Golang?
From overall conceptual standpoint there is nothing wrong in your implementation.
On a detailed view there are inconsistencies that raise questions.
In all cases below there is a potential concurrency issue due to data shared across various Delete calls.
Case A
If models.User{} does all the work, then why can't we just
userModel := &models.User{}
userModel.Delete(userId)
Case B
If User is our public interface:
user := User{model: userModel}
user.Delete(1)
then taking userId to delete is redundant and shall be done as:
user.Delete()
userId is taken from user context.
Case C
Otherwise, we might want to make userModel to be set for all User instances:
package User;
// private package level variable
var model = userModel
func Delete(userId int) {
model.Delete(userId)
}
...
User.Delete(userId)
Conclusion
Each case above solves the same problem with a slightly different emphasis. Case A is straightforward. Case B and C rely on underlying shared code that could be used with event notifications. Case B and C are different in User scope. In Case B User is a structure. In Case C user is a package name. I think Case C is used less often than Case B. So, if use insist on having an underlying model, then Case B is probably the most intuitive solution from user code point of view.
you can use interface with method
In service (connect db)
// UserServiceInterface include method list
type UserServiceInterface interface {
GetAll(helpers.ParamsGetAll) (models.PublicUsers, error)
Get(int64) (models.User, error)
Delete(int64) (bool, error)
Create(models.User) (int64, error)
Update(models.User) (models.User, error)
CheckExistUsername(string) (bool, error)
CheckExistEmail(string) (bool, error)
CreateEmailActive(string, string, int64) error
CheckExistUser(int64) (bool, error)
}
// UserService struct
type userService struct{}
// NewUserService to constructor
func NewUserService() userService {
return userService{}
}
func (userService )GetAll (p helpers.ParamGetAll)(models.PublicUser, error) {
code here....
}
In user controller
// UserController controller
type UserController struct {
Service services.UserServiceInterface
}
func (controller UserController) GetAll(c *gin.Context) {
users, errGetAll := controller.Service.GetAll(params)
}
I'm making use of a third party library that doesn't have any interfaces for its classes. I can use them in my structs no problem, but they have side effects that I want to avoid when unit testing.
// Somewhere there are a couple structs, with no interfaces. I don't own the code.
// Each has only one method.
type ThirdPartyEntry struct {}
func (e ThirdPartyEntry) Resolve() string {
// Do some complex stuff with side effects
return "I'm me!"
}
// This struct returns an instance of the other one.
type ThirdPartyFetcher struct {}
func (f ThirdPartyFetcher) FetchEntry() ThirdPartyEntry {
// Do some complex stuff with side effects and return an entry
return ThirdPartyEntry{}
}
// Now my code.
type AwesomeThing interface {
BeAwesome() string
}
// I have a class that makes use of the third party.
type Awesome struct {
F ThirdPartyFetcher
}
func (a Awesome) BeAwesome() string {
return strings.Repeat(a.F.FetchEntry().Resolve(), 3)
}
func NewAwesome(fetcher ThirdPartyFetcher) Awesome {
return Awesome{
F: fetcher,
}
}
func main() {
myAwesome := NewAwesome(ThirdPartyFetcher{})
log.Println(myAwesome.BeAwesome())
}
This works! But I want to write some unit tests, and so I'd like to Mock both the third party structs. To do so I believe I need interfaces for them, but since ThirdPartyFetcher returns ThirdPartyEntrys, I cannot figure out how.
I created a pair of interfaces which match up with the two third party classes. I'd like to then rewrite the Awesome struct and method to use the generic Fetcher interface. In my test, I would call NewAwesome() passing in a testFetcher, a struct which also implements the interface.
type Awesome struct {
F Fetcher
}
func NewAwesome(fetcher Fetcher) Awesome {
return Awesome{
Fetcher: fetcher,
}
}
type Entry interface {
Resolve() string
}
// Double check ThirdPartyEntry implements Entry
var _ Entry = (*ThirdPartyEntry)(nil)
type Fetcher interface {
FetchEntry() Entry
}
// Double check ThirdPartyFetcher implements Fetcher
var _ Fetcher = (*ThirdPartyFetcher)(nil)
I omit the test code because it's not relevant. This fails on the last line shown.
./main.go:49: cannot use (*ThirdPartyFetcher)(nil) (type *ThirdPartyFetcher) as type Fetcher in assignment:
*ThirdPartyFetcher does not implement Fetcher (wrong type for FetchEntry method)
have FetchEntry() ThirdPartyEntry
want FetchEntry() Entry
The signatures are different, even though I already showed that ThirdPartyEntry implements Entry. I believe this is disallowed because to would lead to something like slicing (in the polymorphic sense, not the golang sense). Is there any way for me to write a pair of interfaces? It should be the case that the Awesome class doesn't even know ThirdParty exists - it's abstracted behind the interface and injected when main calls NewAwesome.
It's not very pretty, but one way would be to:
type fetcherWrapper struct {
ThirdPartyFetcher
}
func (fw fetcherWrapper) FetchEntry() Entry {
return fw.ThirdPartyFetcher.FetchEntry()
}
I'd say mocking things that return structs vs interfaces is a relatively common problem without any great solutions apart from a lot of intermediate wrapping.
I often have a situation where I need to do:
function a1() {
a = getA;
b = getB;
b.doStuff();
.... // do some things
b.send()
return a - b;
}
function a2() {
a = getA;
b = getB;
b.doStuff();
.... // do some things, but different to above
b.send()
return a - b;
}
I feel like I am repeating myself, yet where I have ...., the methods are different, have different signatures, etc..
What do people normally do? Add an if (this type) do this stuff, else do the other stuff that is different? It doesn't seem like a very good solution either.
Polymorphism and possibly abstraction and encapsulation are your friends here.
You should specify better what kind of instructions you have on the .... // do some things part. If you're always using the same information, but doing different things with it, the solution is fairly easy using simple polymorphism. See my first revision of this answer. I'll assume you need different information to do the specific tasks in each case.
You also didn't specify if those functions are in the same class/module or not. If they are not, you can use inheritance to share the common parts and polymorphism to introduce different behavior in the specific part. If they are in the same class you don't need inheritance nor polymorphism.
In different classes
Taking into account you're stating in the question that you might need to make calls to functions with different signature depending on the implementation subclass (for instance, passing a or b as parameter depending on the case), and assuming you need to do something with the intermediate local variables (i.e. a and b) in the specific implementations:
Short version: Polymorphism+Encapsulation: Pass all the possible in & out parameters that every subclass might need to the abstract function. Might be less painful if you encapsulate them in an object.
Long Version
I'd store intermediate state in generic class' member, and pass it to the implementation methods. Alternatively you could grab the State from the implementation methods instead of passing it as an argument. Then, you can make two subclasses of it implementing the doSpecificStuff(State) method, and grabbing the needed parameters from the intermediate state in the superclass. If needed by the superclass, subclasses might also modify state.
(Java specifics next, sorry)
public abstract class Generic {
private State state = new State();
public void a() {
preProcess();
prepareState();
doSpecificStuf(state);
clearState();
return postProcess();
}
protected void preProcess(){
a = getA;
b = getB;
b.doStuff();
}
protected Object postProcess(){
b.send()
return a - b;
}
protected void prepareState(){
state.prepareState(a,b);
}
private void clearState() {
state.clear();
}
protected abstract doSpecificStuf(State state);
}
public class Specific extends Generic {
protected doSpecificStuf(State state) {
state.getA().doThings();
state.setB(someCalculation);
}
}
public class Specific2 extends Generic {
protected doSpecificStuf(State state) {
state.getB().doThings();
}
}
In the same class
Another possibility would be making the preProcess() method return a State variable, and use it inthe implementations of a1() and a2().
public class MyClass {
protected State preProcess(){
a = getA;
b = getB;
b.doStuff();
return new State(a,b);
}
protected Object postProcess(){
b.send()
return a - b;
}
public void a1(){
State st = preProcess();
st.getA().doThings();
State.clear(st);
return postProcess();
}
public void a2(){
State st = preProcess();
st.getB().doThings();
State.clear(st);
return postProcess();
}
}
Well, don't repeat yourself. My golden rule (which admittedly I break from time on time) is based on the ZOI rule: all code must live exactly zero, one or infinite times. If you see code repeated, you should refactor that into a common ancestor.
That said, it is not possible to give you a definite answer how to refactor your code; there are infinite ways to do this. For example, if a1() and a2() reside in different classes then you can use polymorphism. If they live in the same class, you can create a function that receives an anonymous function as parameter and then a1() and a2() are just wrappers to that function. Using a (shudder) parameter to change the function behavior can be used, too.
You can solve this in one of 2 ways. Both a1 and a2 will call a3. a3 will do the shared code, and:
1. call a function that it receives as a parameter, which does either the middle part of a1 or the middle part of a2 (and they will pass the correct parameter),
- or -
2. receive a flag (e.g. boolean), which will tell it which part it needs to do, and using an if statement will execute the correct code.
This screams out loud for the design pattern "Template Method"
The general part is in the super class:
package patterns.templatemethod;
public abstract class AbstractSuper {
public Integer doTheStuff(Integer a, Integer b) {
Integer x = b.intValue() + a.intValue();
Integer y = doSpecificStuff(x);
return b.intValue() * y;
}
protected abstract Integer doSpecificStuff(Integer x);
}
The spezific part is in the subclass:
package patterns.templatemethod;
public class ConcreteA extends AbstractSuper {
#Override
protected Integer doSpecificStuff(Integer x) {
return x.intValue() * x.intValue();
}
}
For every spezific solution you implement a subclass, with the specific behavior.
If you put them all in an Collection, you can iterate over them and call always the common method and evry class does it's magic. ;)
hope this helps
I am trying to translate a poker game to a correct OOP model.
The basics :
class Hand
{
Card cards[];
}
class Game
{
Hand hands[];
}
I get games and hands from a text file. I parse the text file several times, for several reasons:
get somes infos (reason 1)
compute some stats (reason 2)
...
For reason 1 I need some attributes (a1, b1) in class Hand. For reason 2, I need some other attributes (a2, b2). I think the dirty way would be :
class Hand
{
Card cards[];
Int a1,b1;
Int a2,b2;
}
I would mean that some attributes are useless most of the time.
So, to be cleaner, we could do:
class Hand
{
Card cards[];
}
class HandForReason1 extends Hand
{
Int a1,b1;
}
But I feel like using a hammer...
My question is : is there an intermediate way ? Or the hammer solution is the good one ? (in that case, what would be a correct semantic ?)
PS : design patterns welcome :-)
PS2 : strategy pattern is the hammer, isn't it?
* EDIT *
Here is an application :
// Parse the file, read game infos (reason 1)
// Hand.a2 is not needed here !
class Parser_Infos
{
Game game;
function Parse()
{
game.hands[0].a1 = ...
}
}
// Later, parse the file and get some statistics (reason 2)
// Hand.a1 is not needed here !
class Parser_Stats
{
Game game;
function Parse()
{
game.hand[0].a2 = ...
}
}
Using a chain of responsibility to recognize a poker hand is what I would do. Since each hand has it's own characteristics, you can't just have a generic hand.
Something like
abstract class Hand {
protected Hand next;
abstract protected boolean recognizeImpl(Card cards[]);
public Hand setNext(Hand next) {
this.next = next;
return next;
}
public boolean Hand recognize(Card cards[]) {
boolean result = ;
if (recognizeImpl(cards)) {
return this;
} else if (next != null) {
return next.recognize(cards);
} else {
return null;
}
}
}
And then have your implementation
class FullHouse extends Hand {
protected boolean recognizeImpl(Card cards[]) {
//...
}
}
class Triplet extends Hand {
protected boolean recognizeImpl(Card cards[]) {
//...
}
}
Then build your chain
// chain start with "best" hand first, we want the best hand
// to be treated first, least hand last
Hand handChain = new FullHouse();
handChain
.setNext(new Triplet())
//.setNext(...) /* chain method */
;
//...
Hand bestHand = handChain.recognize(cards);
if (bestHand != null) {
// The given cards correspond best to bestHand
}
Also, with each hand it's own class, you can initialize and have then hold and compute very specific things. But since you should manipulate Hand classes as much as you can (to stay as much OO as possible), you should avoid having to cast your hands to a specific hand class.
** UPDATE **
Alright, so to answer your original question (sig) the class Hand is for manipulating and treating "hands". If you need to calculate other statistics or other needs, wrapping your Hand class might not be a good idea as you'll end up with a compound class, which is not desirable (for maintainability's sake and OOP paradigm).
For the reason 1, it is alright to have different kinds of hands, as the chain of responsibility illustrate; you can read your file, create different kinds of hands with the many parameters as is required.
For reason 2, you might look at other solutions. One would be to have your Hand classes fire events (ex: when it is recognized) and your application could register those hands into some other class to listen for events. That other class should also be responsible to collect the necessary data from the files you are reading. Since a hand is not (or should not be) responsible to collect statistical data, the bottom line is that you need to have something else handle that.
One package = coherent API and functionalities
One class = coherent functionalities (a hand is a hand, not a statistical container)
One method = a (single) functionality (if a method needs to handle more than one functionality, break those functionalities into separate private methods, and call them from the public method)
I'm giving you a generic answer here because reason 1 and reason 2 are not specific.