Part 1
This is a good design question. You are correct in detecting code smell concerning getters and setters. They generally indicate a design problem exposing the implementation details of your object.
Try to think in terms of what your objects should do - Tell, Don't Ask:
Your first problem may be that you are trying to design "data classes". Rather than worry about the data (implementation details), think about the functionality. Again, what should your objects do? In your case, what do you want to do with character styles? Who (software-wise) cares about character styles? What do they need to do?
Hopefully that gets you started. Test driven development helps with these kinds of design problems. It forces you to think in terms of function not data.
On the contrary, if all you need is a data container, write a C-style struct class and go to town. I wouldn't recommend that, maintaining it will be a $@#%#.
Good luck!
Part 2
What you want is either a simple data class - skip the getters and setters completely, or you want to create a platform independent abstraction that places a facade (Facade Pattern) in front of the rendering and style setting. It simply provides an interface for setting styles and rendering. Your platform specific implementation does the dirty work (using NSTextView
in your example).
The benefit of the simple data class is that it is initially simple to write. Its drawback is that you will have a hard time avoiding a giant tangle of if-else statements. You will also be lacking a clear place to make you platform specific rendering calls that use the styles. As the system's complexity grows, you may find it more diffcult to decide where implementation details go.
The facade is a more abstracted approach. The benefits are that it is more flexible and can be reused if you decide to port to another platform. Its drawbacks are more upfront development time.
The facade's public interface will provide what you need to set and remove styles as well as initiate rendering when the time comes.
The details of how you want to set styles are up to you. Use what ever system feels best. Simple get
ters and set
ters or a generic set
and get
that uses a dictionary internally works too (see boosts ptree
if you are using C++). You could even take all (or default) styles at construction time. You could decide to not even expose mutators at that point. Your call. Perhaps you decide it is important to data drive the styles you support and use a configuration plus factory system (We can add more detail later if that is important to you). In fact different implementatios of the facade could provide different ways of approaching the problem. You could prototype a few and choose what works best.
The platform specific implementation of you facade abstraction will use the platform specific rendering system (NSTextView
in your case) and the styles you have set to make the appropriate calls to the system. Simply inject the platform specific classes at construction (Dependency Injection), implement your render()
method and you should be good to go.
Part 3
If your system design allows, you could take all styles for a particular element at construction time. This could allow you to avoid getters and setters completely if you chose to make your element immutable. Your would then have a simple, clean and possibly immutable abstraction in front of your character styles system. Immutable state generally leads to fewer bugs but does require you to operate under the premise that you cannot change things willy-nilly.
Taking this a step further, a configuration file might define the different style setups you have. Again this would require prior knowledge of what styles you are setting (similar to constructing with the styles above). Give the type of style you are seeking, say "heading", you might fetch the configuration for headings which specifies a larger, bold font.
These are just some ideas off the top of my head. Without further requirements gathering and use cases it will be tough to get more specific.
Hope that helps. Good luck!
Declaring immutable class final
saves programmer from the need to repeat declaring final in each and every method declaration, over and over and over again.
In classes like java.lang.String, having over 60 methods, this is substantial save, as well as important guarantee that necessary modifier won't be omitted by mistake.
When object is intended to be immutable, mistakes to declare final method may be hard to detect, because there is no reliable way to tell whether programmer omitted final modifier intentionally or by mistake.
final classes have no real purpose except perhaps brevity
Besides brevity and helping to avoid mistakes, a strong benefit of declaring immutable class final is that this makes programmer's intent explicit, unambiguously communicating to API users that none of class methods are intended for override.
Alternative way, that is, declaring all methods final, lacks this important "feature", as it leaves users of the API in the indecisive state, whether API designers intended to only protect some methods from overloading, and it only accidentally turned out that all of them got final, or there was a design decision to cover all the class.
my opinion is that final classes are superfluous as final methods are all you need
Given above, having final modifier for class doesn't look superfluous to me.
It is worth noting that Sun/Oracle Java tutorial presents final classes as a matter of usefulness and not as that of convenience. If final classes purpose was mere brevity / syntactic sugar, one would expect tutorial to explain these as convenience.
...you can also declare an entire class final. A class that is declared final cannot be subclassed. This is particularly useful, for example, when creating an immutable class like the String
class.
Best Answer
Yes, getters/setters do break encapsulation - they basically are just an extra layer between directly accessing the underlying field. You might as well just access it directly.
Now, if you want more complex methods to access the field, that's valid, but instead of exposing the field, you need to think what methods the class should be offering instead. ie. instead of a Bank class with a Money value that is exposed using a property, you need to think what types of access a Bank object should offer (add money, withdraw, get balance) and implement those instead. A property on the Money variable is only syntactically different from exposing the Money variable directly.
DrDobbs has an article that says more.
For your problem, I'd have 2 methods setStyle and clearStyle (or whatever) that take an enum of the possible styles. A switch statement inside these methods would then apply the relevant values to the appropriate class variables. This way, you can change the internal representation of the styles to something else if you later decide to store them as a string (for use in HTML for example) - something that would require all users of your class to be changed too if you used get/set properties.
You can still switch on strings if you want to take arbitrary values, either have a big if-then statement (if there's a few of them), or a map of string values to method pointers using std::mem_fun (or std::function) so "bold" would be stored in a map key with its value being a sts::mem_fun to a method that sets the variable bold to true (if the strings are the same as the member variable names, then you can also use the stringifying macro to reduce the amount of code you need to write)