The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

OP - Compact Perl 5 class prototyping with object persistence

VERSION

This documentation is for version 0.212 of OP.

STATUS

The usual pre-1.0 warnings apply. Consider this alpha code. It does what we currently ask of it, and maybe a little more, but it is a work in progress.

SYNOPSIS

  use OP;

Using the OP module initializes all built-in object types, and causes strict, diagnostics, OP::Class, OP::Type, Perl6::Subs, and Error to be imported by the caller. These may alternately be imported individually.

A cheat sheet, cheat.html, is included with this distribution.

DESCRIPTION

Compact and concise class prototyping, with object persistence.

OP is a Perl 5 dialect for deriving object classes and database schemas. Apps developed and executed under OP have a greater degree of formality and consistency than one may be accustomed to seeing in Perl.

This document covers the high-level concepts implemented in OP.

FEATURES

Class Prototyping with Transparent Persistence

Inspired by Prototype.js in the JavaScript world, OP::Class provides the create function, enabling developers to craft database-backed Perl 5 classes in a compact and concise manner.

Database tables are derived from object classes. By default, new classes include methods to save to and load from persistent backing stores. Complex schemas may be quickly modeled in code and put to use.

Instance Variable Assertions

Mitigate garbage input through the use of typing and subtype rules (OP::Type). Enforce strict control of instance variables, table column behavior, and automatically derive database constraints.

List Collectors

Inspired by language features in Ruby and Python, OP implements list collection methods, complemented by a set of functions which may be used to finely control the flow of execution.

Formal Methods & Exceptions

Exception handling is brought in from the Error module. try, throw, and catch are first-class citizens in the OP runtime.

Perl 6-style method support is provided by the Perl6::Subs source filter, and is used extensively throughout OP source and its examples. OP also implements a generalized subset of Perl 6-derived object types.

Async-Ready

OP provides first-class support for Coro and POE. See OP::Recur and OP::Persistence::Async.

FRAMEWORK ASSUMPTIONS

When using OP, a number of things "just happen" by design. Trying to go against the flow of any of these base assumptions is not recommended.

Default Modules

strict, warnings, Error, and Perl6::Subs are on by default.

Persistent Objects Extend OP::Node

Classes allocated with create will receive an InnoDB backing store, by virtue of being a subclass of OP::Node. This can be overridden if needed, see the subclassing examples in this document, as well as "Inheritance" in OP::Class, for details.

Various backing store options are covered in the OP::Persistence module.

Default Base Attributes

Unless overridden in __baseAsserts, OP::Node subclasses have the following baseline attributes:

  • id => OP::ID

    id is the primary key at the database table level.

    Objects will use a GUID (globally unique identifier) for their id, unless this behavior is overridden in the instance method _newId(), and __baseAsserts() overridden to use a non-GUID data type such as OP::Int.

    id is automatically set when saving an object to its backing store for the time. Modifying id manually is not recommended.

  • name => OP::Name

    OP uses "named objects". By default, name is a human-readable unique secondary key. It's the name of the object being saved. Like all attributes, name must be defined when saved, unless asserted as ::optional (see "undef Requires Assertion").

    The value for name may be changed (as opposed to id, which should not be tinkered with), as long as the new name does not conflict with any objects in the same class when saved.

    name may be may be keyed in combination with multiple attributes via the ::unique OP::Subtype argument, which adds InnoDB reference options to the schema.

      create "YourApp::Class" => {
        #
        # Don't require named objects:
        #
        name => OP::Name->assert(::optional),
    
        # ...
      };
  • ctime => OP::DateTime

    ctime is the Unix timestamp representing the object's creation time. OP sets this when saving an object for the first time.

  • mtime => OP::DateTime

    mtime is the Unix timestamp representing the object's last modified time. OP updates this each time an object is saved.

undef Requires Assertion

Instance variables may not be undef, unless asserted as ::optional.

Object instances in OP may not normally be undef. Generally, if a value is not defined, OP currently returns undef rather than an undefined object instance. This may change at some point.

Namespace Matters

OP's core packages live under the OP:: namespace. Your classes should live in their own top-level namespace, e.g. "YourApp::".

OBJECT TYPES

OP implements the same object class types referred to in Perl6::Subs, several others which are specific to dealing with a SQL backing store (e.g. Double, ExtId), as well as datatypes commonly used in network operations (e.g. EmailAddr, IPv4Addr, URI).

OP object types are used when asserting attributes within a class, and are also suitable for instantiation or subclassing in a self-standing manner.

The usage of these types is not mandatory outside the context of creating a new class-- OP always returns data in object form, but these object types are not a replacement for Perl's native data types in general usage, unless the developer wishes them to be.

These modes of usage are shown below, and covered in greater detail in specific object class docs.

DECLARING AS SUBCLASS

By default, a superclass of OP::Node is used for new classes. This may be overridden using __BASE__:

  use OP;

  create "YourApp::Example" => {
    __BASE__ => "OP::Hash",

  };

or

  package YourApp::Example;

  use strict;
  use warnings;

  use base qw| OP::Hash |;

  1;

ASSERTING AS ATTRIBUTES

When defining the allowed instance variables for a class, the assert() method is used:

  #
  # File: Example.pm
  #
  use OP;

  create "YourApp::Example" => {
    someString => OP::Str->assert,
    someInt    => OP::Int->assert,

  };

INSTANTIATING AS OBJECTS

When instantiating, the class method new() is used, typically with a prototype object for its argument.

  #
  # File: somecaller.pl
  #
  use strict;
  use warnings;

  use YourApp::Example;

  my $example = YourApp::Example->new(
    name       => "Hello",
    someString => "foo",
    someInt    => 12345,
  );

  $example->save("Saving my first object");

  $example->print;

IN METHODS

To ensure method arguments are always of the appropriate type, specify the desired type(s) in a Perl6::Subs prototype.

Constructors and setter methods accept both native Perl 5 data types and their OP object class equivalents. The setters will automatically handle any necessary conversion, or throw an exception if the received arg doesn't quack like a duck.

To wit, native types are OK for constructors:

  my $example = YourApp::Example->new(
    someString => "foo",
    someInt    => 123,
  );

  #
  # someStr became a string object:
  #
  say $example->someString->class;
  # "OP::Str"

  say $example->someString->size;
  # "3"

  say $example->someString;
  # "foo"

  #
  # someInt became an integer object:
  #
  say $example->someInt->class;
  # "OP::Int"

  say $example->someInt->sqrt;
  # 11.0905365064094

Native types are OK for setters:

  $example->setSomeInt(456);

  say $example->someInt->class;
  # "OP::Int"

ABSTRACT CLASSES & MIX-INS

OBJECT TYPES

These Perl 5 classes represent a generalization of their Perl 6 counterparts, at best, also introducing several object types specific to dealing with a SQL backing store. OP is not intended to be a Perl 6 implementation at all; there are inconsistencies and cut corners in the usage of these classes, compared to what Perl 6 will look like. OP borrows many of these class names for consistency with Perl6::Subs, and to have less things to remember when coding.

The basic types listed here may be instantiated as objects, or asserted as inline attributes.

CONSTANTS & ENUMERATIONS

HELPER MODULES

EXPERIMENTAL*: INFOMATICS

Experimental classes are subject to radical upheaval, questionable documentation, and unexplained disappearances. They represent proof of concept in their respective areas, and may move out of experimental status at some point.

EXPERIMENTAL: SCHEDULING

EXPERIMENTAL: FOREIGN DB ACCESS

EXPERIMENTAL: INTERACTIVE SHELL

EXPERIMENTAL: BULK TABLE WRITER

SEE ALSO

Perl6::Subs, OP::Class, OP::Type

Perl6 Synopsis 02: Bits and Pieces (Object Types) - http://svn.pugscode.org/pugs/docs/Perl6/Spec/S02-bits.pod

AUTHOR

  Alex Ayars <pause@nodekit.org>

COPYRIGHT

  File: OP.pm
 
  Copyright (c) 2009 TiVo Inc.
 
  All rights reserved. This program and the accompanying materials
  are made available under the terms of the Common Public License v1.0
  which accompanies this distribution, and is available at
  http://opensource.org/licenses/cpl1.0.txt