[Freeipa-devel] [PATCH] 0270-removing-setters-setup-and-init
Endi Sukma Dewata
edewata at redhat.com
Tue Jul 26 00:18:22 UTC 2011
On 7/25/2011 11:56 AM, Adam Young wrote:
>> 30. The IPA.spacer_widget is used to create spacing for layout.
>> Widgets should not be used this way because it diverges from the
>> original design. Widgets are supposed to correspond to attribute. It
>> has a name (required for storing in a map), metadata, load/save/undo
>> methods, none of which is relevant for spacer. Also, it only handles
>> a narrow case for creating a space between 2 fields which I think
>> better be handled using sections. This should be addressed in a
>> separate patch.
>
> Agreed. Fixing this will be easier to do on top of this patch.
I think we should remove IPA.spacer_widget and leave the
IPA.dnszone_adder_dialog unchanged for now. The current code, although
it might not be very concise, is done correctly and does produce the
desired layout (label on the right of the checkbox and a space below
it). The IPA.spacer_widget on the other hand violates the design and
still doesn't produce all the intended layout. Also, chances are the
priority for fixing this afterward will be low. Suppose we change the
IPA.widget to verify that all widgets have a name, this code will fail
immediately.
>> 31. The create() should only be used to create the visual elements.
>> Creating fields, columns, etc. should not be done inside create()
>> because we might decide to destroy the HTML elements of hidden facets
>> and recreate it again. In that case the fields will be duplicated.
>> Also, by delaying the creation of the fields it makes the object
>> incomplete after creation, which is the reason for removing init().
> Agreed, but I'm going to postpone fixing this until after this patch.
> Can you document where you see this as a problem?
I think this should be done in this patch because moving the code from
init() into create() changes how the code is executed (creating
incomplete objects, changing the assumptions). I've listed the code that
is affected in the new issues below.
>> 32. This is an existing problem but it's worsening without init().
>> Since there is no class constructor, the initialization code is
>> scattered throughout the class, making it difficult to maintain. Some
>> code needs to be written in certain position, but in general should we
>> move the initialization code to the bottom of the class (to make sure
>> all methods are already defined)? Or should init() be used as a
>> constructor and called at the bottom of the class?
> Instead of making a generic init function call, I think making smaller
> (potentially reusable) functions for related chunks of code, and then
> calling all of them at the bottom of the "constructor" makes the most
> sense. I did a little bit of this in this patch for the various sections
> of rules details facets, and I think it will have the desired effect.
Let me clarify the problem, in some of our code the initialization code
is intermixed with attribute declarations and function definitions which
makes it hard to understand and maintain.
IPA.some_class = function() {
... <initialization code> ...
... <attribute declaration> ...
... <initialization code> ...
... <function definition> ...
... <initialization code> ...
};
It's not always clear what attributes the class has or when they are
initialized. In many cases function invocation looks similar to function
definition, so you'd have to carefully read it. Sometimes there are
unexpected function invocation in the middle of the class definition.
Removing the init() and moving the initialization code into the class
definition (different from issue #31) exacerbates the problem further
because it blurs the boundary between function definition and invocation.
The solution is to move the initialization code into a single contiguous
location and clearly mark it as constructor.
One option is to wrap the initialization code in a function and call it
from the bottom of the class.
IPA.some_class = function() {
... <attribute declaration> ...
... <attribute declaration> ...
that.init = function() { // Constructor
... <initialization code> ...
... <initialization code> ...
};
... <function definition> ...
... <function definition> ...
that.init(); // Call constructor
};
The new init() is different from the old init() because it's executed
before the new instance is returned to the caller.
The other option is to move the code to the bottom of the class and mark
the area as constructor.
IPA.some_class = function() {
... <attribute declaration> ...
... <attribute declaration> ...
... <function definition> ...
... <function definition> ...
// Constructor
... <initialization code> ...
... <initialization code> ...
};
I prefer to use the wrapper because it mimics the constructor definition
in proper OO languages. Also we can keep the initialization code at the
beginning of the class which is more intuitive and reduces the changes
to the code. But either way will work just fine.
We can still refactor the initialization code into reusable functions
like you described. It should look like this:
IPA.some_class = function() {
... <attribute declaration> ...
... <attribute declaration> ...
that.init = function() {
that.func1();
that.func2();
};
that.func1 = function() { ... <initialization code> ... };
that.func2 = function() { ... <initialization code> ... };
... <function definition> ...
... <function definition> ...
that.init();
};
But not like this:
IPA.some_class = function() {
... <attribute declaration> ...
... <attribute declaration> ...
that.func1 = function() { ... <initialization code> ... };
that.func1();
... <function definition> ...
that.func2 = function() { ... <initialization code> ... };
... <function definition> ...
that.func2();
};
Here are the itemized list of issues:
41. The radio buttons in the 'As Whom' section in sudo rule section are
missing the labels. It should show the doc attributes of the
ipasudorunasusercategory and ipasudorunasgroupcategory.
42. The code in widget.js:1124-1128 can be replaced with this:
that.entity_name = spec.entity ? spec.entity.name : spec.entity_name;
In general attribute declarations should be 1 liner. If it takes more
than 1 line it should be done in the constructor.
43. The initialization code (set_param_info) in IPA.widget
(widget.js:80) was originally in init(). It should be moved into the
constructor.
44. The initialization code in IPA.column (widget.js:1135-1147) was
originally in init(). It should be moved into the constructor.
45. The initialization code (field creation) in IPA.target_section
(aci.js:401-433) should be moved into the constructor. This is an
existing issue so it can be fixed separately, but this is just to show
the problem we are dealing with.
46. The attribute declaration (target_types) in IPA.target_section
(aci.js:458-592) should be moved to the beginning of the class. This is
also an existing issue.
47. The initialization code (option creation) in IPA.rights_widget
(aci.js:366-369) was originally in init(). It should be moved into the
constructor.
48. The initialization code (button creation) in IPA.add_dialog
(add.js:48-93) was moved from init() to create(). It should be moved
into the constructor.
49. The initialization code (column creation) in
IPA.association_adder_dialog (association.js:157-165) was moved from
init() to create(). It should be moved into the constructor.
50. The attribute declaration (NORMAL_HEIGHT and WITH_EXTERNAL_HEIGHT)
in IPA.adder_dialog (dialog.js:341-342) should be moved to the beginning
of the class.
51. The initialization code (spec validation and table creation) in
IPA.adder_dialog (dialog.js:305-311 and 345-367) was moved from init()
to create(). It should be moved into the constructor.
52. The initialization code (table creation) in IPA.sudo.options_section
(sudo.js:603-638) was originally in init(). It should be moved into the
constructor.
53. The initialization code (field creation) in
IPA.sudo.rule_details_command_section (sudo.js:784-823) was originally
in init(). It should be moved into the constructor.
54. The initialization code (field creation) in
IPA.sudo.rule_details_runas_section (sudo.js:967-1020) was moved from
init() to create(). It should be moved into the constructor.
55. The initialization code (column creation) in
IPA.sudo.rule_association_adder_dialog (sudo.js:1185-1208) were moved
from init() into create(). It should be moved into the constructor.
There maybe more of similar problems. It's a long patch...
--
Endi S. Dewata
More information about the Freeipa-devel
mailing list