{"id":15557706,"url":"https://github.com/fgasper/p5-x-tiny","last_synced_at":"2025-06-24T21:05:18.068Z","repository":{"id":56837300,"uuid":"83163170","full_name":"FGasper/p5-X-Tiny","owner":"FGasper","description":"CPAN’s X::Tiny","archived":false,"fork":false,"pushed_at":"2022-08-10T18:12:19.000Z","size":53,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-03T13:45:13.586Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FGasper.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-25T21:13:23.000Z","updated_at":"2022-10-16T20:18:44.000Z","dependencies_parsed_at":"2022-09-08T05:11:15.549Z","dependency_job_id":null,"html_url":"https://github.com/FGasper/p5-X-Tiny","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-X-Tiny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-X-Tiny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-X-Tiny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-X-Tiny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FGasper","download_url":"https://codeload.github.com/FGasper/p5-X-Tiny/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246135739,"owners_count":20729056,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-02T15:20:26.187Z","updated_at":"2025-03-29T03:46:34.332Z","avatar_url":"https://github.com/FGasper.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nX::Tiny - Base class for a bare-bones exception factory\n\n# SYNOPSIS\n\n    package My::Module::X;\n\n    use parent qw( X::Tiny );\n\n    #----------------------------------------------------------------------\n\n    package My::Module::X::Base;\n\n    use parent qw( X::Tiny::Base );\n\n    #----------------------------------------------------------------------\n\n    package My::Module::X::IO;\n\n    use parent qw( My::Module::X::Base );\n\n    #----------------------------------------------------------------------\n\n    package My::Module::X::Blah;\n\n    use parent qw( My::Module::X::Base );\n\n    sub _new {\n        my ($class, @args) = @_;\n\n        my $self = $class-\u003eSUPER::_new('Blah blah', @args);\n\n        return bless $self, $class;\n    }\n\n    #----------------------------------------------------------------------\n\n    package main;\n\n    local $@;   #always!\n    eval {\n        die My::Module::X-\u003ecreate('IO', 'The message', key1 =\u003e val1, … );\n    };\n\n    if ( my $err = $@ ) {\n        print $err-\u003eget('key1');\n    }\n\n    die My::Module::X-\u003ecreate('Blah', key1 =\u003e val1, … );\n\n# DESCRIPTION\n\nThis stripped-down exception framework provides a baseline\nof functionality for distributions that want to expose exception\nhierarchies with minimal fuss. It’s a pattern that I implemented in some\nother distributions I created and didn’t want to copy/paste around.\n\n# BENEFITS OF EXCEPTIONS\n\nExceptions are better for error reporting in Perl than the\nC-style “return in failure” pattern. In brief,\nyou should use exceptions because they are a logical, natural way to report\nfailures: if you’re given a set of instructions, and something goes wrong\nin one of those instructions, it makes sense to stop and go back to see what\nto do in response to the problem.\n\nPerl’s built-ins unwisely make the caller responsible for error checking—as\na result of which much Perl code fails to check for failures from those\nbuilt-ins, which makes for far more difficult debugging when some code down\nthe line just mysteriously produces an unexpected result.\nThe more sensible pattern is for an exception to be thrown at the spot where\nthe error occurred.\n\nPerl’s default exceptions are just scalars. A more useful pattern is to throw\nexception objects whose type and attributes can facilitate meaningful\nerror checking; for example, you may not care if a call to `unlink()` fails\nwith `ENOENT`, so you can just ignore that failure. Or, you might care, but\nyou might prefer just to `warn()` rather than to stop what you’re doing.\n\nX::Tiny is one of many CPAN modules that facilitates this pattern. What\nseparates X::Tiny from other such modules is its light weight: the only\n“heavy” dependency is [overload](https://metacpan.org/pod/overload), which is (in my experience) a reasonable\ntrade-off for the helpfulness of having stack traces on uncaught exceptions.\n(The stack trace is custom logic, much lighter than [Carp](https://metacpan.org/pod/Carp).)\n\n# FEATURES\n\n- Super-lightweight: No exceptions are loaded until they’re needed.\n- Simple, flexible API\n- String overload with stack trace\n- Minimal code necessary\n\n# USAGE\n\nYou’ll first create a factory class that subclasses `X::Tiny`.\n(In the SYNOPSIS’s example, this module is `My::Module::X`.) All of your\nexceptions **must** exist under that factory class’s namespace.\n\nYou’ll then create a base exception class for your distribution.\nIn the SYNOPSIS’s example, this module is `My::Module::X::Base`.\nYour distribution’s other exceptions should all subclass this one.\n\n# METHODS\n\nThere’s only one method in the factory class:\n\n## _CLASS_-\u003ecreate( TYPE, ARG1, ARG2, .. )\n\nTo create an exception, call the `create()` method of your factory class.\nThis will load the exception class if it’s not already in memory.\nThe TYPE you pass in is equivalent to the exception class’s module name but\nwith the factory class’s name chopped off the left part. So, if you call:\n\n    My::Module::X-\u003ecreate('BadInput', 'foo', 'bar')\n\n… this will instantiate and return an instance of `My::Module::X::BadInput`,\nwith the arguments `foo` and `bar`.\n\n# EXCEPTION OBJECTS\n\nSee [X::Tiny::Base](https://metacpan.org/pod/X%3A%3ATiny%3A%3ABase) for more information about the features that that\nmodule exposes to subclasses.\n\n# DESIGN CONSIDERATIONS\n\nAdmittedly, the lazy-loading behavior here embodies a generally-unwise\npractice of doing failure-prone work (i.e., loading a module at runtime)\nin the process of reporting a failure.\nIn my own experience, though, that’s a reasonable tradeoff for the\nexpressiveness of typed exceptions.\n\nDo be sure that any failure-prone work you do as part of exception\ninstantiation has its own failure-checking mechanism. There really are not\nmeant to be “sub-failures” here!\n\n# REPOSITORY\n\n[https://github.com/FGasper/p5-X-Tiny](https://github.com/FGasper/p5-X-Tiny)\n\n# AUTHOR\n\nFelipe Gasper (FELIPE)\n\n# COPYRIGHT\n\nCopyright 2017-2019 by [Gasper Software Consulting](http://gaspersoftware.com)\n\n# LICENSE\n\nThis distribution is released under the same license as Perl.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgasper%2Fp5-x-tiny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffgasper%2Fp5-x-tiny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgasper%2Fp5-x-tiny/lists"}