-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?

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

4 Answers4

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.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • 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 09 '19 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

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
David Arno
  • 38,972
  • 9
  • 88
  • 121
  • 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 09 '19 at 19:29
  • Downvoting cause the Foo, Baz and Bar names are stupid and confusing. (Esp Bar & Baz) – user949300 May 09 '19 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 '19 at 08: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 '19 at 08:57
  • @user949300, I'm sorry to hear that those universally used metasyntactic names confuse you. [You might want to get used to them as they are frequently used in software engineering](https://en.wikipedia.org/wiki/Metasyntactic_variable). Being a Brit, I actually prefer `wibble`, `wobble` and `flob`, but those pesky Americans won out on this topic so I use their terms for clarity. It's more than a little ironic therefore that it's an American complaining that they are confusing. Ho hum. – David Arno May 10 '19 at 09:02
  • 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](https://softwareengineering.stackexchange.com/a/329731/131624). There are links to relevant blogs [here](https://stackoverflow.com/questions/22909717/is-this-monster-builder-a-good-builder-factory-pattern-for-abstracting-long-co) – candied_orange May 10 '19 at 12:25
  • @DavidArno I don't mind Foo and FooBuilder, or even Bar and Baz as class names. But the **methods** should be named something like `builder .build()` or `builder .make()`, or possibly `.first()`, `second()` as in candied orange's comment. – user949300 May 10 '19 at 18:32
  • @user949300, fair enough. I've given in and used other terms. – David Arno May 13 '19 at 08:23
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.

user949300
  • 8,679
  • 2
  • 26
  • 35