Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This isn't a Go problem, it's programmer problem.

Thanks, but just to be clear, this is not a sample from a real application, it's just a contrived demo designed to illustrate the pattern.

Why does the ProviderFactory hold the knowledge about the query interval for each provider?...Let the query interval be defined on the type, not in the factory.

As previously stated, the example is contrived. If this were a real application it could probably make sense to define the query interval on the specific type, but lets just say, for the sake of illustrating the idea, that the desired interval for a specific provider could depend not only on the type but also the total number of providers already allocated for a given type.

For example, perhaps the ProviderFactory might calculate the total number of WeatherProviders already defined, and reset the query_interval for all WeatherProviders to be (some_weather_provider_specific_constant * total_number_of_allocated_weather_providers). Whenever a new WeatherProvider is requested from the factory, the factory increases the query_interval for all WeatherProviders. In this way, the ProviderFactory acts as an automatic rate limiter for each provider by keeping track of each instance.

With the data structure you have, any time you add a new provider, you'd need to add a new case to that switch statement.

Well yeah, that's pretty critical to the "factory" role of the ProviderFactory, how else could the factory return a variety of types if it didn't have a case/branch for each signal that represents each type? Additionally, if individual logic is required for preparing a certain type of provider, the switch statement is there to accommodate the needs of the specific type before returning it.

That's like the polar opposite of separation of concerns.

How do you figure? In this example, the factory is concerned with all logic related to instantiating and appropriately configuring each instance depending on the type of instance, the state of the app or the state of other instances. I'm not sure what concerns are mixed here. Alternatively, I could export all that logic into a NewFooProvider function for each of the various FooProviders, but the idea is to encapsulate all that custodial work within the factory so that a Provider user only has to request their specific provider and that's it.

What do the types even do in your example?

Nothing. It's just an example.

The same for the host they connect to. Shouldn't that be defined in the type? Like make WeatherProvider.Connect() call ProviderFactory.WeatherHost() to get the host to connect to.

I think you're missing the point. Yes, yes, that design would work fine, but all you're really telling me here is "you don't need to use a factory in this example". What I'm saying is, when I want to use a factory (lets just assume that it makes sense in the design of my app, unless your argument is that a factory is never useful), I have to indicate which type of instance I want the factory to produce by using a zeroed struct or an arbitrary data type, what's going on within my factory is actually irreverent; any example factory snippet could be refactored into something less complex when your only context is 100 lines in a scratch pad.

You're doing everything inside out.

I'll seriously take that opinion into consideration.



Uh yes, probably a factory is never going to be an optimal solution. If you know what type you need, why would you need a factory to create it for you? Just create it. You might need a generic initializer function that sets various values on the type you create, but there's pretty much never a reason to have a function create a variety of types for you.


Uh yes, probably a factory is never going to be an optimal solution.

Never? That seems a little extreme, no? It's a tool like any other and IMO, it's a sometimes useful idiom that works pretty much identically in Go as it does in other imperative languages. However, I'd be interested in any links you could provide which might elaborate on why a factory is never an optimal solution.

If you know what type you need, why would you need a factory to create it for you? Just create it.

I already explained why. The Factory abstracts away instantiation and configuration details for a complex or dynamic initialization process. I understand you don't agree with that approach, but it's fairly common.

(see page 5) http://www.cs.colorado.edu/~kena/classes/6448/f07/lectures/2...

(see accept answer) http://programmers.stackexchange.com/questions/81838/what-is...

but there's pretty much never a reason to have a function create a variety of types for you.

The capability to define a function's return type to as an interface type would suggest otherwise, but we'll have to agree to disagree in that regard. :)


The Factory abstracts away instantiation and configuration details for a complex or dynamic initialization process.

Is there some reason you can't do that by just having this?

  func IntializeFoo(f *foo)
The capability to define a function's return type to as an interface type would suggest otherwise

Uh... if you know what type the function is returning you, why do you need it to return an interface? You don't need the interface until you pass it into a function that requires an interface, at which time, the type you've made will be converted for you... why convert before you need to?

Either the consumer should never need to know about types, in which case, you should probably just make it an enum:

  type ServiceType int
  const (
      Weather ServiceType = iota
      News    ServiceType
  )

  type Service interface {}

  func Service(type ServiceType) Service

Or if the consumer should know about the service types for some reason, you can use the Initialize method above... or to genericize it better, and remove any need for the factory to know about concrete types:

  func Initialize(svc Service)
If you can avoid having both sides know about concrete types, it'll make your life a lot easier.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: