Issue #1645 has been reported by jerico.
----------------------------------------
Feature #1645: Classes vs. Definitions - how to get closer to common design
patterns
http://projects.reductivelabs.com/issues/show/1645
Author: jerico
Status: Unreviewed
Priority: Normal
Assigned to:
Category:
Target version:
Complexity: Unknown
Affected version: 0.24.4
Keywords:
I am a newcomer to puppet. This is bad as I don't know all the nuts and bolts
of the framework. But it is good as well as I still have a "fresh view" of
puppet as a tool. So please forgive me if I am telling nonsense ... Anyhow I'd
like to share some "fresh-view" conceptual thoughts with you.
I am really having conceptual (and practical!!) trouble with the semantics of
puppet's "classes" and "definitions" as they are defined today. IMO the
distinction is quite arbitrary and counter-intuitive. AFAICS there are three
main distinctions between classes and definitions:
1) classes are singletons from a node perspective, definitions are instantiable
2) definitions receive parameters, classes do not
3) classes can declare "class variables" ($class::var), definitions cannot
I have seen many examples in "recipes" where classes were used like this:
node abc {
$globalvar1 = ...
$globalvar2 = ...
include xyz
}
class xyz {
...template("consumes <%= globalvar1 %>...")...
file { ...owner = $globalvar2... }
}
IMO this is counter to basic principles of information hiding and
modularization. (The most exhaustive discussion of the disadvantages of such an
approach is probably in Steve McConnell's "Code Complete"). If you do not have
the most simple classes in your manifests then puppet invites you to use global
variables. I can already see from the few things I did that this quickly
becomes a maintenance nightmare and makes puppet classes very difficult to use
in a more complex setting.
Definitions accept construction parameters and are therefore able to hide their
inner workings and complexity from outer context. This makes them more flexible
and attractive for modularization than classes. Definitions are however not
meant for usage as node singletons. IMO it's always bad if you try to coerce a
syntactical construct into a role that it wasn't meant for. Defintions also
have another big disadvantage: They do not allow for instance variables like
classes do (something like $mydefinition["xyz"]::myvar).
Furtheron the distinction between "classes as singletons" and "definitions as
prototypes" seems quite arbitrary to me. What is called a "class" in puppet is
conceptually a class with "automatic instantiation" (with one "class instance"
per node). This is confusing to me as an OO programmers who considers classes
and instances separate conceptual entities. On the other hand what is called a
"definition" in puppet is conceptually really a class as it defines a
"blueprint" of an object that can be instantiated separately. The conceptual
inconsistency reveals itself in the Class["classname"] syntax which is a
workaround for the fact that puppet classes are instances of classes as well.
Definitions on the other hand can be referenced quite intuitively with the
Definition_name["instance id"] syntax.
IMO the conceptual distinction between classes and definitions is confusing and
unnecessary at the same time. To me it would be much simpler if such a
distinction did not exist. Rather than two resource containers you could simply
have one generic class container without loosing any functionality and winning
flexibility, intuitivity and maintainability:
Here my propositions:
1) Classes should be reframed as universal "blueprints" of resource containers
that can (and must) be instantiated (like definitions today).
2) All classes may define constructor parameters (like definitions today).
3) Classes may be defined as node level "singletons" or node level
"prototypes". The distinction between singleton and prototype is well known to
most OO programmers.
4) Classes can define public instance variables that may be accessed from an
outer context (like they do today). The access syntax would be
($Classname["instance id"]::myvar).
5) Instances of classes can be referenced like definitions today:
Classname["instance id"]
All this can be introduced in a fully backwards compatible way (which is
certainly a must-have!):
1) Definitions will continue to exist but will be deprecated.
2) Classes will be node singletons by default.
3) Class constructor parameter declaration is optional.
4) Singleton classes can still be referenced as Class["xyz"]. This usage will
however be deprecated.
5) Class variables can still be referenced as $classname::var. This usage will
however be deprecated.
6) You can define "inner classes" to replace today's construct of definitions
within class context.
Here is how I'd define the syntax of the ideal resource container (replacing
both classes and definitions), not really BNF but somehow ;-) :
{singleton|prototype} class <classname> [($par1, [$par2, [...]])] {
...
$instance-var = ...
...
{singleton|prototype} class <inner class> [($par1, [$par2, [...]])] { ... }
}
The whole thing certainly is not very well thought out yet. But I'd love to see
a discussion starting from here as I am really fighting with the current
syntax...
----------------------------------------
You have received this notification because you have either subscribed to it,
or are involved in it.
To change your notification preferences, please click here:
http://reductivelabs.com/redmine/my/account
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Bugs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/puppet-bugs?hl=en
-~----------~----~----~----~------~----~------~--~---