Showing posts with label cpan. Show all posts
Showing posts with label cpan. Show all posts

May 3, 2015

Abandoning all Perl modules

As of today I have decided to remove myself as maintainer/comaintainer of all my Perl modules. Feel free to adopt them.

Nov 7, 2012

Business::CyberSource API is stabilizing as of 0.7.x

Business::CyberSource (BC) has been going through API changes for a while now. If you're using it you've probably noticed this and wondered why? The reason behind it was when I first made it I wanted it to be extremely simple to use, and I was realistically a Junior programmer. Over the past year I learned a lot about API design and Object Oriented Programming, as well as payment gateways and credit card transaction processing. From the first production ready release I knew that it had design problems due to a large quantity of duplicated code, but at the time I didn't know how to get rid of it.

Domain Driven Design

My first refactor used some principles I learned from Domain-Driven Design: Tackling Complexity in the Heart of Software I changed the design of the objects to be more clear for experts in CyberSource. I also started restructuring them to more closely match the remote model. This meant making Requests and Responses to be made up of nested objects (Responses were only done as of 0.7.x). Another Change regarding this was to rename the submit method to run_transaction which is the name of the Remote Procedure call that is executed.

Composite Design Pattern

By making the Requests up of nested objects it allowed me to use the Composite Pattern from Design Patterns: Elements of Reusable Object-Oriented Software to serialize all of the objects into a simple nested hashref that XML::Compile::SOAP expects. Moving to these smaller objects that could serialize allowed me to also add more offline tests.

Dependency Injection in Tests

Most of the tests for BC start out exactly the same, except for one change, the value in the amount part of the Credit Card Authorization. This is because CyberSource's Test API uses special amounts to allow you to test getting different responses. e.g. something like (I'd have to look it up) 5000.05 is maybe a REJECT with a special processor code and cv code. Because of this I wired up my tests using Bread::Board to reduce the amount of boilerplate code in all tests that require actual remote interaction.

The Impact

Ultimately changing my Remote Facade to make use of more design patterns and be designed after it's niche domain has allowed me to have both simpler, deduplicated, more robust, more correct, and easier to modify code. Some things were not possible in earlier versions, or would have been incredibly complex to add. Now it'll simply be an issue of adding a Moose attribute to add a feature present in the WSDL. Before certain calls could not return all of information that was in the actual SOAP response, now everything should be accessible.

Possible Bugs

One of the possible bugs of this last refactor is that I use MooseX::StrictConstructor for all of my Moose objects. It is possible now that the XML::Compile::SOAP hash is simply passed to the Response Object that if a key I didn't account for were present that an exception would be thrown. If this is thrown on anything other than a 102 Invalid Field response, then it is a bug in BC and should be reported. I could have turned StrictConstructor off on the responses, but I believe that throwing the exceptions may ultimately make BC a better library. Also with a test suite that totals over 1400 (including generated generic ) tests, I'm fairly confident that there will be no problems in production.

New Debugging

In order to aid in finding bugs and diagnosing problems when they happen cybersource now has 2 debug setting levels. These can be set by having debug be 0 (off), 1 (request/response hash), 2 (full soap payloads). These should not be turned on in production and because they will print out Credit Card numbers.

In Trial

Currently I've left BC v0.7.5 in trial, but barring any bugs being reported, or cpan testers tests failing, I'll probably release v.0.7.6 as stable early early next week.

Stable API

I do not forsee any more major API changes in the future of BC, all of my original problems have been weeded out. This means I'll be able to focus on features and documentation with future work. It is possible that some changes to exceptions and error handling may happen, but I don't see that being a big issue.

Jun 27, 2010

Announcing Dist::Zilla::Plugin::Catalyst

So I just recently finished reading Restful Web Services and decided I wanted to go back and play with Catalyst and REST some.

The original way to create a Catalyst skeleton is to run catalyst.pl MyApp. This creates a lot of nice files to get you started. dzil new basically does the same thing for a generic cpan module. Honestly, without any plugins dzil new isn't that useful. However, once you add Git::Init , you remove several steps from the creation of a new module and repository. Git::Init also makes your first commit of everything it added. I got to thinking why on earth would I want to do the following to get a cat module going and convert it to dzil.

catalyst.pl MyApp && cd MyApp
vi dist.ini # and add numerous lines
rm Makefile.PL README t/* # and maybe more since dzil is better at managing these
git init
git add .
git commit


when I could just be doing this

dzil new -p catalyst MyApp


A lot simpler huh? to get you started you need a few things but then creating cat apps will be easy.

first you can run dzil setup or if your version of dzil doesn't support that yet, you need to create the following ~/.dzil/config.ini file by hand obviously fill in your own credentials and license preferences. This file is pretty much needed for any dzil new operations.

Next you need to create a minting profile (not necessary for barebones doesn't do much for you). run mkdir -p ~/.dzil/profiles/catalyst/ (note: catalyst is arbitrary, it can be anything). now create a profile.ini in that directory. The only mandatory line in this file for this to work is the [Catalyst ...] one, I think you'll want the other two however. You also want to set AUTHOR="your name youremail@example.com since that's how Catalyst::Helper inserts it into its files (I'll probably work on fixing helper later).

Now you can just run dzil new -p catalyst MyApp. Hopefully, this simplifies your catalyst app creation a little bit.

Good patches are welcome, so are feature suggestions and bug reports. Also I registered it as Dist::Zilla::Plugin::Catalyst So if there are any other plugins that you think could be useful that are specific to Catalyst I'd be willing to add them.

Special thanks to Tomas Doran who helped me (ok... he wrote most of it) create this module.

Jun 26, 2010

Solving code generation problems in dzil

Firstly I want to clarify a bit on my opinions of PluginBundle::USERNAME modules, as some comments there have inspired this post. I don't think you should use them because it makes it harder to disable plugins, and I think Robin Smidsrød put it best:
Mostly it is because the Dist::Zilla::PluginBundle::USERNAME doesn't actually say anything about its intention. It only says use Dist::Zilla as this person does, but what does that actually mean? If you don't know the person it doesn't really tell you anything.

I'd much more prefer PluginBundles that actually advocate certain types of standards or behaviors.
...

Essentially Bundle's like @Git and @Basic don't cause problems because they're generic well defined and contained within their distributions. A bundle that wasn't contained within its dist might not cause a problem if it's for a generic well defined purpose. I'd be in favor of a BundleQATests or similar so long as the author was considerate that some tests (PodSpellingTests) don't work well on some *nix distributions and isn't included in the bundle. But Something like @Xeno (my cpan username) would be my own special settings... who wants to use something that's only for me? and more importantly why would they ever think they have a right to bug something that the name itself implies it's only for me.

But another problem was brought up... code generation. Here's what Nilson said:
dzil is very nice, but I don't if I like the idea of different line numbers and files in the repository vs. the CPAN release. I'm still trying to fully digest this idea.

I remember one of the main mentioned drawbacks of source filters were the possibilities of error messages in the wrong lines. And now, everyone seems to embrace this without hesitation.

So to start dzil's generation isn't quite as bad as a source filter which will give you the wrong line number period, using this generation will still give you the right line number for the module being run at the time. It just means the cpan line number may not match the repo line number. I'm going to show you how to fix this, but you don't always have to. The most common place I've found problems with in code generation has been tests created by extending InlineFiles. In these cases you just want to go and bug the author of the Plugin. I think using these plugins is much better than writing your own EOL Tests, NoTabs, Critic, and Kwalitee etc. It helps keep your dist quality up without extra work, ultimately leaving you with just the responsibility of writing good tests that are specific to just your distribution.

Now on to making sure that your repository matches your cpan dist. The first thing you want to do is use [Git::CommitBuild] (if you're not using git look for something like it or write something like it) This will take all the generated output and commit it to another branch each time you build. Then make sure this branch is pushed to your public repository. I think the biggest problem this solves is having things like your README and your LICENSE actually be in your public repository (if your repo doesn't have a LICENSE... what's the legal situation?). If you're using github you can also change this to be the default branch to be displayed in the repo admin settings.

Next thing is don't use ::Plugin::Prepender This will evil-y insert lines at the beginning of your code which will definitely throw off the line numbers being output. It even seems to suggest using it to insert use strict; use warnings;. If you need output prepended to all files, I suggest writing a plugin that takes advantage of dzil new and maybe just write a script that you can fire off whenever you need to create a new file. This is the only module I know for sure that does this, but avoid ANY that insert actual code or prepend lines to your files (in a way that isn't added to your actual 'master'/'trunk' that should be patched).

POD can also screw up your line numbers, if you're using PodWeaver (or module that has similar side effects) with dzil, which you likely are. Perl Best Practices page 140 will save you here (actual quote pg 475 a summary chapter).
  • Keep all user documentation in a single place within your source file. [Contiguity]
  • Place POD as close as possible to the end of the file. [Position]
This includes the # ABSTRACT: my abstract here line. If you put the # ABSTRACT and any actual pod after the code then all the pod generated will be after the code in your build, and thus any line number errors will be correct. Of course this doesn't save you if your error is in the output pod, but I suspect that's not the original complaint anyhow, and there are lots of dzil plugins to help you keep your pod sane.

Essentially don't do anything that will change line numbers for the code in the resulting build output. Following this will ease contribution, and debugging; I do not believe it significantly increases maintainer load. Happy Hacking!

UPDATE:
just remembered... dzil inserts a BEGIN block... sigh... can't win for nothing.

UPDATE:
I recommend using Dist::Zilla::Plugin::OurPkgVersion to avoid dzil's BEGIN block / VERSION insertion.

Jun 19, 2010

please don't use Dist::Zilla::PluginBundle::USERNAME

or create them. Here's the problem.... (short version is Don't put PodSpellingTests in them)
normally you'd have
[pluginA]
[pluginB]
[pluginC]
[pluginXTests]
[pluginYTests]
[pluginZTests]


and one of them doesn't work on your system (for whatever reason), well you can just do this.
[pluginA]
[pluginB]
[pluginC]
;[pluginXTests]
[pluginYTests]
[pluginZTests]


the ; is a comment in ini, now dzil won't use that plugin. But people will say well you don't want to do that of course I want that plugin enabled. Here's why you may not temporarily. Casual user X has a bug in /your/ module that's using dzil, they code up a patch, and they want to run your test suite. The can't, because [pluginXTests] won't even install properly on their system due to a non perl dependency. They could have just commented it out, but now because you've used this PluginBundle it become difficult. They can't just comment it out.

They might be able to
[@Filter]
-bundle = @USERNAME
-remove = pluginXTests

IF they can get your bundle installed in the first place. This requires them find a way to install your Bundle without installing said broken module.

as I stated at the top my problem is with [PodSpellingTests] it itself isn't broken, but it's dependency Test::Spelling is on some systems, due to the lack of a 'spell' command.

Yes I know there's a workaround... I could just copy a shell script into my path that makes aspell or something work, but really that's not the right solution. No I'm not packaging GNU Spell for my system either, the other spell programs work much better (from what I've read).

Also I find modules with your own username in them to be fairly obnoxious.

If you'd like less code, can't we start making a few more generic Bundle's? I wouldn't minde seeing a Bundle for Tests, and maybe another one for other stuff. I think 1/3 of the lines in my dist.ini's are tests.

May 10, 2010

GPL 3 and Artistic 2.0 Software::License

As of right now Software::License has no way to combine licenses on the fly. To be honest this deficiency might not be a bug in SL, it could be in Pod::Weaver or Dist::Zilla this is a know deficiency and RJBS plans on fixing it at some point. In the mean time we can implement dual licenses (and multi-licenses) in much the same way the Perl5 license is implemented.

I was probably in legal violation (I am not a lawyer) with Template::ShowStartStop version 0.05 and 0.06 because I used Perl_5 licensing because that's the closest I could get with Dist::Zilla, due to the limitation. So I created Software::License::GPL3andArtistic2 which is sort of a perl5 license, except that it mandates the latest version of GPL and Artistic (at the time of this writing). Version 0.07 of Template::ShowStartStop is back in compliance with the licensing of the code I forked from Template::Timer.

This hasn't, and will probably not be merged into Software::License because it's just a stopgap measure until multi-license support can be implemented.

UPDATE:
this is apparently not necessary according to Duncan and the this interview I've updated the module to reflect this. Hopefully, it can serve as an educational source.

Curious... why doesn't Perl5 switch to the Artistic 2.0 then... (I wonder what that would mean for 'under the same terms as perl5' but actually including gpl1 and artistic 1).

Mar 14, 2010

Managing CPAN on Arch Linux

So if you're running Arch Linux and want to install a bunch of packages from CPAN the best way is NOT to use the official cpan client, or even the new cpanminus. No your best bet is to use AUR or lacking AUR packages, create your own, and I'm gonna walk you through how I do it. The really nice thing about installing packages with Pacman is that unlike cpan there is a utility to uninstall them.

The first thing you'll want is a utility that allows you to easily manage aur. Right now the Recommended tool appears to be a CLI utility called packer you'll want to download the PKGBUILD, on the packer page, to a directory of it's own and run makepkg -s in that directory and then (as root) pacman -U pkgname-pkgver.pkg.tar.gz. You've now installed Packer, which means you'll never have to install an AUR package like that again (barring a new install of arch). If you really want you can stop now and just use the packages provided by arch, myself, and other aur contributors. The general conversion in name is is the CPAN module DBIx::Class becomes perl-dbix-class. However running packer dbix-class will find it. packer is capable of searching all of aur and the official repositories and giving you options if more than one is available. If you want to learn how to make your own packages, or just plain ignore aur and use cpanp to install read on.

So now you'll want to install CPANPLUS with packer. This is easy just run packer perl-cpanplus. This should install CPANPLUS and any of its deps. Now install CPANPLUS::Dist::Arch
with packer perl-cpanplus-dist-arch. There are other 'cpan' options but this is the only one that's on both CPAN and AUR, and it has some really nice functionality.

Now you have your entire installer stack but you still need to configure C::D::A. Run setupdistarch. This will configure cpanplus to automatically create any package it creates as an Arch pkg, it can even install them. For example packer perl-moose and cpanp -i Moose will both install Moose with Pacman. The first will use the package I've uploaded to AUR and the second will use C::D::A to create one (which is exactly what I did).

So now you know the basics of Installing packages, but I'm guessing you still want to know, how I'm managing over 200 perl packages. C::D::A is actually making this easier all the time (esp since I talk to the author). first you'll want to create a directory to store all your AUR packages, the name isn't important. So you'll want to create your first package like cpan2aur -d Catalyst::Runtime you'll note that this creates the directory perl-catalyst-runtime in that directory there is a PKGBUILD.tt it contains syntax similar to Template::Toolkit, it is however home grown by the author of C::D::A. you can use it to add stuff the the resulting PKGBUILD. To create the PKGBUILD you'll run cpan2aur perl-catalyst-runtime it will create the PKGBUILD and the tarball for AUR. However, if you're really planning on making this for AUR and no package is on AUR or you own the one on AUR you can just run cpan2aur -u perl-catalyst-runtime and it will create all the aforementioned things plus upload them with your AUR account. It's worth noting that if you attempt to run cpan2aur and a PKGBUILD already exists it will ask you if you wish to overwrite, unless you've made changes to it say yes, if you aren't updating to a new version on cpan it will ask if you want to update the pkgrel. I specifically requested that because it was annoying to increment by hand and I needed to update the PKGBUILD because of things like dep or provides changes.

Unfortunately cpan2aur cannnot generate an entire dep tree worth of directories. It's worth saying that you don't really have to run cpan2aur -d at all, you could just go right to cpan2aur -u, but then you'd miss out on the wonder that is cpan2aur --check. You can run cpan2aur --check perl-* and it will automagically check for updates of any directory that starts with perl- and upload the updates to AUR.

Unfortunately C::D::A has some limitations. The first is that it really Doesn't use Template Toolkit or even Template::Tiny (which I suggested). This doesn't seem to matter to much... but I wonder if it could help me with the other problem. C::D::A can't correctly determine optdepends because it gets the deps from the generated Makefiles. I'm not sure if this could be fixed or not, I don't yet understand this part of making CPAN packages enough.

Happy packaging.

UPDATE:

you don't need cpan2aur -u --check, cpan2aur --check implies -u

Mar 13, 2010

Iron Man and introductions

So I've decided to "compete" in the Iron Man competition.

My name is Caleb Cushing, I'm a 25 year old, unemployed, student, living in the Greater Lansing, MI, USA, area. I've been programming perl for approximately 6 months. This includes a lot of off time, time to relearn the language from the class I took a couple years ago (and learn modern perl), learning Catalyst and DBIC, all of which is an ongoing process. I would guess I've been writing useful code for about 4 months and even that is a slow going process as I've still got a lot to learn.

Previously, I was the tree maintainer for Funtoo, and tried spinning my own fork of Funtoo/Gentoo, it needed more devs than me to survive though. I now use Arch Linux. After an arch/perl user who went by aCiD2 moved to OS X I adopted most of his perl AUR (arch user repository) packages in addition to ones I had created myself. I now have over 200 CPAN packages on AUR in Arch's PKGBUILD format.

I'm a contributer to Catalyst::Manual and I created Template::ShowStartStop by forking Template::Timer.

I'm sure I'll become more active as time goes on, and have more interesting posts than this one.