-1

Is there some sort of pattern for enforcing the calling of a populator method before any of the rest of the interface is used?

I say this because it is not generally a good idea to put something that has network calls or something that does large calculations in a constructor.

That work needs to be done before the other methods are used though. I was thinking that maybe a factory pattern could be used to initialize and then run the methods that are necessary to populate data. I don't really want the main class to be usable if the population doesn't happen but I don't want to check this with each method.

Is there a pattern that handles this?

  • 2
    Kilian Foth already gave you a hint. The second hint works alongside with lazy initialization: Proxy pattern. – Laiv May 9 at 10:21
  • Why dont you use the adapter pattern as working just in case according your needs – marven May 18 at 14:01
0

You want lazy initialization. Let the object remember whether or not it's been initialized, and perform the init just in time. (This means that the first of several seemingly equivalent calls may be much slower than the others, but generally that is not a big problem.)

The alternative - forcing all clients to remember that you must call X before calling any of A, B, or C - decreases usability; stateful APIs are much harder to operate than stateless ones.

  • OTOH, since OP specified that the initialization requires network calls, this just makes the client wait even longer. I'd spin off a thread (or similar) just after construction to do the work. – user949300 May 9 at 17:22
0

Your problem here is that you didn't separate responsibilities. You need to calculate some data, which is one responsibility, and second one is what to do with that data. So just prepare that data before and pass it as argument to constructor.

0

You don't give your language, but you could return the "result" as something like a

This way your intentions are clear and your client doesn't have to think.

0

Is there a pattern that handles this?

Yes, it's the builder pattern. The builder design pattern (not to be confused with specific implementations of that pattern, eg in the GoF book) is a simple pattern that provides a stateful setup environment (that often includes a sequenced set of setup steps too) that terminates through building the end product.

So in this case, rather than having that one interface,

interface ISomething
{
    void Step1(); // this must be called before Step2()
    void Step2();
}

and hoping that implementers and consumers of the interface pay attention to your comment, you enforce that order through handing the first step over to a simple builder:

interface ISomething
{
    void Step2();
}

class SomethingBuilder
{
    ISomething Step1();
}

var builder = new SomethingBuilder();
var something = builder.Step1();
something.Step2(); // Now Step1 and Step2 can only be called in the correct order
  • That's neither the GoF builder pattern (abstracts builder implementation) nor Joshua Blochs builder pattern (a static member class returns this until it can build the immutable main class). That is the start of an internal Domain Specific Language. iDSLs return different types. But it does do exactly what was asked for. – candied_orange May 9 at 19:29
  • Downvoting cause the Foo, Baz and Bar names are stupid and confusing. (Esp Bar & Baz) – user949300 May 9 at 21:21
  • @candied_orange, in all honesty, I'm hugely relieved to hear that my builder looks nothing like the GoF version. That tome is full of antipatterns and over-engineered implementations of what ought to be very simple patterns and really should be seen as a historic document, rather than a modern source of useful info. – David Arno May 10 at 8:50
  • @candied_orange, I've never heard of Bloch, but you appear to be describing a fluent builder. Fluent builders are indeed an excellent implementation of the pattern and it's an approach I use a lot. But such a builder would likely be over the top for a simple scenario like the OP describes. A builder is simply a holder of intermediate state, which might involve orchestration of a sequence of actions too. As you say, my simple builder here does "exactly what was asked for" and thus is exactly what's needed. Anything more would over complicate things. – David Arno May 10 at 8:57
  • 1
    @DavidArno only trying to improve this answer. It's the only structurally correct one. But its given the pattern a misleading name. Mentioning iDSL and fluent would lead people to better resources. And user949300 has a point. Bar and Baz are well established meaningless names but First() and Second() will serve you better. Naming a pattern is not an endorcement. There are links to relevant blogs here – candied_orange May 10 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.