Chad Granum > DCI > DCI

Download:
DCI-0.013.tar.gz

Dependencies

Annotate this POD

View/Report Bugs
Module Version: 0.013   Source  

NAME ^

DCI - Collection of utilities for writing perl code that fits the DCI methodology.

DESCRIPTION ^

The DCI concept was created by Trygve Reenskaug, (inventor of MVC) and James Coplien.

DCI Stands for Data, Context, Interactions. It was created to solve the problem of unpredictable emergent behavior in networks of interacting objects. This problem shows itself in complex OOP projects, most commonly in projects with deep polymorphism. This is a problem that Procedural/Imperative Programming does not have.

DCI does not replace OOP, instead it augments it with lessons learned from looking back at Procedural Programming. It defines a way to encapsulate use cases into a single place. This provides an advantage to the programmer by reducing the number of interactions that need to be tracked. Another advantage is the reduction of side-effects between contexts.

Another way to look at it is that a DCI implementation is much more maintainable as a project matures. Changes to requirements and additional features cause clean OOP project to degrade into spaghetti. DCI on the other hand maintains code clarity under changing requirements.

MORE ABOUT DCI ^

Look at DCI::Introduction for a complete introduction into DCI concepts.

SYNOPSIS ^

This synopsis is very basic, see individual modules for better module-specific examples. Also see DCI::Introduction if you do not yet understand DCI concepts.

DUMB DATA CLASS

    package Test::Data;
    use strict;
    use warnings;

    sub new {
        my $class = shift;
        my ( $value ) = @_;
        return bless( \$value, $class );
    }

    sub get_text { ${ $_[0] } }

    sub set_text { 
        my $self = shift;
        my ( $new_val ) = @_;
        $$self = $new_val;
    }

    1;

TRIVIAL CAST CLASS (ROLE)

    package Test::Cast;
    use strict;
    use warnings;

    use DCI qw/Cast/;

    # Delegate the text() method to the 'core'
    delegate qw/text/;

    # Restrict core to being a Test::Data object.
    require_core qw/Test::Data/;

    # Generate some accessors which keep state in the Cast, but do not interfer
    # with the Core object.
    accessors qw/cache/;

    # Add a method to our cast
    sub render {
        my $self = shift;

        my $cached = $self->cache;

        # text() is delgated to the underlying 'core'
        $cached = $self->cache(
            "The text is: '" . $self->text() . "'\n"
        ) unless $cached;

        return $cached;
    }

    1;

A CONTEXT

    package Test::Context;
    use strict;
    use warnings;

    use DCI qw/Context/;
    use Test::Cast;

    # Declare some required member objects
    cast first => 'Test::Cast',
         last  => 'Test::Cast';

    # export a function named 'quick_render' that constructs the object from
    # arguments, and returns the result of running the 'render()' method on the
    # created object.
    sugar quick_render => (
        method  => 'render',
        ordered => [qw/ first last /]
    );

    # A sugar export that takes named arguments.
    sugar parametric_render => 'render';

    # Method we use to kick-off the encapsulated task of the Context.
    sub render { shift->first->render }

    1;

PUTTING IT ALL TOGETHER

    use Test::More;

    use Test::Context qw/quick_render/;

    is(
        quick_render( "String A", "String B" ),
        "The text is: 'String A'\nThe text is: 'String B'",
        "Rendered first and last strings using quick sugar"
    );

    is(
        parametric_render(
            first => "String A",
            last  => "String B",
        ),
        "The text is: 'String A'\nThe text is: 'String B'",
        "Rendered first and last strings using named parameters"
    );

    my $it = Test::Context->new(
        first => "String A",
        last  => "String B",
    );

    is(
        $it->render,
        "The text is: 'String A'\nThe text is: 'String B'",
        "Rendered first and last strings from onbject instance"
    );

    1;

OBJECT TYPES ^

CONTEXT

SUGAR FUNCTIONS

See DCI::Meta::Context which actually exports the sugar.

METHODS

See DCI::Context the base class for all Casts.

CAST

SUGAR FUNCTIONS

See DCI::Meta::Cast which actually exports the sugar.

METHODS

See DCI::Cast the base class for all Casts.

API STABILITY ^

Versions below 0.011 were a prototype, the API was subject to flux. For 0.011 the API has been completely re-written using the lessons learned from the old API.

As of 0.011, the API can be considered stable. This means that changes which break backwards compatibility will be few and far between.

SEE ALSO ^

DCI::Meta::Context

Meta class for contexts

DCI::Meta::Cast

Meta class for casts

DCI::Context

Base class for contexts

DCI::Cast

Base class for casts

ACHNOWLEDGEMENTS ^

The DCI concept was created by Trygve Reenskaug, (inventor of MVC) and James Coplien.

AUTHORS ^

Chad Granum exodist7@gmail.com

COPYRIGHT ^

Copyright (C) 2011 Chad Granum

DCI is free software; Standard perl licence.

DCI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.

syntax highlighting: