DEV Community

Al Newkirk
Al Newkirk

Posted on

Introduction to Venus

In a previous article, 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]

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;
Enter fullscreen mode Exit fullscreen mode

[example of standardized methods]

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;
Enter fullscreen mode Exit fullscreen mode

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]

package main;

use Venus::Path;

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

my $write = $path->do('mkdirs')->write('something');
Enter fullscreen mode Exit fullscreen mode

[example fork server operation]

package main;

use Venus::Process;

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

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

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]

package Person;

use Venus::Class;

attr 'fname';
attr 'lname';

1;
Enter fullscreen mode Exit fullscreen mode

[example class with base]

package User;

use Venus::Class;

base 'Person';

attr 'login';
attr 'password';

1;
Enter fullscreen mode Exit fullscreen mode

[example role]

package Authorizable;

use Venus::Role;

attr 'login';
attr 'password';

sub EXPORT {
  ['login', 'password']
}
Enter fullscreen mode Exit fullscreen mode

[example class with base and role]

package User;

use Venus::Class;

base 'Person';

with 'Authorizable';

1;
Enter fullscreen mode Exit fullscreen mode

[example class with automation]

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;
Enter fullscreen mode Exit fullscreen mode

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]

package MyApp::Error;

use Venus::Class;

base 'Venus::Error';

1;
Enter fullscreen mode Exit fullscreen mode

[example of in-memory error class]

package main;

use Venus 'raise';

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

# $error->throw;
Enter fullscreen mode Exit fullscreen mode

[example of in-memory error hierarchy]

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');
Enter fullscreen mode Exit fullscreen mode

[example catch of error class]

package main;

use Venus 'catch';

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

# $error->throw if $error;
Enter fullscreen mode Exit fullscreen mode

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]

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;
Enter fullscreen mode Exit fullscreen mode

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]

#
# Opt-in to autoboxing
#

use Venus::String;

Venus::String->new('hello world')->box->do('say')->lowercase->titlecase->do('say')->say('get');
Enter fullscreen mode Exit fullscreen mode

[example of date/time operations]

#
# ISO8601 string, 2 days from the start of the month
#

use Venus::Date;

Venus::Date->new->restart_month->add_days(2)->say('iso8601');
Enter fullscreen mode Exit fullscreen mode

[example of async operations]

#
# Launch 5 processes and report all PIDs
#

use Venus::Process;

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

See for Yourself!

Venus on CPAN

Top comments (4)

Collapse
 
oldtechaa profile image
oldtechaa

This looks stunning. Are there any major limitations that would inhibit it in major usecases? Also, is there a concern about it becoming too monolithic (see Boost)?

Collapse
 
iamalnewkirk profile image
Al Newkirk

@oldtechaa No, the distribution is extremely well-tested and stable, see CPANTS (and the history there). I’m not familiar with the Boost story (but I do know what it is), could you explain the story around Boost becoming too monolithic?!

The plan for Venus is for it to roll out two more major features that I think embody a modern/futuristic standard library and then to consider the project complete, then work on marketing, documentation, and enhancing stability.

Collapse
 
oldtechaa profile image
oldtechaa

Sounds great! Yeah, Boost is just known for being a massive collection of addons for C++ that includes everything from image processing to random number generation to multithreading to testing. It's humongous. I like the idea of a Perl standard library though.

Thread Thread
 
iamalnewkirk profile image
Al Newkirk

Oh, I see. Yeah, the scope of Venus is much narrower than that. Maybe that scope creep happened to Boost because C++ doesn't have a CPAN equivalent. Simply put, I don't think you should need to go to the CPAN for things like string manipulation, hash operations, and a proper forking library, but CPAN is still the right choice for web frameworks, cryptography, DB drivers, etc.