Introduction to Venus
Tags: perl, oop, programming, venus
Published: 2023-09-25 11:34:47

In a [previous article](https://dev.to/iamalnewkirk/why-i-created-venus-4049), I talked about why I created Venus. In this article, I'd like to formally introduce you to Venus, what it is, and what it does.

## Standard library

Venus provides a standard library; a rich collection of pre-written packages, classes, and roles (i.e. traits) that come bundled with the distribution. This library provides a wide range of functionality that simplifies common programming tasks, making it a valuable resource for both new and experienced Perl developers.

At the heart of Venus' standard library is its focus on simplicity, productivity, and reusability. It includes classes for working with data structures like array references, and hash references, making it easy to manipulate and process collections of data. The String class offers powerful text manipulation capabilities, while the Path and Process classes allow easy and intuitive handling of files and forks. Additionally, the Venus standard library excels in handling dates, JSON, YAML, and more, thanks to those respective classes.

_[example of standardized methods]_
```perl
package main;

use Venus 'array';

my $array = array [1..4];

$array->count;

# 4

# $array->all(sub{ $_ > 0 });
# $array->any(sub{ $_ > 0 });
# $array->each(sub{ $_ > 0 });
# $array->grep(sub{ $_ > 0 });
# $array->map(sub{ $_ > 0 });
# $array->none(sub{ $_ < 0 });
# $array->one(sub{ $_ == 0 });
# $array->random;
```

_[example of standardized methods]_
```perl
package main;

use Venus 'hash';

my $hash = hash {1..8};

$hash->count;

# 4

# $hash->all(sub{ $_ > 0 });
# $hash->any(sub{ $_ > 0 });
# $hash->each(sub{ $_ > 0 });
# $hash->grep(sub{ $_ > 0 });
# $hash->map(sub{ $_ > 0 });
# $hash->none(sub{ $_ < 0 });
# $hash->one(sub{ $_ == 0 });
# $hash->random;
```

## Industry standards

As mentioned in the previous article, Venus is meant to provide Perl with what I refer to as a "baseline feature set for modern software development", i.e. a standard library reflecting industry standards. This baseline tends to include libraries for operating on IO (input/output), data structures, strings (and manipulating them), numbers (and mathematics), concurrency, networking, date and time, serialization, error handling, security (i.e. cryptography), testing, debugging, and more. Venus covers most of these topics fairly well.

_[example file and path creation]_
```perl
package main;

use Venus::Path;

my $path = Venus::Path->new('/path/to/file');

my $write = $path->do('mkdirs')->write('something');
```

_[example fork server operation]_
```perl
package main;

use Venus::Process;

my $parent = Venus::Process->new;

$parent->serve(10, sub {
  my ($process) = @_;
  # do something in forked process ...
  $process->exit;
});
```

## Object orientation

Although Perl is a multiparadigm programming language, Perl and its CPAN are overwhelmingly object-oriented, and Venus builds on this convention by designating everything as an object, and this concept lies at the heart of its design philosophy.

Why roll your own object system? What about Moose, Moo, etc.? The answers are much more sophisticated than what I'll cite here, but suffice to say, Moose is slow to load, operate, and reflect, Moo is fast but hides its automation and uses Moose for reflection. I needed something fast and accessible to load, operate, and reflect on.

Venus' object system was designed to be used by the standard library built atop, but like most things in Venus, it can be reused and leveraged for applications outside of the standard library. The object system will in some ways be familiar to Perl developers who have experience with other bespoke Perl object systems, and in some ways will seem strange.

_[example class with attributes]_
```perl
package Person;

use Venus::Class;

attr 'fname';
attr 'lname';

1;
```

_[example class with base]_
```perl
package User;

use Venus::Class;

base 'Person';

attr 'login';
attr 'password';

1;
```

_[example role]_
```perl
package Authorizable;

use Venus::Role;

attr 'login';
attr 'password';

sub EXPORT {
  ['login', 'password']
}
```

_[example class with base and role]_
```perl
package User;

use Venus::Class;

base 'Person';

with 'Authorizable';

1;
```

_[example class with automation]_
```perl
package User;

use Venus::Class;

base 'Person';

with 'Authorizable';

with 'Venus::Role::Optional';

sub assert_login {

  return 'string';
}

sub default_login {
  my ($self) = @_;
  return join '.', $self->fname, $self->lname;
}

sub assert_password {

  return 'string';
}

sub default_password {
  my ($self) = @_;
  require Venus::Random;
  Venus::Random->new->collect(15, "character");
}

1;
```

## Exception handling

In 20 years of writing Perl, error handling remains one of the most aloof, inconsistent, and disjointed aspects of writing, operating, and integrating with Perl software. Venus attempts to solve this issue with its Error class and error handling architecture. Once you've accepted Venus' mechanisms for deriving, throwing, catching, and identifying errors, you'll never have to "figure it out" again. 

Venus provides an Error class from which all error classes should derive, but as with most things in Venus, it can integrate with other systems and handle foreign error classes just fine too. Venus errors can exist both on-disk and in-memory, helping to avoid having numerous error classes on-disk. Errors can be made and identified as hierarchal in-memory, helping to easily react to classes of errors in addition to specific ones.

_[example of on-disk error class]_
```perl
package MyApp::Error;

use Venus::Class;

base 'Venus::Error';

1;
```

_[example of in-memory error class]_
```perl
package main;

use Venus 'raise';

my $error = raise 'MyApp::Error';

# $error->throw;
```

_[example of in-memory error hierarchy]_
```perl
package main;

use Venus 'raise';

my $error = raise 'Http::Error', {
  name => 'on.http.4xx.401'
};

# $error->is('on.http.4xx.401');
# $error->of('on.http.4xx');
# $error->of('on.http');
```

_[example catch of error class]_
```perl
package main;

use Venus 'catch';

my ($error, $result) = catch {error};

# $error->throw if $error;
```

## Abstract behaviors

The impetus for Venus, and indeed all standard libraries, is to set developers up for success within a given programming language. The standard library classes, which are largely value and utility classes, can be derived and extended. The consistency (i.e. the standardization of names and behaviors) in those classes is owed to the collection of roles (i.e. traits) they consume. Providing these core behaviors as roles is intentional as it allows users of the Venus distribution to extend their own classes and applications using the same abstract behaviors used in the standard library, all of which are well-written and well-tested.

_[example using built-in try/catch/throw]_
```perl
package MyApp;

use Venus::Class;

with 'Venus::Role::Tryable';
with 'Venus::Role::Catchable';
with 'Venus::Role::Throwable';

sub execute {
  die;
}

package main;

my $myapp = MyApp->new;

# my $result = $myapp->try('execute')->maybe->result;
# my $error = $myapp->catch('execute')
# $myapp->throw->error;
```

## Architecture

Venus itself is an attempt to solve some of Perl's language and core library problems with architecture. There's no magic, no source filtering, no experimental features. It's just vanilla Perl and know-how from years of using Perl to build production systems, and some inspiration from other popular programming languages.

The Venus standard library is mostly comprised of value classes, i.e. classes with wrap native Perl values and provides methods for operating on them, all of which are derived from Venus::Kind::Value, and utility classes, i.e. classes that represent an operation or set of operations specific to a language ability, e.g. manipulating files and file paths, and which are derived from Venus::Kind::Utility.

Additionally, Venus provides mechanisms for object orientation, autoboxing, gradual typing, concurrency, prototype-based programming, and more. The design is meant to promote convention over configuration and be intuitive.

_[example of opt-in autoboxing]_
```perl
#
# Opt-in to autoboxing
#

use Venus::String;

Venus::String->new('hello world')->box->do('say')->lowercase->titlecase->do('say')->say('get');
```

_[example of date/time operations]_
```perl
#
# ISO8601 string, 2 days from the start of the month
#

use Venus::Date;

Venus::Date->new->restart_month->add_days(2)->say('iso8601');
```

_[example of async operations]_
```perl
#
# Launch 5 processes and report all PIDs
#

use Venus::Process;

Venus::Process->new->do('works', 5, sub {warn $_})->do('waitall')->say('get');
```

**See for Yourself!**

[Venus on CPAN](https://metacpan.org/dist/Venus)