After reading multiple style guides and trying to not use inheritance in my node definitions (as suggested by puppet labs), I would like to know what the common way of including classes in puppet without using inheritance.
I have been trying the following with my node definitions, but it does not seem to work:
# in module 'baseclass'
# baseclass.pp
class baseclass {
include xclass
include yclass
include zclass
}
# servernode01.pp
node 'servernode01' {
include baseclass
}
where xclass, yclass and zclass are funcitonal puppet classes and including them in the node servernode01 produces the desired state (i.e. the resources are applied to the node).
My question(s) are:
Is including classes in classes a good alternative to inheritance?
Are there some issues in the methodology I am using as an alternative to inheritance?
I ask my second question since it seems the nodes that include baseclass do not receive the resources defined in xclass, yclass and zclass.
My ultimate goal is to have a base class that will implement the minimum requirements which I specify.
yes, composition is better than inheritance in Puppet
your example should work fine
An alternative to include baseclass is class { 'baseclass': }. You need the latter if you want to use parameters, and also have into account that you can use include multiple times but not the class syntax, as puppet will complain with duplicate class definition.
The official puppet docs state clearly that inheritance should be used only really "sparingly". They actually name exactly two situations where this should happen:
when you want to overwrite a parmeter of a resource defined in the parent class
when you want to inherit from a parameters class for standard parameter values
see http://bit.ly/1r1RO0K
So yes, this is clearly better, even with official blessing :)
Related
I am in the unfortunate situation where the names of a number of the classes in my project conflict with the classes that are imported from a framework. In general, I want to use the class from the framework in almost all cases. I know that I can specify which class to use by using Framework.ClassName or Module.ClassName. However, this would require adding Framework. to a large number of types.
Is there a mechanism to default to using the framework over the current module class. I.e. in the following example can I make sure that ambiguousInstance is of type MyFramework.ClassName by default?
import MyFramework
struct MyStruct {
var frameworkInstance: MyFramework.ClassName
var moduleInstance: MyModule.ClassName
var ambiguousInstance: ClassName
}
Or, failing that, can someone explain to me the logic behind which class is used when the framework or module is not specified. I.e. in the above case, I have seen the compiler infer that ambiguousInstance is MyFramework.ClassName in some instances and MyModule.ClassName in other instances, and cannot figure out why.
Note: I know having names which can conflict with a framework is not good design, the reason I do now is that I am moving a lot of my code from iOS native to Kotlin multiplatform, and so for the migration, I temporarily have two versions of essentially the same model
Is it possible to distribute the code of a class to several files?
Honestly, I think the best route is to break it up into different roles that you compose into your class.
After all, how are you planning on breaking up your class?
Are you going to group methods and attributes according to similarity?
At that point you've just about come up with a role, so you might as well make it a role.
If you look at the source for Rakudo you see things like this:
class Perl6::Metamodel::ClassHOW
does Perl6::Metamodel::Naming
does Perl6::Metamodel::Documenting
does Perl6::Metamodel::LanguageRevision
does Perl6::Metamodel::Stashing
does Perl6::Metamodel::AttributeContainer
does Perl6::Metamodel::MethodContainer
does Perl6::Metamodel::PrivateMethodContainer
does Perl6::Metamodel::MultiMethodContainer
does Perl6::Metamodel::MetaMethodContainer
does Perl6::Metamodel::RoleContainer
does Perl6::Metamodel::MultipleInheritance
does Perl6::Metamodel::DefaultParent
does Perl6::Metamodel::C3MRO
does Perl6::Metamodel::MROBasedMethodDispatch
does Perl6::Metamodel::MROBasedTypeChecking
does Perl6::Metamodel::Trusting
does Perl6::Metamodel::BUILDPLAN
does Perl6::Metamodel::Mixins
does Perl6::Metamodel::ArrayType
does Perl6::Metamodel::BoolificationProtocol
does Perl6::Metamodel::REPRComposeProtocol
does Perl6::Metamodel::InvocationProtocol
does Perl6::Metamodel::ContainerSpecProtocol
does Perl6::Metamodel::Finalization
does Perl6::Metamodel::Concretization
does Perl6::Metamodel::ConcretizationCache
{
… # only 300 lines of code
}
If you do a good job of splitting up your roles, you should be able to use them in many classes.
How many classes in the Rakudo code base do you think compose in the Perl6::Metamodel::Naming role?
That role only provides a few things, and is only 45 lines long.
Here is an abbreviated version.
(All of the code in the methods has been deleted here for brevity.)
role Perl6::Metamodel::Naming {
has $!name;
has $!shortname;
method name($obj) {
…
}
method set_name($obj, $name) {
…
}
method shortname($obj) {
…
}
method set_shortname($obj, $shortname) {
…
}
}
Yes, there always is. But there us no standard supported way (yet anyway).
You can take the approach that Raku takes itself when creating the core settings: concatenate the files into a single file, and compile that. When you're building Rakudo from scratch, that's what's happening when you see the line:
+++ Generating gen/moar/foo
The generated files can be inspected in the gen/moar directory. At one point, I brought this up in a problem solving issue, but that never went anywhere. Perhaps that should be revisited.
You can use augment class. But that currently only makes sense inside a single file, because with multiple files it is creating multiple versions of the same "module" in pre-compilation. And the system is not able to determine what to resolve to what. This is when you realize that pre-compilation of Raku modules currently is creating libraries that need to be statically linkable at runtime.
I have a Prism project with several modules. Using EF code first for generating the database.
I am trying to build the context using partial class. For each module will have its partial class context (one context whole solution).
I am using the same namespace for each module to create the context. However, when initializing the database, only the tables defined in the main module is created, but not the others.
Is there anything I could look for or is there a better way? Tks.
All parts of partial class must be in the same assembly (in your case probably in the same module) because it is just syntactic sugar to divide single file (class) into multiple parts but these parts are concatenated during build. Partial classes will not help you to achieve modularity (if you expect to add or remove modules to deployed application).
I've done some searching on this, but I cannot find info. I'm building an application inside sinatra, and using the coffeescript templating engine. By default the compiled code is wrapped as such:
(function() {
// code
}).call(this);
I'd like to remove that using the --bare flag, so different files can access classes and so forth that I'm defining. I realize that having it more contained helps against variable conflicts and so forth, but I'm working on two main pieces here. One is the business logic, and arrangement of data in class structures. The other is the view functionality using raphaeljs. I would prefer to keep these two pieces in separate files. Since the two files wrapped as such cannot access the data, it obviously won't work. However, if you can think of a better solution than using the --bare option, I'm all ears.
Bare compilation is simply a bad practice. Each file should export to the global scope only the public objects that matter to the rest of your app.
# foo.coffee
class Foo
constructor: (#abc) ->
privateVar = 123
window.Foo = Foo # export
Foo is now globally available. Now if that pattern isn't practical, maybe you should rethink your structure a bit. If you have to export too may things, you nest and namespace things better, so that more data can be exposed through fewer global variables.
I support Alex's answer, but if you absolutely must do this, I believe my answer to the same question for Rails 3.1 is applicable here as well: Put the line
Tilt::CoffeeScriptTemplate.default_bare = true
somewhere in your application.
We have to deal with production and test connection strings in our environment. Database First Solution.
I have an extremely picky client that is not happy with the fact that you can create a partial class with a second constructor with a parameter, or inherit from the named Entities class with an empty parameter constructor.
He claims that a developer could unknowingly use the base constructor.
Is there any way to modify the generated constructor, or set an option so that the base constructor does not get generated, so we can write our own?
Thanks!
If you are using T4 template for context generation you can do whatever you want. For example:
Make your context sealed
Remove partial keywork from generated context class
Define constructor you want directly in the template
The only thing you need to do is modify the ModelName.Context.tt template.
Anyway your client should concentrate on business requirements and not on stupid assumption about coding.
He claims that a developer could unknowingly use the base constructor.
I claim that this can happen but it is not an issue if your application is correctly tested and if you make code review for new team members or junior developers.