CONTENUS

  • NOM
  • INTRODUCTION
  • LISTE DE CONTRÔLE RAPIDE
    • Avant de commencer
    • L'API
    • Stabilité
    • Documentation
    • Considérations sur la version
  • AVANT DE COMMENCER À ÉCRIRE UN MODULE
    • Cela a-t-il déjà été fait auparavant ?
    • Faites une seule chose et faites-la bien
    • Qu'y a-t-il dans un nom ?
    • Obtenez des commentaires avant de publier
  • CONCEVOIR ET ÉCRIRE VOTRE MODULE
    • OO ou pas OO ?
    • Concevoir votre API
    • Stricteté et avertissements
    • Rétrocompatibilité
    • Traitement des erreurs et messages
  • DOCUMENTER VOTRE MODULE
    • POD
    • README, INSTALL, notes de version, changelogs
  • CONSIDÉRATIONS SUR LA VERSION
    • Numérotation des versions
    • Pré-requis
    • Tests
    • Emballage
    • Licences
  • PIÈGES COMMUNS
    • Réinventer la roue
    • Essayer d'en faire trop
    • Documentation inappropriée
  • VOIR AUSSI
  • AUTEUR

NOM

perlmodstyle - Guide de style des modules Perl

INTRODUCTION

Ce document tente de décrire les "meilleures pratiques" de la communauté Perl pour l'écriture de modules Perl. Il étend les recommandations trouvées dans perlstyle , qui devrait être considéré comme une lecture obligatoire avant de lire ce document.

Bien que ce document soit destiné à être utile à tous les auteurs de modules, il est particulièrement destiné aux auteurs qui souhaitent publier leurs modules sur CPAN.

L'accent est mis sur les éléments de style qui sont visibles par les utilisateurs d'un module, plutôt que sur les parties qui ne sont vues que par les développeurs du module. Cependant, beaucoup des directives présentées dans ce document peuvent être extrapolées et appliquées avec succès aux internes d'un module.

Ce document diffère de perlnewmod en ce qu'il est un guide de style plutôt qu'un tutoriel sur la création de modules CPAN. Il fournit une liste de contrôle à laquelle les modules peuvent être comparés pour déterminer s'ils sont conformes aux meilleures pratiques, sans nécessairement décrire en détail comment y parvenir.

Tous les conseils contenus dans ce document ont été glanés lors de conversations approfondies avec des auteurs et des utilisateurs expérimentés de CPAN. Chaque conseil donné ici est le résultat d'erreurs antérieures. Ces informations sont là pour vous aider à éviter les mêmes erreurs et le travail supplémentaire qui serait inévitablement nécessaire pour les corriger.

La première section de ce document présente une liste de contrôle détaillée ; les sections suivantes traitent plus en détail des éléments de la liste. La dernière section, "Pièges courants", décrit certaines des erreurs les plus populaires commises par les auteurs de CPAN.

LISTE DE CONTRÔLE RAPIDE

Pour plus de détails sur chaque élément de cette liste de contrôle, voir ci-dessous.

Avant de commencer

  • Ne réinventez pas la roue

  • Patch, extension ou sous-classe d'un module existant lorsque cela est possible.

  • Faites une seule chose et faites-la bien

  • Choisissez un nom approprié

  • Obtenez des commentaires avant de publier

L'API

  • L'API doit être compréhensible par le programmeur moyen.

  • Des méthodes simples pour des tâches simples

  • Séparer la fonctionnalité de la sortie

  • Nommage cohérent des sous-routines ou des méthodes.

  • Utiliser des paramètres nommés (un hachage ou un hashref) lorsqu'il y a plus de deux paramètres.

Stabilité

  • Assurez-vous que votre module fonctionne sous use strict et -w

  • Les modules stables doivent maintenir la compatibilité ascendante

Documentation

  • Ecrire la documentation en POD

  • Documenter l'objet, le champ d'application et les applications cibles

  • Documenter chaque méthode ou sous-routine accessible au public, y compris les paramètres et les valeurs de retour.

  • Donnez des exemples d'utilisation dans votre documentation

  • Fournissez un fichier README et peut-être aussi des notes de version, un changelog, etc.

  • Fournissez des liens vers des informations complémentaires (URL, email).

Considérations sur la version

  • Spécifier les pré-requis dans Makefile.PL ou Build.PL.

  • Spécifiez les exigences de la version de Perl avec use

  • Inclure des tests avec votre module

  • Choisissez un schéma de numérotation des versions judicieux et cohérent (X.YY est le schéma commun de numérotation des modules Perl).

  • Incrémentez le numéro de version pour chaque changement, aussi petit soit-il.

  • Empaquetez le module en utilisant "make dist"

  • Choisissez une licence appropriée (GPL/Artistic est un bon défaut).

AVANT DE COMMENCER À ÉCRIRE UN MODULE

Essayez de ne pas vous lancer tête baissée dans le développement de votre module sans passer un peu de temps à réfléchir avant. Un peu de prévoyance peut vous épargner une grande quantité d'efforts par la suite.

Est-ce que cela a déjà été fait auparavant ?

Il se peut que vous n'ayez même pas besoin d'écrire le module. Vérifiez si cela a déjà été fait en Perl, et évitez de réinventer la roue, sauf si vous avez une bonne raison.

Les bons endroits pour rechercher des modules préexistants comprennent . MetaCPAN et PrePAN et demandant sur [email protected] (https://lists.perl.org/list/module-authors.html).

Si un module existant presque fait ce que vous voulez, envisagez d'écrire un patch, d'écrire une sous-classe, ou d'étendre autrement le module existant plutôt que de le réécrire.

Faites une seule chose et faites-la bien

Au risque d'énoncer une évidence, les modules sont destinés à être modulaires. Un développeur Perl devrait être en mesure d'utiliser des modules pour assembler les blocs de construction de son application. Cependant, il est important que les blocs soient de la bonne forme, et que le développeur n'ait pas à utiliser un gros bloc quand tout ce dont il a besoin est un petit.

Votre module doit avoir une portée clairement définie qui n'est pas plus longue qu'une seule phrase. Votre module peut-il être décomposé en une famille de modules connexes ?

Mauvais exemple :

"FooBar.pm fournit une implémentation du protocole FOO et de la norme BAR associée."

Bon exemple :

"Foo.pm fournit une mise en œuvre du protocole FOO. Bar.pm implémente le protocole BAR associé."

Cela signifie que si un développeur n'a besoin que d'un module pour la norme BAR, il ne devrait pas être obligé d'installer également des bibliothèques pour FOO.

Qu'y a-t-il dans un nom ?

Assurez-vous de choisir un nom approprié pour votre module dès le début. Cela aidera les gens à trouver et à se souvenir de votre module, et rendra la programmation avec votre module plus intuitive.

Lorsque vous nommez votre module, tenez compte des éléments suivants :

  • Soyez descriptif (c'est-à-dire qu'il décrit avec précision l'objectif du module).

  • Soyez cohérent avec les modules existants.

  • Refléter la fonctionnalité du module, et non son implémentation.

  • Évitez de commencer une nouvelle hiérarchie de haut niveau, surtout s'il existe déjà une hiérarchie appropriée sous laquelle vous pourriez placer votre module.

Obtenez des commentaires avant de publier.

Si vous n'avez jamais téléchargé un module sur CPAN (et même si vous l'avez fait), vous êtes fortement encouragé à obtenir un retour d'information sur... PréPAN. PrePAN est un site dédié à la discussion d'idées de modules CPAN avec d'autres développeurs Perl et constitue une excellente ressource pour les nouveaux développeurs Perl (et les plus expérimentés).

Vous devriez également essayer d'obtenir des commentaires de personnes qui sont déjà familières avec le domaine d'application du module et le système de nommage CPAN. Les auteurs de modules similaires, ou de modules avec des noms similaires, peuvent être un bon point de départ, tout comme les sites communautaires comme . Perl Monks.

CONCEVOIR ET ÉCRIRE VOTRE MODULE

Considérations pour la conception et le codage des modules :

To OO or not to OO ?

Votre module peut être orienté objet (OO) ou non, ou il peut avoir les deux types d'interfaces disponibles. Il y a des avantages et des inconvénients de chaque technique, qui doivent être pris en compte lorsque vous concevez votre API.

Dans Meilleures pratiques en Perl (copyright 2004, publié par O'Reilly Media, Inc.), Damian Conway fournit une liste de critères à utiliser pour décider si l'OO est la bonne solution à votre problème :

  • Le système à concevoir est de grande taille, ou est susceptible de le devenir.

  • Les données peuvent être agrégées dans des structures évidentes, surtout s'il y a une grande quantité de données dans chaque agrégat.

  • Les différents types d'agrégats de données forment une hiérarchie naturelle qui facilite l'utilisation de l'héritage et du polymorphisme.

  • Vous avez une donnée sur laquelle de nombreuses opérations différentes sont appliquées.

  • Vous devez effectuer les mêmes opérations générales sur des types de données apparentés, mais avec de légères variations en fonction du type spécifique de données auquel les opérations sont appliquées.

  • Il est probable que vous devrez ajouter de nouveaux types de données plus tard.

  • Les interactions typiques entre les pièces de données sont mieux représentées par des opérateurs.

  • L'implémentation des différents composants du système est susceptible de changer au fil du temps.

  • La conception du système est déjà orientée objet.

  • Un grand nombre d'autres programmeurs utiliseront vos modules de code.

Réfléchissez bien pour savoir si l'OO est appropriée pour votre module. L'orientation objet gratuite donne lieu à des API complexes qui sont difficiles à comprendre ou à utiliser pour l'utilisateur moyen du module.

Conception de votre API

Vos interfaces doivent être compréhensibles par un programmeur Perl moyen. Les directives suivantes peuvent vous aider à juger si votre API est suffisamment simple :

Ecrivez des routines simples pour faire des choses simples.

Il est préférable d'avoir de nombreuses routines simples que quelques routines monolithiques. Si votre routine change son comportement de manière significative en fonction de ses arguments, c'est un signe que vous devriez avoir deux (ou plus) routines séparées.

Séparer la fonctionnalité de la sortie.

Renvoyez vos résultats sous la forme la plus générique possible et laissez l'utilisateur choisir comment les utiliser. La forme la plus générique possible est généralement une structure de données Perl qui peut ensuite être utilisée pour générer un rapport textuel, HTML, XML, une requête de base de données ou tout ce dont vos utilisateurs ont besoin.

Si votre routine itère à travers une sorte de liste (comme une liste de fichiers, ou des enregistrements dans une base de données), vous pouvez envisager de fournir un callback afin que les utilisateurs puissent manipuler chaque élément de la liste à tour de rôle. File::Find fournit un exemple de cela avec sa fonction find(&wanted, $dir) syntaxe.

Fournissez des raccourcis et des valeurs par défaut judicieux.

N'obligez pas chaque utilisateur de module à sauter par les mêmes cerceaux pour obtenir un résultat simple. Vous pouvez toujours inclure des paramètres optionnels ou des routines pour un comportement plus complexe ou non standard. Si la plupart de vos utilisateurs doivent taper quelques lignes de code presque identiques lorsqu'ils commencent à utiliser votre module, c'est un signe que vous auriez dû faire de ce comportement un défaut. Un autre bon indicateur que vous devriez utiliser des valeurs par défaut est si la plupart de vos utilisateurs appellent vos routines avec les mêmes arguments.

Conventions de nommage

Votre nommage devrait être cohérent. Par exemple, il est préférable d'avoir :

display_day();
display_week();
display_year();

que

display_day();
week_display();
show_year();

Cela s'applique également aux noms de méthodes, aux noms de paramètres et à tout ce qui est visible par l'utilisateur (et à la plupart des choses qui ne le sont pas !).

Passage de paramètres

Utilisez des paramètres nommés. Il est plus facile d'utiliser un hachage comme ceci :

$obj->do_something(
        name =>"wibble",
        type =>"text",
        size =>1024,);

... que d'avoir une longue liste de paramètres non nommés comme ceci :

$obj->do_something("wibble","text",1024);

Alors que la liste des arguments peut fonctionner correctement pour un, deux ou même trois arguments, tout argument supplémentaire devient difficile à mémoriser pour l'utilisateur du module, et difficile à gérer pour l'auteur du module. Si vous voulez ajouter un nouveau paramètre, vous devrez l'ajouter à la fin de la liste pour la compatibilité rétroactive, et cela rendra probablement votre ordre de liste peu intuitif. En outre, si de nombreux éléments peuvent être indéfinis, vous pouvez voir les appels de méthode peu attrayants suivants :

$obj->do_something(undef,undef,undef,undef,undef,1024);

Fournissez des valeurs par défaut raisonnables pour les paramètres qui en ont. N'obligez pas vos utilisateurs à spécifier des paramètres qui seront presque toujours les mêmes.

La question de savoir s'il faut passer les arguments dans un hash ou un hashref est largement une question de style personnel.

L'utilisation de clés de hachage commençant par un trait d'union (-name) ou entièrement en majuscules (NAME) est une relique d'anciennes versions de Perl dans lesquelles les chaînes ordinaires en minuscules n'étaient pas traitées correctement par la commande => . Alors que certains modules conservent des clés d'arguments en majuscules ou avec un trait d'union pour des raisons historiques ou par style personnel, la plupart des nouveaux modules devraient utiliser des clés simples en minuscules. Quel que soit votre choix, soyez cohérent !

Stricteté et avertissements

Votre module devrait s'exécuter avec succès sous le pragme strict et devrait s'exécuter sans générer d'avertissements. Votre module devrait également gérer le taint-checking lorsque cela est approprié, bien que cela puisse causer des difficultés dans de nombreux cas.

Compatibilité ascendante

Les modules qui sont "stables" ne devraient pas rompre la compatibilité ascendante sans au moins une longue phase de transition et un changement majeur de numéro de version.

Gestion des erreurs et messages

Lorsque votre module rencontre une erreur, il devrait faire une ou plusieurs des choses suivantes :

  • Renvoyer une valeur non définie.

  • définir $Module::errstr ou similaire (errstr est un nom commun utilisé par DBI et d'autres modules populaires ; si vous choisissez autre chose, veillez à le documenter clairement).

  • warn() ou carp() un message vers STDERR.

  • croak() uniquement lorsque votre module ne sait absolument pas quoi faire. (croak() est une meilleure version de die() pour une utilisation au sein des modules, qui rapporte ses erreurs du point de vue de l'appelant. Voir Carp pour les détails de croak(), carp() et d'autres routines utiles).

  • Comme alternative à ce qui précède, vous pouvez préférer lancer des exceptions en utilisant le module Error.

La gestion configurable des erreurs peut être très utile pour vos utilisateurs. Envisagez d'offrir un choix de niveaux pour les messages d'avertissement et de débogage, une option pour envoyer les messages dans un fichier séparé, un moyen de spécifier une routine de gestion des erreurs, ou d'autres fonctionnalités de ce type. Assurez-vous de proposer par défaut toutes ces options pour l'utilisation la plus courante.

DOCUMENTER VOTRE MODULE

POD

Votre module doit inclure une documentation destinée aux développeurs Perl. Vous devriez utiliser la "plain old documentation" (POD) de Perl pour votre documentation technique générale, bien que vous puissiez souhaiter écrire une documentation supplémentaire (livres blancs, tutoriels, etc.) dans un autre format. Vous devez couvrir les sujets suivants :

  • Un synopsis des utilisations courantes du module.

  • Le but, la portée et les applications cibles de votre module.

  • L'utilisation de chaque méthode ou sous-routine accessible au public, y compris les paramètres et les valeurs de retour.

  • Exemples d'utilisation

  • Sources d'informations complémentaires

  • Une adresse électronique de contact pour l'auteur/mainteneur.

Le niveau de détail de la documentation des modules Perl va généralement du moins détaillé au plus détaillé. Votre section SYNOPSIS devrait contenir un exemple minimal d'utilisation (peut-être aussi peu qu'une ligne de co...de; sautez les cas d'utilisation inhabituels ou tout ce qui n'est pas nécessaire à la plupart des utilisateurs) ; la DESCRIPTION doit décrire votre module en termes généraux, généralement en quelques paragraphes ; plus de détails sur les routines ou les méthodes du module, de longs exemples de code ou d'autres éléments approfondis doivent être donnés dans les sections suivantes.

Idéalement, une personne qui connaît un peu votre module devrait pouvoir se rafraîchir la mémoire sans appuyer sur "page suivante". Au fur et à mesure que votre lecteur continue à parcourir le document, il devrait recevoir une quantité de connaissances de plus en plus grande.

L'ordre recommandé des sections dans la documentation des modules Perl est le suivant :

  • NOM

  • SYNOPSIS

  • DESCRIPTION

  • Une ou plusieurs sections ou sous-sections donnant plus de détails sur les méthodes et routines disponibles et toute autre information pertinente.

  • BUGS/CAVEATS/etc

  • AUTEUR

  • VOIR AUSSI

  • COPYRIGHT et LICENSE

Gardez votre documentation à proximité du code qu'elle documente (documentation "inline"). Incluez la POD pour une méthode donnée juste au-dessus de la sous-routine de cette méthode. Cela facilite la mise à jour de la documentation et évite de devoir documenter chaque morceau de code deux fois (une fois dans la POD et une fois dans les commentaires).

README, INSTALL, notes de version, changelogs.

Votre module devrait également inclure un fichier README décrivant le module et donnant des pointeurs vers des informations complémentaires (site web, email de l'auteur).

Un fichier INSTALL devrait être inclus, et devrait contenir des instructions d'installation simples. Lorsque vous utilisez ExtUtils::MakeMaker, ce sera généralement :

perl Makefile.PL
make
make test
make install

Lorsque vous utilisez Module::Build, ce sera généralement :

perl Build.PL
perl Build
perl Build test
perl Build install

Des notes de version ou des changelogs doivent être produits pour chaque version de votre logiciel décrivant les changements visibles par l'utilisateur de votre module, en termes pertinents pour l'utilisateur.

À moins que vous n'ayez de bonnes raisons d'utiliser un autre format (par exemple, un format utilisé au sein de votre entreprise), la convention est de nommer votre fichier changelog... Changes, et de suivre le format simple décrit dans CPAN::Changes::Spec.

CONSIDÉRATIONS SUR LA VERSION

Numérotation des versions

Les numéros de version doivent indiquer au moins les versions majeures et mineures, et éventuellement les versions subminoritaires. Une version majeure est une version dans laquelle la plupart des fonctionnalités ont été modifiées, ou dans laquelle de nouvelles fonctionnalités majeures ont été ajoutées. Une version mineure est une version dans laquelle une petite quantité de fonctionnalités a été ajoutée ou modifiée. Les numéros de version subminor sont généralement utilisés pour les modifications qui n'affectent pas la fonctionnalité, comme les correctifs de la documentation.

Le schéma de numérotation des versions CPAN le plus courant ressemble à ceci :

1.00,1.10,1.11,1.20,1.30,1.31,1.32

Un numéro de version CPAN correct est un nombre à virgule flottante avec au moins 2 chiffres après la décimale. Vous pouvez tester s'il est conforme à CPAN en utilisant la fonction

perl -MExtUtils::MakeMaker -le'print MM->parse_version(shift)''Foo.pm'

Si vous voulez publier une version 'beta' ou 'alpha' d'un module mais ne voulez pas que CPAN.pm la liste comme étant la plus récente, utilisez un '_' après le numéro de version normal suivi d'au moins 2 chiffres, par exemple 1.20_01. Si vous faites cela, l'idiome suivant est recommandé :

our$VERSION="1.12_01";# so CPAN distribution will have# right filenameour$XS_VERSION=$VERSION;# only needed if you have XS code$VERSION=eval$VERSION;# so "use Module 0.002" won't warn on# underscore

Avec cette astuce, MakeMaker ne lira que la première ligne et donc l'underscore, tandis que l'interpréteur perl évaluera la $VERSION et convertira la chaîne en un nombre. Les opérations ultérieures qui traitent $VERSION comme un nombre pourront alors le faire sans provoquer un avertissement sur le fait que $VERSION n'est pas un nombre.

Ne jamais publier quoi que ce soit (même un patch de documentation d'un mot) sans incrémenter le nombre. Même un patch de documentation d'un mot devrait entraîner un changement de version au niveau subminor.

Une fois choisi, il est important de s'en tenir à votre schéma de version, sans réduire le nombre de chiffres. C'est parce que les empaqueteurs "en aval", comme le système de ports FreeBSD, interprètent les numéros de version de différentes manières. Si vous changez le nombre de chiffres dans votre schéma de version, vous pouvez confondre ces systèmes afin qu'ils obtiennent les versions de votre module dans le désordre, ce qui est évidemment mauvais.

Pré-requis

Les auteurs de modules devraient examiner attentivement s'ils doivent s'appuyer sur d'autres modules, et sur quels modules s'appuyer.

Surtout, choisissez des modules qui sont aussi stables que possible. Par ordre de préférence :

  • Modules Perl de base

  • Modules CPAN stables

  • Modules CPAN instables

  • Modules non disponibles sur le CPAN

Spécifiez les exigences de version pour les autres modules Perl dans les prérequis de votre Makefile.PL ou Build.PL.

Assurez-vous de spécifier les exigences de la version de Perl à la fois dans Makefile.PL ou Build.PL et avec require 5.6.1 ou autre. Voir la section sur use VERSION de "require" dans perlfunc pour plus de détails.

Test de

Tous les modules devraient être testés avant d'être distribués (en utilisant "make disttest"), et les tests devraient également être disponibles pour les personnes qui installent les modules (en utilisant "make test"). Pour Module::Build, vous utiliseriez l'option make test équivalent perl Build test.

L'importance de ces tests est proportionnelle à la stabilité supposée d'un module. Un module qui prétend être stable ou qui espère atteindre une large utilisation devrait adhérer à un régime de tests aussi strict que possible.

Les modules utiles pour vous aider à écrire des tests (avec un impact minimal sur votre processus de développement ou votre temps) comprennent Test::Simple, Carp::Assert et Test::Inline. Pour des suites de tests plus sophistiquées, il existe Test::More et Test::MockObject.

Emballage

Les modules doivent être packagés en utilisant l'un des outils de packaging standard. Actuellement, vous avez le choix entre ExtUtils::MakeMaker et Module::Build, plus indépendant de la plateforme, permettant aux modules d'être installés de manière cohérente. Lorsque vous utilisez ExtUtils::MakeMaker, vous pouvez utiliser "make dist" pour créer votre paquetage. Des outils existent pour vous aider à construire votre module dans un style convivial pour MakeMaker. Ils incluent ExtUtils::ModuleMaker et h2xs. Voir aussi perlnewmod.

Licences

Assurez-vous que votre module a une licence, et que le texte complet de celle-ci est inclus dans la distribution (à moins qu'il ne s'agisse d'une licence commune et que les termes de la licence ne vous obligent pas à l'inclure).

Si vous ne savez pas quelle licence utiliser, la double licence sous les licences GPL et Artistic (la même que Perl lui-même) est une bonne idée. Voir perlgpl et perlartistique.

PIÈGES COMMUNS

Réinventer la roue

Il y a certains espaces d'application qui sont déjà très, très bien servis par CPAN. Un exemple est celui des systèmes de templating, un autre celui des modules de date et d'heure, et il y en a beaucoup d'autres. Bien que ce soit un rite de passage d'écrire votre propre version de ces choses, veuillez considérer attentivement si le monde Perl a vraiment besoin que vous la publiiez.

Essayer d'en faire trop

Votre module fera partie de la boîte à outils d'un développeur. Il ne constituera pas, en lui-même, la totalité de boîte à outils. Il est tentant d'ajouter des fonctionnalités supplémentaires jusqu'à ce que votre code soit un système monolithique plutôt qu'un ensemble de blocs de construction modulaires.

Une documentation inappropriée

Ne tombez pas dans le piège d'écrire pour le mauvais public. Votre public principal est un développeur raisonnablement expérimenté avec au moins une compréhension modérée du domaine d'application de votre module, qui vient de télécharger votre module et veut commencer à l'utiliser aussi rapidement que possible.

Les tutoriels, la documentation pour l'utilisateur final, les documents de recherche, les FAQ, etc. ne sont pas appropriés dans la documentation principale d'un module. Si vous voulez vraiment les écrire, incluez-les en tant que sous-documents tels que My::Module::Tutorial ou My::Module::FAQ et fournissez un lien dans la section VOIR AUSSI de la documentation principale.

VOIR AUSSI

perlstyle

Guide de style général Perl

perlnewmod

Comment créer un nouveau module

perlpod

Documentation sur le POD

podchecker

Vérifie l'exactitude de votre POD.

Outils d'emballage

ExtUtils::MakeMaker, Module::Build

Outils de test

Test::Simple, Test::Inline, Carp::Assert, Test::More, Test::MockObject.

https://pause.perl.org/

Serveur de téléchargement des auteurs Perl. Contient des liens vers des informations destinées aux auteurs de modules.

Tout bon livre sur le génie logiciel.

AUTEUR

Kirrily "Skud" Robert <[email protected]>