Why so many private classes in the Jucer's components?


#1

Hi,
I picked a header ‘juce_SliderHandler.h’ from the Jucer’s ‘src/model/components’ and I’m wondering, why there are so many
class declarations and definitions in the private part. I have counted 6 classes and each of them
have in there private part another class declaration and definition. Why?
The class is not a part of a ‘security’ system or something else. It is difficult, to read such source code and to extend!
Dear jules, is it your own fabrication or is it common practice?
I have extended this class with an slider enabling property and its works, but if I want to put more properties into
this class (SliderHandler) it will grow to an unreadable code. Is there a better solution?
BTW: I found 4 private functions as static, but static is not needed, right?

My version of the header (extended with a source file):

#ifndef __JUCER_SLIDERHANDLER_JUCEHEADER__
#define __JUCER_SLIDERHANDLER_JUCEHEADER__

#include "../../jucer_Headers.h"

#include "jucer_ComponentTypeHandler.h"
#include "jucer_ComponentUndoableAction.h"
#include "../../properties/jucer_ComponentBooleanProperty.h"
#include "../../properties/jucer_ComponentChoiceProperty.h"
#include "../../properties/jucer_ComponentTextProperty.h"


class SliderHandler : public ComponentTypeHandler
{
public:

    /* Constructor */
    SliderHandler(void);

    Component *createNewComponent(JucerDocument *);

    XmlElement *createXmlFor(Component *comp, const ComponentLayout *layout);

    bool restoreFromXml(const XmlElement &xml, Component *comp, const ComponentLayout *layout);

    const String getCreationParameters(Component *component);

    void fillInCreationCode(GeneratedCode &code, Component *component, const String &memberVariableName);

    void fillInGeneratedCode(Component *component, GeneratedCode &code);

    void getEditableProperties(
            Component *component,
            JucerDocument &document,
            Array<PropertyComponent *> &properties);

    /* Returns true */
    static bool needsCallback(Component * /*slider*/);

private:

    const String sliderStyleToString(Slider::SliderStyle style);

    Slider::SliderStyle sliderStringToStyle(const String &s);

    const String textBoxPosToString(const Slider::TextEntryBoxPosition pos);

    const Slider::TextEntryBoxPosition stringToTextBoxPos(const String &s);
};

#endif /* __JUCER_SLIDERHANDLER_JUCEHEADER__ */

I want to extend all components with the same property (for example ‘enabling/disabling’),
where can I do this?

Thomas


#2

Well, the old jucer was never designed to be extensible… If you want to hack it then that’s great, but since you’ll need to modify the code anyway, why not just change the visibility of the things you need to access?

But it is good practice to minimise the exposure between different areas of code - you should never make anything public unless it really needs to be public for some reason.

I don’t really understand what you mean.


#3

[quote=“jules”]Well, the old jucer was never designed to be extensible… If you want to hack it then that’s great, but since you’ll need to modify the code anyway, why not just change the visibility of the things you need to access?

But it is good practice to minimise the exposure between different areas of code - you should never make anything public unless it really needs to be public for some reason.

I don’t really understand what you mean.[/quote]

Old, is there a newer one or newer one coming?

They are in the original file defined as static:

private:

    static const String sliderStyleToString(Slider::SliderStyle style);

    static Slider::SliderStyle sliderStringToStyle(const String &s);

    static const String textBoxPosToString(const Slider::TextEntryBoxPosition pos);

    static const Slider::TextEntryBoxPosition stringToTextBoxPos(const String &s);

It is not necessary, I think. Or is there a advantage (speed, memory…)?

Thomas


#4

Well, it’s just basic good practice… Any function should depend on as little external state as possible, so a free-floating or static function is always preferable to a method, because it’s not coupled to the state of the instance that you call it on.


#5

I’d add the following, which gets to the heart of several topics here lately:

You should never make anything private unless it really needs to be private for some reason.

I recognize that after “Design Patterns” by the Gang of Four came out it became fashionable to focus entirely on programming to an interface with completely opaque implementation. However, this makes code extension and reuse difficult at best.

It is important to acknowledge that an SDK like JUCE plays more than one role; there are parts that are well suited to an opaque interface-driven approach. However, the part that serves as a basis for building things like GUI widgets might be better served by allowing inheritance for extension of the basic functionality. Otherwise, the provided components are not truly base classes; they are example implementations. That’s a legitimate design choice to make, but disappointing because it throws away a big chunk of the benefits of an object-oriented approach with inheritance. The whole reason protected exists is to provide strong encapsulation to unrelated classes while relaxing encapsulation among related classes to allow for inheritance.

I know this comes close to a religious issue, but enough people have expressed a concern about excessively restrictive declarations that perhaps a more balanced approach is worth considering.


#6

I don’t think it makes sense to have a general discussion about this sort of thing. I’ve been building user interfaces using Juce for a long time now, and I can probably count on one hand the times when there was something marked as private in a superclass that I wanted to access or change in some way. If there’s something specific in a particular UI class that you’d like to be public, bring it up for discussion… But I don’t think there’s any general problem with Juce’s object structure; when it comes down to it, I’ve found it far easier to create customized user interfaces in Juce than any other framework / language I’ve worked with in the past…


#7

[attachment=0]YUNO.png[/attachment]


#8

Genuinely terrible advice. Really, I couldn’t think of anything worse to suggest.

If a piece of code is private and properly decoupled from other code, then you can instantly see all the places where it gets used, and can easily change/update/fix/refactor it, because the impact of any changes is easy to see.

But when I make a piece of code public, there may be thousands of random people using it in stupid ways that I can’t even imagine, and the tiniest change to it could cause untold havoc with their codebases. The only way to make it possible to maintain a library like juce is to minimise the “surface area” that the public can interact with. So for me, keeping implementations hidden is a no-brainer. But even in your own closed-source projects, decoupling your implementations from external code still makes good code-hygiene practice.


#9

It’s funny the things you miss when you don’t actually read the other person’s statement…

Nowhere in my post do I advocate for making anything public. I’m advocating for greater consideration of whether protected would be a more suitable choice in the cases where SDK users are most likely to use inheritance to extend base classes.

Encapsulation and Inheritance are two features of OO languages that exist in tension; blind adherence to aggressive encapsulation compromises inheritance. Overdependence on inheritance forces loose encapsulation.

You’ve made it clear that JUCE unapologetically adheres to strict encapsulation, and users who dare question this dogma (which include at least ThomasM, Rail Jon Rogut and myself just in the last week or two) will be derided and insulted. Duly noted, though I think it’s an odd way to treat people who (at least some of which) are paying customers.


#10

Woah… who did any deriding or insulting!? I thought I just gave a pretty decent explanation of why any sane library writer needs to keep things out of sight! Questioning dogma is good! But this isn’t some piece of trendy advice that I just read in a book, it’s the result of 15 years of experience, which is finally starting to give me a good feel for how to design good APIs.

I’ve been using the word “public” in a looser sense, just meaning “non-private”. If something is protected, then the general public can still access it via inheritance, so I’d still describe that as “public”.

What I would say to anyone who feels that they’re repeatedly wanting access to private data, is you might just be approaching things with too much of an inheritance-centric viewpoint… Hard to explain exactly what I mean by that, but I bet that if you were to post some examples of things that you’re struggling to do, I’d be able to suggest other (and often better) ways to achieve it.


#11

Just happened to read a post about this on stackexchange, where people answer the same question more eloquently than my attempts on this thread!

http://programmers.stackexchange.com/questions/162643/why-is-clean-code-suggesting-avoiding-protected-variables