<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Damien Krotkine</title>
 <link href="http://dams.github.com/atom.xml" rel="self"/>
 <link href="http://dams.github.com/"/>
 <updated>2020-08-16T14:38:52+00:00</updated>
 <id>http://dams.github.com/</id>
 <author>
   <name>Damien Krotkine</name>
   <email>dams@zarb.org</email>
 </author>

 
 <entry>
   <title>Riak as Events Storage</title>
   <link href="http://dams.github.com/2018/01/01/RiakEventsStorage.html"/>
   <updated>2018-01-01T00:00:00+00:00</updated>
   <id>http://dams.github.com/2018/01/01/RiakEventsStorage</id>
   <content type="html">&lt;p&gt;– &lt;em&gt;This post is a compilation of four old posts. They are gathered here in one piece for more clarity, and for archiving purpose. The work described in this post was done over the years 2014-2016&lt;/em&gt; –&lt;/p&gt;

&lt;h1 id=&quot;riak-as-events-storage&quot;&gt;Riak as Events Storage&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://booking.com&quot;&gt;Booking.com&lt;/a&gt; constantly monitors, inspects, and
analyzes our systems in order to make decisions. We capture and channel
&lt;strong&gt;events&lt;/strong&gt; from our various subsystems, then perform real-time, medium
and long-term computation and analysis.&lt;/p&gt;

&lt;p&gt;This is a critical operational process, since our daily work always gives
precedence to data. Relying on data removes the guesswork in making sound
decisions.&lt;/p&gt;

&lt;p&gt;In this series of blog posts, we will outline details of our data pipeline, and
take a closer look at the short and medium-term storage layer that was
implemented using &lt;a href=&quot;http://basho.com/products/#riak&quot;&gt;&lt;strong&gt;Riak&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;introduction-to-events-storage&quot;&gt;Introduction to Events Storage&lt;/h2&gt;

&lt;p&gt;Booking.com receives, creates, and sends an enormous amount of data. Usual
business-related data is handled by traditional databases, caching systems,
etc. We define &lt;em&gt;events&lt;/em&gt; as data that is generated by all the subsystems on
Booking.com.&lt;/p&gt;

&lt;p&gt;In essence, events are free-form documents that contain a variety of metrics.
The generated data does not contain any direct operational information.
Instead, it is used to report status, states, secondary information, logs,
messages, errors and warnings, health, and so on. The data flow represents a
detailed status of the platform and contains crucial information that will be
harvested and used further down the stream.&lt;/p&gt;

&lt;p&gt;To put this in numerical terms - we have more than &lt;strong&gt;billions of events per
day&lt;/strong&gt;, streaming at more than &lt;strong&gt;100 MB per second&lt;/strong&gt;, and adding up to more than
&lt;strong&gt;6 TB per day&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here are some examples of how we use the events stream:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Visualisation&lt;/strong&gt;: Wherever possible, we use graphs to express data. To create them, we use a heavily-modified version of &lt;a href=&quot;http://graphite.readthedocs.org/en/latest/overview.html&quot;&gt;Graphite&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Looking for anomalies&lt;/strong&gt;: When something goes wrong, we need to be notified. We use threshold-based notification systems (like &lt;a href=&quot;https://github.com/scobal/seyren&quot;&gt;seyren&lt;/a&gt;) as well as a custom &lt;em&gt;anomaly detection software&lt;/em&gt;, which creates statistical metrics (e.g. change in standard deviation) and alerts if those metrics look suspicious.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gathering errors&lt;/strong&gt;: We use our data pipeline to pass stack traces from all our production servers into &lt;a href=&quot;https://www.elastic.co/products/elasticsearch&quot;&gt;ElasticSearch&lt;/a&gt;. Doing it this way (as opposed to straight from the web application log files) allows us to correlate errors with the wealth of the information we store in the events.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These typical use-cases are made available in less than one-minute after the related event has been generated.&lt;/p&gt;

&lt;h2 id=&quot;high-level-overview&quot;&gt;High Level overview&lt;/h2&gt;

&lt;p&gt;This is a very simplified diagram of the data flow:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak1_flow.png&quot; alt=&quot;simplified diagram of the data flow&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;We can generate events by using literally any piece of code that exists on our
servers. We pass a HashMap to a function, which packages the provided document
into a UDP packet and sends it to a collection layer. This layer aggregates all
the events together into “blobs”, which are split by seconds (also called
epochs) and other variables. These event &lt;em&gt;blobs&lt;/em&gt; are then sent to the storage
layer running Riak. Finally, Riak sends them on to
&lt;a href=&quot;https://hadoop.apache.org/&quot;&gt;Hadoop&lt;/a&gt;. The Riak cluster is meant to safely store
around ten days of data. It is used for &lt;strong&gt;near real-time&lt;/strong&gt; analysis (something
that happened seconds or minutes ago), and &lt;strong&gt;medium-term&lt;/strong&gt; analysis of
relatively small amounts of data. We use Hadoop for older data analysis or
analysis of a larger volume of data.&lt;/p&gt;

&lt;p&gt;The above diagram is a simplified version of our data flow. In practical application, it’s spread across multiple datacenters (DC), and includes an additional aggregation layer.&lt;/p&gt;

&lt;h2 id=&quot;individual-events&quot;&gt;Individual Events&lt;/h2&gt;

&lt;p&gt;An event is a small &lt;strong&gt;schema-less&lt;/strong&gt; &lt;strong&gt;[1]&lt;/strong&gt; piece of data sent by our systems.
That means that the data can be in any structure with any level of depth, as
long as the top level is a HashTable. This is crucial to Booking.com - the goal
is to give as much flexibility as possible for the sender, so that it’s easy to
add or modify the structure, or the type and number of events.&lt;/p&gt;

&lt;p&gt;Events are also tagged in four different ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the epoch at which they were created&lt;/li&gt;
  &lt;li&gt;the DC where they originated&lt;/li&gt;
  &lt;li&gt;the type of event&lt;/li&gt;
  &lt;li&gt;the subtype.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some common types are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;WEB events (events produced by code running under a web server)&lt;/li&gt;
  &lt;li&gt;CRON events (output of cron jobs)&lt;/li&gt;
  &lt;li&gt;LB events (load balancer events)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subtypes are there for further specification and can answer questions like:
“Which one of web server systems are we talking about?”.&lt;/p&gt;

&lt;p&gt;Events are compressed &lt;a href=&quot;https://github.com/Sereal/Sereal&quot;&gt;Sereal&lt;/a&gt;
blobs. Sereal is possibly the
&lt;a href=&quot;https://github.com/Sereal/Sereal/wiki/Sereal-Comparison-Graphs&quot;&gt;best schema-less serialisation format&lt;/a&gt;
currently available. It was also
&lt;a href=&quot;http://blog.booking.com/sereal-a-binary-data-serialization-format.html&quot;&gt;written at Booking.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An individual event is not very big, but a huge number of them are sent every
second.&lt;/p&gt;

&lt;p&gt;We use UDP as transport because it provides a fast and simple way to send data.
Despite some (very low) risk of data loss, it doesn’t impact senders sending
events. We are experimenting with an UDP-to-TCP relay that will be local to the
senders.&lt;/p&gt;

&lt;h2 id=&quot;aggregated-events&quot;&gt;Aggregated Events&lt;/h2&gt;

&lt;p&gt;Literally every second, events from this particular second (called &lt;em&gt;epoch&lt;/em&gt;), DC
number, type, and subtype are merged together as an Array of events on the
aggregation layer. At this point, it’s important to try and get the smallest
size possible, so the events of a given epoch are re-serialized as a Sereal
blob, using these options:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;compress =&amp;gt; Sereal::Encoder::SRL_ZLIB,
dedupe_strings =&amp;gt; 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dedupe_strings&lt;/code&gt; increases the serialisation time slightly. However it removes
strings duplications which occur a lot since events are usually quite similar
between them. We also add gzip compression.&lt;/p&gt;

&lt;p&gt;We also add the checksum of the blob as a postfix, to be able to ensure data
integrity later on. The following diagram shows what an aggregated blob of
events looks like for a given epoch, DC, type, and subtype. You can get more
information about the Sereal encoding in the
&lt;a href=&quot;https://github.com/Sereal/Sereal/blob/master/sereal_spec.pod&quot;&gt;Sereal Specification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the general structure of an events blob:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak1_blob.png&quot; alt=&quot;general structure of an events blob&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The compressed payload contains the events themselves. It’s an Array of HashMaps,
Serialized in a Sereal structure and gzip-compressed. Here is an example of a
trivial payload of two events, as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[
  { cpu =&amp;gt; 5  },
  { cpu =&amp;gt; 99 }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the gzipped payload would be the compressed version of this binary string:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak1_gzip.png&quot; alt=&quot;gzipped payload would be the compressed version of this binary string&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;It can be hard to follow these hexdigits &lt;strong&gt;[2]&lt;/strong&gt;, yet it’s a nice illustration
of why the Sereal format helps us to reduce the size of serialised data. The
second array element is encoded on far fewer bytes than the first one, since
the key has already be seen. The resulting binary is then re-compressed. The
Sereal implementation offers multiple compression algorithms, including
&lt;a href=&quot;http://google.github.io/snappy/&quot;&gt;Snappy&lt;/a&gt; and &lt;a href=&quot;http://www.gzip.org/&quot;&gt;gzip&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A typical blob of events for one second/DC/type/subtype can weight anywhere from
several kilobytes to several megabytes, which translates into a (current) average
of around 250 gigabytes per hour.&lt;/p&gt;

&lt;p&gt;Side note: smaller subtypes on this level of aggregation aren’t always used,
because we want to minimise the data we transmit over our network by having good
compression ratios. Therefore we split types into subtypes only when the blobs
are big enough. The downside to this approach is that consumers have to fetch
data for the whole type, then filter out only subtypes they want. We’re looking
at ways to find more balance here.&lt;/p&gt;

&lt;h2 id=&quot;data-flow-size-and-properties&quot;&gt;Data flow size and properties&lt;/h2&gt;

&lt;p&gt;Data flow properties are important, since they’re used to decide how data
should be stored:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The data is timed and all the events blobs are associated with an epoch. It’s
important to bear in mind that events are schema-less, so the data is not a
traditional time series.&lt;/li&gt;
  &lt;li&gt;Data can be considered read-only; the aggregated events blobs are written every second and almost never modified
(history rewriting happens very rarely).&lt;/li&gt;
  &lt;li&gt;Once sent to the storage, the data must be available as soon as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Data is used in different ways on the client side. A lot of consumers are
actually daemons that will consume the fresh data as soon as possible - usually
seconds after an event was emitted. A large number of clients read the last few
hours of data in a chronological sequence. On rare occasions, consumers access
random data that is over a few days old. Finally, consumers that want to work on larger
amounts of older data would have to create Hadoop jobs.&lt;/p&gt;

&lt;p&gt;There is a large volume of data to be moved and stored. In numerical terms:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Once serialized and compressed into blobs, it is usually larger than 50 MB/s&lt;/li&gt;
  &lt;li&gt;That’s around &lt;strong&gt;250 GB per hour&lt;/strong&gt; and more than &lt;strong&gt;6 TB per day&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;There is a daily &lt;em&gt;peak hour&lt;/em&gt; but the variance of the data size is not huge:
There are no quiet periods&lt;/li&gt;
  &lt;li&gt;Yearly &lt;em&gt;peak season&lt;/em&gt; stresses all our systems, including events
transportation and storage, so we need to provision capacity for that&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-riak&quot;&gt;Why Riak&lt;/h2&gt;

&lt;p&gt;In order to find the best storage solution for our needs, we tested and
benchmarked several different products and solutions.&lt;/p&gt;

&lt;p&gt;The solutions had to reach the right balance of multiple features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Read performance had to be high as a lot of external processes will use the data.&lt;/li&gt;
  &lt;li&gt;Write security was important, as we had to ensure that the continuous flow of
data could be stored. Write performance should not be impacted by reads.&lt;/li&gt;
  &lt;li&gt;Horizontal scalability was of utmost importance, as our business and traffic continuously grows.&lt;/li&gt;
  &lt;li&gt;Data resilience was key: we didn’t want to lose portions of our data because of a hardware problem.&lt;/li&gt;
  &lt;li&gt;Allowed a small team to administrate and make the storage evolve.&lt;/li&gt;
  &lt;li&gt;The storage shouldn’t require the data to have a specific schema or
structure.&lt;/li&gt;
  &lt;li&gt;If possible, it would be able to bring code to data, perform computation on the
storage itself, instead of having to get data out of the storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After exploring a number of distributed file systems and databases, we chose
Riak over distributed Key-Value stores. Riak had good performance and
predictable behavior when nodes fail and when scaling up. It also had the
advantage of being easy to grasp and implement within a small team. Extending
it was very easy (which we’ll see in the next part of this series of blog
posts) and we found the system very robust - we never had to face dramatic
issues or data loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: This is not an endorsment for Riak. We compared it carefully to
other solutions over a long period of time and it seemed to be the best product
to suit our needs. As an example, we thoroughly tested Cassandra as an
alternative: it had a larger community and similar performance but was less
robust and predictable; it also lacked some advanced features. The choice is
ultimately a question of priorities. The fact that our events are
&lt;em&gt;schema-less&lt;/em&gt; made it almost impossible for us to use solutions that require
knowledge of the data structures. Also we needed a small team to be able to
operate the storage, and a way to process data on the cluster itself, using
MapReduce or similar mechanisms.&lt;/p&gt;

&lt;h2 id=&quot;riak-101&quot;&gt;Riak 101&lt;/h2&gt;

&lt;p&gt;The Riak cluster is a collection of nodes (in our case physical servers), each
of which claims ownership of a given key. Depending on the chosen replication
factor, each key might be owned by multiple nodes. You can ask any node for
a key and your request will be redirected to one of the owners. Same goes for
writes.&lt;/p&gt;

&lt;p&gt;On closer inspection of Riak, we see that keys are grouped into virtual nodes.
Each physical node can own multiple virtual nodes. This simplifies data
rebalancing when growing a cluster. Riak does not need to recalculate the owner
for each individual key; it will only do it per virtual node.&lt;/p&gt;

&lt;p&gt;We won’t cover Riak architecture in a great detail in this post, but we
recommend reading the
&lt;a href=&quot;http://docs.basho.com/riak/latest/theory/concepts/Clusters/&quot;&gt;following article&lt;/a&gt;
for further information.&lt;/p&gt;

&lt;h2 id=&quot;riak-clusters-configuration&quot;&gt;Riak clusters configuration&lt;/h2&gt;

&lt;p&gt;The primary goal of this storage is to keep the data safe. We went with the
regular replication number value of &lt;em&gt;three&lt;/em&gt;. Even if two nodes owning the same
data will go down, we won’t lose our data.&lt;/p&gt;

&lt;p&gt;Riak offers multiple back-ends for actual data storage. The main three are
Memory, LevelDB, and Bitcask. We chose Bitcask, since it was suitable for our
particular needs. Bitcask uses log-structured hash tables that provide very
fast access. As data gets written to the storage, Bitcask simply appends data
to a number of opened files. Even if a key is modified or deleted, the
information will be written at the end of these storage files. An in-memory
HashTable maps the keys with the position of their (latest) value in files.
That way, at most one seek is needed to fetch data from the file system.&lt;/p&gt;

&lt;p&gt;Data files are then periodically compacted, and Bitcask provides very good
expiration flexibility. Since Riak is a temporary storage solution for us, we
set it up with automatic expiration. Our expiration period varies. It depends
on the current cluster shape, but usually falls between 8-11 days.&lt;/p&gt;

&lt;p&gt;Bitcask keeps all of the keys of a node in memory, so keeping large numbers of
individual events as key value pairs isn’t trivial. We sidestep any issues by
using aggregations of events (blobs), which drastically reduce the number of
needed keys.&lt;/p&gt;

&lt;p&gt;More information about Bitcask can be found &lt;a href=&quot;http://docs.basho.com/riak/latest/ops/advanced/backends/bitcask/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For our conflict resolution strategy, we use Last Write Wins. The nature of our
data (which is immutable as we described before) allows us to avoid the need
for conflict resolution.&lt;/p&gt;

&lt;p&gt;The last important part of our setup is load balancing. It is crucial in an
enviromnent with a high level of reads, and only 1 gigabyte network. We use our
own solution for that based on &lt;a href=&quot;https://zookeeper.apache.org/&quot;&gt;Zookeeper&lt;/a&gt;.
Zooanimal daemons are running on the riak nodes, and collect information about
system health. The information is then aggregated into simple text files, where
we have an ordered list of IP addresses, plus up and running Riak nodes, which
we can connect to. All our Riak clients simply choose a random node to send
their requests to.&lt;/p&gt;

&lt;p&gt;We currently have two Riak clusters in different geographical locations, each
of which have more than 30 nodes. More nodes equates to more storage space, CPU
power, RAM, and more network bandwidth available.&lt;/p&gt;

&lt;h2 id=&quot;data-design&quot;&gt;Data Design&lt;/h2&gt;

&lt;p&gt;Riak is primarily a key-value store. Although it provides advanced features
(secondary indexes, MapReduce, CRDTs), the simplest and most efficient way to
store and retrieve data is to use the key-value model.&lt;/p&gt;

&lt;p&gt;Riak has three concepts - a &lt;strong&gt;bucket&lt;/strong&gt; is a namespace, in which a key is
unique. A &lt;strong&gt;key&lt;/strong&gt; is the identifier of the data; and has to be stored in a
bucket. A &lt;strong&gt;value&lt;/strong&gt; is the data; it has an associated mime-type, which can
enable Riak awareness of its type.&lt;/p&gt;

&lt;p&gt;Riak doesn’t provide efficient ways to retrieve the list of buckets or the list
of keys by default &lt;strong&gt;[3]&lt;/strong&gt;. When using Riak, it’s important to know the bucket
and key to access. This is usually resolved by using self-explanatory
identifiers.&lt;/p&gt;

&lt;p&gt;In our case, our events are stored as Sereal-encoded blobs. From these, we know
the datacenter, type, subtype, and of course the time at which it was created.&lt;/p&gt;

&lt;p&gt;When we need to retrieve data, we always know the time we want. We are also
confident in the list of our datacenters. It doesn’t change unexpectedly so we
can make it static for our applications. We are not always sure about what
types or subtypes will appear in a given epoch for a given datacenter. On some
seconds events of certain types may not arrive.&lt;/p&gt;

&lt;p&gt;We came up with this simple data design:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;events blobs are stored in the &lt;strong&gt;events&lt;/strong&gt; bucket, keys being
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;epoch&amp;gt;:&amp;lt;dc&amp;gt;:&amp;lt;type&amp;gt;:&amp;lt;subtype&amp;gt;:&amp;lt;chunk&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;metadata are stored in the &lt;strong&gt;epochs&lt;/strong&gt; bucket, keys being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;epoch&amp;gt;:&amp;lt;dc&amp;gt;&lt;/code&gt; and
values being the list of events keys for this epoch and DC combination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The value of chunk is an integer, starting at zero, which keeps event blobs
smaller than 500 kilobytes each. We use the integer to split big events blobs
into smaller ones, so that Riak can function more efficiently.&lt;/p&gt;

&lt;p&gt;We’ll now see this data design in action when pushing data to Riak&lt;/p&gt;

&lt;h1 id=&quot;pushing-to-riak&quot;&gt;Pushing to Riak&lt;/h1&gt;

&lt;p&gt;Pushing data to Riak is done by a number of &lt;strong&gt;relocators&lt;/strong&gt;, which are daemons
running on the aggregation layer that then push events blobs to Riak.&lt;/p&gt;

&lt;p&gt;Side note: it’s not recommended to have keys more then 1-2MB in Riak (see &lt;a href=&quot;http://docs.basho.com/riak/latest/community/faqs/developing/#is-there-a-limit-on-the-size-of-files-that-can-be&quot;&gt;this FAQ&lt;/a&gt;).
And since our blobs can be 5-10MB in size, we shard them into chunks, 500KB each.
Chunks are valid Sereal documents, which means we do not have to stich chunks together in order to retrieve data back.&lt;/p&gt;

&lt;p&gt;This means that we have quite a lot of blobs to send to Riak, so to maximise our usage of
networking, I/O, and CPU, it’s best to send data in a mass-parallel way. To do so, we maintain a number of
forked processes (20 per host is a good start), in which each of them push data to Riak.&lt;/p&gt;

&lt;p&gt;Pushing data to Riak can be done using the
&lt;a href=&quot;http://docs.basho.com/riak/latest/dev/references/http/&quot;&gt;HTTP API&lt;/a&gt;, or the
&lt;a href=&quot;http://docs.basho.com/riak/latest/dev/references/protocol-buffers/&quot;&gt;Protocol Buffers Client (PBC) API&lt;/a&gt;.
PBC has a slighly better performance.&lt;/p&gt;

&lt;p&gt;Whatever protocol is used, it’s important to maximise I/O utilisation. One way
is to use an HTTP library that parallelises the requests in term of I/O
(&lt;a href=&quot;https://metacpan.org/pod/YAHC&quot;&gt;YAHC&lt;/a&gt; is an example). Another method is to use
an asynchronous Riak Client like
&lt;a href=&quot;https://metacpan.org/pod/AnyEvent::Riak&quot;&gt;AnyEvent::Riak&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We use an in-house library to create and maintain a pool of forks, but there are more than one existing libraries on CPAN, like
&lt;a href=&quot;https://metacpan.org/pod/Parallel::ForkManager&quot;&gt;Parallel::ForkManager&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;put-to-riak&quot;&gt;PUT to Riak&lt;/h2&gt;

&lt;p&gt;Writing data to Riak is rather simple. For a given epoch, we have the list of
events blobs, each of them having a different DC/type/subtype combination (remember, DC is short for Data Center). For example:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak_put.png&quot; alt=&quot;PUT to Riak&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The first task is to slice the blobs into 500 KB chunks and add a postfix index
number to their name. That gives:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak_put_result.png&quot; alt=&quot;PUT to Riak - result&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Next, we can store all the event blobs in Riak in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;events&lt;/code&gt; bucket. We can
simulate it with curl:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -d &amp;lt;data&amp;gt; -XPUT &quot;http://node:8098/buckets/events/keys/1413813813:1:type1:subtype1:0&quot;
# ...
curl -d &amp;lt;data&amp;gt; -XPUT &quot;http://node:8098/buckets/events/keys/1413813813:2:type3::0&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Side note: we store all events in each of the available Riak clusters. In other
words, all events from all DCs will be stored in the Riak cluster which is in DC
1, as well as in the Riak cluster which is in DC 2. We do not use cross DC
replication to achieve that - instead we simply push data to all our clusters
from the relocators.&lt;/p&gt;

&lt;p&gt;Once all the events blobs are stored, we can store the &lt;strong&gt;metadata&lt;/strong&gt;, which is
the list of the event keys, in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;epochs&lt;/code&gt; bucket. This metadata is stored in one
key per epoch and DC. So for the current example, we will have 2 keys:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1413813813-1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1413813813-2&lt;/code&gt;. We have chosen to store the list of events
blobs names as pipe separated values. Here is a simulation with curl for
DC 2:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -d &quot;type1:subtype1:0|type1:subtype1:1|type3::0&quot; -XPUT &quot;http://riak_host:8098/buckets/epochs/keys/1413813813-2&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Because the epoch and DC are already in the key name, it’s not necessary to
repeat that in the content. It’s important to push the metadata &lt;strong&gt;after&lt;/strong&gt; 
pushing the data.&lt;/p&gt;

&lt;h2 id=&quot;put-options&quot;&gt;PUT options&lt;/h2&gt;

&lt;p&gt;When pushing data to the Riak cluster, we can use different attributes to
change the way data is written - either by specifying which ones when using the PBC
API, or by setting the buckets defaults.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://docs.basho.com/riak/latest/dev/advanced/replication-properties/#Available-Parameters&quot;&gt;Riak’s documentation&lt;/a&gt; provides a comprehensive list of the parameters and their meaning. We have set these parameters as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;n_val&quot; : 3,

&quot;allow_mult&quot;      : false,
&quot;last_write_wins&quot; : true,

&quot;w&quot;  : 3,
&quot;dw&quot; : 0,
&quot;pw&quot; : 0,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is a brief explanation of these parameters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n_val:3&lt;/code&gt; means that the data is replicated three times&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allow_mult&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;last_write_wins&lt;/code&gt; prohibit siblings values; conflicts are resolved right away by using the last value
written&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w:3&lt;/code&gt; means that when writing data to a node, we get a success response only when the data has been written to all the three
replica nodes&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dw:0&lt;/code&gt; instruct Riak to wait for the data to have reached the node, not the backend on the node, before returning success.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pw:0&lt;/code&gt; is here to specify that it’s OK if the nodes that store the replicas are not the primary nodes (i.e. the ones that are supposed to hold the data), but replacement nodes, in case the primary ones were unavailable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a nutshell, we have a reasonably robust way of writing data. Because our
data is immutable and never modified, we don’t want to have siblings or
conflict resolution on the application level. Data loss could, in theory, happen
if a major network issue happened just after having acknowledged a write, but
before the data reached the backend. However, in the worst case we would lose a
fraction of one second of events, which is acceptable for us.&lt;/p&gt;

&lt;h1 id=&quot;reading-from-riak&quot;&gt;Reading from Riak&lt;/h1&gt;

&lt;p&gt;This is how the data and metadata for a given epoch is laid out in Riak:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bucket: epochs
key: 1428415043-1
value: 1:cell0:WEB:app:chunk0|1:cell0:EMK::chunk0

bucket: events
key: 1428415043:1:cell0:WEB:app:chunk0
value: &amp;lt;binary sereal blob&amp;gt;

bucket: events
key: 1428415043:1:cell0:EMK::chunk0
value: &amp;lt;binary sereal blob&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fetching one second of data from Riak is quite simple. Given a DC and an epoch,
the process is as follow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Read the metadata by fetching the key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;epoch&amp;gt;-&amp;lt;dc&amp;gt;&lt;/code&gt; from the bucket &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;epochs&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Parse the metadata value, split on the pipe character to get data keys, and prepend the epoch to them&lt;/li&gt;
  &lt;li&gt;Reject data keys that we are not interested in by filtering on type/subtype&lt;/li&gt;
  &lt;li&gt;Fetch the data keys in parallel&lt;/li&gt;
  &lt;li&gt;Deserialise the data&lt;/li&gt;
  &lt;li&gt;Data is now ready for processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reading a time range of data is done the same way. Fetching ten minutes of
data from &lt;em&gt;Wed, 01 Jul 2015 11:00:00 GMT&lt;/em&gt; would be done by enumerating all the
epochs, in this case:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1435748400
1435748401
1435748402
...
1435749000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, for each epoch, fetch the data as previously mentioned. It should be noted
that Riak is specifically tailored for this kind of workload, where multiple
parallel processes perform a huge number of small requests on different keys.
This is where distributed systems shine.&lt;/p&gt;

&lt;h2 id=&quot;get-options&quot;&gt;GET options&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;events&lt;/code&gt; bucket (where the event data is stored) has the following properties:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;r&quot;            : 1,
&quot;pr&quot;           : 0,
&quot;rw&quot;           : &quot;quorum&quot;,
&quot;basic_quorum&quot; : true,
&quot;notfound_ok&quot;  : true,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, let’s look at these parameters in detail:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r:1&lt;/code&gt; means that when fetching data, as soon as we have a reply from one replica
node, Riak considers this as a valid reply, it won’t to compare it with
other replicas.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pr:0&lt;/code&gt; remove the requirement that the data comes from a primary node&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notfound_ok:true&lt;/code&gt; makes it so that as soon as one node can’t find a key, Riak considers that the
key doesn’t exist (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notfound_ok:true&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These parameter values allow to be as fast as possible when fetching data. In
theory, such values don’t protect against conflicts or data corruption.
However, in the “Aggregated Events” section (see the first post), we’ve seen that every event blob
has a suffix checksum. When fetching them from Riak, this enables the consumer
to verify that there is no data corruption. The fact that the events are never
modified ensures that no version conflict can occur. This is why having such
“careless” parameter values is not an issue for this use case.&lt;/p&gt;

&lt;h1 id=&quot;real-time-data-processing-outside-of-riak&quot;&gt;Real time data processing outside of Riak&lt;/h1&gt;

&lt;p&gt;After the events are properly stored in Riak, it’s time to use them. The first
usage is quite simple: extract data out of them and process it on dedicated
machines, usually grouped in clusters or aggregations of machines that perform
the same kind of analysis. These machines are called &lt;em&gt;consumers&lt;/em&gt;, and they
usually run daemons that fetch data from Riak, either continuously or on
demand. Most of the continuous consumers are actually small clusters of machines
spreading the load of fetching data.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak_outside.png&quot; alt=&quot;Real time data processing outside of Riak&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Some data processing is required at near real-time. This is the case for
monitoring, and building graphs. Booking.com heavily uses graphs at every
layer of its technical stack. A big portion of graphs are generated from
Events. Data is fetched every second from the Riak storage, processed, and
dedicated graphing data is sent to an in-house &lt;a href=&quot;http://graphite.wikidot.com/&quot;&gt;Graphite&lt;/a&gt; cluster.&lt;/p&gt;

&lt;p&gt;Other forms of monitoring also consume the events stream- fetched continuously
and aggregated in per-second, per-minute, and daily aggregations in external
databases, which are then provided to multiple departments via internal tools.&lt;/p&gt;

&lt;p&gt;These kind of processes try to be as close as possible to real-time.
Currently there are 10 to 15 seconds of lag. This lag could be shorter: a
portion of it is due to the collection part of the pipeline, and an even bigger
part of it is due to the re-serialisation of the events as they are grouped
together, to reduce their size. A good deal of optimisation could be done there
to reduce the lag down to a couple of seconds &lt;strong&gt;[4]&lt;/strong&gt;. However, there was no operational
requirement for reducing it and 15 seconds is small enough for our current
needs.&lt;/p&gt;

&lt;p&gt;Another way of using the data is to stick to real-time, but accumulate seconds
in periods. One example is our Anomaly Detector, which continuously fetches
events from the Riak clusters. However, instead of using the data right away,
it accumulates it on short moving windows of time (every few minutes) and applies
statistical algorithms on it. The goal is to detect anomalous patterns in our
data stream and provide the first alert that prompts further action. Needless to
say, this client is critical.&lt;/p&gt;

&lt;p&gt;Another similar usage is done when gathering data related to A/B testing. A large
number of machines harvest data from the events’ flow before processing it and storing
the results in dedicated databases for use in experimentation-related tooling.&lt;/p&gt;

&lt;p&gt;There are a number of other usages of the data outside of Riak, including
manually looking at events to check new features behaviours or analysing past
issues / outages.&lt;/p&gt;

&lt;h2 id=&quot;limitations-of-data-processing-outside-of-riak&quot;&gt;Limitations of data processing outside of Riak&lt;/h2&gt;

&lt;p&gt;Fetching data outside of the Riak clusters raises some issues that are
difficult to work around without changing the processing mechanism.&lt;/p&gt;

&lt;p&gt;First of all, there is a clear network bandwidth limitation to the design: the
more consumer clusters there are, the more network bandwidth is used. Even with
large clusters (more than 30 nodes), it’s relatively easy to exhaust the
network capacity of all the nodes as more and more fetchers try to get data
from them.&lt;/p&gt;

&lt;p&gt;Secondly, each consumer cluster tends to use only a small part of the events
flow. Even though consumers can filter out types, subtypes, and DCs, the
resulting events blobs still contain a large quantity of data that is
useless to the consumer. For storage efficiency, events need to be stored as
large compressed serialised blobs, so splitting them more by allowing more
subtyping is not possible &lt;strong&gt;[5]&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, statically splitting the events content is too rigid since use of
the data changes over time and we do not want to be a bottleneck to change for
our downstream consumers. Part of an event from a given type that was critical
2 years ago might be used for minor monitoring now. A subtype that was heavily
used for six month may now be rarely used because of a technical change in the
producers.&lt;/p&gt;

&lt;p&gt;Finally, the amount of CPU time needed to uncompress, load, and filter the
big events blobs is not tiny. It usually takes around five seconds to fetch,
uncompress, and filter one second’s worth of events. Which means that any
real-time data crunching requires multiple threads and likely multiple hosts -
usually a small cluster. It would be much simpler if Riak could provide a
real-time stream of data exactly tailored to the consumer need.&lt;/p&gt;

&lt;h2 id=&quot;next-data-filtering-and-processing-inside-riak&quot;&gt;Next: data filtering and processing inside Riak&lt;/h2&gt;

&lt;p&gt;What if we could remove the CPU limitations by doing processing &lt;em&gt;on&lt;/em&gt; the Riak
cluster itself? What if we could work around the network bandwidth issue
by generating sub-streams on the fly and in real-time &lt;em&gt;on&lt;/em&gt; the Riak cluster?&lt;/p&gt;

&lt;p&gt;This is exactly what we implemented, using simple concepts, and leveraging the
ease of use and &lt;em&gt;hackability&lt;/em&gt; of Riak. These concepts and implementations will
be described in the next sections&lt;/p&gt;

&lt;h2 id=&quot;real-time-server-side-data-processing-the-theory&quot;&gt;Real-time server-side data processing: the theory&lt;/h2&gt;

&lt;p&gt;The reasoning is actually very simple. The final goal is to perform data
processing of the events blobs that are stored in Riak &lt;strong&gt;in real-time&lt;/strong&gt;. Data
processing usually produces a very small result, and it appears to be a waste
of network bandwidth to fetch data outside of Riak to perform data analysis on consumer clusters, as in this example::&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/riak_outside.png&quot; alt=&quot;The Theory&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This diagram is equivalent to:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/equivalent_to.png&quot; alt=&quot;This diagram is equivalent to&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;So instead of bringing the data to the processing code, let’s bring the code to
the data:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/code_to_data.png&quot; alt=&quot;instead of bringing the data to the processing code, let's bring the code to the data&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This is a typical use case for MapReduce. We’re going to see how to use
MapReduce on our dataset in Riak, and also why it’s not a usable solution.&lt;/p&gt;

&lt;p&gt;For the rest of this post, it’s important to establish a reference for &lt;strong&gt;all the events that are stored for a time period of exactly one second&lt;/strong&gt;. Because we already happen to store our events by a second (and call it an “epoch”), using this unit of measure is a practical consideration that we’ll refer to as &lt;strong&gt;epoch-data&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;a-first-attempt-mapreduce&quot;&gt;A first attempt: MapReduce&lt;/h2&gt;

&lt;p&gt;MapReduce is a very well known (if somewhat outdated) way of bringing the code near the data and distributing data processing. There are excellent papers explaining this approach for further background study.&lt;/p&gt;

&lt;p&gt;Riak has a very good MapReduce implementation. MapReduce jobs can be written in
Javascript or Erlang. We highly recommend using Erlang for better performance.&lt;/p&gt;

&lt;p&gt;To perform events processing of an epoch-data on Riak, the MapReduce job would
look like the following list. Metadata and data keys concepts are explained in
the &lt;a href=&quot;using-riak-as-events-storage-part2.html&quot;&gt;part 2&lt;/a&gt; of the blog series. Here are the MapReduce phases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Given a list of epochs and DCs, the &lt;strong&gt;input&lt;/strong&gt; is the list of metadata keys,
and as additional parameter, the processing code to apply to the data.&lt;/li&gt;
  &lt;li&gt;A first &lt;strong&gt;Map&lt;/strong&gt; phase reads the metadata values and returns a list of data keys.&lt;/li&gt;
  &lt;li&gt;A second &lt;strong&gt;Map&lt;/strong&gt; phase reads the data values, deserialises it, applies the
processing code and returns the list of results.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;Reduce&lt;/strong&gt; phase aggregates the results together&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/mapreduce.png&quot; alt=&quot;MapReduce&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This works just fine. For one epoch-data, one data processing code is properly
mapped to the events, the data deserialised and processed in around 0.1 second
(on our initial 12 nodes cluster). This is by itself an important result: it’s
taking less than one second to fully process one second worth of events. Riak
makes it possible to implement a &lt;strong&gt;real-time MapReduce processing system&lt;/strong&gt; &lt;strong&gt;[6]&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Should we just use MapReduce and be done with it? Not really, because our
use case involves multiple consumers doing different data processing &lt;strong&gt;at the
same time&lt;/strong&gt;. Let’s see why this is an issue.&lt;/p&gt;

&lt;h2 id=&quot;the-metrics&quot;&gt;The metrics&lt;/h2&gt;

&lt;p&gt;To be able to test the MapReduce solution, we need a use case and some metrics
to measure.&lt;/p&gt;

&lt;p&gt;The use case is the following: every second, multiple consumers (say 20) need
the result of one of the data processing (say 10) of the previous second.&lt;/p&gt;

&lt;p&gt;We’ll consider that an epoch-data is roughly &lt;strong&gt;70MB&lt;/strong&gt;, data processing results
are around &lt;strong&gt;10KB&lt;/strong&gt; each. Also, we’ll consider that the Riak cluster is a 30
nodes ring with 10 real CPUs available for data processing on each node.&lt;/p&gt;

&lt;p&gt;The first metric we can measure is the &lt;strong&gt;external network bandwidth&lt;/strong&gt; usage. This is
the first factor that encouraged us to move away from fetching the events out
of Riak to do external processing. External bandwidth usage is the bandwidth
used to transfer data between the cluster as a whole, and the outside world.&lt;/p&gt;

&lt;p&gt;The second metric is the &lt;strong&gt;internal network bandwidth&lt;/strong&gt; usage. This represents
the network used between the nodes, inside of the Riak cluster.&lt;/p&gt;

&lt;p&gt;Another metric is the time (more precisely the CPU-time) it takes to
&lt;strong&gt;deserialise&lt;/strong&gt; the data. Because of the heavily compressed nature of our data,
decompression and deserialising one epoch-data takes roughly &lt;strong&gt;5 sec&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The fourth metric is the CPU-time it take to &lt;strong&gt;process&lt;/strong&gt; the deserialized data,
analyze it and produce a result. This is very fast (compared to
deserialisation), let’s assume &lt;strong&gt;0.01 sec.&lt;/strong&gt; at most.&lt;/p&gt;

&lt;p&gt;Note: we are not taking into account the impact of storing the data in the
cluster (remember that events blobs are being stored every second) because it’s impacting the system the same way in both external processing and MapReduce.&lt;/p&gt;

&lt;h2 id=&quot;metrics-when-doing-external-processing&quot;&gt;Metrics when doing external processing&lt;/h2&gt;

&lt;p&gt;When doing standard data processing as seen in the previous part of this blog
series, one &lt;strong&gt;epoch-data&lt;/strong&gt; is fetched out from Riak, and deserialised and
processed outside of Riak.&lt;/p&gt;

&lt;h4 id=&quot;external-bandwidth-usage&quot;&gt;External bandwidth usage&lt;/h4&gt;

&lt;p&gt;The external bandwidth usage is high. For each query, the epoch-data is
transferred, so that’s 20 queries times 70MB/s = 1400 MB/s. Of course, this
number is properly spread across all the nodes, but that’s still roughly 1400
/ 30 = 47 MB/s. That, however, is just for the data processing. There is a small
overhead that comes from the clusterised nature of the system and from gossiping,
so let’s round that number to 50 MB/s per node, in external output network
bandwidth usage.&lt;/p&gt;

&lt;h4 id=&quot;internal-bandwidth-usage&quot;&gt;Internal bandwidth usage&lt;/h4&gt;

&lt;p&gt;The internal bandwidth usage is very high. Each time a key value is requested,
Riak will check its 3 replicas, and return the value. So 3 x 20 x 70MB/s = 4200
MB/s. Per node, it’s 4200 MB/s / 30 = 140 MB/s&lt;/p&gt;

&lt;h4 id=&quot;deserialise-time&quot;&gt;Deserialise time&lt;/h4&gt;

&lt;p&gt;Deserialise time is zero: the data is deserialised outside of Riak.&lt;/p&gt;

&lt;h4 id=&quot;processing-time&quot;&gt;Processing time&lt;/h4&gt;

&lt;p&gt;Processing time is zero: the data is processed outside of Riak.&lt;/p&gt;

&lt;h2 id=&quot;metrics-when-using-mapreduce&quot;&gt;Metrics when using MapReduce&lt;/h2&gt;

&lt;p&gt;When using MapReduce, the data processing code is sent to Riak, included in an
ad hoc MapReduce job, and executed on the Riak cluster by sending the orders
to the nodes where the &lt;strong&gt;epoch-data&lt;/strong&gt; related data chunks are stored.&lt;/p&gt;

&lt;h4 id=&quot;external-bandwidth-usage-1&quot;&gt;External bandwidth usage&lt;/h4&gt;

&lt;p&gt;When using MapReduce to perform data processing jobs, there is certainly a huge
gain in network bandwidth usage. For each query, only the results are
transferred, so 20 x 10KB/s = 200 KB/s.&lt;/p&gt;

&lt;h4 id=&quot;internal-bandwidth-usage-1&quot;&gt;Internal bandwidth usage&lt;/h4&gt;

&lt;p&gt;The internal usage is also very low: it’s only used to spread the MapReduce
jobs, transfer the results, and do bookkeeping. It’s hard to put a proper number
on it because of the way jobs and data are spread on the cluster, but overall
it’s using a couple of MB/s at most.&lt;/p&gt;

&lt;h4 id=&quot;deserialise-time-1&quot;&gt;Deserialise time&lt;/h4&gt;

&lt;p&gt;Deserialise time is high: for each query, the data is deserialised, so 20 x 5 =
100 sec for the whole cluster. Each node has 10 CPUs available for
deserialisation, so the time needed to deserialise one second worth of data is
100/300 = 0.33 sec. We can easily see that this is an issue, because already
one third of all our CPU power is used for deserialising the same data in each
MapReduce instance. It’s a big waste of CPU time.&lt;/p&gt;

&lt;h4 id=&quot;processing-time-1&quot;&gt;Processing time&lt;/h4&gt;

&lt;p&gt;Processing time is 20 x 0.01 = 0.2s for the whole cluster. This is really low
compared to the deserialise time.&lt;/p&gt;

&lt;h2 id=&quot;limitations-of-mapreduce&quot;&gt;Limitations of MapReduce&lt;/h2&gt;

&lt;p&gt;As we’ve seen, using MapReduce has its advantages: it’s a well-known standard,
and allows us to create real-time processing jobs. However it doesn’t scale:
because MapReduce jobs are isolated, they can’t share the deserialised data,
and CPU time is wasted, so it’s not possible to have more than one or two
dozens of real-time data processing jobs at the same time.&lt;/p&gt;

&lt;p&gt;It’s possible to overcome this difficulty by caching the deserialised data in
memory, within the Erlang VM, on each node. CPU time would still be 3 times
higher than needed (because a map job can run on any of the 3 replicas that
contains the targeted data) but at least it wouldn’t be tied to the number of
parallel jobs.&lt;/p&gt;

&lt;p&gt;Another issue is the fact that writing MapReduce jobs is not that easy,
especially because — in this case — it’s a prerequisite to know Erlang.&lt;/p&gt;

&lt;p&gt;Last but not least, it’s possible to create very heavy MapReduce jobs, easily
consuming all the CPU time. This directly impacts the performance and
reliability of the cluster, and in extreme cases the cluster may be unable to
store incoming events at a sufficient pace. It’s not trivial to fully protect
the cluster against MapReduce misuse.&lt;/p&gt;

&lt;h1 id=&quot;a-better-solution-post-commit-hooks&quot;&gt;A better solution: post-commit hooks&lt;/h1&gt;

&lt;p&gt;To work around these limitations, We explored a different approach to enable real-time data processing on the
cluster that scales properly by deserialising data only once, allows us to cap
its CPU usage, and allows us to write the processing jobs in any language, while
still bringing the code to the data, removing most of the internal and external
network usage.&lt;/p&gt;

&lt;p&gt;This technical solution is what is currently in production at
&lt;a href=&quot;http://www.booking.com&quot;&gt;Booking.com&lt;/a&gt; on our Riak events storage clusters, and
it uses post-commit hooks and a companion service on the cluster nodes.&lt;/p&gt;

&lt;h2 id=&quot;strategy-and-features&quot;&gt;Strategy and Features##&lt;/h2&gt;

&lt;p&gt;The previous parts introduced the need for data processing of the events blobs
that are stored in Riak &lt;strong&gt;in real-time&lt;/strong&gt;, and the strategy of bringing the code to the data:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/code_to_data.png&quot; alt=&quot;instead of bringing the data to the processing code, let's bring the code to the data&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Using MapReduce for computing on-demand data processing worked fine but didn’t
scale to many users (see &lt;a href=&quot;using-riak-as-events-storage-part3.html&quot;&gt;part 3&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Finding an alternative to MapReduce for server-side real-time data processing
requires listing the required features of the system and the compromises that
can be made:&lt;/p&gt;

&lt;h3 id=&quot;real-time-isolated-data-transformation&quot;&gt;Real-time isolated data transformation&lt;/h3&gt;

&lt;p&gt;As seen in the previous parts of this blog series, we need to be able to
perform transformation on the incoming events, with as little delay as
possible. We don’t want any lag induced by a large batch processing. Luckily,
these transformations are usually small and fast. Moreover, they are
&lt;em&gt;isolated&lt;/em&gt;: the real-time processing may involve multiple types and subtypes of
events data, but should not depend on previous events knowledge. Cross-epoch
data processing can be implemented by reusing the MapReduce concept, computing
a Map-like transformation on each events blobs by computing them independently,
but leaving the Reduce phase up to the consumer.&lt;/p&gt;

&lt;h3 id=&quot;performance-and-scalability&quot;&gt;Performance and scalability&lt;/h3&gt;

&lt;p&gt;The data processing should have a very limited bandwidth usage and reasonable
CPU usage. However, we also need the CPU usage not to be affected by the number
of clients using the processed data. This is where the previous attempt using
MapReduce showed its limits. Of course, horizontal scalability has to be
ensured, to be able to scale with the Riak cluster.&lt;/p&gt;

&lt;p&gt;One way of achieving this is to perform the data processing continuously for
every datum that reach Riak, upfront. That way, client requests are actually
only querying the &lt;em&gt;results&lt;/em&gt; of the processing, and not triggering computation at
query time.&lt;/p&gt;

&lt;h3 id=&quot;no-back-processing&quot;&gt;No back-processing&lt;/h3&gt;

&lt;p&gt;The data processing will have to be performed on real-time data, but no
back-processing will be done. When a data processing implementation changes, it
will be effective on future events only. If old data is changed or added
(usually as a result of reprocessing), data processing will be applied,
but using the latest version of processing jobs. We don’t want to maintain any
history of data processing, nor any migration of processed data.&lt;/p&gt;

&lt;h3 id=&quot;only-fast-transformations&quot;&gt;Only fast transformations&lt;/h3&gt;

&lt;p&gt;To avoid putting too much pressure on the Riak cluster, we only allow data
transformation that produces a small result (to limit storage and bandwidth
footprint), and that runs quickly, with a strong timeout on execution time.
Back-pressure management is very important, and we have a specific strategy to
handle it (see &lt;strong&gt;“Back-pressure management strategy”&lt;/strong&gt; below)&lt;/p&gt;

&lt;h2 id=&quot;the-solution-substreams&quot;&gt;The solution: Substreams&lt;/h2&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/simplified_substream.png&quot; alt=&quot;Substreams, a simplified overview&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;With these features and compromises listed, it is now possible to describe the
data processing layer that we ended up implementing at Booking.com.&lt;/p&gt;

&lt;p&gt;This system is called &lt;strong&gt;Substreams&lt;/strong&gt;. Every seconds, the list of keys of the
data that has just been stored is sent to a companion app - a home-made daemon -
running on every Riak node. This fetches the data, decompresses it, runs a
list of data transformation code on it, and stores the results back into Riak,
using the same key name but with a different namespace. Users can now fetch the
processed data.&lt;/p&gt;

&lt;p&gt;A data transformation code is called a &lt;em&gt;substream&lt;/em&gt; because most of the time the
data transformation is more about cherry-picking exactly the needed fields and
values out of the full stream, rather than performing complex operations.&lt;/p&gt;

&lt;p&gt;The companion app is actually a simple pre-forking daemon with a Rest API. It’s
installed on all nodes of the cluster, with around 10 forks. The Rest API is
used to send it the list of keys, and wait for the process completion. The
events data doesn’t transit via this API; the daemon is fetching itself the key
values from Riak, and stores the substreams (results of data transformation)
back into Riak.&lt;/p&gt;

&lt;p&gt;The main purpose of this system is to drastically reduce the size of data
transferred to the end user by enabling the cherry-picking of specific branches
or leaves of the events structures, and also to perform preliminary data
processing on the events. Usually, clients are fetching these substreams to
perform more complex and broader aggregations and computations (for instance
as a data source for Machine Learning).&lt;/p&gt;

&lt;p&gt;Unlike MapReduce, this system has multiple benefits:&lt;/p&gt;

&lt;h3 id=&quot;data-decompressed-only-once&quot;&gt;Data decompressed only once&lt;/h3&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/decompress_once.png&quot; alt=&quot;Deserialisation and decompression is done once, for many data processing jobs&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;A given binary blob of events (at mot 500K of compressed data) is handled by
one instance of the companion app, which will decompress it once, then run all
the data processing jobs on the decompressed data structure in RAM. This is a
big improvement compared to MapReduce, the most CPU intensive task is
actually to &lt;em&gt;decompress&lt;/em&gt; and deserialise the data, not to &lt;em&gt;transform&lt;/em&gt; it. Here
we have the guarantee that data is decompressed only once in its lifetime.&lt;/p&gt;

&lt;h3 id=&quot;transformation-at-write-time-not-at-query-time&quot;&gt;Transformation at write time, not at query time&lt;/h3&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/computation_once.png&quot; alt=&quot;Data is created once and for all&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Unlike MapReduce, once a transformation code is setup and enabled, it’ll be
computed for every epoch, &lt;strong&gt;even if nobody uses the result&lt;/strong&gt;. However, the
computation will happen &lt;strong&gt;only once&lt;/strong&gt;, even if multiple users request it later
on. Data transformation is already done when users want to fetch the result.
That way, the cluster is protected against simultaneous requests of a big
number of users. It’s also easier to predict the performance of the substreams
creations.&lt;/p&gt;

&lt;h3 id=&quot;hard-timeout---open-platform&quot;&gt;Hard timeout - open platform&lt;/h3&gt;

&lt;p&gt;Data decompression and transformation by the companion app is performed under a
global timeout that would kill the processing if it takes too long. It’s easy
to come up with a realistic timeout value given the average size of event
blobs, the number of companion instances, and the total number of nodes. The
hard timeout makes sure that data processing is not using too many resources,
ensuring that Riak KV works smoothly.&lt;/p&gt;

&lt;p&gt;This mechanism allows the cluster to be an open platform: any developer in the
company can create a new substream transformation and quickly get it up and
running on the cluster on its own without asking for permission. There is no
critical risk for the business as substreams runs are capped by a global
timeout. This approach is a good illustration of the flexible and agile
spirit in IT that we have at Booking.com.&lt;/p&gt;

&lt;h2 id=&quot;implementation-using-a-riak-commit-hook&quot;&gt;Implementation using a Riak commit hook&lt;/h2&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/commit_hook.png&quot; alt=&quot;detailed picture with the commit hook&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;In this diagram we can see where the Riak commit hook kicks in. We can also see
that when the companion requests data from the Riak service, there is a high
chance that the data is not on the current node and Riak has to get it from
other nodes. This is done transparently by Riak, but it consumes bandwidth. In
the next section we’ll see how to reduce this bandwidth usage and have full
data locality. But for now, let’s focus on the commit hook.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://docs.basho.com/riak/kv/latest/developing/usage/commit-hooks/&quot;&gt;Commit hooks&lt;/a&gt; are
a feature of Riak that allow the Riak cluster to execute a provided callback
just before or just after a value is written, using respectively pre-commit and
post-commit hooks. The commit hook is executed on the node that coordinated the
write.&lt;/p&gt;

&lt;p&gt;We set up a post-commit hook on the metadata bucket (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;epochs&lt;/code&gt; bucket). We
implemented the commit hook callback, which is executed each time a key is
stored to that metadata bucket. In
&lt;a href=&quot;using-riak-as-events-storage-part2.html&quot;&gt;part 2&lt;/a&gt; of this series, we explained
that the metadata is stored in the following way:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the key is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;epoch&amp;gt;-&amp;lt;datacenter_id&amp;gt;&lt;/code&gt;, for example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1413813813-1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;the value is the list of data keys (for instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1413813813:2:type3::0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post-commit hook callback is quite simple: for each &lt;em&gt;metadata&lt;/em&gt; key, it gets
the value (the list of &lt;em&gt;data&lt;/em&gt; keys), and sends it over HTTP in async
mode to the &lt;em&gt;companion app&lt;/em&gt;. Proper timeouts are set so that the execution of
the callback is capped and can’t impact the Riak cluster performance.&lt;/p&gt;

&lt;h3 id=&quot;hook-implementation&quot;&gt;Hook implementation&lt;/h3&gt;

&lt;p&gt;First, let’s write the post commit hook code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:::erlang
metadata_stored_hook(RiakObject) -&amp;gt;
    Key = riak_object:key(RiakObject),
    Bucket = riak_object:bucket(RiakObject),
    [ Epoch, DC ] = binary:split(Key, &amp;lt;&amp;lt;&quot;-&quot;&amp;gt;&amp;gt;),
    MetaData = riak_object:get_value(RiakObject),
    DataKeys = binary:split(MetaData, &amp;lt;&amp;lt;&quot;|&quot;&amp;gt;&amp;gt;, [ global ]),
    send_to_REST(Epoch, Hostname, DataKeys),
    ok.

send_to_REST(Epoch, Hostname, DataKeys) -&amp;gt;
    Method = post,
    URL = &quot;http://&quot; ++ binary_to_list(Hostname)
       ++ &quot;:5000?epoch=&quot; ++ binary_to_list(Epoch),
    HTTPOptions = [ { timeout, 4000 } ],
    Options = [ { body_format, string },
    		         { sync, false },
            		  { receiver, fun(ReplyInfo) -&amp;gt; ok end }
              ],
    Body = iolist_to_binary(mochijson2:encode( DataKeys )),
    httpc:request(Method,
                  {URL, [], &quot;application/json&quot;, Body},
                  HTTPOptions, Options),
    ok.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These two Erlang functions (here they are simplified and would probably not
compile), are the main part of the hook. The function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadata_stored_hook&lt;/code&gt; is
going to be the entry point of the commit hook, when a &lt;em&gt;metadata&lt;/em&gt; key is
stored. It receives the key and value that was stored, via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RiakObject&lt;/code&gt;,
uses its value to extract the list of data keys. This list is then sent to the
companion damone over Http using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send_to_REST&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second step is to get the code compiled and Riak setup to be able to use it
is properly. This is described in the documentation about
&lt;a href=&quot;http://docs.basho.com/riak/kv/latest/using/reference/custom-code/&quot;&gt;custom code&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;enabling-the-hook&quot;&gt;Enabling the Hook&lt;/h3&gt;

&lt;p&gt;Finally, the commit hook has to be added to a Riak bucket-type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;riak-admin bucket-type create metadata_with_post_commit \
'{&quot;props&quot;:{&quot;postcommit&quot;:[&quot;metadata_stored_hook&quot;]}'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then the type is activated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;riak-admin bucket-type activate metadata_with_post_commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, anything sent to Riak to be stored with a key within a bucket whose
bucket-type is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadata_with_post_commit&lt;/code&gt; will trigger our callback
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadata_stored_hook&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The hook is executed on the coordinator node, that is, the node that received
the write request from the client. It’s not necessary the node where this
metadata will be stored.&lt;/p&gt;

&lt;h3 id=&quot;the-companion-app&quot;&gt;The companion app&lt;/h3&gt;

&lt;p&gt;The companion app is a Rest service, running on all Riak nodes, listening on
port 5000, ready to receive a json blob, which is the list of data keys that
Riak has just stored. The daemon will fetch these keys from Riak, decompress
their values, deserialise them and run the data transformation code on them.
The results are then stored back to Riak.&lt;/p&gt;

&lt;p&gt;There is little point showing the code of this piece of software here, as it’s
trivial to write. We implemented it in Perl using
a &lt;a href=&quot;https://en.wikipedia.org/wiki/PSGI&quot;&gt;PSGI&lt;/a&gt; preforking web server
(&lt;a href=&quot;https://metacpan.org/pod/Starman&quot;&gt;Starman&lt;/a&gt;). Using a Perl based web server
allowed us to also have the data transformation code in Perl, making
it easy for anyone in the IT department to write some of their own.&lt;/p&gt;

&lt;h3 id=&quot;optimising-intra-cluster-network-usage&quot;&gt;Optimising intra-cluster network usage&lt;/h3&gt;

&lt;p&gt;As seen saw earlier, if the commit hook simply sends the request to the local
companion app on the same Riak node, additional bandwidth usage is consumed to
fetch data from other Riak nodes. As the full stream of events is quite big
(around 150 MB per second), this bandwidth usage is significant.&lt;/p&gt;

&lt;p&gt;In an effort to optimise the network usage, we have changed the post-commit
hook callback to group the keys by the node that is responsible for their
values. The keys are then sent to the companion apps running on the associated
nodes. That way, a companion app will always receive event keys for which data
are on the node they are running on. Hence, fetching events value will not use
any network bandwidth. We have effectively implemented 100% data locality
when computing substreams.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&quot;/images/substream_optimized.png&quot; alt=&quot;Better implementation where metadata is sent to the Riak node that contains the data&quot; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This optimisation is implemented by using Riak’s internal API that gives the list
of primary nodes responsible for storing the value of a given key. More
precisely, Riak’s Core application API provides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preflist()&lt;/code&gt; function: (see
&lt;a href=&quot;http://basho.github.io/riak_core/riak_core_apl.html&quot;&gt;the API here&lt;/a&gt;) that is
used to map the result of the hashed key to its primary nodes.&lt;/p&gt;

&lt;p&gt;The result is a dramatic reduction of network usage. Data processing is
optimised by taking place on one of the nodes that store the given data. Only
the metadata (very small footprint) and the results (a tiny fraction
of the data) travel on the wire. Network usage is greatly reduced.&lt;/p&gt;

&lt;h2 id=&quot;back-pressure-management-strategy&quot;&gt;Back-pressure management strategy&lt;/h2&gt;

&lt;p&gt;For a fun and easy-to-read description of what back-pressure is and how to
react to it, you can read this great post by Fred Hebert (&lt;a href=&quot;https://twitter.com/mononcqc/&quot;&gt;@mononcqc&lt;/a&gt;):
&lt;a href=&quot;http://ferd.ca/queues-don-t-fix-overload.html&quot;&gt;Queues Don’t Fix Overload&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What if there are too many substreams, or one substream is buggy and performs
very costly computations (especially as we allow developers to easily write
their own substream), or all of a sudden the events fullstream change, one
type becomes huge and a previously working substream now takes 10 times
more to compute?&lt;/p&gt;

&lt;p&gt;One way of dealing with that is to allow back-pressure: the substream creation
system will inform the stream storage (Riak) that it cannot keep up, and that
it should reduce the pace at which it stores events. This is however not
practical here. Doing back-pressure that way will lead to the storage slowing
down, and transmitting the back-pressure upward the pipeline.
However, events can’t be “slowed down”. Applications send events at a given pace
and if the pipeline can’t keep up, events are simply lost. So propagating
&lt;em&gt;back-pressure&lt;/em&gt; upstream will actually lead to &lt;em&gt;load-shedding&lt;/em&gt; of events.&lt;/p&gt;

&lt;p&gt;The other typical alternative is applied here: doing &lt;em&gt;load-shedding&lt;/em&gt; straight
away. If a substream computation is too costly in CPU time, wallclock time,
disk IO or space, the data processing is simply aborted. This protects the Riak
cluster from slowing down events storage - which after all, is its main and
critical job.&lt;/p&gt;

&lt;p&gt;That leaves the substream consumers downstream with missing data. Substreams
creation is &lt;em&gt;not guaranteed&lt;/em&gt; anymore. However, we used a trick to mitigate the
issue. We implemented a dedicated feature in the common consumer library code;
when a substream is unavailable, the &lt;em&gt;full stream&lt;/em&gt; is fetched instead, and the
data transformation is performed on the &lt;em&gt;client side&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It effectively pushes the overloading issue down to the consumer, who can
react appropriately, depending on the guarantees they have to fulfill, and
their properties.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Some consumers are part of a cluster of hosts that are capable of sustaining
the added bandwidth and CPU usage for some time.&lt;/li&gt;
  &lt;li&gt;Some other systems are fine with delivering their results later on, so the consumers will simply be very slow and lag behind real-time.&lt;/li&gt;
  &lt;li&gt;Finally, some less critical consumers will be rendered useless because they
cannot catch up with real-time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, this multitude of ways of dealing with the absence of
substreams, concentrated at the end of the pipeline, is a very safe yet
flexible approach. In practice, it is not so rare that a substream result for
one epoch is missing (one blob every couple of days), and such blips have no
incidence on the consumers, allowing for a very conservative behaviour of the Riak
cluster regarding substreams: “when in doubt, stop processing substreams”.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This data processing mechanism proved to be very reliable and well-suited for
our needs. The implementation required surprisingly small amount of
code, leveraging features of Riak that proved to be flexible and easy to use.&lt;/p&gt;

&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[1]&lt;/strong&gt; It is not strictly true that our events are schema-less. They obey the
structure that the producers found the most useful and natural. But they are so
many producers which each of them sending events that have a different schema,
so it’s almost equivalent to considering them schema-less. Our events can be
seen as structured, yet with so many schemas that they can’t be traced. There
is also complete technical freedom to change the structure of an event, if it’s
seen as useful by a producer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[2]&lt;/strong&gt; After spending some time looking at and decoding Sereal blobs, the
human eye easily recognizes common data structures like small HashMaps, small
Arrays, small Integers and VarInts, and of course, Strings, since their content
is untouched. That makes Sereal an almost human readable serialisation format,
especially after a hexdump.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[3]&lt;/strong&gt; This can be worked around by using secondary indexes (2i) if the
backend is eleveldb or Riak Search, to create additional indexes on keys, thus
enabling listing them in various ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[4]&lt;/strong&gt; Some optimisation has been done, the main action was to implement a
module to split a sereal blob without deserialising it, thus speeding up the
process greatly. This module can be found here:
&lt;a href=&quot;https://metacpan.org/pod/Sereal::Splitter&quot;&gt;Sereal::Splitter&lt;/a&gt;. Most of the time
spent in splitting sereal blobs is now spent in decompressing it. The next
optimization step would be to use compression that decrunches faster than the
currently used gzip; for instance &lt;a href=&quot;https://code.google.com/p/lz4/&quot;&gt;LZ4_HC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[5]&lt;/strong&gt; At that point, the attentive reader may jump in the air and proclaim
“LevelDB and snappy compression!”. It is indeed possible to use LevelDB as Riak
storage backend, which provides an option to use Snappy compression on the
blocks of data stored. However, this compression algorithm is not good enough
for our need (using gzip reduced the size by a factor of almost 2). Also,
Leveldb (or at least the eleveldb implementation that is used in Riak) doesn’t
provide automatic expiration which is critical to us, and had issues with
reclaiming free space after key deletions, with versions below 2.x&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[6]&lt;/strong&gt; Using MapReduce on Riak is usually somewhat discouraged because most of the
time it’s being used in a wrong way, for instance when performing bulk fetch or bulk
insert or traversing a bucket. The MapReduce implementation in Riak is very
powerful and efficient, but must be used properly. It works best when
used on a small number of keys, even if the size of data processed is very
large. The fewer keys the less bookkeeping and the better performance. In our
case, there are only a couple of hundred keys for one second worth of data (but
somewhat large values, around 400K), which is not a lot. Hence the great
performance of MapReduce we’ve witnessed. YMMV.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>PromCon2017 - Prometheus Conference 2017</title>
   <link href="http://dams.github.com/2017/08/22/PromCon.html"/>
   <updated>2017-08-22T00:00:00+00:00</updated>
   <id>http://dams.github.com/2017/08/22/PromCon</id>
   <content type="html">&lt;h1 id=&quot;promcon2017---prometheus-conference-2017&quot;&gt;PromCon2017 - Prometheus Conference 2017&lt;/h1&gt;

&lt;p&gt;This post is a list of things that I found interesting about Prometheus and its
ecosystem while attending &lt;a href=&quot;https://promcon.io/2017-munich/&quot;&gt;PromCon2017, the Prometheus Conference&lt;/a&gt;, the 17th and
18th august 2017 in Munich (Germany). Things are not split per talks; instead I
have gathered information from all the talks and grouped them by topics, so
that it’s more organised, and easier to read.&lt;/p&gt;

&lt;p&gt;The conference was very nice, well organized, and with a good mix of talks:
technical, less technical, war zone experience, (remotely) related topics and
products. It was a medium-sized one track conference, which are the ones I
prefer, as one can grasp everything that happens and talk to everybody in the
hallways.&lt;/p&gt;

&lt;h1 id=&quot;best-practises---general&quot;&gt;Best practises - general&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;monitor all metrics from all services, and from all libraries&lt;/li&gt;
  &lt;li&gt;when coding, instead of printing debug messages or sending to log, send
metrics!&lt;/li&gt;
  &lt;li&gt;USE method for resources (queues, CPU, disks…): “Utilization, Saturation, Errors”&lt;/li&gt;
  &lt;li&gt;RED method for endpoints and services: “Rate, Errors, Duration”&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;best-practises---metrics-and-label-naming&quot;&gt;Best practises - metrics and label naming&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;standardize metric names and labels early on before it’s chaos&lt;/li&gt;
  &lt;li&gt;you need conventions&lt;/li&gt;
  &lt;li&gt;add unit suffixes&lt;/li&gt;
  &lt;li&gt;base units (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;seconds&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;milliseconds&lt;/code&gt;, bytes instead of megabytes)&lt;/li&gt;
  &lt;li&gt;add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_total&lt;/code&gt; counter suffixes to differenciate between counters and gauge&lt;/li&gt;
  &lt;li&gt;all the labels of a given metrics should be summable or average-able&lt;/li&gt;
  &lt;li&gt;be carefull about label cardinality
    &lt;ul&gt;
      &lt;li&gt;it’s OK to ingest millions of series&lt;/li&gt;
      &lt;li&gt;but one metric should have max 1000 or 10_000 series (labels combinations)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;more best practises (&lt;a href=&quot;https://prometheus.io/docs/practices/naming&quot;&gt;website&lt;/a&gt;]&lt;/li&gt;
  &lt;li&gt;when querying counters, don’t do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rate(sum())&lt;/code&gt;, because it masks the resets. Do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum(rate())&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;best-practises---alerting&quot;&gt;Best practises - alerting&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;use label and regex to do alert routing&lt;/li&gt;
  &lt;li&gt;page only on user-visible symptoms, not causes&lt;/li&gt;
  &lt;li&gt;“My Philosophy on Alerting” (see the SRE book or the &lt;a href=&quot;https://docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q/edit&quot;&gt;google doc&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;for all jobs: have these 2 basic alerts
    &lt;ul&gt;
      &lt;li&gt;alert on the prometheus job being up&lt;/li&gt;
      &lt;li&gt;alert if the job is not even there&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;don’t use a too short FOR duration (4 or 5 min) or too long (no persistence between restart)&lt;/li&gt;
  &lt;li&gt;keep labels when alerting (both recording and alerting rules) to know where it comes from&lt;/li&gt;
  &lt;li&gt;use filtering per job, as metrics are per jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;remote-storage&quot;&gt;Remote storage&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;prometheus provides an API to send/read/write data to a remote storage&lt;/li&gt;
  &lt;li&gt;it also provides a gateway to act as a proxy to other DB like OpenTSDB or
InfluxDB&lt;/li&gt;
  &lt;li&gt;in real life some people use OpenTSDB, others influxDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;influxdb&quot;&gt;InfluxDB&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;influxDB works fine with remote storage, read/write&lt;/li&gt;
  &lt;li&gt;influxDB will (once again) change a lot of things
    &lt;ul&gt;
      &lt;li&gt;new data model similar to prometheus&lt;/li&gt;
      &lt;li&gt;new QL called Influx Functional Query Language (IFQL)&lt;/li&gt;
      &lt;li&gt;isolate QL, storage, computation, have them on different nodes&lt;/li&gt;
      &lt;li&gt;generate a DAG for queries, and use an execution engine&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;exporters&quot;&gt;Exporters&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;telegraf: having one telegraf instance per service is a SPOF, so be careful
and either have redundant telegraf instances or multiple telegrafs per
service.&lt;/li&gt;
  &lt;li&gt;useful exporters: node exporters, blackbox (check urls), mtail&lt;/li&gt;
  &lt;li&gt;don’t use one exporter to collect more than one service: one thing going
crazy won’t pollute other metrics collections.&lt;/li&gt;
  &lt;li&gt;graphite exporter is easy and useful but it’s tricky to get labels exported
and transformed in graphite metric names in the right way&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;alerting-tools&quot;&gt;Alerting tools&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;alert manager deduplicates, so can be used from federated prometheus&lt;/li&gt;
  &lt;li&gt;use jiralert (&lt;a href=&quot;https://github.com/fabxc/jiralerts&quot;&gt;github&lt;/a&gt;), it’ll reopen
existing ticket if an alarm is triggered, avoids overcreating tickets.&lt;/li&gt;
  &lt;li&gt;use alertmanager2es (&lt;a href=&quot;https://github.com/cloudflare/alertmanager2es&quot;&gt;github&lt;/a&gt;) to
index alerts in ES&lt;/li&gt;
  &lt;li&gt;unsee (&lt;a href=&quot;https://github.com/cloudflare/unsee&quot;&gt;github&lt;/a&gt;) is a dashboard for alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;meta-alerting&quot;&gt;Meta Alerting&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;send one alert on page duty at start of shift, make sure it’s received&lt;/li&gt;
  &lt;li&gt;or use grafana for graphing alert manager and to alert about it (basic alerts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;grafana&quot;&gt;Grafana&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;lots of improvements of the query box (auto complettion, syntax highlighting, etc)&lt;/li&gt;
  &lt;li&gt;improvements of displaying graph, with spread, upper limit points&lt;/li&gt;
  &lt;li&gt;emoji available for quick glimpse at a state&lt;/li&gt;
  &lt;li&gt;table panels available&lt;/li&gt;
  &lt;li&gt;heatmap panel: histogram over time&lt;/li&gt;
  &lt;li&gt;diagram panel: awesome feature to display your pipeline with annotated metrics/colors&lt;/li&gt;
  &lt;li&gt;dashboard version history is available&lt;/li&gt;
  &lt;li&gt;dashboards in git:
    &lt;ul&gt;
      &lt;li&gt;currently possible via the grafana lib from cortex&lt;/li&gt;
      &lt;li&gt;later on will be provided by grafana&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;dashboards folders available&lt;/li&gt;
  &lt;li&gt;grafana data source supports templating so you can change quickly data
sources when one prometheus instance is down, nice for fault tolerance&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;cortex&quot;&gt;Cortex&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;A multitenant, horizontally scalable Prometheus as a Service (&lt;a href=&quot;https://github.com/weaveworks/cortex&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;has multiple parts, ingesters, storage, service discovery, read/write query paths&lt;/li&gt;
  &lt;li&gt;storage is implemented through an API so one could use a different storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;various&quot;&gt;Various&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;promgen: a prometheus configuration tool, worth checking
out (&lt;a href=&quot;https://github.com/line/promgen&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;load testing: &lt;a href=&quot;http://gatling.io/&quot;&gt;Gatling&lt;/a&gt; (scriptable, generate scala code, Akka
based) vs &lt;a href=&quot;http://jmeter.apache.org/&quot;&gt;JMeter&lt;/a&gt; (UI oriented, XML, threads)&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;prometheus-limitations&quot;&gt;Prometheus limitations&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;HA issues: when restarting/upgrading prometheus, gaps in data/graph can appear&lt;/li&gt;
  &lt;li&gt;there is no horizontal scaling but sharding + federation; can be surprising at first&lt;/li&gt;
  &lt;li&gt;remote storage API and gateway can work around limitation of the local storage&lt;/li&gt;
  &lt;li&gt;hard time figuring out where the data is located on disk&lt;/li&gt;
  &lt;li&gt;retention issues: you can’t specify a disk size, only expiration date; there
is no downsampling feature, which limit retention capacity&lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;h1 id=&quot;prometheus-v2&quot;&gt;Prometheus v2&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;will use Facebook’s Gorilla paper optimization, and Damian Gryski
(&lt;a href=&quot;https://github.com/dgryski&quot;&gt;github&lt;/a&gt;) implementation&lt;/li&gt;
  &lt;li&gt;prometheus 2 new storage, not a distributed storage but huge improvement in
ram, cpu, disk usage&lt;/li&gt;
  &lt;li&gt;libTSDB is the new storage lib for prometheus v2. It can be used outside of
prometheus: an embeddable TSDB Go library.&lt;/li&gt;
  &lt;li&gt;alertmanager with HA through gossip protocol and CRDTs using the mesh library
by Weaveworks (&lt;a href=&quot;https://github.com/weaveworks/mesh&quot;&gt;github&lt;/a&gt;). It’s AP.&lt;/li&gt;
  &lt;li&gt;beta avaioable now, stable enough for testing and some level of production use&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Exception::Stringy - Modern exceptions for legacy code</title>
   <link href="http://dams.github.com/2015/02/10/exception-stringy.html"/>
   <updated>2015-02-10T00:00:00+00:00</updated>
   <id>http://dams.github.com/2015/02/10/exception-stringy</id>
   <content type="html">&lt;h1 id=&quot;exceptionstringy---modern-exceptions-for-legacy-code&quot;&gt;Exception::Stringy - Modern exceptions for legacy code&lt;/h1&gt;

&lt;h1 id=&quot;a-small-recap-of-perl-exceptions&quot;&gt;A small recap of Perl exceptions&lt;/h1&gt;

&lt;h2 id=&quot;basic-usage-of-exceptions&quot;&gt;Basic Usage Of Exceptions&lt;/h2&gt;

&lt;p&gt;In Perl, exceptions are a well known and widely used mechanism. It is an old
feature that has been enhanced over time. At the basic level, exceptions are
triggered by the keyword &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;die&lt;/code&gt;. Exceptions were initially used as a way to stop
the execution of a program in case of a fatal error. The too famous line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;failed to open '&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;', error: $!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;is a good example.&lt;/p&gt;

&lt;p&gt;The original way to catch exceptions in Perl has a somewhat strange syntax,
it’s based on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; keyword and the special variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$@&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;code_that_may_die&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;exception has been caught: $@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nowadays, exceptions are usually thrown using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;croak&lt;/code&gt; and friends, from the
&lt;a href=&quot;https://metacpan.org/pod/Carp&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carp&lt;/code&gt;&lt;/a&gt; module. It allows for a much better flexibility about where the exception
seems to originate, and how to display the stack trace, if any.&lt;/p&gt;

&lt;p&gt;Catching exceptions with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; is also supersed by try/catch mechanisms. The
most used one is via the [&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Try::Tiny&lt;/code&gt;][try-tiny] module by Yuval Kogman and Jesse Luehrs,
and goes like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;croak&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;warn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;caught error: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;throwing-objects&quot;&gt;Throwing Objects&lt;/h2&gt;

&lt;p&gt;The good thing about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;die&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;croak&lt;/code&gt;), is that it’s very easy to use, when
given a string. It’s perfect for using in scripts, or moderately big
projects. However, for more features, or extensive usage of exceptions, then
it’s better to throw objects instead of strings, like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MyExceptions::IO::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$!&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For this snippet of code to work, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyExceptions::IO::File&lt;/code&gt; class has to be
declared, its fields as well, and the it should probably inherit from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyExceptions::IO&lt;/code&gt;. So it requires some amount of work.&lt;/p&gt;

&lt;p&gt;Some modules have been created - long time ago - to automate or help with
declaring exception classes. The most well known one is [&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Class&lt;/code&gt;][exception-class], by
Dave Rolsky. For instance, here is how to declare two exceptions matching with
previous example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyExceptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Exception::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MyException::IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MyException::IO::File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MyException::IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;    
            &lt;span class=&quot;nv&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And then, here is the code to make use of that and throw an exception when
failing to open a file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyExceptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MyException::IO::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$!&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;catching-objects-exceptions&quot;&gt;Catching Objects Exceptions&lt;/h2&gt;

&lt;p&gt;When using objects as exceptions, a set of features becomes available, thanks
to Object Oriented Programming. Inheritance, attributes and introspection are
some of them. However the most visible and used feature is about catching such
exceptions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MyException::IO::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$!&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;MyException::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# we know how to handle these&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rethrow&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, it’s easy to introspect an exception if it’s an object. In this
case we use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isa&lt;/code&gt; keyword to know if the exception is or inherits from a
given class name.&lt;/p&gt;

&lt;h1 id=&quot;when-things-go-wrong&quot;&gt;When things go wrong&lt;/h1&gt;

&lt;h2 id=&quot;mixing-objects-and-string-exceptions&quot;&gt;Mixing Objects And String Exceptions&lt;/h2&gt;

&lt;p&gt;As we saw in the previous chapter, Perl allows exceptions being whatever you
like (string, objects, but actually numbers, structures, etc, work as well).&lt;/p&gt;

&lt;p&gt;Usually, when starting a project, the author decides whether to use simple
strings or objects with a class hierarchy. With very big projects, it is
sometimes not possible to impose one kind of exceptions. This may be due to
legacy code, a subproject that was included, or the wish to give people freedom
about what they want to use depending on the context.&lt;/p&gt;

&lt;p&gt;In these cases, the code may have to handle exceptions of two kinds: strings
and objects. This can be done via this kind of code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Scalar::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Util&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;qw(blessed)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# ... code that may die&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;blessed&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# exception is an object&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# exception is a normal string&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;mixed-exceptions-issues&quot;&gt;Mixed Exceptions Issues&lt;/h2&gt;

&lt;p&gt;The previous code snippet suffers from increased complexity due to the
additional checks and two different codepaths for handling potential errors.
This is clearly both suboptimal and error prone.&lt;/p&gt;

&lt;p&gt;Another issue is that some code may consider that the exception it is catching
is of one type, whereas it could be of an other type, especially because of the
action-at-distance nature of the exception. Consider this function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do_stuff&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# ... code that can only throw objects exceptions&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# exception is always an object&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code assumes that the exception will always be an object. However,
let’s consider this: in following example, the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_stuff&lt;/code&gt; is called
(its original code is unchanged), but before doing so, the special signal
handler for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__DIE__&lt;/code&gt; is changed.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$SIG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;__DIE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;FATAL: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;do_stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The first line of the example is being called when an exception is raised, and
will be executed instead of propagating the exception. What this code does is
prepending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FATAL: &lt;/code&gt;to it, then propagate the exception again by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;die&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Alas, it is doing so in a naive way, by forcing the exception (in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_[0]&lt;/code&gt;) to be
evaluated as a string. So when the exception is then re-thrown, it is now a
string ! and Boom, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt;isa&lt;/code&gt; call in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_stuff&lt;/code&gt; won’t work.&lt;/p&gt;

&lt;p&gt;The worst thing about this kind of issue is that it doesn’t appear at compile
time, nor at execution time, but at &lt;em&gt;exception time&lt;/em&gt;, which is the worst
time…&lt;/p&gt;

&lt;h2 id=&quot;the-overloaded-stringification-route&quot;&gt;The Overloaded Stringification Route&lt;/h2&gt;

&lt;p&gt;So at that point, most developers will choose the following strategy. Use
object exceptions for their code, but guard against receiving string exceptions,
and also make their object exceptions nicely degrade into strings, by using
stringification overloading. That means that if an object exception is managed
by a handler that threats it as a string, the exception will transform itself
into a string, and try to present some meaningful aspect of itself.&lt;/p&gt;

&lt;p&gt;The issue is that handling exception is now back to square one, having to deal
with strings, trying to parse it looking for meaningful information to
hopefully make a good decision.&lt;/p&gt;

&lt;p&gt;What if, instead of taking an object exception and &lt;strong&gt;downgrading it to a
string&lt;/strong&gt; while keeping as much information as possible, one &lt;strong&gt;starts from a
string, and enhance it until it looks like an object&lt;/strong&gt;, without being one ? That
way we would have the best of both worlds&lt;/p&gt;

&lt;p&gt;This is what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Stringy&lt;/code&gt; tries to achieve.&lt;/p&gt;

&lt;h1 id=&quot;exceptionsstringy-from-scratch&quot;&gt;Exceptions::Stringy from scratch&lt;/h1&gt;

&lt;h2 id=&quot;the-needed-features&quot;&gt;The Needed Features&lt;/h2&gt;

&lt;p&gt;A perfect exception would have these features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;be a string, containing an error message&lt;/li&gt;
  &lt;li&gt;be an instance of a class&lt;/li&gt;
  &lt;li&gt;be able to inherit from an other exception&lt;/li&gt;
  &lt;li&gt;have simple fields with values&lt;/li&gt;
  &lt;li&gt;provide a way to introspect itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This set of features is not big, but it’s probably enough for a start. Let’s
see how we can implement them in a simple string. We’re going to use an
exception with these attributes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;an error message ‘permission denied’&lt;/li&gt;
  &lt;li&gt;from the class MyException::IO&lt;/li&gt;
  &lt;li&gt;which inherits from MyException&lt;/li&gt;
  &lt;li&gt;with a field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filename&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;class-instance&quot;&gt;Class Instance&lt;/h2&gt;

&lt;p&gt;Let’s start with the first feature: &lt;em&gt;be a string, containing an error message&lt;/em&gt;.
That’s easy:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;permission denied&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Being an instance of a class is usually done in Perl by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bless&lt;/code&gt; on a
ScalarRef. But we don’t want the eception to be an object. What &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bless&lt;/code&gt; does -
and what it ultimately means to “be an instance of a class”, is just attaching
a &lt;em&gt;label&lt;/em&gt; to a value. Let’s do that, by having a label as a substring in our
exception. For instance:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[MyException::IO]permission denied&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We could add a magic mark or have a more complex label syntax to make sure it’s
a legit label.&lt;/p&gt;

&lt;p&gt;To know what the class of a given exception is, we just need to extract the
label, for instance with a regex.&lt;/p&gt;

&lt;h2 id=&quot;class-inheritance&quot;&gt;Class Inheritance&lt;/h2&gt;

&lt;p&gt;Inheritance is easy, it only requires that standard Perl classes be created to
map the exception labels, and then Perl usual inheritance can be used.&lt;/p&gt;

&lt;p&gt;So, following our example, we need two packages, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyException&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyException::IO&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@MyException::IO::ISA&lt;/code&gt; set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;['MyException']&lt;/code&gt;. This can
be made automatically at exception declaration time.&lt;/p&gt;

&lt;h2 id=&quot;fields&quot;&gt;Fields&lt;/h2&gt;

&lt;p&gt;For simplicity, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Stringy&lt;/code&gt; only handles simple field values, that is
strings and numbers basically. To put fields into our string, we need to be
able to identify them, so for instance with a separator between the different
fields, and an other one between a field name and its value. Like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[MyException::IO|filename:/tmp/file|]permission denied&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And if the field name or value contains one of the separators ( &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;
or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt;), let’s encode them in base64, and mark it as such.&lt;/p&gt;

&lt;p&gt;So, by now, we have fleshed out a string with useful data, which is properly
parseable, and can be described. Let’s add methods to the data now.&lt;/p&gt;

&lt;h2 id=&quot;introspection-and-modification&quot;&gt;Introspection and Modification&lt;/h2&gt;

&lt;p&gt;Given an exception, it is mandatory to be able to introspect and modify it, namely be able to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;get/set the class of the exception,&lt;/li&gt;
  &lt;li&gt;get/set the fields values attached to the exception,&lt;/li&gt;
  &lt;li&gt;get/set the exception message,&lt;/li&gt;
  &lt;li&gt;other useful methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an ideal world, we would want methods, that we can call on our exception
instances. However because our exceptions are regular strings, we can’t do
this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Usually, this way of calling a method (the arrow notation) works only if
$exception is a blessed reference (that is, an object). However, there are
other cases in which we can use the arrow notation, and have it work in a
similar way. One of it is this one:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If $message is a variable that contains a reference on a subroutine, then the previous line will translate into:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And it works whatever the type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$exception&lt;/code&gt;, like in our case, a string. So,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Stringy&lt;/code&gt; creates the needed subroutine references for the user and
allow such arrow notation, which is very similar to the OO method invocation. I
call these &lt;strong&gt;pseudo methods&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, to avoid clobbering an existing variable, the pseudo methods need to
have names that are unlikely to be already used in the target package. It’s
even better if there is an option to add a prefix to these pseudo-methods.
Once again, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Stringy&lt;/code&gt; provides these features. The default pseudo
method names are :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xthrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xrethrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xraise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xclass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xisa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xfields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xfield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xmessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;launching-the-exception&quot;&gt;Launching The Exception&lt;/h2&gt;

&lt;p&gt;Finally, once we have created the exception, let’s throw it. The first think to
do is to implement a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt;or `raise class method on all the exception class,
so that we can do&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;MyException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That will basically craft a new exception string, with all the properties
encoded in it, and call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;die&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;croak&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;We can also use a &lt;strong&gt;pseudo method&lt;/strong&gt; on an existing exception to (re)throw it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xthrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;exceptionsstringy-example&quot;&gt;Exceptions::Stringy example&lt;/h1&gt;

&lt;h2 id=&quot;synopsis&quot;&gt;Synopsis&lt;/h2&gt;

&lt;p&gt;Below is the synopsis of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exceptions::Stringy&lt;/code&gt; module. It’s basically a
wrap up of what has been explained above. The exceptions definition is heavily
inspired from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Class&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Exception::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Stringy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Exception::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Stringy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;declare_exceptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MyException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
     
        &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;YetAnotherException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;AnotherException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     
        &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ExceptionWithFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;YetAnotherException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;grandiosity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;quixotic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;throw_alias&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;throw_fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;### with Try::Tiny&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Try::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Tiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     
    &lt;span class=&quot;nv&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# throw an exception&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;MyException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;I feel funny.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;
    
        &lt;span class=&quot;c1&quot;&gt;# or use an alias&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;throw_fields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Error message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;grandiosity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
        &lt;span class=&quot;c1&quot;&gt;# or with fields&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;ExceptionWithFields&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;I feel funny.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
                                   &lt;span class=&quot;nv&quot;&gt;quixotic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                   &lt;span class=&quot;nv&quot;&gt;grandiosity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
        &lt;span class=&quot;c1&quot;&gt;# you can build exception step by step&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ExceptionWithFields&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;The error message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xfield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;quixotic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;some_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xthrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xisa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Exception::Stringy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;')&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;warn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xisa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ExceptionWithFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;')&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xfield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;quixotic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;')&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;handle_quixotic_exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;handle_non_quixotic_exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$xrethrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
   
    &lt;span class=&quot;c1&quot;&gt;### without Try::Tiny&lt;/span&gt;
   
    &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;MyException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;I feel funny.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# .. same as above with $e instead of $_&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This was an in-depth look at why and how to build up a resilient and
non-intrusive exception mecanism. I hope to have demonstrated one aspect of the
extreme flexibility of Perl.&lt;/p&gt;

&lt;p&gt;Feel free to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception::Stringy&lt;/code&gt;, it is being used in production code for
some time now. Feedback welcome !&lt;/p&gt;

&lt;h1 id=&quot;links&quot;&gt;Links&lt;/h1&gt;

</content>
 </entry>
 
 <entry>
   <title>Perl Redis Mailing List</title>
   <link href="http://dams.github.com/2013/11/12/perl-redis-mailing-list.html"/>
   <updated>2013-11-12T00:00:00+00:00</updated>
   <id>http://dams.github.com/2013/11/12/perl-redis-mailing-list</id>
   <content type="html">&lt;h1 id=&quot;perl-redis-mailing-list&quot;&gt;Perl Redis Mailing List&lt;/h1&gt;

&lt;p&gt;This is going to be a short post. I’m the new maintainer of
&lt;a href=&quot;https://metacpan.org/module/Redis&quot;&gt;Redis.pm&lt;/a&gt;, the most used Redis Perl client.
Pedro Melo was the previous maintainer, but due to Real Life, he is unable to
continue. I’d like to thank him for all his efforts so far in maintaining and
improving this module. I hope I’ll be able to achieve the same level of
quality. Pedro will actually stay around for a while, watching over my
shoulder and giving his opinions about stuff, to allow for a smooth transition.&lt;/p&gt;

&lt;p&gt;We’ve used this maintainership change to improve the tools we use around this
project. So we’ve moved the code to the github’s
&lt;a href=&quot;https://github.com/PerlRedis&quot;&gt;PerlRedis&lt;/a&gt; organization (notice the cool logo),
and I’ve performed quite a few code cleanups and housekeeping.&lt;/p&gt;

&lt;p&gt;But the big thing is the creation of a mailing list, that aims at gathering
forces around Redis support in Perl. It’s
&lt;a href=&quot;http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/redis&quot;&gt;located here&lt;/a&gt;, and
hosted by the good folks at &lt;a href=&quot;http://shadow.cat/&quot;&gt;ShadowCat Systems Limited&lt;/a&gt;
(thank you guys).&lt;/p&gt;

&lt;p&gt;It is not limited to the Redis.pm module: any Perl related Redis topic is
welcome, including other Perl clients. So if you have any interest in Perl and
Redis, feel free to &lt;a href=&quot;http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/redis&quot;&gt;subscribe&lt;/a&gt; !&lt;/p&gt;

&lt;p&gt;dams.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>p5-mop: a gentle introduction</title>
   <link href="http://dams.github.com/2013/09/17/p5-mop.html"/>
   <updated>2013-09-17T00:00:00+00:00</updated>
   <id>http://dams.github.com/2013/09/17/p5-mop</id>
   <content type="html">&lt;h1 id=&quot;p5-mop-a-gentle-introduction&quot;&gt;p5-mop: a gentle introduction&lt;/h1&gt;

&lt;p&gt;I guess that you’ve heard about p5-mop by now.&lt;/p&gt;

&lt;p&gt;If not, in a nutshell, p5-mop is an attempt to implement a subset of
&lt;a href=&quot;http://moose.iinteractive.com/&quot;&gt;Moose&lt;/a&gt; into the core of Perl. Moose provides a
Meta Object Protocol (MOP) to Perl. So does p5-mop, however p5-mop is
implemented in a way that it can be properly included in the Perl core.&lt;/p&gt;

&lt;p&gt;Keep in mind that p5-mop goal is to implement a &lt;em&gt;subset&lt;/em&gt; of Moose, and. As
Stevan Little says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We are not putting “Moose into the core” because Moose is too opinionated,
instead we want to put a minimal and less opinionated MOP in the core that is
capable of hosting something like Moose&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As far as I understood, after a first attempt that failed, Stevan Little
restarted the p5-mop implementation: the so-called p5-mop-redux
&lt;a href=&quot;https://github.com/stevan/p5-mop-redux&quot;&gt;github project&lt;/a&gt;, using
&lt;a href=&quot;https://metacpan.org/module/Devel::Declare&quot;&gt;Devel::Declare&lt;/a&gt;, ( then
&lt;a href=&quot;https://metacpan.org/module/Parse::Keyword&quot;&gt;Parse::Keyword&lt;/a&gt; ), so that he can
experiment and release often, while keeping the implementation core-friendly.
Once he’s happy with the features and all, he’ll make sure it finds its way to
the core. A small team (Stevan Little, &lt;a href=&quot;http://tozt.net/&quot;&gt;Jesse Luehrs&lt;/a&gt;, and
other contributors) is actively developping p5-mop, and Stevan is regularly
&lt;a href=&quot;http://blogs.perl.org/users/stevan_little/&quot;&gt;blogging about it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want more details about the failing first attempt, there is a bunch of
backlog and mailing lists archive to read. However, here is how Stevan would
summarize it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We started the first prototype, not remembering the old adage of “write the
first one to throw away” and I got sentimentally attached to my choice of
design approach. This new approach (p5-mop-redux) was purposfully built with
a firm commitment to keeping it as simple as possible, therefore making it
simpler to hack on.
Also, instead of making the MOP I always wanted, I approached as building the
mop people actually needed (one that worked well with existing perl classes,
etc)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Few months ago, when p5-mop-redux was announced, I tried to give it a go. And
you should too ! Because it’s easy.&lt;/p&gt;

&lt;h2 id=&quot;why-is-it-important-to-try-it-out-&quot;&gt;Why is it important to try it out ?&lt;/h2&gt;

&lt;p&gt;It’s important to have at least a vague idea of where p5-mop stands at, because
this project is shaping a big part of Perl’s future. IMHO, there will be a
&lt;em&gt;before&lt;/em&gt; and an &lt;em&gt;after&lt;/em&gt; having a MOP in core. And it is being designed and
tested &lt;em&gt;right&lt;/em&gt; &lt;em&gt;now&lt;/em&gt;. So as Perl users, it’s our chance to have a look at it,
test it, and give our feedback.&lt;/p&gt;

&lt;p&gt;Do we like the syntax ? Is it powerful enough? What did we prefer more/less
in Moose ? etc. In few months, things will be decided and it’ll only be a
matter of time and implementation details. Now is the most exciting time to
participate in the project. You don’t need to hack on it, just try it out, and
provide feedback.&lt;/p&gt;

&lt;h2 id=&quot;install-it&quot;&gt;Install it&lt;/h2&gt;

&lt;p&gt;p5-mop is very easy to install:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you need at least perl 5.16. If you need to upgrade, consider &lt;a href=&quot;http://perlbrew.pl/&quot;&gt;perlbrew&lt;/a&gt; or &lt;a href=&quot;https://github.com/tokuhirom/plenv&quot;&gt;plenv&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;if you don’t have cpanm, get it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -L http://cpanmin.us | perl - App::cpanminus&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;first, we need to install twigils, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpanm --dev twigils&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;if you’re using github, just fork the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p5-mop-redux&lt;/code&gt; project. Otherwise you can get a zip &lt;a href=&quot;https://github.com/stevan/p5-mop-redux/archive/master.zip&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;using cpanm, execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpanm .&lt;/code&gt; from within the p5-mop-redux directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;a-first-example&quot;&gt;A first example&lt;/h2&gt;

&lt;p&gt;Here is the classical point example from the &lt;a href=&quot;https://github.com/stevan/p5-mop-redux/blob/master/t/001-examples/001-point.t&quot;&gt;p5-mop test suite&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ro&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ro&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set_x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set_y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;y =&amp;gt; $self-&amp;gt;y }
    }
}

# ... subclass it ...

class Point3D extends Point {
    has $!z is ro = 0;

    method set_z ($z) {
        $!z =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This examples shows how straightforward it is to declare a class and a
subclass. The syntax is very friendly and similar to what you may find in other
languages.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; declares a class, with proper scoping. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;method&lt;/code&gt; is used to define
methods, so no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub&lt;/code&gt; there. The distinction is important, because in &lt;em&gt;methods&lt;/em&gt;,
additional variables will be automatically available:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$self&lt;/code&gt; will be available directly, no need to shift &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@_&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;attributes variable will be available automatically, so you can access
attributes from within the class without having to use their
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$self-&amp;gt;accessors&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Functions defined with the regular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub&lt;/code&gt; keyword won’t have all these features,
and that’s for good: it makes the difference between &lt;em&gt;function&lt;/em&gt; and &lt;em&gt;method&lt;/em&gt;
more explicit.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has&lt;/code&gt;declares an attribute. Attribute names are &lt;em&gt;twigils&lt;/em&gt;. Borrowed from Perl6,
and implemented by Florian Ragwitz in its
&lt;a href=&quot;https://github.com/rafl/twigils/&quot;&gt;twigils project on github&lt;/a&gt;, twigils are
useful to differenciate standard variables from attributes variables:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;do_stuff&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;stuff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, it’s important to be able to differenciate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stuff&lt;/code&gt; (the
variable) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stuff&lt;/code&gt; (the attribute).&lt;/p&gt;

&lt;p&gt;The added benefit of attributes variables is that one doesn’t need to contantly
use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$self&lt;/code&gt;. A good proportion of the code in a class is about attributes.
Being able to use them directly is great.&lt;/p&gt;

&lt;p&gt;Other notes worth mentiong:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Classes can have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUILD&lt;/code&gt; method, as with Moose.&lt;/li&gt;
  &lt;li&gt;A class can inherit from an other one by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extend&lt;/code&gt;-ing it.&lt;/li&gt;
  &lt;li&gt;In a inheriting class, calling the parent method is not done using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SUPER&lt;/code&gt;,
but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$self-&amp;gt;next::method&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; declared in the package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bar&lt;/code&gt; will be defined as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bar::Foo&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;attributes-traits&quot;&gt;Attributes traits&lt;/h2&gt;

&lt;p&gt;When declaring an attribute name, you can add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt;, which is followed by a list of
&lt;em&gt;traits&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ro&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ro&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rw&lt;/code&gt; means it’s read-only / read-write&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lazy&lt;/code&gt; means the attribute constructor we’ll be called only when the
attribute is being used&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;weak_ref&lt;/code&gt; enables an attribute to be a weak reference&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;default-value--builder&quot;&gt;Default value / builder&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;default value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which is actually&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;default value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, there is no default value, only builders. That means that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has $!foo = {};&lt;/code&gt;
will work as expected ( creating a new hashref each time ).&lt;/p&gt;

&lt;p&gt;You can reference the current instance in the attribute builder by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_init_foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There has been some comments about using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt;, but this syntax is used in a lot of other programing language, and
considered somehow the default (ha-ha) syntax. I think it’s worth sticking with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; for an easier learning curve for newcomers.&lt;/p&gt;

&lt;h2 id=&quot;class-and-method-traits&quot;&gt;Class and method traits&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Similarly to attributes, classes and methods can have traits. I
won’t go in details to keep this post short, but you can make a class abstract,
change the default behaviour of all its attributes, make it work better with
Moose, etc. Currently there is only one method trait to allow for operator
overloading, but additional ones may appear shortly.&lt;/p&gt;

&lt;h2 id=&quot;methods-parameters&quot;&gt;Methods parameters&lt;/h2&gt;

&lt;p&gt;When calling a method, the parameters are as usual available in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@_&lt;/code&gt;. However
you can also declare these parameters in the method signature:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$arg2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; you can specify a default value. In the method body, these parameters
will be available directly.&lt;/p&gt;

&lt;h2 id=&quot;types&quot;&gt;Types&lt;/h2&gt;

&lt;p&gt;Types are not yet core to the p5-mop, and the team is questioning this idea.
The concensus is currently that types should not be part of the mop, to keep it
simple and flexible. You ought to be able to choose what type system you want
to use. I’m particularly happy about this decision. Perl is so versatile and
flexible that it can be used (and bent to be used) in numerous environment and
configuration. Sometimes you need robustness and high level powerful features,
and it’s great to use a powerful typing system like Moose’s one. Sometimes
(most of the time? ) Type::Tiny (before that I used Params::Validate) is good
enough and gives you faster processing. Sometimes you don’t want any type
checking.&lt;/p&gt;

&lt;h2 id=&quot;clearer--predicate&quot;&gt;Clearer / predicate&lt;/h2&gt;

&lt;p&gt;Because the attribute builder is already implemented using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;, what about
clearer and predicate?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# clearer&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clear_foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;undef&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# predicate&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;has_foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That was pretty easy, right? Predicates and clearers have been introduced in
Moose because writing them ourselves would require to access the underlying
HashRef behind an instance (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub predicate { exists $self-&amp;gt;{$attr_name}}&lt;/code&gt;)
and that’s very bad. To work around that, Moose has to generate that kind of
code and provide a way to enable it or not. Hence the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;predicate&lt;/code&gt;and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clearer&lt;/code&gt;
options. So you see that they exists mostly because of the implementation.&lt;/p&gt;

&lt;p&gt;In p5-mop, thanks to the twigils, there is no issue in writing predicates and
cleare ourselves.&lt;/p&gt;

&lt;p&gt;But I hear you say “Wait, these are no clearer nor predicate ! They are not testing the
existence of the attributes, but their define-ness!” You’re right, but read on!&lt;/p&gt;

&lt;h2 id=&quot;undef-versus-not-set&quot;&gt;Undef versus not set&lt;/h2&gt;

&lt;p&gt;In Moose there is a difference between an attribute being unset, and an
attribute being undef. In p5-mop, there is no such distinction. Technically, it
would be very difficult to implemente that distinction, because an attribute
variable is declared even if the attribute has not been set yet.&lt;/p&gt;

&lt;p&gt;In Moose, because objects are stored in blessed hashes, an attribute can either
be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;non-existent in the underlying hash&lt;/li&gt;
  &lt;li&gt;present in the hash but with an undef value&lt;/li&gt;
  &lt;li&gt;present and defined but false&lt;/li&gt;
  &lt;li&gt;present, defined and true&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s probably too many cases… Getting rid of one of them looks sane to me.&lt;/p&gt;

&lt;p&gt;After all, we got this “not set” state only because objects are stored in
HashRef, so it looks like it’s an implementation detail that made its way into
becoming a concept on its own, which is rarely a good thing.&lt;/p&gt;

&lt;p&gt;Plus, in standard Perl programming, if an optional argument is not passed to a
function, it’s not “non-existent”, it’s &lt;em&gt;undef&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# $arg is undef&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So it makes sense to have a similar behavior in p5-mop - that is, an attribute
that is not set is undef.&lt;/p&gt;

&lt;h2 id=&quot;roles&quot;&gt;Roles&lt;/h2&gt;

&lt;p&gt;Roles definition syntax is quite similar to defining a class.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;additional_attr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;more_feature&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;additional_attr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;They are consumed right in the class declaration line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Baz&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;meta&quot;&gt;Meta&lt;/h2&gt;

&lt;p&gt;Going meta is not difficult either but I won’t describe it here, as I just want
to showcase default OO programming syntax. On that note, it looks like Stevan
will make classes immutable by default, unless specified. I think that this is
a good idea (how many time have you written make_immutable ?).&lt;/p&gt;

&lt;h1 id=&quot;my-hopefully-constructive-remarks&quot;&gt;My (hopefully constructive) remarks&lt;/h1&gt;

&lt;h2 id=&quot;method-modifiers&quot;&gt;Method Modifiers&lt;/h2&gt;

&lt;p&gt;Method modifiers are not yet implemented, but they won’t be difficult to
implement. Actually, here is an example of how to implement method modifiers
using p5-mop very own meta. It implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;around&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mop::method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$meta&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;associated_meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mop::role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;around&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;after:COMPOSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;has_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$old_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;remove_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;nv&quot;&gt;$other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                            &lt;span class=&quot;nv&quot;&gt;$other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;method_class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                                &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;NEXT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$old_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                                    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                                    &lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;before not yet supported&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;after not yet supported&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;I have no idea what to do with &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mop::class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;modifiers on classes not yet supported&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It is supposed to be used like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my_method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;modifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;around&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;')&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$arg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;NEXT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I would like to see method modifiers in p5-mop. As per Stevan Little and Jesse
Luehrs, it may be that these won’t be part of the mop, but in a plugin or
extension. I’m not to sure about that, for me method modifier is really linked
to OO programmning. I prefer using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;around&lt;/code&gt; than fiddling with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$self-&amp;gt;next::method&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${^NEXT}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here are some syntax proposals I’ve gathered on IRC and blog comments regarding
what could be method modifiers in p5-mop:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;around foo { }
method foo is around { ... }
method foo is modifier(around) { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;next-and-self&quot;&gt;${^NEXT} and ${^SELF}&lt;/h2&gt;

&lt;p&gt;These special variables are pointing to the current instance (useful when
you’re not in a method - otherwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$self&lt;/code&gt; is available), and the next method
in the calling chain. It’s OK to have such variables, but their horrible name
makes it difficult to remember and use.&lt;/p&gt;

&lt;p&gt;Can’t we have yet an other type of twigils for these variables ? so that we can
write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$^NEXT&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$^SELF&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;twigils-for-public--private-attributes&quot;&gt;Twigils for public / private attributes&lt;/h2&gt;

&lt;p&gt;Just an idea, but maybe we could have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$!public_attribute&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$.private_attribute&lt;/code&gt;. Or is it the other way around ?&lt;/p&gt;

&lt;h2 id=&quot;why-is--we-already-have-has-&quot;&gt;why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; ? we already have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has&lt;/code&gt; !&lt;/h2&gt;

&lt;p&gt;This one thing is bothering me a lot: why do we have to use the word &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; when
declaring an attribute? The attribute declaration starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has&lt;/code&gt;. So with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt;, that makes it &lt;em&gt;two&lt;/em&gt; &lt;em&gt;verbs&lt;/em&gt; for &lt;em&gt;one&lt;/em&gt; line of code. For me it’s too much.
in Moo* modules, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; was just one property. We had &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lazy&lt;/code&gt;,
etc. Now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; is just a seperator between the name and the ‘traits’. In my
opinion, it’s redundant.&lt;/p&gt;

&lt;p&gt;Also, among the new keywords added by p5-mop, we have only &lt;em&gt;nouns&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;method&lt;/code&gt;). Only one &lt;em&gt;verb&lt;/em&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The counter argument on this is that this syntax is inspired by Perl6:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nv&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Point a x=$.x y=$.y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, “blame Larry” ? :)&lt;/p&gt;

&lt;h2 id=&quot;exporter&quot;&gt;Exporter&lt;/h2&gt;

&lt;p&gt;p5-mop doesn’t use @ISA for inheritance, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use base 'Exporter'&lt;/code&gt; won’t work.
You have to do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use Exporter 'import'&lt;/code&gt;. That is somewhat disturbing because
most Perl developers (I think) implement functions and variables exporting by inheriting from
Exporter (that’s also what the documentation of Exporter recommends).&lt;/p&gt;

&lt;p&gt;You could argue that one should code clean classes (that don’t export anything,
and clean modules (that export stuff but don’t do OO). Mixing OO in a class
with methods and exportable subs looks a bit un-orthodox. But that’s what we do
all day long and it is almost part of the Perl culture now. Think about all the
modules that provides 2 APIs, a functional one and an OO one. All in the same
namespace. So, &lt;em&gt;somehow&lt;/em&gt;, being able to easily export subs is needed.&lt;/p&gt;

&lt;p&gt;However, as per Jesse Luehrs and Stevan Little, they don’t think a MOP
implementation should be in charge of implementing an Exporter module, and I
can totally agree with this. So it looks like the solution will be a method
trait, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportable&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;exportable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But that is not yet implemented.&lt;/p&gt;

&lt;h2 id=&quot;inside-out-objects-versus-blessed-structure-objects&quot;&gt;Inside Out objects versus blessed structure objects&lt;/h2&gt;

&lt;p&gt;p5-mop is not using the standard scheme where an object is simply a blessed
structure (usually a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashRef&lt;/code&gt;). Instead, it’s using InsideOut objects, where
all you get as an object is some kind of identification number (usually a
simple reference), which is used internally to retrieve the object properties,
only accessible from within the class.&lt;/p&gt;

&lt;p&gt;This way of doing may seem odd at first: if I recall correctly, there a time
where InsideOut objects were trendy, especially using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Class::Std&lt;/code&gt;. But that
didn’t last long, when Moose and its follow ups came back to using regular
blessed structured objects.&lt;/p&gt;

&lt;p&gt;The important thing to keep in mind is that it doesn’t matter too much. Using
inside out objects is not a big deal because p5-mop provides so much power to
interact and introspect with the OO concepts that it’s not a problem at all
that the attributes are not in a blessed HashRef.&lt;/p&gt;

&lt;p&gt;However, a lot of third-party modules &lt;em&gt;assume&lt;/em&gt; that your objects are blessed
HashRef. So when switching to p5-mop, a whole little ecosystem will need to be
rewritten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: ilmari pointed out in the comments that there is a class trait
called &lt;code&gt;repr&lt;/code&gt; that makes it possible to change the way an instance
is implemented. You can specify if an object should be a reference on a scalar,
array, hash, glob, or even a reference on a provided CodeRef. This makes p5-mop
objects much more compatible with the OO ecosystem.&lt;/p&gt;

&lt;h1 id=&quot;now-where-to-&quot;&gt;Now, where to ?&lt;/h1&gt;

&lt;p&gt;Now, it’s your turn to try it out, make up your mind, try to port an
module or write on from scratch using p5-mop, and give your feedback. To do
that, go to the IRC channel #p5-mop on the irc.perl.org server, say hi,
and explain what you tried, what went well and what didn’t, and how you feel
about the syntax and concepts.&lt;/p&gt;

&lt;p&gt;Also, spread the word by writing about your experience with p5-mop, for
instance on &lt;a href=&quot;blogs.perl.org&quot;&gt;blogs.perl.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, don’t hesitate to participate in the comments below :) Especially if
you don’t agree with my remarks above.&lt;/p&gt;

&lt;h2 id=&quot;reference--see-also&quot;&gt;Reference / See also&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/stevan/p5-mop-redux&quot;&gt;p5-mop-redux on github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/rafl/twigils&quot;&gt;twigils on github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/stevan/p5-mop-redux/blob/master/lib/mop/manual/tutorials/moose_to_mop.pod&quot;&gt;Moose to mop tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://moose.iinteractive.com/&quot;&gt;Moose project homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;&quot;&gt;Moops&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;contributors&quot;&gt;Contributors&lt;/h2&gt;

&lt;p&gt;This article has been written by &lt;a href=&quot;damien.krotkine.com&quot;&gt;Damien Krotkine&lt;/a&gt;, but these people helped
proof-reading it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Stevan Little&lt;/li&gt;
  &lt;li&gt;Jesse Luehrs&lt;/li&gt;
  &lt;li&gt;Toby Inkster&lt;/li&gt;
  &lt;li&gt;Lukas Atkinson&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>MooX::LvalueAttribute - improved</title>
   <link href="http://dams.github.com/2013/08/21/mooxlvalueattribute-improved.html"/>
   <updated>2013-08-21T00:00:00+00:00</updated>
   <id>http://dams.github.com/2013/08/21/mooxlvalueattribute--improved</id>
   <content type="html">&lt;h1 id=&quot;mooxlvalueattribute---improved&quot;&gt;MooX::LvalueAttribute - improved&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/images/val_approuve.png&quot; alt=&quot;New and Improved!&quot; title=&quot;I borrowed the image from @yenzie -
 hope you don't mind, Yannick !&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Just a quick note to mention that following &lt;a href=&quot;https://github.com/dams/moox-lvalueattribute/issues/1&quot;&gt;Mike Doherty’s bug report&lt;/a&gt;, I’ve released a new version of &lt;a href=&quot;https://metacpan.org/module/DAMS/MooX-LvalueAttribute-0.12/lib/Method/Generate/Accessor/Role/LvalueAttribute.pm&quot;&gt;MooX::LvalueAttribute&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This release (version 0.12) allows you to use MooX::LvalueAttribute in a Moo::Role, like this;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyRole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Moo::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MooX::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LvalueAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Moo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MyRole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;rw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
                  &lt;span class=&quot;nv&quot;&gt;lvalue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Joe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So now it’s easier to specify which classes will have lvalue attributes and
which one won’t. Until now I avoided adding a flag to globally enable lvalue
attributes across all Moo classes (without having to say &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvalue =&amp;gt; 1&lt;/code&gt;). Maybe
that’s something some of you would like ?&lt;/p&gt;

&lt;p&gt;Anyway, that’s all folks! Nothing revolutionary, but I’ve been told we should
talk more about what we do, so that’s what I’m doing.&lt;/p&gt;

&lt;p&gt;For more detail about Moox::LvalueAttribute, see my &lt;a href=&quot;http://damien.krotkine.com/2013/02/11/lvalue-accessors-in-moo.html&quot;&gt;original post&lt;/a&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>New And Improved: Bloomd::Client</title>
   <link href="http://dams.github.com/2013/06/13/new-and-improved-bloomdclient.html"/>
   <updated>2013-06-13T00:00:00+00:00</updated>
   <id>http://dams.github.com/2013/06/13/new-and-improved-bloomdclient</id>
   <content type="html">&lt;h1 id=&quot;new-and-improved-bloomdclient&quot;&gt;New And Improved: Bloomd::Client&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/images/val_approuve.png&quot; alt=&quot;New and Improved!&quot; title=&quot;I borrowed the image from @yenzie -
 hope you don't mind, Yannick !&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;thanks to @yenzie for the picture :P&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;bloom-filters&quot;&gt;Bloom filters&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Bloom_filter&quot;&gt;Bloom filters&lt;/a&gt; are statistical data
structures. The most common use of them is to consider them as buckets. In one
bucket, you add elements. Once you’ve added a bunch of elements, it’s ready to
be used.&lt;/p&gt;

&lt;p&gt;You use it by presenting it yet an other element, and it’ll be able to say
almost always if the element is already in the bucket or not.&lt;/p&gt;

&lt;p&gt;More precisely, when asking the question &lt;em&gt;“is this element in the filter ?”&lt;/em&gt;, if it
answers &lt;strong&gt;no&lt;/strong&gt;, then you are sure that it’s &lt;strong&gt;not&lt;/strong&gt; in there. If it answers &lt;strong&gt;yes&lt;/strong&gt;,
then there is a &lt;strong&gt;high probability&lt;/strong&gt; that it’s there.&lt;/p&gt;

&lt;p&gt;So basically, you never have false negatives, but you can get a few false
positives. The good thing is that depending on the space you allocate to the
filter, and the number of elements it contains, you know what will be the
probability of having false positives.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;huge&lt;/strong&gt; benefit is that a bloom filter is very small, compared to a hash
table.&lt;/p&gt;

&lt;h2 id=&quot;bloomd&quot;&gt;bloomd&lt;/h2&gt;

&lt;p&gt;At work, I replaced a heavy Redis instance ( using 60g of RAM) that was used primarily as a
huge hash table, by a couple of bloom filters ( using 2g ). For that I used
&lt;a href=&quot;https://github.com/armon/bloomd&quot;&gt;bloomd&lt;/a&gt;, from &lt;em&gt;Armon Dadgar&lt;/em&gt;. It’s light,
fast, has enough features, and the code looks sane.&lt;/p&gt;

&lt;p&gt;All I needed was a Perl client to connect to it.&lt;/p&gt;

&lt;h2 id=&quot;bloomdclient&quot;&gt;Bloomd::Client&lt;/h2&gt;

&lt;p&gt;So I wrote &lt;a href=&quot;https://metacpan.org/module/Bloomd::Client&quot;&gt;Bloomd::Client&lt;/a&gt;. It is a light
client that connects to bloomd using a regular INET socket, and speaks the
simple ASCII protocol (very similar to Redis’ one) that bloomd implements.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Bloomd::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Bloomd::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;test_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$hash_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;u1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;u1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	  &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;it exists!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When you use bloomd it usually means that you are in a high availibility
environment, where you can’t get stuck waiting on a socket, just because
something went wrong. So Bloomd::Client implements non-blocking timeouts on the
socket. It’ll die if bloomd didn’t answer fast enough or if something broke.
That allows you to incorporate the bloomd connection in a retry strategy to try
again later, or fallback to another server…&lt;/p&gt;

&lt;p&gt;To implement such a strategy, I recommend using
&lt;a href=&quot;https://metacpan.org/module/Action::Retry&quot;&gt;Action::Retry&lt;/a&gt;. There is a blog
post about it &lt;a href=&quot;http://damien.krotkine.com/2013/01/21/new-module-actionretry.html&quot;&gt;here&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;dams.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MooX::LvalueAttribute - Lvalue accessors in Moo</title>
   <link href="http://dams.github.com/2013/02/11/lvalue-accessors-in-moo.html"/>
   <updated>2013-02-11T00:00:00+00:00</updated>
   <id>http://dams.github.com/2013/02/11/lvalue-accessors-in-moo</id>
   <content type="html">&lt;h1 id=&quot;mooxlvalueattribute---lvalue-accessors-in-moo&quot;&gt;MooX::LvalueAttribute - Lvalue accessors in Moo&lt;/h1&gt;

&lt;p&gt;Yesterday I was reading &lt;a href=&quot;http://blogs.perl.org/users/joel_berger/2013/02/in-the-name-of-create-great-things-in-perl.html&quot;&gt;Joel’s
post&lt;/a&gt;,
where he lists great Perl things he’s seen done lately. Indeed these are great
stuff. I was particulary interested by his try at playing with &lt;a href=&quot;https://gist.github.com/jberger/4740303&quot;&gt;Lvalue accessors&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I thought that it would be a great exercise to try to implement it in Moo, as
an additional feature, trying to get rid of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AUTOLOAD&lt;/code&gt;. Also, I was willing
to avoid doing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tie&lt;/code&gt; every time an instance attribute accessor was called.
Surely, I needed to tie only &lt;em&gt;once&lt;/em&gt; per instance and per attribute, not each
time the attribute is accessed.&lt;/p&gt;

&lt;p&gt;So I started hacking on the code of Moo. Getting rid of the AUTOLOAD was easy,
as I could change the way the accessor generator was, well, generating the,
err, accessors.&lt;/p&gt;

&lt;p&gt;Shortly after I started having issues to cache a tied variable. I asked the
all-mighty &lt;a href=&quot;https://metacpan.org/author/VPIT&quot;&gt;Vincent Pit&lt;/a&gt;, and he found a
solution for my tied variables, but more importanlty pointed me to
&lt;a href=&quot;https://metacpan.org/module/Variable::Magic&quot;&gt;Variable::Magic&lt;/a&gt;, which is
faster, more flexible and powerful.&lt;/p&gt;

&lt;p&gt;All I needed was to move my hacks in a proper Role, and wrap the whole in a
module, and push it on CPAN. Tadaa, &lt;a href=&quot;https://metacpan.org/module/MooX::LvalueAttribute&quot;&gt;MooX::LvalueAttribute&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;In the process I used &lt;a href=&quot;http://play-perl.org&quot;&gt;play-perl&lt;/a&gt; to register my quests,
and exchanged &lt;a href=&quot;http://play-perl.org/quest/511800ae94f611130b000025&quot;&gt;thoughts with Joel
Berger&lt;/a&gt;. I think I’m going
to use this website more, see if it can boost my productivity, and help me
figure out what’s really important to do.&lt;/p&gt;

&lt;p&gt;On IRC, haarg discovered a bug and recommended to use so-called &lt;em&gt;fieldhashes&lt;/em&gt;,
from
&lt;a href=&quot;https://metacpan.org/module/Hash::Util::FieldHash::Compat&quot;&gt;Hash::Util::FieldHash::Compat&lt;/a&gt;.
At the end of the day, I only acted as a glue between different pieces of
knowledges, and that was very satisfactory.&lt;/p&gt;

&lt;h2 id=&quot;tldr&quot;&gt;TL:DR&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://metacpan.org/module/MooX::LvalueAttribute&quot;&gt;MooX::LvalueAttribute&lt;/a&gt; is a
module that provides Lvalue attributes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Moo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MooX::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LvalueAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;rw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;lvalue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Elsewhere&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Bar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>New Perl module: Action::Retry</title>
   <link href="http://dams.github.com/2013/01/21/new-module-actionretry.html"/>
   <updated>2013-01-21T00:00:00+00:00</updated>
   <id>http://dams.github.com/2013/01/21/new-module-actionretry</id>
   <content type="html">&lt;h1 id=&quot;new-perl-module-actionretry&quot;&gt;New Perl module: Action::Retry&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;UPDATE: I have included a functional API, as per Oleg Komarov request, and amended this post accordingly&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’ve just released a new module called
&lt;a href=&quot;https://metacpan.org/module/Action::Retry&quot;&gt;Action::Retry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Use it when you want to run some code until it succeeds, waiting between two
retries.&lt;/p&gt;

&lt;p&gt;A simple way to use it is :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Action::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Retry&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;qw(retry)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;retry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And the Object Oriented API:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nn&quot;&gt;Action::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Retry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;attempt_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The purpose of this module is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Retry&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sub::Retry&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Attempt&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnyEvent::Retry&lt;/code&gt;. However, it’s highly configurable, more flexible and has
more features.&lt;/p&gt;

&lt;p&gt;You can specify the code to try, but also a callback that will be executed to
check the success or failure of the attempt. There is also a callback to execute code on
failure.&lt;/p&gt;

&lt;p&gt;The module also supports different sleep strategies ( Constant, Linear,
Fibonacci…) and it’s easy to build yours. Strategies can have their options
as well.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Action::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Retry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;attempt_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;retry_if_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/Connection lost/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Fibonacci&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;multiplicator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;nv&quot;&gt;initial_term_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;nv&quot;&gt;max_retries_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;on_failure_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Given up retrying&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And the functional API:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;  &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Action::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Retry&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;qw(retry)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;retry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;retry_if_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/Connection lost/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Fibonacci&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;multiplicator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;nv&quot;&gt;initial_term_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;nv&quot;&gt;max_retries_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;on_failure_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Given up retrying&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Strategies can decide if it’s worthwhile continuing trying, or if it should fail.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://metacpan.org/module/Action::Retry&quot;&gt;Action::Retry&lt;/a&gt; also supports a
pseudo “non-blocking” mode, in which it doesn’t actually sleep, but instead
returns immediately, and won’t perform the action code until required time has
elapsed. Basicaly it allows to do this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Action::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Retry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;attempt_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;non_blocking&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Constant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# if the action failed, it doesn't sleep&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# next time it's called, it won't do anything until it's time to retry&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;do_something_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# do something else while time goes on&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;of course &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_something_else&lt;/code&gt; should be very fast, so that the loop goes back
quickly to retrying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attempt_code&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://metacpan.org/module/Action::Retry&quot;&gt;Action::Retry&lt;/a&gt; is based on
&lt;a href=&quot;https://metacpan.org/module/Moo&quot;&gt;Moo&lt;/a&gt; for performance (and because the module
is simple enough to not require Moose). Moo classes properly expand to Moose
ones if needed, so there is no excuse not to use it.&lt;/p&gt;

&lt;p&gt;So, please give a try to
&lt;a href=&quot;https://metacpan.org/module/Action::Retry&quot;&gt;Action::Retry&lt;/a&gt;, and let me know
what you think.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Mass-Testing Dancer's Plugins</title>
   <link href="http://dams.github.com/2012/09/20/masstesting-dancers-plugins.html"/>
   <updated>2012-09-20T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/09/20/masstesting-dancers-plugins</id>
   <content type="html">&lt;h1 id=&quot;mass-testing-dancers-plugins&quot;&gt;Mass-Testing Dancer’s Plugins&lt;/h1&gt;

&lt;p&gt;So, as I said at YAPC::EU 2012, one thing that remains to be done before Dancer
2 can be released : migrating the plugins, making sure they work with it.&lt;/p&gt;

&lt;p&gt;To be able to do that, what’s best than an automatic testing facility ?&lt;/p&gt;

&lt;p&gt;The goal is to get all Dancer plugins, test them with Dancer1, and Dancer2, and
produce a report, to check which one fails and need fixing.&lt;/p&gt;

&lt;h2 id=&quot;step-1-get-the-list-of-dancer-plugins&quot;&gt;Step 1. Get the list of Dancer plugins.&lt;/h2&gt;

&lt;p&gt;Easy ! let’s use &lt;a href=&quot;https://metacpan.org/&quot;&gt;Metacpan&lt;/a&gt;. After searching, I finally
got a way to get the list of all modules that depend on Dancer. Then filtering
out the ones that don’t contain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;Plugin&quot;&lt;/code&gt; will do the trick.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env perl&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modern::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Perl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ElasticSearch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$es&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ElasticSearch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;servers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;api.metacpan.org&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;no_refresh&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scroller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;scrolled_search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;query&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;match_all&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;search_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;scroll&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;5m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;index&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;v0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;size&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                     &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;release.dependency.module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Dancer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scroller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scroller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/Dancer-Plugin/&lt;/span&gt;
      &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;s/-\d.*//&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;s/-/::/g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Cool, let’s save this script as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_modules_list.pl&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;step-2-prepare-two-perl-environments&quot;&gt;Step 2. Prepare two Perl environments&lt;/h2&gt;

&lt;p&gt;We want two instance of Perl, without polluting anything. We’ll use
&lt;a href=&quot;http://www.perlbrew.pl/&quot;&gt;perlbrew&lt;/a&gt; for that. Easy. The small trick is to have
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PERLBREW_ROOT&lt;/code&gt; initialized to a local directory to not polute existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/perl5&lt;/code&gt;
installation.&lt;/p&gt;

&lt;h2 id=&quot;step-3-have-a-way-to-test-modules&quot;&gt;Step 3. Have a way to test modules&lt;/h2&gt;

&lt;p&gt;Well, let’s use &lt;a href=&quot;http://cpanmin.us/&quot;&gt;cpanm&lt;/a&gt;, which has an option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--test-only&lt;/code&gt;
to only test a module without installing it. Oh but plugin modules that we’ll
test may require dependances. We’ll install them using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpanm --installdeps&lt;/code&gt;,
which does just that.&lt;/p&gt;

&lt;h2 id=&quot;step-4-create-a-result-file&quot;&gt;Step 4. Create a result file&lt;/h2&gt;

&lt;p&gt;I was lazy and just output to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.csv&lt;/code&gt; text file, but I may store the results
somewhere else later.&lt;/p&gt;

&lt;h2 id=&quot;step-5-lets-glue-all-that-in-a-makefile&quot;&gt;Step 5. Let’s glue all that in a Makefile&lt;/h2&gt;

&lt;p&gt;The beauty of this is that by writing a proper Makefile, we can install this
auto-tester anywhere. The requirements are minimal : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perl&lt;/code&gt;, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ElasticSearch&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Modern::Perl&lt;/code&gt; installed.&lt;/p&gt;

&lt;p&gt;( This post is intentionally named the same as
&lt;a href=&quot;http://babyl.dyndns.org/techblog/entry/test-dancer-plugins&quot;&gt;the one from Yannick&lt;/a&gt;,
because he proposed a different implementation. We’ll try to merge the good
ideas together )&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;HERE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PWD&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# set up the local Perlbrew location&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HERE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/perlbrew
&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_ROOT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/etc/bashrc &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;PERLBREW_ROOT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/perlbrew

&lt;span class=&quot;c&quot;&gt;# This will run the cpanm from the local Perlbrew, on each of the 2 perls&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with&lt;/span&gt; dancer1_plugin_tests &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/cpanm
&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with&lt;/span&gt; dancer2_plugin_tests &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/cpanm

&lt;span class=&quot;c&quot;&gt;# loop on the plugin list, install the deps and test each plugin and output result&lt;/span&gt;
all: got_curl got_bash got_perlbrew_perl plugins_list
	&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Plugin name,Pass on Dancer 1,Pass on Dancer 2&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; result.csv
	@for i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;plugins_list&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pass_d1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pass_d2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; ---------- TESTING on Dancer 1 : &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;i&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--installdeps&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;i &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--test-only&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;i &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pass_d1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; ---------- TESTING on Dancer 2 : &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;i&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--installdeps&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;i &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;DANCER_FORCE_PLUGIN_REGISTRATION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--test-only&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;i &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pass_d2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;i,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pass_d1,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pass_d2&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; result.csv&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

clean:
	&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; plugins_list

fullclean:
	&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Get and install Perlbrew locally&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/perlbrew:
	@echo &lt;span class=&quot;s2&quot;&gt;&quot; - creating a local perlbrew&quot;&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_ROOT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class=&quot;nt&quot;&gt;-kL&lt;/span&gt; http://install.perlbrew.pl | bash

&lt;span class=&quot;c&quot;&gt;# Get and install cpanm in the local Perlbrew&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/cpanm:
	&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; install-cpanm

got_curl:
	@which curl &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you don't have curl, please install it and retry&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

got_bash:
	@which bash &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you don't have bash, please install it and retry&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

got_perlbrew_perl: &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/perlbrew &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/cpanm perlbrew_dancer1_plugin_tests perlbrew_dancer2_plugin_tests

&lt;span class=&quot;c&quot;&gt;# Build perl from scratch and call this instance dancer1&lt;/span&gt;
perlbrew_dancer1_plugin_tests:
	&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; list | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;dancer1_plugin_tests &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; perl-5.16.1 &lt;span class=&quot;nt&quot;&gt;--as&lt;/span&gt; dancer1_plugin_tests &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Build perl from scratch and call this instance dancer2&lt;/span&gt;
perlbrew_dancer2_plugin_tests:
	&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; list | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;dancer2_plugin_tests &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PERLBREW&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; perl-5.16.1 &lt;span class=&quot;nt&quot;&gt;--as&lt;/span&gt; dancer2_plugin_tests &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
             &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CPANM_DANCER2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HERE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/../.. &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# This gets the list of plugins, as previously described&lt;/span&gt;
plugins_list:
	&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HERE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/get_modules_list.pl &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; plugins_list&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s really cool to see what you can do with modern tools of the Perl ecosystem !&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Paris.pm technical meeting</title>
   <link href="http://dams.github.com/2012/09/15/paris-pm-technical-meeting.html"/>
   <updated>2012-09-15T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/09/15/paris-pm-technical-meeting</id>
   <content type="html">&lt;h1 id=&quot;parispm-technical-meeting&quot;&gt;Paris.pm technical meeting&lt;/h1&gt;

&lt;p&gt;( french version below )&lt;/p&gt;

&lt;p&gt;The next Paris.pm technical meeting will happen the &lt;strong&gt;25th september 2012&lt;/strong&gt;, with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Elizabeth Cholet: Firefox automatization with Perl using AnyEvent, Coro and MozRepl modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt; :
      181 avenue Daumesnil, 75012 Paris, France&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google map&lt;/strong&gt; :
      &lt;a href=&quot;http://goo.gl/OGUbI&quot;&gt;google map&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are interested, and live in Paris, please join us ! If you need more info, ask in the comments.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;La prochaine réunion technique de Paris.pm se tiendra mardi &lt;strong&gt;25 septembre 2012&lt;/strong&gt;, et le programme est :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Elizabeth Cholet : l’automatisation de Firefox avec Perl en utilisant AnyEvent, Coro et les modules MozRepl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Adresse&lt;/strong&gt; :
      181 avenue Daumesnil, 75012 Paris&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google map&lt;/strong&gt; :
      &lt;a href=&quot;http://goo.gl/OGUbI&quot;&gt;google map&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si vous êtes intéressé, n’hésitez pas à venir, entrée libre et gratuite. Pour plus d’info, demandez dans les commentaires.&lt;/p&gt;

&lt;p&gt;dams.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MooseX::Singleton is slow</title>
   <link href="http://dams.github.com/2012/07/04/moosexsingleton-is-slow.html"/>
   <updated>2012-07-04T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/07/04/moosexsingleton-is-slow</id>
   <content type="html">&lt;h1 id=&quot;moosexsingleton-is-slow&quot;&gt;MooseX::Singleton is slow&lt;/h1&gt;

&lt;p&gt;Just a quick note : if you plan to use
&lt;a href=&quot;https://metacpan.org/module/MooseX::Singleton&quot;&gt;MooseX::Singleton&lt;/a&gt;, beware ! It
is easy to use and it implements properly what it claims, however it is quite
slow.&lt;/p&gt;

&lt;p&gt;If my profilings are corrects, each call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt;instance()&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meta()&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_metaclass_by_name()&lt;/code&gt; one time, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blessed()&lt;/code&gt; two times.&lt;/p&gt;

&lt;p&gt;So for now I’ll avoid it and implement a simplified version using something
similar to this :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Moose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$singleton&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CLASS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# to protect against people using new() instead of instance()&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;around&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$orig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$singleton&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$orig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$singleton&lt;/span&gt;
      &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;croak&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;__PACKAGE__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; singleton has already been instanciated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt; 
    &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;__PACKAGE__&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;dams.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dancer is community-driven</title>
   <link href="http://dams.github.com/2012/06/20/dancer-is-communitydriven.html"/>
   <updated>2012-06-20T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/06/20/dancer-is-communitydriven</id>
   <content type="html">&lt;h1 id=&quot;dancer-is-community-driven&quot;&gt;Dancer is community-driven&lt;/h1&gt;

&lt;p&gt;Long time I haven’t blogged about Dancer.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.antelink.com/&quot;&gt;Antelink&lt;/a&gt; is a french startup, specializing in
Software Life Cycle Management and Open Source Component Detection. They
provided us with cool Dancer sourcecode analyzis graphs.&lt;/p&gt;

&lt;h2 id=&quot;overall-contribution-by-users&quot;&gt;Overall contribution by users&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts_by_users.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts_by_users.png&quot; width=&quot;376.5&quot; height=&quot;162&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;pm-files-contribution-by-users&quot;&gt;.pm files contribution by users&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pm-by_users.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pm-by_users.png&quot; width=&quot;366&quot; height=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;pod-files-contribution-by-users&quot;&gt;Pod files contribution by users&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pod-by_users.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pod-by_users.png&quot; width=&quot;366&quot; height=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;test-files-contribution-by-users&quot;&gt;Test files contribution by users&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_t-by_users.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_t-by_users.png&quot; width=&quot;366&quot; height=&quot;150&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;reading-these-graphs&quot;&gt;Reading these graphs&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;UPDATE&lt;/em&gt; : The surfaces represent a mean between the number of commits, and the weight of
modifications contributed (in term of “code line”), only when these are
original content addition. Moving content around isn’t counted as active
contribution.&lt;/p&gt;

&lt;p&gt;Note that some people are registered twice with different names, I’ll try to
post an updated version&lt;/p&gt;

&lt;p&gt;What does that demonstrate ? It shows that Dancer is &lt;em&gt;really&lt;/em&gt; powered by its
community. Decisions are made together, the code is hacked by multiple hands,
and the management is done in a collegial manner on github.&lt;/p&gt;

&lt;p&gt;It’s a great reward to be visible on these graphs :)&lt;/p&gt;

&lt;h1 id=&quot;more-graphs&quot;&gt;More Graphs&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;UPDATE&lt;/em&gt; : Erwan (@Labynocle) sent me new graphics, they show the difference
between core devs and contributors. By the ay, Erwan will be at the
&lt;a href=&quot;http://journeesperl.fr/fpw2012/&quot;&gt;French Perl Workshop&lt;/a&gt; in Strasbourg, France.&lt;/p&gt;

&lt;p&gt;So here we go :&lt;/p&gt;

&lt;h2 id=&quot;pm-files-contribution-by-groups&quot;&gt;.pm files contribution by groups&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pm-by_groups.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pm-by_groups.png&quot; width=&quot;366&quot; height=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;pod-files-contribution-by-groups&quot;&gt;Pod files contribution by groups&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pod-by_groups.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_pod-by_groups.png&quot; width=&quot;366&quot; height=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;test-files-contribution-by-groups&quot;&gt;Test files contribution by groups&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_t-by_groups.png&quot;&gt;
&lt;img src=&quot;/images/dancer_analysis_by_Antelink-contribution_parts-only_t-by_groups.png&quot; width=&quot;366&quot; height=&quot;150&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a side note, I’ve proposed 2 talks related to Dancer for
&lt;a href=&quot;http://act.yapc.eu/ye2012/&quot;&gt;YAPC::EU&lt;/a&gt;. One called &lt;em&gt;“Dancer + WebSocket +
AnyEvent + Twiggy”&lt;/em&gt;, and an other one mixing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dancer&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Log::Message::Structured&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Message::Passing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s hope they’ll get accepted !&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Cross Posting to blogs.perl.org</title>
   <link href="http://dams.github.com/2012/04/05/cross-posting-to-blogsperlorg.html"/>
   <updated>2012-04-05T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/04/05/cross-posting-to-blogsperlorg</id>
   <content type="html">&lt;h1 id=&quot;cross-posting-to-blogsperlorg&quot;&gt;Cross Posting to blogs.perl.org&lt;/h1&gt;

&lt;p&gt;So, a while ago, I moved &lt;a href=&quot;http://damien.krotkine.com&quot;&gt;my blog&lt;/a&gt; to github, using
&lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;jekyll&lt;/a&gt; and
&lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;markdown&lt;/a&gt;, with &lt;a href=&quot;http://metajack.im/2009/01/02/manage-jekyll-from-emacs/&quot;&gt;jekyll
integration&lt;/a&gt; in
&lt;a href=&quot;http://www.gnu.org/software/emacs/&quot;&gt;Emacs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That works great, and I like the fasct that posting a blog entry is just a regular git push.&lt;/p&gt;

&lt;p&gt;My blog is aggregated in some places, but it doesn’t appear on
&lt;a href=&quot;http://blogs.perl.org&quot;&gt;blogs.perl.org&lt;/a&gt;, because it’s not an aggregator (and that’s
cool, it’s not its purpose). But, blogs.perl.org audience is big, and I’m
missing all these potential readers (in improbable case people would actually
be interested in what I have to say :) )&lt;/p&gt;

&lt;p&gt;Anyway, so I decided to bite the bullet and write a script that would cross
post my entry to blogs.perl.org. I made the script generic enough to work with
different type of blogs, but here I’m going to explain only the blogs.perl.org
specific case.&lt;/p&gt;

&lt;p&gt;blogs.perl.org is a &lt;a href=&quot;http://www.movabletype.org/&quot;&gt;Movable Type&lt;/a&gt; blog engine. A
look on &lt;a href=&quot;http://metacpan.org&quot;&gt;Metacpan&lt;/a&gt; indicates us there is a
&lt;a href=&quot;https://metacpan.org/module/Net::MovableType&quot;&gt;Net::MovableType&lt;/a&gt; module. That’s
great, let’s use that.&lt;/p&gt;

&lt;p&gt;There is a catch: to use this module, you need your login, and your &lt;em&gt;API
password&lt;/em&gt;, not your regular password. You can get it easily though, by &lt;a href=&quot;https://github.com/davorg/blogs.perl.org/issues/137&quot;&gt;following these instructions&lt;/a&gt; (thanks to davorg for directing me to it).&lt;/p&gt;

&lt;p&gt;To avoid storing the user / password in the script, and to have to pass it on
the command line, let’s have a configuration file, that will lie at
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.crosspost.ini&lt;/code&gt;, and that we’ll load with
&lt;a href=&quot;https://metacpan.org/module/Config::Any::Merge&quot;&gt;Config::Any::Merge&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The file name of the original post will have to be passed on the command line,
using &lt;a href=&quot;https://metacpan.org/module/Getopt::Long&quot;&gt;Getopt::Long&lt;/a&gt; and
&lt;a href=&quot;https://metacpan.org/module/Path::Class&quot;&gt;Path::Class&lt;/a&gt; to retrieve and slurp
it.&lt;/p&gt;

&lt;p&gt;Here is the configuration file.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# file ~/.corsspost.ini
[ main_blog ]
title = dams blog
url = http://damien.krotkine.com

[ blogs.perl.org ]
type = mt
username = foo
password = bar
url = http://blogs.perl.org/rsd.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here’s the code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# file crosspost.plcorsspost.ini&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modern::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Perl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Carp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Net::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;MovableType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Config::Any::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Getopt::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Path::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Text::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Markdown&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;qw(markdown)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;GetOptions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;file=s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;croak&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;failed to parse command line options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;
  &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;croak&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;need a file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Get a hash representing the config file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Config::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/.crosspost.ini&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;use_ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]})[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Grab some main info&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$main_blog_title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cfg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;main_blog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$main_blog_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cfg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;main_blog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slurp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# In reality, I do some transformation on $text to interpret jekyll specific&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# syntax&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &amp;lt;i&amp;gt;cross-posted from [&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$main_blog_title&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$main_blog_url&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)&amp;lt;/i&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# So now we have the content to be posted, but it's in markdown. Let's&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# transform it in HTML&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Then we loop on all the other blog to cross post to&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$site&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;main_blog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'}&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;posting to &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;properties&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cfg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# for now we handle only movable type&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;')&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$mt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Net::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;MovableType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$mt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;croak&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$mt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;errstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$mt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;croak&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$mt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;errstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;We&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;need&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;s blog id
        my $user_blogs = $mt-&amp;gt;getUsersBlogs
          or croak $mt-&amp;gt;errstr;
        $mt-&amp;gt;blogId($user_blogs-&amp;gt;[0]-&amp;gt;{blogid})
          or croak $mt-&amp;gt;errstr;

        # finally, the post
        $mt-&amp;gt;newPost({
                      title       =&amp;gt; $title,
                      description =&amp;gt; $html,
                      mt_allow_comments =&amp;gt; $properties{allow_comments} // 1,
                     },
                     # uncomment this line to directly post it
                     # 1
                    );

    }
    
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Missing in this code is some mungling of the text to manage jekyll specific syntax. And while I was at it, I improved it so that it supports cross-posting to twitter, using &lt;a href=&quot;https://metacpan.org/module/Net::Twitter&quot;&gt;Net::Twitter&lt;/a&gt;, and posting only a short description of the entry. Here is an example (I had to create a custom Twitter app called blog-cross-poster)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/twitter_cross_post.png&quot; alt=&quot;Twitter cross posting&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now, I just need to add a git hook to be executed at push time, check if there is a new post or a modified one, and cross post it. Yay !&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Perl, fun again!</title>
   <link href="http://dams.github.com/2012/03/02/perlfunagain.html"/>
   <updated>2012-03-02T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/03/02/perlfunagain</id>
   <content type="html">&lt;h1 id=&quot;perl-fun-again&quot;&gt;Perl, fun again!&lt;/h1&gt;

&lt;p&gt;I’m happy to announce a new Perl event that will be held in Paris (France) next
Monday, presented by the &lt;a href=&quot;http://mongueurs.typepad.com/&quot;&gt;French&lt;/a&gt; &lt;a href=&quot;http://mongueurs.net/&quot;&gt;Perl&lt;/a&gt; &lt;a href=&quot;http://planet.mongueurs.net/&quot;&gt;Mongers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s called &lt;strong&gt;Perl, fun again!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It will be held at &lt;a href=&quot;http://lacantine.org/events/perl-fun-again&quot;&gt;La cantine&lt;/a&gt;
Monday 5 March 2012, in the evening.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.sukria.net/fr/wp-content/uploads/2012/02/6234213565_830637e185_m.jpg&quot; alt=&quot;La Cantine&quot; /&gt;&lt;/p&gt;

&lt;p&gt;From 19:00 to 22:00, a set of short talks (15 min) will be given. I expect a
wide audience, beyond Perl users, primarily geeks, coders, web designers,
administrators, basically IT-related people with some knowledge of programming
( in any language), and interested in seeing what makes Perl so appealing these
days.&lt;/p&gt;

&lt;p&gt;I organised the event ( representing the French Perl Mongers ), with the help
of Laurent Boivin, and &lt;em&gt;La cantine&lt;/em&gt;, kindly hosting the event for free. I
managed to enroll 8 speakers, including some well-known Perl figures, to
deliver the following set of talks. &lt;em&gt;Of course, in French :)&lt;/em&gt; :&lt;/p&gt;

&lt;p&gt;19:00&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Perl Intro  ( Sylvain Lhullier )&lt;/li&gt;
  &lt;li&gt;Modern Perl Object with Moose   (Damien “dams”Krotkine )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;20:00&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Dancer, the light web framework   ( Alexis “sukria” Sukrieh )&lt;/li&gt;
  &lt;li&gt;Perl and NoSQL, with MongoDB.  ( Jean-Marie Gouarné )&lt;/li&gt;
  &lt;li&gt;Build a webservice easily with Dancer &amp;amp; Spore ( Camille Maussang )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;21:00&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;How to deploy modules and applications with Perl  ( Vincent Pit )&lt;/li&gt;
  &lt;li&gt;Debug and profile with Perl and NYTProf  ( David Morel )&lt;/li&gt;
  &lt;li&gt;Perl development, Perl future  ( Rafael “rgs” Garcia-Suarez )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d like to thank the speakers to devote their time and passion to help
promoting Perl in France.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dancer::Plugin::Params::Normalization</title>
   <link href="http://dams.github.com/2012/02/27/dancerpluginparamsnormalization.html"/>
   <updated>2012-02-27T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/02/27/dancerpluginparamsnormalization</id>
   <content type="html">&lt;h1 id=&quot;dancerpluginparamsnormalization&quot;&gt;Dancer::Plugin::Params::Normalization&lt;/h1&gt;

&lt;p&gt;Just released a new version of &lt;a href=&quot;https://metacpan.org/module/Dancer::Plugin::Params::Normalization&quot;&gt;Dancer::Plugin::Params::Normalization&lt;/a&gt;. This plugin allows to normalize or alter parameters recieved by a Dancer route.&lt;/p&gt;

&lt;p&gt;An example of what developers usually want is to accept mixedcased request parameters, and have them all lowercased. That is done easily :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# In your configuration file
plugins:
  Params::Normalization:
    method: lowercase
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s it, now you are sure that all your parameter names will be lowercases.&lt;/p&gt;

&lt;p&gt;Now this plugin goes further by being very flexible and powerful. It supports standard methods like &lt;em&gt;lowercase&lt;/em&gt;, &lt;em&gt;uppoercase&lt;/em&gt;, &lt;em&gt;ucfirst&lt;/em&gt;. But you can also give it a class name, which have to implement a &lt;em&gt;normalize&lt;/em&gt; method, thus giving you full flexibility.&lt;/p&gt;

&lt;p&gt;If you don’t want all parameters of all routes to be normalized, you can set &lt;em&gt;general_rule&lt;/em&gt; to &lt;em&gt;ondemand&lt;/em&gt;, and use the added keyword &lt;em&gt;normalize&lt;/em&gt; to trigger the normalization. Or, you can instead specify a filter to be applied on parameters. Only those matching it will be normalized.&lt;/p&gt;

&lt;p&gt;But that’s not the end. This plugin also allows you to specify which parameters should be normalized: &lt;em&gt;query&lt;/em&gt; parameters, &lt;em&gt;body&lt;/em&gt; parameters, or the parameters from the &lt;em&gt;route&lt;/em&gt; definitions.&lt;/p&gt;

&lt;p&gt;I tried to be pretty exhaustive with this plugin, but if anything happen to be missing for your usage, let me know :)&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Paris.pm January Technical Meeting</title>
   <link href="http://dams.github.com/2012/01/13/parispm-january-technical-meeting.html"/>
   <updated>2012-01-13T00:00:00+00:00</updated>
   <id>http://dams.github.com/2012/01/13/parispm-january-technical-meeting</id>
   <content type="html">&lt;h1 id=&quot;parispm-january-technical-meeting&quot;&gt;Paris.pm January Technical Meeting&lt;/h1&gt;

&lt;p&gt;( french version below )&lt;/p&gt;

&lt;p&gt;Since September 2011, I’ve taken over the management of the &lt;a href=&quot;http://goo.gl/1i6rI&quot;&gt;Paris.pm&lt;/a&gt; monthly technical meetings. Paris.pm is part of the &lt;a href=&quot;http://goo.gl/DVhUw&quot;&gt;French Perl Mongers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These meetings happen every months in a very nice building in Paris (it’s an ancient rail station), and usually 15 people gather for one evening. We are relatively well equipped, with a video beamer, microphone and video camera. Thanks to other mongers that help, things go smotthly.&lt;/p&gt;

&lt;p&gt;The next meeting will happen the &lt;strong&gt;18th january 2012&lt;/strong&gt;, with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Guillaume Rousse: advanced LWP&lt;/li&gt;
  &lt;li&gt;Pierre Marc: demonstration of the &lt;a href=&quot;http://goo.gl/AKTFq&quot;&gt;Nirva Systems&lt;/a&gt; Application Server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt; :
      181 avenue Daumesnil, 75012 Paris, France&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goggle map&lt;/strong&gt; :
      &lt;a href=&quot;http://goo.gl/OGUbI&quot;&gt;google map&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are interested, and live in Paris, please join us ! it’s free of course.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Depuis septembre 2011, j’ai repris la gestion des réunions techniques de &lt;a href=&quot;http://goo.gl/1i6rI&quot;&gt;Paris.pm&lt;/a&gt; (groupe parisien des &lt;a href=&quot;http://goo.gl/DVhUw&quot;&gt;Mongueurs de Perl&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Ces réunions ont lieu tous les mois dans des très beaux locaux dans Paris (l’ancienne gare de Bercy), et accueille habituellement une quinzaine de personnes, intéressées par Perl . Nous sommes relativement bien équipé, avec projecteur, micro et caméra, et grâce à l’aide des autres mongueurs, tout se passe bien.&lt;/p&gt;

&lt;p&gt;Lors de ces réunions, deux à trois présentations techniques ont lieu, suivis de questions. Le tout se fini généralement dans un restaurant dans le coin.&lt;/p&gt;

&lt;p&gt;La prochaine réunion se tient mercredi &lt;strong&gt;18 janvier 2012&lt;/strong&gt;, et le programme est :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Guillaume Rousse : LWP avancé&lt;/li&gt;
  &lt;li&gt;Pierre Marc : présentation du serveur d’application de &lt;a href=&quot;http://goo.gl/AKTFq&quot;&gt;Nirva Systems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Adresse&lt;/strong&gt; :
      181 avenue Daumesnil, 75012 Paris&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lien goggle map&lt;/strong&gt; :
      &lt;a href=&quot;http://goo.gl/OGUbI&quot;&gt;google map&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si vous êtes intéressé, n’hésitez pas à venir, entrée libre et gratuite.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>protect a screen session with a password</title>
   <link href="http://dams.github.com/2011/09/01/protect-a-screen-session-with-a-password.html"/>
   <updated>2011-09-01T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/09/01/protect-a-screen-session-with-a-password</id>
   <content type="html">&lt;h1 id=&quot;protect-a-screen-session-with-a-password&quot;&gt;protect a screen session with a password&lt;/h1&gt;

&lt;p&gt;At work, I’m currently deploying my Perl modules on a new platform ( multiple
servers ), which doesn’t have an automated deployment mechanism yet. I use &lt;a href=&quot;http://www.gnu.org/software/screen/&quot;&gt;Gnu
Screen&lt;/a&gt; a lot. It’s a must have tool when
working on remote servers.&lt;/p&gt;

&lt;p&gt;Long time ago, I spent time to craft a good &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.screenrc&lt;/code&gt; configuration file for
my needs. But I only discovered yesterday that I could protect my screen
session from being recovered from a super user on the remote server. The
documentation is lacking precise description on how to set it up, so here is
a quick tutorial.&lt;/p&gt;

&lt;p&gt;The idea is that when a screen is running, it can be detached and reattached.
However, a super user has the possibility to attach any screen launched by a
user of the system. Now, what if inside the screen, you use sensitive
informations, or connect to other remote servers ? The super user will have
access to these as well. To protect yourself from that (actually to mitigate the issue), it’s possible to have
screen ask for a password when trying to reattach it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In no way this method will prevent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; to access your sensitive information.
This method will just make it more difficult for a super user to see your screen content using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;su $user&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen -r -d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;daxim&lt;/code&gt; pointed out on &lt;em&gt;#dancer&lt;/em&gt;, there are numerous ways for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; to get at your sensitive information :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;attach to the process with a debugger, then skip the password check when it comes up&lt;/li&gt;
  &lt;li&gt;read the process memory of screen and dig out interesting stuff&lt;/li&gt;
  &lt;li&gt;install a network monitor and grabs your password as it is transmitted next time.  rsa encryption (via ssh) does not help because root also has the keys&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;launch-a-new-screen&quot;&gt;Launch a new screen&lt;/h2&gt;

&lt;p&gt;Easily done :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;screen&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;encrypt-a-new-password&quot;&gt;Encrypt a new password&lt;/h2&gt;

&lt;p&gt;screen provides a way to encrypt a password right from a screen session. In the following snippets, I assume the default screen key is A, as default.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# hit ctrl A :password&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# enter the new password twice&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, the encrypted password is in the screen clipboard. We need to retrieve it&lt;/p&gt;

&lt;h2 id=&quot;paste-the-crypted-password&quot;&gt;Paste the crypted password&lt;/h2&gt;

&lt;p&gt;The key shortcut for pasting the clipboard is by default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-A ]&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# hit ctrl A ]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# the encrypted password should be pasted in the console&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;edit-the-screen-configuration-file&quot;&gt;Edit the screen configuration file&lt;/h2&gt;

&lt;p&gt;Copy the encrypted password and paste it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.screenrc&lt;/code&gt; (or whatever your screen configuration file is)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# add this line, with your encrypted password&lt;/span&gt;
password VGdGzMopF&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;restart-screen&quot;&gt;Restart screen&lt;/h2&gt;

&lt;p&gt;You need to restart screen to take the password in account. Now, next time a
screen is reattached, the password will be prompted.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;dams@foo:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;screen &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; plop
Screen password: &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>Moose and enum</title>
   <link href="http://dams.github.com/2011/06/17/enum-in-moose.html"/>
   <updated>2011-06-17T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/06/17/enum-in-moose</id>
   <content type="html">&lt;h1 id=&quot;moose-and-enum&quot;&gt;Moose and enum&lt;/h1&gt;

&lt;p&gt;At $work, we are using Moose a lot. So I spend a lot of time declaring
attributes, and some of them are Strings that should be picked from a fixed
list of values.&lt;/p&gt;

&lt;p&gt;For instance, I need to be able to define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;task&lt;/code&gt; that can be only one of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'profit'&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'world_domination'&lt;/code&gt;. And use it like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# works fine&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;profit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# fails&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;failure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;');&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So basically, the attribute is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-painful-way&quot;&gt;The painful way&lt;/h2&gt;

&lt;p&gt;Until now, I was defining a new subtype for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; I needed. Something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# type definition&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Moose::Util::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TypeConstraints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;subtype&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;My:Type:Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;__PACKAGE__&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;get_possible_tasks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^(?:$r)$/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;coerce&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;My:Type:Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;via&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_possible_tasks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;qw(profit world_domination)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# attribute declaration&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;My:Type:Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s very verbose, painful and not readable, isn’t it ?&lt;/p&gt;

&lt;h2 id=&quot;the-right-way&quot;&gt;The right way&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Moose::Util::TypeConstraints&lt;/code&gt; provides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; method, that serves exactly
our purpose. It’s basically a shortcut to create a subtype based on ‘Str’,
limited to a list of possible values. You can use it to build a &lt;em&gt;named&lt;/em&gt; enum
subtype, or an &lt;em&gt;anonymous&lt;/em&gt; subtype. See the usage in our case :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# using a named enum subtype:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Moose::Util::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TypeConstraints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;My:Enum:Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;',&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;qw(profit world_domination)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;My:Enum:Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# using an anonymous enum subtype:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Moose::Util::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TypeConstraints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;isa&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;qw(profit world_domination)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So that’s all, I guess this kind of feature is nothing new for seasoned Moose
developers, but it may help beginners, as there is no mention of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Moose::Manual::Attributes&lt;/code&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Perlbrew, Emacs, Flymake</title>
   <link href="http://dams.github.com/2011/05/27/perlbrew-emacs-flymake.html"/>
   <updated>2011-05-27T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/05/27/perlbrew-emacs-flymake</id>
   <content type="html">&lt;h1 id=&quot;perlbrew-emacs-flymake&quot;&gt;Perlbrew, Emacs, Flymake&lt;/h1&gt;

&lt;p&gt;So I’m a seasoned user of &lt;a href=&quot;http://www.gnu.org/software/emacs/&quot;&gt;Emacs&lt;/a&gt; (I
started using it back to 1999). I’m using it for all things, especially Perl
coding, using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cperl-mode&lt;/code&gt; Emacs mode.&lt;/p&gt;

&lt;p&gt;Lately, I’ve come to using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flymake&lt;/code&gt;.
&lt;a href=&quot;http://flymake.sourceforge.net/&quot;&gt;Flymake&lt;/a&gt; is a tool in Emacs, which tries to
compile the file you are editing, and displays compilation errors in your
buffer. There is a mode for Perl, so the result is really nice : realtime
syntax checking of the current Perl file you’re editing. It looks like that :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/perl_flymake.png&quot; alt=&quot;Perl and Flymake in Emacs&quot; title=&quot;Perl and Flymake in Emacs&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;perl--emacs--flymake--perlbrew&quot;&gt;Perl + Emacs + Flymake + PerlBrew&lt;/h1&gt;

&lt;p&gt;Then comes &lt;a href=&quot;http://search.cpan.org/perldoc?App::perlbrew&quot;&gt;perlbrew&lt;/a&gt;, which
allows you to have multiple Perl interpretors installed on your machine, and
switching between them easily.&lt;/p&gt;

&lt;p&gt;Alas, flymake is not working by default with Perlbrew, as it uses
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/bin/perl&lt;/code&gt;. So one needs to configure Emacs to recognize various perls
installed via Perlbrew, and tell Flymake to use one of them.&lt;/p&gt;

&lt;p&gt;kentaro has made a Perlbrew mode, and &lt;a href=&quot;http://d.hatena.ne.jp/antipop/20110413/1302671667&quot;&gt;explained how to use it with
flymake&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, for various reasons, this Perlbrew mode it doesn’t work well on my
machine and Franck ( &lt;a href=&quot;http://lumberjaph.net/&quot;&gt;lumperjaph&lt;/a&gt; ) reported similar
issues.&lt;/p&gt;

&lt;p&gt;So I went on and rewrote a simple Perlbrew mode that would do almost nothing.
It would only play with directories path, to allow you to say where the various
Perlbrew perls are installed, and which one to use. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perlbrew-mini.el&lt;/code&gt; was
born.&lt;/p&gt;

&lt;h1 id=&quot;perlbrew-miniel&quot;&gt;perlbrew-mini.el&lt;/h1&gt;

&lt;p&gt;Requirements : you need Emacs, a functional perlbrew with at least one Perl
installed, and you need
&lt;a href=&quot;http://search.cpan.org/perldoc?Project::Libs&quot;&gt;Project::Libs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, download perlbrew-mini.el &lt;a href=&quot;https://github.com/dams/perlbrew-mini.el&quot;&gt;from
github&lt;/a&gt;, and put it in a place where
Emacs will see it.&lt;/p&gt;

&lt;p&gt;Then, edit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.emacs&lt;/code&gt; so that it contains these lines:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(require 'perlbrew-mini)
;; change to your username below
(perlbrew-mini-set-perls-dir &quot;/home/uername/perl5/perlbrew/perls/&quot;)
;; change the version you wish to use
(perlbrew-mini-use &quot;perl-5.12.2&quot;)

(require 'flymake)

(defun flymake-perl-init ()
  (let* ((temp-file (flymake-init-create-temp-buffer-copy
                     'flymake-create-temp-inplace))
         (local-file (file-relative-name
                      temp-file
                      (file-name-directory buffer-file-name))))
    (list (perlbrew-mini-get-current-perl-path)
          (list &quot;-MProject::Libs&quot; &quot;-wc&quot; local-file)))
)

(add-hook 'cperl-mode-hook (lambda () (flymake-mode t)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And &lt;em&gt;voilà&lt;/em&gt;, Flymake will work with your Perlbrew Perl, as it used to work with
the system Perl.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DateTime duration in seconds</title>
   <link href="http://dams.github.com/2011/05/25/datetime-duration-in-seconds.html"/>
   <updated>2011-05-25T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/05/25/datetime-duration-in-seconds</id>
   <content type="html">&lt;h1 id=&quot;datetime-duration-in-seconds&quot;&gt;DateTime duration in seconds&lt;/h1&gt;

&lt;p&gt;It has been too many times that I forget how to get a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime::Duration&lt;/code&gt;
between two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; objects in seconds (and nanoseconds). That is, where I
can then do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt;seconds&lt;/code&gt; and have the duration in seconds between the two dates.&lt;/p&gt;

&lt;p&gt;I know it’s in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; POD, but I keep forgetting it, and it takes me
always a lot of time to find it back.&lt;/p&gt;

&lt;p&gt;Here it is so that hopefully the next time I search for “Perl DateTime Duration
seconds” on the Intarweb, it shows up…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$dt2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;subtract_datetime_absolute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$dt1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$duration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>Simple usage of Perl state variables</title>
   <link href="http://dams.github.com/2011/05/24/simple-usage-of-state-variables.html"/>
   <updated>2011-05-24T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/05/24/simple-usage-of-state-variables</id>
   <content type="html">&lt;h1 id=&quot;simple-usage-of-perl-state-variables&quot;&gt;Simple usage of Perl state variables&lt;/h1&gt;

&lt;p&gt;I see this type of code too often:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$structure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$structure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or things like that:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cache&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_load_cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you are using a non-ancient version of Perl (that is, 5.10 or more), you should consider using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; keyword. It’s similar to the static variables inherited from C.&lt;/p&gt;

&lt;p&gt;From the &lt;a href=&quot;http://perldoc.perl.org/functions/state.html&quot;&gt;documentation&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; declares a lexically scoped variable, just like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my&lt;/code&gt; does. However, those
variables will never be reinitialized, contrary to lexical variables that are
reinitialized each time their enclosing block is entered.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the two code snippets become :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$structure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$structure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;';&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;nb&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_load_cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nothing terribly amazing here, but it’s really easy, saves keystrokes and makes
the code more readable. So why not use it more widely ?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Moose trick with MooseX-Getopt and roles</title>
   <link href="http://dams.github.com/2011/05/18/MooseX-Getopt-trick.html"/>
   <updated>2011-05-18T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/05/18/MooseX-Getopt-trick</id>
   <content type="html">&lt;h1 id=&quot;moose-trick-with-moosex-getopt-and-roles&quot;&gt;Moose trick with MooseX-Getopt and roles&lt;/h1&gt;

&lt;p class=&quot;meta&quot;&gt; 18 May 2011 - Paris&lt;/p&gt;

&lt;h1 id=&quot;on-moosexgetopt&quot;&gt;On MooseX::Getopt&lt;/h1&gt;

&lt;p&gt;At work I extensively use Moose in my everyday Perl coding. I also use
&lt;a href=&quot;http://search.cpan.org/perldoc?MooseX::Getopt&quot;&gt;MooseX::Getopt&lt;/a&gt; to
automatically handle command line arguments as attributes, thus simplifying the
implementation of scripts.&lt;/p&gt;

&lt;p&gt;By default, MooseX::Getopt consider all public attributes to be mapped on a
command line argument. There are many ways to tell MooseX::Getopt to ignore a
public attribute:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;you can turn your attribut to a private one, but with public accessors&lt;/li&gt;
  &lt;li&gt;you can have the attribute use &lt;a href=&quot;http://search.cpan.org/perldoc?MooseX::Getopt::Meta::Attribute::Trait::NoGetopt&quot;&gt;MooseX::Getopt::Meta::Attribute::Trait::NoGetopt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;you can have the attribute use the &lt;a href=&quot;http://search.cpan.org/perldoc?MooseX::Getopt::Meta::Attribute::NoGetopt&quot;&gt;MooseX::Getopt::Meta::Attribute::NoGetopt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;act-on-distant-attributes&quot;&gt;Act on distant attributes&lt;/h1&gt;

&lt;p&gt;The previous actions are to be performed on the attribute definition. But what about
the situations where you don’t write the attribute definition yourself ? Like,
for instance, if you inherits the attributes from an other class, or if you got
the attributes by consuming a role ?&lt;/p&gt;

&lt;p&gt;In this case, you’ll need to perform an action on the attribute &lt;strong&gt;from a
distance&lt;/strong&gt;. Here are two solutions, that were given to me by the nice folks on
#moose (namely &lt;em&gt;sartak&lt;/em&gt; and &lt;em&gt;doy&lt;/em&gt;)&lt;/p&gt;

&lt;h2 id=&quot;apply-the-trait-from-a-distance&quot;&gt;Apply the trait from a distance&lt;/h2&gt;

&lt;p&gt;The first solution is to run this code after having consumed a role, or inherited a class, that provides the attribute ‘some_attr’:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;   &lt;span class=&quot;nn&quot;&gt;MooseX::Getopt::Meta::Attribute::Trait::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;NoGetopt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;__PACKAGE__&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;get_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;some_attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;')&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;adds-the-trait-to-the-attribute-definition&quot;&gt;Adds the trait to the attribute definition&lt;/h2&gt;

&lt;p&gt;A syntactically simpler solution is to add the trait in the attribute, in our class:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;+some_attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;traits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;NoGetopt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;'])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The ‘+’ character allows to add things to an already defined attribute, instead
of trying to overwrite its definition altogether.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Migrating to Jekyll</title>
   <link href="http://dams.github.com/2011/04/30/migrating-to-jekyll.html"/>
   <updated>2011-04-30T00:00:00+00:00</updated>
   <id>http://dams.github.com/2011/04/30/migrating-to-jekyll</id>
   <content type="html">&lt;h1 id=&quot;migrating-to-jekyll&quot;&gt;Migrating to Jekyll&lt;/h1&gt;

&lt;p class=&quot;meta&quot;&gt; 30 Apr 2011 - Paris&lt;/p&gt;

&lt;p&gt;So, this post is about migrating this blog from &lt;a href=&quot;http://typepad.com&quot;&gt;Typepad&lt;/a&gt;
to &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, using a small Perl script.&lt;/p&gt;

&lt;p&gt;The reasons why I’m moving away from Typepad are :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Typepad is slow&lt;/li&gt;
  &lt;li&gt;Typepad is not free&lt;/li&gt;
  &lt;li&gt;Typepad editor is not techie compatible&lt;/li&gt;
  &lt;li&gt;Typepad is a blog engine…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And blog engines are not hype anymore :) Seriously, I was looking for something
easy and simple, and compatible with my geek side.&lt;/p&gt;

&lt;p&gt;Back in the days, I remember that I enjoyed a lot using
&lt;a href=&quot;http://nanoblogger.sourceforge.net/&quot;&gt;nanoblogger&lt;/a&gt;. But it’s too slow, and you
need to host it yourself.&lt;/p&gt;

&lt;p&gt;So I followed the current trend, and set up my pages on github, and transfered
my posts from Typepad to jekyll.&lt;/p&gt;

&lt;p&gt;Jekyll is :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;light&lt;/li&gt;
  &lt;li&gt;easy&lt;/li&gt;
  &lt;li&gt;simple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the real power is that it can be coupled with github’s pages. So I feel right at
home, and so editing code and pushing to git(hub) (stuff I do everyday) won’t
be different from editing blog posts and pushing to github.&lt;/p&gt;

&lt;p&gt;Oh, but how did I migrate my blog posts from Typepad to Jekyll ? I couldn’t
find any migration script on internet or importers in jekyll, so I wrote a
quick and not so dirty Perl script. it’s all on github here : the mighty
&lt;a href=&quot;https://github.com/dams/typepad_to_jekyll&quot;&gt;typepad_to_jekyll&lt;/a&gt; ! Feel free to
fork it. Feedback welcome :)&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Perl Moderne, a new Perl book</title>
   <link href="http://dams.github.com/all/perl/2011/02/16/perl-moderne-a-new-perl-book.html"/>
   <updated>2011-02-16T00:00:00+00:00</updated>
   <id>http://dams.github.com/all/perl/2011/02/16/perl-moderne-a-new-perl-book</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://perlmoderne.fr&quot; style=&quot;float: left;&quot;&gt;&lt;img alt=&quot;image from www.pearson.fr&quot; class=&quot;asset  asset-image at-xid-6a0120a63366ed970b014e861c3dc0970d&quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b014e861c3dc0970d-800wi&quot; style=&quot;border: 1px solid black; margin: 10px 10px 10px 10px;&quot; title=&quot;Perl Moderne&quot; /&gt;&lt;/a&gt; I haven&amp;#39;t been blogging a lot this year-and-half, and for various reasons. But the reason number one is that I&amp;#39;ve been very busy writing a &lt;strong&gt;&lt;a href=&quot;http://perlmoderne.fr/&quot; target=&quot;_self&quot;&gt;Perl book&lt;/a&gt;&lt;/strong&gt; from scratch, in French, with 3 other fellow French &lt;a href=&quot;http://mongueurs.net/&quot; target=&quot;_self&quot;&gt;Perl Mongers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The book is called &lt;em&gt;&lt;a href=&quot;http://perlmoderne.fr/&quot; target=&quot;_self&quot;&gt;Perl Moderne&lt;/a&gt;&lt;/em&gt;. That means &amp;quot;Modern Perl&amp;quot;, but it has nothing to do with chromatic&amp;#39;s book. The book was actually published long time ago, end October 2010. But it took us authors some time to recover :)&lt;/p&gt;
&lt;p&gt;This book is written in French, for French speaking readers. Its goal is to present the Perl 5 language as it exists &lt;strong&gt;now&lt;/strong&gt;, and tries to teach the reader how to start using it the &lt;em&gt;right way&lt;/em&gt;, that is, the &lt;em&gt;modern way&lt;/em&gt;. The book is not a bible, nor an encyclopedia of the historical language. Instead, it&amp;#39;s a collection of the useful concepts that are used nowadays, and how to use them in the latest version of Perl and CPAN.&lt;/p&gt;
&lt;p&gt;The reader can be a total newbie in Perl, but it has to have a previous development experience with an other language, for instance PHP, Ruby, Python, or Java. However, the book goes far beyond introducing the language. It allows the reader to become fluent with the Perl data structure, regexps, Moose OO and typing, POE, interacting with databases, files, DateTime, XML and configuration files, Web interactions, and more...&lt;/p&gt;
&lt;p&gt;It&amp;#39;s big in content (many subjects covered, and 450 pages !) but small in size, as it&amp;#39;s an A5 format, so it fits easily in a bag, and it&amp;#39;s not heavy :)&lt;/p&gt;
&lt;h2&gt;The people&lt;/h2&gt;
&lt;p&gt;Historically, Pearson France, the press editor, posted a request on the French Perl Mongers mailing list, saying that they were looking for authors willing to write a new Perl Book in French.&lt;/p&gt;
&lt;p&gt;I decided to not let this opportunity pass : it&amp;#39;s very rare that French editors are interested by Perl, and willing to produce good quality books. After some struggling, I ended up setting up a team of 4 brave French Perl Mongers, that became 4 Perl book authors :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sébastien Aperghis-Tramoni&lt;/strong&gt;&amp;#0160;(SAPER on CPAN) : active French Perl Monger, he knows almost everything about CPAN modules. He wrote several modules himself, and maintains numerous others. He wrote several Perl articles in the &lt;a href=&quot;http://www.gnulinuxmag.com&quot; target=&quot;_self&quot;&gt;GNU/Linux Magazine France&lt;/a&gt;.&amp;#0160;He is also the hidden admin of your Perl conferences, as he maintains &lt;a href=&quot;http://act.mongueurs.net/&quot; target=&quot;_self&quot;&gt;Act&lt;/a&gt;, empowering a lot of &lt;a href=&quot;http://act.mongueurs.net/conferences.html&quot; target=&quot;_self&quot;&gt;Perl conferences&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Philippe Bruhat&lt;/strong&gt;&amp;#0160;(BOOK on CPAN) :&amp;#0160;well known Perl figure, active French Perl Monger, former president of them, founder and treasurer of the&amp;#0160;&lt;a href=&quot;http://www.yapceurope.org&quot; target=&quot;_self&quot;&gt;YAPC Europe Foundation&lt;/a&gt;. Received a&amp;#0160;White Camel Award in 2009, and maintains quite a few modules on CPAN. Also wrote articles in the GNU/Linux Magazine France.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Jérôme Quelin&lt;/strong&gt; (JQUELIN&amp;#0160;on CPAN) :&amp;#0160;active French Perl Monger, knows a great deal about Tk, wrote &lt;a href=&quot;http://search.cpan.org/perldoc?Games::Risk&quot; target=&quot;_self&quot;&gt;Games::Risk&lt;/a&gt;&amp;#0160;among other things, and maintains a bunch of CPAN modules. He is also maintaining a lot of Perl packages at Mandriva and &lt;a href=&quot;http://mageia.org&quot; target=&quot;_self&quot;&gt;Mageia&lt;/a&gt;.&amp;#0160;Also wrote articles in the GNU/Linux Magazine France.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Damien Krotkine&lt;/strong&gt;&amp;#0160;(DAMS on CPAN) : well that&amp;#39;s me ! I&amp;#39;m an&amp;#0160;active French Perl Monger, using Perl for 11 years or so, I wrote a couple of Perl articles in the GNU/Linux Magazine France, have some modules on CPAN (among them &lt;a href=&quot;http://search.cpan.org/perldoc?Curses::Toolkit&quot; target=&quot;_self&quot;&gt;Curses::Toolkit&lt;/a&gt;), and I&amp;#39;m now a proud core developer of &lt;a href=&quot;http://perldancer.org&quot; target=&quot;_self&quot;&gt;Dancer, the new big thing&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The content&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://perlmoderne.fr&quot; target=&quot;_self&quot;&gt;&lt;em&gt;Perl Moderne&lt;/em&gt;&lt;/a&gt; starts with a gentle (but concise) introduction to Perl, with many pointers to external resources, focusing on ease-of-use. For instance, we mention CPAN and&amp;#0160;&lt;span style=&quot;font-family: &amp;#39;courier new&amp;#39;, courier;&quot;&gt;cpanm&lt;/span&gt;&lt;span&gt;&amp;#0160;very early. Then the real business starts with an explanation of the major programming concepts (data structures, OO, databases, formats, event programming and the intarweb).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We tried to provide a preferred way to do each thing, while mentioning alternatives. We didn&amp;#39;t separated the language and CPAN. &lt;em&gt;&amp;quot;Perl is the syntax, CPAN is the language&amp;quot;&lt;/em&gt;... So about half of the book describes how to solve a problem using this or that CPAN module. And I think it&amp;#39;s great. It allowed us to teach Object Oriented programming with &lt;a href=&quot;http://www.iinteractive.com/moose/&quot; target=&quot;_self&quot;&gt;Moose&lt;/a&gt;, explain event programming with &lt;a href=&quot;http://poe.perl.org/&quot; target=&quot;_self&quot;&gt;POE&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;I think it is very important that new Perl books get written, and very important that some are written natively in non-english. It fits better its purpose to the localized need (students, teachers, academic structures and way of thinking are different from one country to another). That also makes editors aware of the local Perl activity, and help spreads the words about the language in schools and universities, where native books are preferred to translations.&lt;/p&gt;
&lt;p&gt;So, if you know any French speaking (or learning) geek or computer scientist, around you, please consider recommending them this book. It was crafted with care and love by Perl passionated ! :) You can point them to the &lt;a href=&quot;http://perlmoderne.fr&quot; target=&quot;_self&quot;&gt;dedicated website of Perl Moderne&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#0160;&lt;/p&gt;
&lt;p&gt;Here is an english translation of the table of content :&lt;/p&gt;
&lt;p&gt;01. Start with&amp;#0160;Perl&lt;br /&gt;02. Install a&amp;#0160;Perl&amp;#0160;module&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I. Language and data structures&lt;/strong&gt;&lt;br /&gt;03. Language&lt;br /&gt;04. Data structures&lt;br /&gt;05. Regular expressions&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;II. Modern object programming&lt;/strong&gt;&lt;br /&gt;06. Basic&amp;#0160;Perl&amp;#0160;objects&lt;br /&gt;07. Moose&lt;br /&gt;08. Typing system in Moose&lt;br /&gt;09. Methods in Moose&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;III. Data manipulation&lt;/strong&gt;&lt;br /&gt;10. Files and directories&lt;br /&gt;11. SQL databases&lt;br /&gt;12. SQL abstraction, ORM, non-SQL databases&lt;br /&gt;13. Dates and times&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IV. Formats&lt;/strong&gt;&lt;br /&gt;14. XML&lt;br /&gt;15. Data serialisation&lt;br /&gt;16. Configuration files&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;V. Event programming&lt;/strong&gt;&lt;br /&gt;17. Introduction to POE&lt;br /&gt;18. Practical POE&lt;br /&gt;19. Distributed POE&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;VI. Web&lt;/strong&gt;&lt;br /&gt;20. HTML documents parsing&lt;br /&gt;21. HTTP and the Web&lt;br /&gt;22. LWP&lt;br /&gt;23. Web browsing&lt;br /&gt;24. WWW::Mechanize&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Perl Dancer and DBIC</title>
   <link href="http://dams.github.com/2010/12/13/perl-dancer-and-dbic.html"/>
   <updated>2010-12-13T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/12/13/perl-dancer-and-dbic</id>
   <content type="html">&lt;p&gt;Are you curious to see how to create a real app from scratch with Perl Dancer, using DBIX::Class ? Well, my Perl Dancer Advent Calendar article has been published saturday :&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://advent.perldancer.org/2010/11&quot; target=&quot;_self&quot; title=&quot;Perl Advent Calendar article&quot;&gt;http://advent.perldancer.org/2010/11&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b0148c6ac8b3a970c-popup&quot; onclick=&quot;window.open( this.href, &amp;#39;_blank&amp;#39;, &amp;#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&amp;#39; ); return false&quot; style=&quot;display: inline;&quot;&gt;&lt;img alt=&quot;Dancer_dbic&quot; class=&quot;asset  asset-image at-xid-6a0120a63366ed970b0148c6ac8b3a970c&quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b0148c6ac8b3a970c-320wi&quot; title=&quot;Dancer_dbic&quot; /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Enjoy !&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Disqus on Typepad</title>
   <link href="http://dams.github.com/2010/12/07/disqus-on-typepad.html"/>
   <updated>2010-12-07T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/12/07/disqus-on-typepad</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://disqus.com&quot; target=&quot;_self&quot;&gt;Disqus&lt;/a&gt; is great. It's a full featured cross-site comments free management system. I have an account on it, so I wanted to use disqus instead of the typepad comments system.&lt;/p&gt;
&lt;p&gt;&quot;Easy enough&quot; I said to myself : there is a dedicated page to help you install Disqus in Typepad. This includes adding a new &quot;Embed your own HTML&quot; module in your blog content, and copy-pasting a Javacript snippet in it.&lt;/p&gt;
&lt;p&gt;Alas, the Javascript snippet didn't work fine. I suspect that the Typepad code has changed since the Disqus install documentation has been written. &amp;nbsp;Maybe the Javascript code of Typepad tries to block other scripts playing with the comment tags.&lt;/p&gt;
&lt;p&gt;Anyway, here is a solution : I changed the code a bit, and wrapped it in an Javascript&amp;nbsp;&lt;span style=&quot;font-family: 'andale mono', times;&quot;&gt;onload&lt;/span&gt;&amp;nbsp;. I'm not saying it's the best solution, but it works for me... Here is the Javascript code snippet to be used instead of the one Disqus provides in the Typepad Install section. Of course, replace &lt;span style=&quot;font-family: 'andale mono', times;&quot;&gt;YOUR_DISQUS_LOGIN&lt;/span&gt; with, well, your disqus login...&lt;/p&gt;


&lt;code class=&quot;brush: javascript&quot;&gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;

var my_func = function() {
  var div = document.getElementById('all-comments');
  var script = document.createElement('script');
  script.type = 'text/javascript'; script.src = 'http://disqus.com/forums/YOUR_DISQUS_LOGIN/embed.js';
  document.getElementsByTagName('body')[0].appendChild(script);
  div.innerHTML = '' ;
  div.id = 'disqus_thread';
};

var x = window.onload;
window.onload = function() {my_func(); if (x) x(); }

&amp;lt;/script&amp;gt;
&lt;/code&gt;

Let me know if it works for your Typepad blog.


</content>
 </entry>
 
 <entry>
   <title>Perl Dancer version 1.2 and Advent Calendar</title>
   <link href="http://dams.github.com/2010/12/01/perl-dancer-version-1-2-and-advent-calendar.html"/>
   <updated>2010-12-01T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/12/01/perl-dancer-version-1-2-and-advent-calendar</id>
   <content type="html">&lt;p&gt;&amp;#0160;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://perldancer.org/&quot; target=&quot;_self&quot; title=&quot;Perl Dancer&quot;&gt;Perl Dancer&lt;/a&gt; should at least ring a bell to you : it&amp;#39;s a popular Perl micro web framework. Route based, easy to use, simple clean design, with low dependancies, Dancer is gaining in popularity and maturity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Version 1.2&lt;/strong&gt; has been released ( see &lt;a href=&quot;http://www.backup-manager.org/pipermail/dancer-users/2010-November/000513.html&quot; target=&quot;_self&quot; title=&quot;Dancer 1.2000 announcement&quot;&gt;sawyer&amp;#39;s announcement&lt;/a&gt; here ), and is described as the &lt;em&gt;first stable community release.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But that&amp;#39;s not all ! Go check out the awesome &lt;a href=&quot;http://advent.perldancer.org/2010&quot; target=&quot;_self&quot; title=&quot;Perl Dancer Advent Calendar&quot;&gt;Perl Dancer Advent Calendar&lt;/a&gt;. You&amp;#39;ll learn all about Dancer, how to get started with it, what cool plugins are available, what are the nice tricks. Step by step, a new article will be revealed each day.&lt;/p&gt;
&lt;p&gt;Dancer is a young project with a nice community. Check it out :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http -&amp;#0160;&lt;a href=&quot;http://perldancer.org/&quot; target=&quot;_self&quot;&gt;http://perldancer.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IRC - &lt;strong&gt;#dancer&lt;/strong&gt; on&amp;#0160;irc.mongueurs.net&lt;/li&gt;
&lt;li&gt;ml -&amp;#0160;&lt;a href=&quot;http://www.backup-manager.org/cgi-bin/listinfo/dancer-users&quot; target=&quot;_self&quot;&gt;http://www.backup-manager.org/cgi-bin/listinfo/dancer-users&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#0160;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Ulimit doesn't work on Leopard (memory limitation)</title>
   <link href="http://dams.github.com/2010/10/06/ulimit-doesn-t-work-on-leopard-memory-limitation.html"/>
   <updated>2010-10-06T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/10/06/ulimit-doesn-t-work-on-leopard-memory-limitation-</id>
   <content type="html">&lt;p&gt;&lt;br /&gt;After many tests on my side, I got confirmation from &lt;a href=&quot;http://forums.macrumors.com/showthread.php?t=573616&quot; target=&quot;_self&quot;&gt;this page&lt;/a&gt;&amp;#0160;: it looks like ulimit doesn&amp;#39;t work for memory limitation starting from Mac OS 10.5. That&amp;#39;s a shame...&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;#39;andale mono&amp;#39;, times;&quot;&gt;perl -E &amp;#39;use BSD::Resource; &amp;#0160;setrlimit(RLIMIT_VMEM, 2000, 2000); my $s; for my $i (1..50_000) { $s .= &amp;quot;A&amp;quot; x 1024 } say &amp;quot;damned, I should have been killed&amp;quot;&amp;#39;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;#0160;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Merge PDFs easily with Perl</title>
   <link href="http://dams.github.com/2010/06/29/merge-pdfs-easily-with-perl.html"/>
   <updated>2010-06-29T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/06/29/merge-pdfs-easily-with-perl</id>
   <content type="html">&lt;p&gt;Today I discovered an easy way to merge PDFs files using Perl.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In my current project, I have to automatically generate a technical documentation from my perl modules PODs. It&amp;#39;s easy to create one PDF file for each modules, but then I need to merge them all in one.&lt;/p&gt;

&lt;p&gt;The very easy to use CAM::PDF Perl module provides &lt;a href=&quot;http://search.cpan.org/%7Ecdolan/CAM-PDF-1.52/bin/appendpdf.pl&quot; title=&quot;appelpdf.pl on CPAN&quot;&gt;appendpdf.pl&lt;/a&gt;. However it can only merge 2 files together.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve copied and modified it for my need, and renamed it &lt;span style=&quot;font-family: Courier;&quot;&gt;mergepdf.pl&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Download : &lt;span class=&quot;asset asset-generic at-xid-6a0120a63366ed970b01348515fed6970c&quot;&gt;&lt;a href=&quot;http://damien.krotkine.com/files/mergepdf.pl&quot; title=&quot;merge.pl script&quot;&gt;mergepdf.pl&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Usage :&amp;#0160; &lt;span style=&quot;font-family: Courier;&quot;&gt;appendpdf.pl [options] file1.pdf file2.pdf ... fileN.pdf outfile.pdf&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;See the help for more options.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>flagedit</title>
   <link href="http://dams.github.com/2010/03/29/flagedit.html"/>
   <updated>2010-03-29T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/03/29/flagedit</id>
   <content type="html">&lt;h2&gt;Description&lt;/h2&gt;

&lt;p&gt;
flagedit is a CLI USE flag editor for Gentoo Linux. It let you edit the 
use flags of /etc/make.conf, as well as the /etc/portage/package.use 
file.
&lt;/p&gt;
&lt;p&gt;
&lt;span style=&quot;text-decoration: underline;&quot;&gt;features : &lt;/span&gt;


&lt;ul&gt;
&lt;li&gt;edit system use flags (in /etc/make.conf)&lt;/li&gt;
&lt;li&gt;edit per package use flags (in /etc/portage/package.use)&lt;/li&gt;
&lt;li&gt;edit system keyword (ACCEPT_KEYWORDS in /etc/make.conf)&lt;/li&gt;
&lt;li&gt;edit per package keywords (in /etc/portage/package.keywords)&lt;/li&gt;
&lt;li&gt;get the list of possible use flags, and keywords, with their 
descriptions&lt;/li&gt;
&lt;li&gt;flagedit warns you when you try to edit a flag or keyword that 
doesn't exist&lt;/li&gt;
&lt;li&gt;you can specify alternates files for package.use package.keywords 
make.conf&lt;/li&gt;
&lt;li&gt;it creates a backup before overwriting&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;br&gt;
&lt;h2&gt;News&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2009.01.16&lt;/span&gt; Version 0.0.8. make flagedit compatible with directories support ( as per &lt;a href=&quot;http://bugs.gentoo.org/241668&quot;&gt;bug 241668&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2005.12.26&lt;/span&gt; Version 0.0.7. The help fits in 80 columns
&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2005.11.24&lt;/span&gt; Version 0.0.6. some improvments
&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2005.11.15&lt;/span&gt; Version 0.0.5. some improvments
&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2005.10.14&lt;/span&gt; Version 0.0.2. An ebuild is available for 
gentoo linux.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2005.09.29&lt;/span&gt; New version : now warns if the flag is not a valid
 one. More features also&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2005.07.24&lt;/span&gt; just did this web page.&lt;/p&gt;

&lt;br&gt;
&lt;h2&gt;Download&lt;/h2&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://damien.krotkine.com/flagedit/download&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;br&gt;
&lt;h2&gt;Documentation&lt;/h2&gt;
&lt;p&gt;This is just the raw output of flagedit --help, but I think it's 
self-explanatory :
&lt;/p&gt;&lt;pre&gt;flagedit allows you to edit the use flags or the keywords for a particular&lt;br&gt;ebuild, or for the whole system. a backup is done for each modified file, named&lt;br&gt;file.old.&lt;br&gt;&lt;br&gt;Usage: flagedit [PACKAGE] [ACTIONS | -- KEYWORD_ACTIONS] [ OPTIONS ]&lt;br&gt;&lt;br&gt;Examples:&lt;br&gt; flagedit net-im/amsn --show # shows the use flag set for net-im/amsn&lt;br&gt; flagedit net-im/amsn +gnome # adds the gnome use flag to net-im/amsn&lt;br&gt; flagedit net-im/amsn -kde +xmms # adds the xmms use flag and set the -kde one&lt;br&gt; flagedit net-im/amsn %kde # reset the kde use flag (it's removed from the line)&lt;br&gt;&lt;br&gt; flagedit %kde # reset the global use flag (it's removed in make.conf)&lt;br&gt; flagedit +gnome -qt # add gnome and -qt in make.conf&lt;br&gt;&lt;br&gt; flagedit net-im/amsn -- %x86 # reset the x86 keyword for net-im/amsn&lt;br&gt; flagedit net-im/amsn -- +~ppc +~x86 # adds the ~ppc and ~x86 keywords for net-im/amsn&lt;br&gt; flagedit net-im/amsn -- % # resets the keywords for this package&lt;br&gt; flagedit -- +~x86 # sets ACCEPT_KEYWORDS to &quot;~x86&quot; in /etc/make.conf&lt;br&gt;&lt;br&gt;You can mix the flags and keywords :&lt;br&gt; flagedit net-im/amsn +gnome -- +~x86&lt;br&gt;&lt;br&gt;PACKAGE is a package name (like dev-ruby/ruby-atk). If no package is given,&lt;br&gt;flagedit will edit the maine USE flags (in make.conf), or the main&lt;br&gt;ACCEPT_KEYWORDS (in make.conf)&lt;br&gt;&lt;br&gt;ACTIONS are :&lt;br&gt;+FLAG enable the FLAG. Example : +sse&lt;br&gt;-FLAG disable the FLAG. Example : -sse&lt;br&gt;%FLAG reset the FLAG to default. Example : %sse&lt;br&gt;% reset the whole flags of PACKAGE to default. In this case, PACKAGE is not optional&lt;br&gt;&lt;br&gt;KEYWORD_ACTIONS are :&lt;br&gt;+KEYWORD enable the keyword. Example : +x86&lt;br&gt;-KEYWORD disable the KEYWORD. Example : -~x86&lt;br&gt;%KEYWORD reset the KEYWORD to default. Example : %x86&lt;br&gt;% reset the whole keywords of PACKAGE to default. In this case, PACKAGE is not optional&lt;br&gt;&lt;br&gt;&lt;br&gt;OPTIONS are :&lt;br&gt; --package-file &amp;lt;path&amp;gt; specify an alternate package.use file (default is /etc/portage/package.use)&lt;br&gt; --keywords-file &amp;lt;path&amp;gt; specify an alternate package.keywords file (default is /etc/portage/package.keywords)&lt;br&gt; --make-conf-file &amp;lt;path&amp;gt; specify an alternate make.conf file (default is /etc/make.conf)&lt;br&gt; --portage-dir &amp;lt;path&amp;gt; specify an alternate portage directory path (default is /usr/portage)&lt;br&gt; --alpha-order sort the flags or keywords alphabetically instead of keeping the original order&lt;br&gt; --show don't edit, display the flags or keywords of the PACKAGE. If no package is given, display the system USE flags or the system ACCEPT_KEYWORDS.&lt;br&gt; --list don't edit, display the entire list of possible flags or possible keywords.&lt;br&gt; --desc if specified with --list, display the flags or keywords description also.&lt;br&gt; --keywords specifies that actions are to be done on keywords, not on use flags&lt;br&gt; -- same as --keywords&lt;br&gt; --strict if a specified flag or keyword name is invalid, dies, instead of just warning.&lt;br&gt; --nowarn if a specified flag or keyword name is invalid, don't warn.&lt;br&gt; --help this help&lt;br&gt; --version prints the version&lt;br&gt; &lt;br&gt;see http://dkrotkine.com/flagedit/&lt;br&gt;&lt;/pre&gt;

&lt;br&gt;
&lt;h2&gt;About&lt;/h2&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;author : &lt;a href=&quot;http://damien.krotkine.com&quot;&gt;dams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;license : GPL-2 (not upper version)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Thanks to&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tigger for requesting it, and testing.&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Syntax Highlighting in Typepad</title>
   <link href="http://dams.github.com/2010/03/15/syntax-highlighting-in-typepad.html"/>
   <updated>2010-03-15T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/03/15/syntax-highlighting-in-typepad</id>
   <content type="html">&lt;p&gt;&lt;/p&gt;&lt;h1&gt;Code Snippets, Syntax Highlighting, Source examples, Verbatim text, etc...&lt;/h1&gt;I&amp;#39;m sure I&amp;#39;m not the only one to need to display nice clean and compatible code snippets, source code examples, and similar stuff. I&amp;#39;m using Typepad as blog engine, but what I&amp;#39;ll explain here should work with MovableType as well (as the former is a professional version of the open source latter one).&lt;p&gt;First of all, the needs :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I need a tool to display code snippets, examples,&lt;/li&gt;
&lt;li&gt;It has to be easy to use,&lt;/li&gt;
&lt;li&gt;It has to be nice&lt;/li&gt;
&lt;li&gt;It should have syntax highlighting and coloring&lt;/li&gt;
&lt;li&gt;It has to support Perl, Javascript, and ruby syntax&lt;/li&gt;
&lt;li&gt;It has to allow download and view as text&lt;/li&gt;
&lt;li&gt;It has to degrade properly, so that it works in RSS clients&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution is of course &lt;a href=&quot;http://alexgorbatchev.com/wiki/SyntaxHighlighter&quot;&gt;SyntaxHighlighter&lt;/a&gt;, the well known tool by &lt;a href=&quot;http://alexgorbatchev.com&quot;&gt;Alex Gorbatchev&lt;/a&gt;. This tool is used &lt;a href=&quot;http://alexgorbatchev.com/wiki/SyntaxHighlighter:Spotlight&quot;&gt;widely &lt;/a&gt;and some people have already written on &lt;a href=&quot;http://www.jontesays.com/jonte-says/2009/03/adding-syntaxhighlighter-to-a-typepad-pro-account-using-advanced-templates.html&quot;&gt;including it in Movable Type&lt;/a&gt;, or even &lt;a href=&quot;http://www.jontesays.com/jonte-says/2009/03/adding-syntaxhighlighter-to-a-typepad-pro-account-using-advanced-templates.html&quot;&gt;in Typepad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But I thought I would write on it as well, because there are some subtleties, and both SyntaxHighlighter and Typepad evolved since these entries were created.&lt;/p&gt;

&lt;p&gt;So, if you don&amp;#39;t know this too yet, or are too lazy to check its description page, SyntaxHighlighter is a pure JavaScript + CSS tool that finds and renders content, from a specific standard HTML tag you specify.&amp;#0160;&lt;/p&gt;

&lt;h1&gt;Example&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;brush: perl&quot;&gt;
# Some Perl code&lt;br /&gt;
my $var = 42;&lt;br /&gt;
my @array = map { reverse }&lt;br /&gt;
 grep { length }&lt;br /&gt;
 @strings;&lt;br /&gt;&lt;br /&gt;

sub my_function {&lt;br /&gt;
 my ($a, $b) = @_;&lt;br /&gt;
 return ($a * $b);&lt;br /&gt;
}
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;Download&lt;/h1&gt;&lt;p&gt;First of all, you &lt;strong&gt;don&amp;#39;t&lt;/strong&gt; want to download SyntaxHighlighter 
from it &amp;quot;&lt;em&gt;official&lt;/em&gt;&amp;quot; google code home, &lt;span style=&quot;text-decoration: line-through;&quot;&gt;because it&amp;#39;s hosted by Google&lt;/span&gt;
 (sorry, just kidding) because only the version 1.5 is available there. 
What we want is &lt;strong&gt;version 2.0&lt;/strong&gt;, which has more features, and 
includes a Perl syntax &lt;em&gt;brush&lt;/em&gt; by default (so no need to get it 
from elsewhere).&lt;/p&gt;

&lt;p&gt;Download SyntaxHighlighter from &lt;a href=&quot;http://alexgorbatchev.com/wiki/SyntaxHighlighter:Download&quot; title=&quot;download page for SyntaxHighlighter&quot;&gt;this page&lt;/a&gt;. I downloaded version &lt;a href=&quot;http://alexgorbatchev.com/downloads/grab.php?name=sh&quot; title=&quot;version 2.1.364 of SyntaxHighlighter&quot;&gt;2.1.364&lt;/a&gt; (&lt;a href=&quot;http://damien.krotkine.com/files/syntaxhighlighter_2.1.364.zip&quot; title=&quot;version 2.1.364 of SyntaxHighlighter&quot;&gt;local copy here&lt;/a&gt; in case the site is down)&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;h1&gt;Upload to your TypePad Account&lt;/h1&gt;Next, you need to upload the files to your TypePad File Manager. You&amp;#39;ll find it in the Library Tab.&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b0120a93a0550970b-pi&quot; onclick=&quot;window.open(this.href,&amp;#39;_blank&amp;#39;,&amp;#39;scrollbars=no,resizable=yes,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&amp;#39;);
 return false&quot; style=&quot;display: inline;&quot;&gt;&lt;img alt=&quot;Image 9&quot; class=&quot;asset asset-image 
at-xid-6a0120a63366ed970b0120a93a0550970b &quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b0120a93a0550970b-320pi&quot; style=&quot;margin: 0pt;&quot; title=&quot;Image 9&quot; /&gt;&lt;/a&gt;&amp;#0160; &lt;/p&gt;

&lt;p&gt;Then create a directory (I created mine as &lt;em&gt;syntaxhighlighter&lt;/em&gt; at the root), and upload the following files. This list is the bare minimum to have it working, but you can (you should) add more &lt;em&gt;brush&lt;/em&gt;es to support more languages highlighting, and also upload the icons (the .png files). You could as well upload all the languages brushes. And you can also use a different theme (I&amp;#39;ll try the Emacs one, as I&amp;#39;m an Emacs addict).&lt;/p&gt;

&lt;p&gt;&amp;#0160; &lt;a href=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b0120a93a094e970b-popup&quot; onclick=&quot;window.open(this.href,&amp;#39;_blank&amp;#39;,&amp;#39;scrollbars=no,resizable=yes,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&amp;#39;);

 return false&quot; style=&quot;display: inline;&quot;&gt;&lt;img alt=&quot;Image 7&quot; class=&quot;asset 
asset-image at-xid-6a0120a63366ed970b0120a93a094e970b 
 &quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b0120a93a094e970b-320wi&quot; style=&quot;margin: 0pt;&quot; title=&quot;Image 7&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Make sure your upload works by trying to access one of the file (of course replace your real site host name) :&lt;/p&gt;

&lt;p&gt;http://YOURSITE.COM/syntaxhighlighter/shCore.js&lt;/p&gt;

&lt;p&gt;If you can see or download the file, it means the files are properly uploaded.&lt;/p&gt;&lt;h1&gt;Add some magic&lt;/h1&gt;&lt;p&gt;For SyntaxHighlighter to work, you need to include some Javascript and CSS to the pages that will contain things you want to highlight. The best is to include it on every pages, as the tool is smart enough to find and apply styling only on what you specify to be highlighted.&lt;/p&gt;

&lt;p&gt;Now, how do you add CSS and Javascript to your TypePad blog? There are two cases :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either you are using a &lt;strong&gt;simple TypePad design&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Or you are using an &lt;strong&gt;advanced TypePad design&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
All blog entries I&amp;#39;ve seen on this topic only handles the case of &lt;strong&gt;advanced&lt;/strong&gt; design, because it&amp;#39;s easier to do. But, people using advanced design don&amp;#39;t need a tutorial to include SyntaxHighlighter on their blog, they are, you know, &lt;em&gt;advanced&lt;/em&gt; enough to do it on their own... So I thought it would be &lt;em&gt;more useful&lt;/em&gt; to describe how to do with a simple design.&lt;/p&gt;

&lt;p&gt;With a simple design on TypePad, you don&amp;#39;t have access to the templates of the pages, but luckily, you can add a module that allows you to add any HTML code in your page. So the idea is to this module to your design content, and add the needed javascript and CSS reference to it. Here is how you can do it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From your TypePad dashboard, go to &lt;strong&gt;Design&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Content&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add a new module, called &amp;quot;&lt;em&gt;Embed your own HTML&lt;/em&gt;&amp;quot; (see picture)&lt;/li&gt;
&lt;li&gt;Give it a name (it&amp;#39;s not used in the page, it&amp;#39;s just to see what this module is here for).&lt;/li&gt;
&lt;li&gt;Be sure that you move the module to be on the lowest part of your blog content (to be loaded last)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#0160;&lt;a href=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b01310fa186af970c-popup&quot; onclick=&quot;window.open( this.href, &amp;#39;_blank&amp;#39;, &amp;#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&amp;#39; ); return false&quot; style=&quot;display: inline;&quot;&gt;&lt;img alt=&quot;Image 10&quot; class=&quot;asset asset-image at-xid-6a0120a63366ed970b01310fa186af970c &quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b01310fa186af970c-320wi&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The content of the module will be used to load SyntaxHighlighter. Here is what I input in the module :&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;
&lt;code class=&quot;brush: xml&quot;&gt;
&amp;lt;!-- Include required JS files --&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://YOURSITE.com&lt;br /&gt;/syntaxhighlighter/shCore.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- At least one brush, here we choose Perl.--&amp;gt;&lt;br /&gt;
&amp;lt;!-- You need to include a brush for every language you want to highlight --&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://YOURSITE.com&lt;br /&gt;/syntaxhighlighter/shBrushPerl.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Include *at least* the core style and default theme --&amp;gt;&lt;br /&gt;
&amp;lt;!-- You can choose a different theme --&amp;gt;&lt;br /&gt;
&amp;lt;link href=&amp;quot;http://YOURSITE.com/syntaxhighlighter/shCore.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;link href=&amp;quot;http://YOURSITE.com/syntaxhighlighter/shThemeDefault.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Important options, and finally the main call --&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
 SyntaxHighlighter.config.tagName = &amp;quot;code&amp;quot; // use &amp;lt;code&amp;gt; tags&lt;br /&gt;
 SyntaxHighlighter.config.stripBrs = true&amp;#0160; // disregard trailing &amp;lt;br&amp;gt;&lt;br /&gt;
 SyntaxHighlighter.all()&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;The Options&lt;/h1&gt;
&lt;p&gt;As you can see, there are 2 options set at the end. These options are to make SyntaxHighlighter more compatible with the TypePad graphical editor. By default, SyntaxHighlighter looks for &lt;strong&gt;&amp;lt;pre&amp;gt;&lt;/strong&gt; tags. But these are rebuilt each time you modify an entry in the graphical editor. So one of the option is to be able to use &lt;strong&gt;&amp;lt;code&amp;gt;&lt;/strong&gt; tags, that are left untouched by TypePad. Well, almost untouched, TypePad tends to add &lt;strong&gt;&amp;lt;br&amp;gt;&lt;/strong&gt; tags at the end of line, which is why the seconde option is there.&lt;/p&gt;

&lt;h1&gt;Include your code snippet in TypePad&lt;/h1&gt;

&lt;p&gt;Now that everything is setup, all there is to do to have a nice code example into TypePad is to create a new Post, write the text using the &amp;quot;&lt;em&gt;Rich Text&lt;/em&gt;&amp;quot; view of the editor. Then when you want to include a code snippet, switch to the &amp;quot;&lt;em&gt;HTML&lt;/em&gt;&amp;quot; view, and add this :&lt;/p&gt;

&lt;p&gt;
&lt;code class=&quot;brush: xml&quot;&gt;
&amp;lt;code class=&amp;quot;brush: perl&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Your code example goes here. For instance, some Perl :&amp;lt;br&amp;gt;&lt;br /&gt;
my %hash = { foo =&amp;gt; &amp;#39;bar&amp;#39; };&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;Which will output on your blog page as :&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;brush: perl&quot;&gt;
# Your code example goes here. For instance, some Perl :&lt;br /&gt;
my %hash = { foo =&amp;gt; &amp;#39;bar&amp;#39; };&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;&lt;p&gt;

And inside the TypePad graphical editor, this is what you will see. Most of the Atom / RSS feeds client (like Google Reader) will also have it like this : &lt;/p&gt;&lt;p&gt;&amp;#0160;&lt;a href=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b01310fa1a77f970c-popup&quot; onclick=&quot;window.open( this.href, &amp;#39;_blank&amp;#39;, &amp;#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&amp;#39; ); return false&quot; style=&quot;display: inline;&quot;&gt;&lt;img alt=&quot;Image 11&quot; class=&quot;asset asset-image at-xid-6a0120a63366ed970b01310fa1a77f970c &quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b01310fa1a77f970c-320wi&quot; /&gt;&lt;/a&gt; &lt;br /&gt; &lt;/p&gt;&lt;p&gt;Which is in my opinion, not too bad !&lt;/p&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;p&gt;So here it is : a nice, free and open source syntax highlighter in your TypePad posts, easily included, wich themes, colors, a lot of languages supported, and which degrades nicely for feeds readers. There is more customization possible, I suggest you go look at the SyntaxHighlighter documentation.&lt;/p&gt;&lt;p&gt;I have tried to make this post / tutorial as easy as I possible, but please let me know if you think I should clear ups things, or add more screenshots. If you try to do it on your TypePad account and it works, let me know in the comment. If it doesn&amp;#39;t work, I&amp;#39;ll try to help.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Typepad</title>
   <link href="http://dams.github.com/2010/03/05/typepad.html"/>
   <updated>2010-03-05T00:00:00+00:00</updated>
   <id>http://dams.github.com/2010/03/05/typepad</id>
   <content type="html">&lt;p&gt;I&amp;#39;m in the metro of Paris, testing Typepad :&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;new beta account I just subscribed to&lt;/li&gt;
&lt;li&gt;new mobile version of the blog&lt;/li&gt;
&lt;li&gt;Iphone App&lt;/li&gt;
&lt;li&gt;automatic Twitter posting&lt;/li&gt;
&lt;li&gt;per category feeds&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typepad is Based on Movable Type, the best blog system ouuta there. It&amp;#39;s Perl based. It rocks. &lt;/p&gt;&lt;p&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Perl tests in Hudson via JUnit</title>
   <link href="http://dams.github.com/2009/11/25/perl-tests-in-hudson-via-junit.html"/>
   <updated>2009-11-25T00:00:00+00:00</updated>
   <id>http://dams.github.com/2009/11/25/perl-tests-in-hudson-via-junit</id>
   <content type="html">&lt;p&gt;&lt;/p&gt;&lt;h2&gt;Perl tests in Hudson&lt;/h2&gt;

&lt;p&gt;I&amp;#39;m willing to automate the unit testing of my Perl modules, by plugging them into &lt;a href=&quot;http://hudson-ci.org/&quot;&gt;Hudson&lt;/a&gt;. Hudson is a continuous integration server, it &amp;quot;&lt;em&gt;monitors executions of repeated jobs, such as building a software project or jobs run by cron&lt;/em&gt;&amp;quot;. It works well, is extensible, and looks good.&lt;/p&gt;

&lt;p&gt;So, The easiest way to do that is have Hudson to execute the module test suite, and look at the output. Actually, not really the output, but a file containing the output of the tests, in &lt;a href=&quot;http://www.junit.org/&quot;&gt;JUnit&lt;/a&gt; format.&lt;/p&gt;

&lt;p&gt;Now, by default, Perl unit tests doesn&amp;#39;t output JUnit. You know, that kind of stuff :&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/242615.js?file=gistfile1.txt&quot;&gt;&lt;/script&gt;

&lt;p&gt;That&amp;#39;s the standard output of tests run through TAP, the &lt;a href=&quot;http://testanything.org/wiki/index.php/Main_Page&quot;&gt;Test Anything Protocol&lt;/a&gt;, which is great, and (imho) better than JUnit.&lt;/p&gt;

&lt;p&gt;Anyway, that output is generated because the tests are run through &lt;a href=&quot;http://search.cpan.org/perldoc?TAP::Harness&quot;&gt;TAP::Harness&lt;/a&gt;, that outputs the result in TAP format on the console.&lt;/p&gt;

&lt;p&gt;So first of all, let&amp;#39;s see how to transform the tests output into JUnit. My modules use &lt;a href=&quot;http://search.cpan.org/perldoc?Module::Build&quot;&gt;Module::Build&lt;/a&gt; (and also &lt;a href=&quot;http://search.cpan.org/perldoc?Dist::Zilla&quot;&gt;Dist::Zilla&lt;/a&gt;, but that&amp;#39;s an other story) as building and releasing system. When using Module::Build, running the test suite is easy :&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/242619.js?file=gistfile1.txt&quot;&gt;&lt;/script&gt;

&lt;h2&gt;Solution 1 : use TAP::Formatter::JUnit&lt;/h2&gt;

&lt;p&gt;After some research and looking in the source code, I discovered that you can pass a lot of options to TAP::Harness, via Module::Build. Especially, you can specify a formatter to TAP::Harness when running the test suite. TAP formatters are modules that all inherit of TAP::Formatter::Base.&lt;/p&gt;

&lt;p&gt;For instance, if instead of outputing the result on the console, you want it to be stored in a file, use &lt;a href=&quot;http://search.cpan.org/perldoc?TAP::Formatter::File&quot;&gt;TAP::Formatter::File&lt;/a&gt;. As you may have guessed now, there is a formatter that outputs JUnit : &lt;a href=&quot;http://search.cpan.org/perldoc?TAP::Formatter::JUnit&quot;&gt;TAP::Formatter::Junit&lt;/a&gt;. That&amp;#39;s exactly what we want. By issuing the following command line, the output of the test suite is in JUnit format.&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/242627.js?file=gistfile1.sh&quot;&gt;&lt;/script&gt;&lt;p&gt;

 Now we just need to tell Hudson to run it and look at the output &lt;/p&gt;

&lt;h2&gt;Solution 2 : use TAP::Harness::JUnit&lt;/h2&gt;

&lt;p&gt;For some reasons, I had some trouble with TAP::Formatter::Junit on windows, mainly because there is no ActiveState PPM for this package. So I decided to give a go with &lt;a href=&quot;http://search.cpan.org/dist/TAP-Harness-JUnit/&quot;&gt;TAP::Harness::JUnit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its documentation is self-explanatory : it&amp;#39;s a child class of TAP::Harness, that accepts an xml file name as argument, and procudes directly a JUnit output. This module being directly available in ActiveState Perl, it seemed to be aa good approach.&lt;/p&gt;

&lt;p&gt;So the goal is to replace the call to TAP::Harness into TAP::Harness::JUnit, when doing Build test. And actually, it would be better to have an additional action to Build, so that we could do Build test, and Build hudson_test.&lt;/p&gt;

&lt;p&gt;Luckily, Module::Build makes it easy to add an action. By looking at the ACTION_test method in Module::Build::Base, it&amp;#39;s easy to see what needs to be changed. See this code snippet. What we want is a copy of that code that would run TAP::Harness::JUnit instead of TAP::Harness.&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/242842.js?file=gistfile1.pl&quot;&gt;&lt;/script&gt;

&lt;p&gt;After some work, here is what I eneded with. This code is to be added into your Build.PL.&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/242852.js?file=gistfile1.pl&quot;&gt;&lt;/script&gt;

&lt;p&gt;Now, build and run your tests in hudson mode&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/242855.js?file=gistfile1.txt&quot;&gt;&lt;/script&gt;

&lt;h2&gt;Configure Hudson&lt;/h2&gt;

&lt;p&gt;That&amp;#39;s the easiest part : Setup a new project, add as execution line &amp;quot;&lt;span style=&quot;font-family: Courier;&quot;&gt;perl Build.PL &amp;amp; Build hudson_test&lt;/span&gt;&amp;quot; (if you are on a windows hudson node). And point the project to the output file called &amp;quot;hudson_test_output.xml&amp;quot;. That&amp;#39;s it !&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b012875d92f9e970c-popup&quot; onclick=&quot;window.open( this.href, &amp;#39;_blank&amp;#39;, &amp;#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&amp;#39; ); return false&quot; style=&quot;display: inline;&quot;&gt;&lt;img alt=&quot;Image 57&quot; class=&quot;asset asset-image at-xid-6a0120a63366ed970b012875d92f9e970c &quot; src=&quot;http://damien.krotkine.com/.a/6a0120a63366ed970b012875d92f9e970c-320wi&quot; /&gt;&lt;/a&gt; &lt;br /&gt; &lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Curses Toolkit is on CPAN</title>
   <link href="http://dams.github.com/2009/10/31/curses-toolkit-is-on-cpan.html"/>
   <updated>2009-10-31T00:00:00+00:00</updated>
   <id>http://dams.github.com/2009/10/31/curses-toolkit-is-on-cpan</id>
   <content type="html">&lt;p&gt;After few months of delay, &lt;a href=&quot;http://search.cpan.org/perldoc?Curses::Toolkit&quot; title=&quot;Curses::Toolkit on CPAN&quot;&gt;Curses::Toolkit is now available on CPAN&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Curses::Toolkit tries to be a modern toolkit to implement semi-graphical interfaces using Curses. It&amp;#39;s inspired by Gtk.&lt;/p&gt;&lt;p&gt;I gave a presentation of Curses::Toolkit at the &lt;a href=&quot;http://conferences.mongueurs.net/fpw2009/&quot; title=&quot;FPW&amp;#39;09&quot;&gt;French Perl Workshop 2009&lt;/a&gt;, and at the &lt;a href=&quot;http://act.osdc.fr/osdc2009fr/&quot;&gt;Open Source Developers conference France 2009&lt;/a&gt;. BooK presented it as part of a Lightning Talk at &lt;a href=&quot;http://yapceurope2009.org/ye2009/&quot; title=&quot;YAPC::EU 2009&quot;&gt;YAPC EU 2009&lt;/a&gt; where I couldn&amp;#39;t participate. Thanks to him for that. I will try to participate to &lt;a href=&quot;http://conferences.yapceurope.org/lpw2009/&quot; title=&quot;LPW 09&quot;&gt;London Perl Workshop&lt;/a&gt; this year and give a talk about it as well. I have received quite good feedback from people and users about it.&lt;/p&gt;&lt;p&gt;I&amp;#39;d like to mention that &lt;a href=&quot;http://jquelin.blogspot.com/&quot; title=&quot;Jerome Quelin&quot;&gt;Jerome Quelin&lt;/a&gt; helped me with the initial release, injecting some Dist::Zilla magic into Curses::Toolkit. Thanks, Jerome.&lt;/p&gt;&lt;p&gt;What next ? I&amp;#39;ll try to post a video of what is currently possible with Curses::Toolkit. I need to add more widgets and signals, and fix some bugs. Also, migrating to Moose is on the todo list. The module is usable now, but you can&amp;#39;t really build a very nice big application with it.&lt;/p&gt;&lt;p&gt;Want to help ? If you have some free time, please consider helping me on next development of the module. You don&amp;#39;t need to be a coder, here are some of the things you could help with :&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Improve documentation : current documentation has some errors, and a better front page for the module would be good.&lt;/li&gt;
&lt;li&gt;Create a Tutorial : preferably in POD, but not tied to follow sub-modules&amp;#39; names&lt;/li&gt;
&lt;li&gt;Help implementing additional widgets&lt;/li&gt;
&lt;li&gt;Create new themes : it&amp;#39;s all about colors&lt;/li&gt;
&lt;li&gt;Help the migration to Moose&lt;/li&gt;
&lt;/ul&gt;
If you&amp;#39;re interested, contact me. The source is &lt;a href=&quot;http://github.com/dams/curses-toolkit&quot; title=&quot;Curses::Toolkit on github&quot;&gt;here&lt;/a&gt;

</content>
 </entry>
 
 <entry>
   <title>New Home</title>
   <link href="http://dams.github.com/2009/10/29/new-home.html"/>
   <updated>2009-10-29T00:00:00+00:00</updated>
   <id>http://dams.github.com/2009/10/29/new-home</id>
   <content type="html">&lt;p&gt;The new server I had setup few weeks ago got hacked, brute force ssh attacks being made from it... I had spent some time setting it up, and now I&amp;#39;m bored.&lt;/p&gt;&lt;p&gt;So, I decided to migrate my blog to a hosted solution. As I&amp;#39;m a big fan of &lt;a href=&quot;http://www.movabletype.org/&quot;&gt;movable type&lt;/a&gt;, I decided to give Typepad a go. So this is yet another rebirth of my blog (I think it&amp;#39;s the 6th time now).&lt;/p&gt;&lt;p&gt;I&amp;#39;ll use that opportunity to catch up with the Perl blogging &lt;a href=&quot;http://www.typepad.com/site/blogs/6a0120a63366ed970b0120a689fba3970c/post/compose&quot;&gt;Iron Man&lt;/a&gt; competition.&lt;/p&gt;&lt;p&gt;More to come about Perl and &lt;a href=&quot;http://search.cpan.org/perldoc?Curses::Toolkit&quot;&gt;Curses::Toolkit&lt;/a&gt;, my baby :)&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

</content>
 </entry>
 
 
</feed>
