GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages


Manual Reference Pages  -  BREAD::BOARD::MANUAL::CONCEPTS::ADVANCED (3)

.ds Aq ’

NAME

Bread::Board::Manual::Concepts::Advanced - An overview of some of the more advanced Bread::Board concepts

CONTENTS

VERSION

version 0.32

INTRODUCTION

In the Bread::Board::Manual::Concepts document we attempted to explain the conceptual foundations of Bread::Board. In that we exposed you to the idea of a container and a service and showed how they could be used. In that document we built a hierarchal container which organized different sets of services into what could be seen as subsystems within an overall application. While this alone has plenty of value, you might be asking yourself, what about re-use? Bread::Board already encourages decoupled object design by removing the need to manually wire your application components together, but what about re-using Bread::Board components themselves?

This document will illustrate some of the more advanced concepts in Bread::Board with the specific focus on re-use and extension.

ADVANCED CONCEPTS

NOTE: This is just a quick sketch of these docs, more to come in the next few releases, for now I need to get this one out the door.

    Subclassing

Bread::Board was built from the very start to be an open system and to allow for the subclassing of all its internal components.

Here is a simple example of extending Bread::Board::Container to build a container specific to your application.



  package My::Application::Container;
  use Moose;
  use Bread::Board;

  extends Bread::Board::Container;

  has log_file_name => (
      is      => ro,
      isa     => Str,
      default => logfile.log,
  );

  sub BUILD {
      my $self = shift;
      container $self => as {

          service log_file => $self->log_file_name;

          service logger => (
              class        => My::FileLogger,
              lifecycle    => Singleton,
              dependencies => {
                  log_file => depends_on(log_file),
              }
          );

          service application => (
              class        => My::Application,
              dependencies => {
                  logger => depends_on(logger),
              }
          );
      };
  }



Then you can simply create an instance of the container and instantiate an instance of the application.



  my $c = My::Application::Container->new(
      name          => MyLoggingContainer,
      log_file_name => other_logfile.log
  );

  my $app = $c->resolve( service => application);



It should be noted that when calling the constructor of a subclass of Bread::Board::Container, you must pass the name attribute as a parameter. Additionally you could use the +name syntax in the subclass itself like so:



  has +name => ( default => MyLoggingContainer );



which will remove the requirement in the constructor unless you choose to override it.

It is also possible to extend/specialize a Bread::Board::Service type to customize it for your needs.

More to come later.

    Parameterized Containers

Extending containers is just one form of re-use, just like extending a class in plain old OOP. But Bread::Board also provides another means of re-use, and that is parameterized containers.

If you are familiar with functors in Standard ML or O’Caml then this might look familiar to you. A parameterized container is basically a container which expects another container (or containers) as an argument and produces a third container as the result.

Lets take a simple example here of a Logger object which logs to a database.



  my $db_logger = container DatabaseLogger => [ DBConnInfo ] => as {
      service handle => (
          class        => My::Database::Logger,
          dependencies => {
              dsn      => depends_on(DBConnInfo/dsn),
              username => depends_on(DBConnInfo/username),
              password => depends_on(DBConnInfo/password),
          }
      );
  };



It is parameterized with a DBConnInfo container which has three services, a dsn, a username and a password. Now let’s create a simple container which fufills these requirements.



  my $db_conn_info = container DatabaseConnection => as {
      service dsn      => dbi:mysql:foo;
      service username => bar;
      service password => ***;
  };



The above container fulfills the bare minimum, but this could have just as easily have been a much more complex container which also had a service for a DBIx::Class schema, or a KiokuDB directory object. As long as the container provided the three required services, that was all that the DatabaseLogger parameterized container required.

Now, a parameterized container is not a usable container, you must create an instance of it. That is as simple as calling the create method, like so.



  my $my_db_logger = $db_logger->create(
      DBConnInfo => $db_conn_info
  );



After which you can use it just like any other Bread::Board container would be used.



  my $log_handle = $my_db_logger->resolve(
      service => handle
  );



Parameterized containers can also be nested, here is an example of an Application container that expects a Logger.



  my $app = container Application => [ Logger ] => as {
      service app => (
          class        => My::Application,
          dependencies => {
              log_handle => depends_on(Logger/handle)
          }
      );
  };



And here we instantiate an instance of our Application container using the DatabaseLogger.



  my $db_app = $app->create(
      Logger => $db_logger->create(
          DBConnInfo => $db_conn_info
      )
  );



And of course, since the Logger is a parameter we could just as easily pass in a simpler screen logger for a test environment or something. Here is what that would look like.



  my $simple_logger = container SimpleLogger => as {
      service handle => (
          class => My::Simple::Logger
      );
  };

  my $simple_app = $app->create(
      Logger => $simple_logger
  );



Parameterized containers provide a useful and powerful means of re-use and abstraction, making it easy to create flexible containers to model your applications subsystems.

AUTHOR

Stevan Little <stevan@iinteractive.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by Infinity Interactive.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

Search for    or go to Top of page |  Section 3 |  Main Index


perl v5.20.3 BREAD::BOARD::MANUAL::CONCEPTS::ADVANCED (3) 2014-06-03

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with manServer 1.07.