We are finally there! You have learned enough about all the JavaScript concepts that make SOOJS what it is. It’s time to dive into the real pattern itself. This should be much easier now that you see why things are being done this way.

Note: There is a LOT of JavaScript closure going on with SOOJS to manage scope. Closure is much less magical than it sounds. I will leave it to the reader to investigate on their own if needed.

So, now where is our object?

As a note, but you know this already, the above class would be in a file called Dog.js. Very likely in a subdirectory holding our standard objects.

So, let’s start here. This is the main mechanism of SOOJS. We start by overtly defining my as this in the very beginning. Thus we never bump into nasty scoping issues as we dive deeper into internal objects later. Now, everywhere within this class when we use my we mean this instance of the main object. I also show the delegateRef here because the delegate pattern is very emebeded in the SOOJS pattern. You can remove it or not use it (like anything else here) but I bet once you see the value it will become a great friend of yours, as it is mine.

Also, note that the signature here can be anything at all. I’ve added the breed and name from before just to show we could start with anything we like. This is, in essence, your constructor. Let’s step into the next elements:

 

Okay, it got just a little more complex here. First know that SOOJS advises an explicit “initialize” function to be called at the end of the class definition. There are some reasons I won’t cover here, but it has to do with forward-definitions. If you don’t wait until things are truly defined in the class then you run into all those odd “undefined” errors. Basically, you will call a function at the end to run the initialize() code. Very little else has any order of precedence in the pattern.

It would be fine to not include the init mechanism, and in simple objects I often find myself pulling the code out all together to make cleaner implementations, but the pattern has it there by default. Again, you are writing all of this so do whatever is needed. Later I will share some standard “templates” with you. If the editor you use allows for file templates I highly advise plugging these in. Then you will always start with a stubbed-out SOOJS class that has this stuff in this order already.

Great, let’s dive just a bit deeper. (See how easy this is now?)

 

Alright. Now we have something quite new here. And it’s a core concept in the SOOJS pattern. Internal objects to create namespace.

Scope is very important in an OO pattern. We need to be careful about not redefining things or attaching things at the wrong layer. SOOJS deals with all of these complexities with a little inner-object name-spacing. In this case I’m showing the requests object. It will be easiest if you don’t think of these things as objects as much as containers for functionality and scope. They are, of course, objects.

As you can see in the initialize() function we can now ask this dog to bark. So this is all coming together nicely. First, let’s extend our internal objects a bit to show why they are separated like this…

Okay, this is really filling in with a structure now. Looking closely at it you can see there is a new internal object defined: internals. This is exactly the same as the requests object we created earlier. Nothing magical here, and any names at all can be used.

Note: I highly advise sticking with these names for your early work. It’s this consistency that makes SOOJS a real pattern. If the next guy can’t trust that you have a requests object then all is lost.

The idea I’m showing you here (slowly) is that internal to the object there are sections or areas of scope. The internals object above is your object’s guts. This is where you can put all your functional work that you need to make the dog a Dog. It also serves (as the name indicates) as a private section. None of this will be visible to the outside user. Their code inspector will show them the requests object and requests.bark().

SOOJS is very concerned with code-completion and IDEs. One of the biggest reducers of bugs is clearly exposed APIs to objects and subsystems. If you have barkToConsole() exposed to the outside world as well as bark() then how does a developer using your object know which he should use? Are they the same? Are they equal? Then when someone needs to update the Dog object they have to account for the fact that some code-lines are pointing to bark() and others to barkToConsole().

Let’s illustrate this with a boolean that changes how our dog barks:

Okay, things are getting really large here. We have several namespaces (internal objects) that are being tested and called internally to keep things nice and tidy. Now the dog can bark in several ways depending on the debug setting. And this setting is specific to each dog.

If you’re reading along in the code and trying to make real sense of it I think things are starting to click about now. Basically, we have a fully-formed object. But wait… there is one thing that doesn’t work at all here. From the outside world let’s say we did this:

Then we pulled up our code completion dialog in an IDE for sallyDog and we don’t see anything externally exposed. We have forgotten to “hang” the requests object out for the public. That is very easy code, and standard in the SOOJS pattern. It looks like this:

And it’s placed right before the initialize() call. So we get this

After we do that what we see is this:

  • sallyDog
    • requests
      • bark
      • getName

So, we have created a complete and encapsulated object here. There is one major item left to discuss and I’ll save that for the next section: the delegate pattern.

Oh, and if you are wondering about our object at this point it looks like this:

 

 

Series Navigation<< Core Concepts: Public vs. PrivateThe Delegate Pattern >>