No Primities.
My idea with not using the default data types centers around them being data storage. Working on object oriented langauges, we don't need to be concerned about the raw data storage mechanism.
We deal with objects that communicate with each other, not raw data we process.
Then how do we do anything?
Today I had a bit of an epiphany on that, which I'll get to later. I'm not yet sure how I feel about it; but I like it better than what I've been doing.
Without this "mysterious" realization, how do we do anything without the data.
The data comes into the system somehow. There's a class that abstracts that raw data from the rest of the system. It knows the data and how to turn the raw data into data our system uses.
No God Classes.
The primitive data types are god classes. Just look at the class/struct declaration of any of them in C# or Java. They've got about a 1/2 dozen interfaces. They have A LOT of methods. They do WAY too much. I understand it from a system level performance factor. I find a lot of fault in how system and the mscorb classes are written, from an object oriented approach. I give these a lot of leeway in their additional tighter performance constraints; though I'm not sure there'd be performance issues doing it in a stricter OO fashion... a discussion for another time.
The classes do too much.
It's a massive violation of the single responsibility principle.
What I've done to rid myself of this god class is to ... well... wrap it in a class that isn't a god class. This is the core idea behind my FluentTypes repo. It removes the god class nature mostly. The idea is to add only the functionality needed in the product. The work isn't done in Text
(or other type) but it provides methods which return objects that will perform that functionality.
An added bonus in this style is that we have lazy execution. The work won't be performed until it's actually used.
This is what I do to get rid of the primitives. There's still some wrapper classes, but we've removed the "do anything" objects.
We're moving into the mentality of a 'password is not a string'. We have objects, we will tend towards more objects.
It'll look really wrong to have new TextOf(userPassword)
... A password isn't text. It stands out more. We get a better intuitive feel that we should have a Password
class.
When I originally did this with Password
it's because it's very much not a string. Same with my ResourceKey
- It's not a string. It should never be manipulated.
No More Wrapping.
Not entirely no more wrapping. I'm still keeping my Fluent Types for a while. I need to see my new style evolve further. As I think through things I've done... It makes sense. I've done it already, just never clicked to take it even further.
There aren't many texts. Not often. Passwords aren't, resource keys aren't. In the work that gave me the epiphany, we have a SystemCode
which isn't a Text
. It's the letter "A"
. It gets its own type, not derived from Text
, like most/all of the other types were.
I never really liked doing it that way... I just didn't have a better way. Some of them slipped in like the new way.
It's an object. If I need the value out, I can override ToString
and get a string
back. Except we still never deal with the primitive. We still need segregate the behaviors into classes. Text
enables us to have the desired behavior available, and still isolated in their own class.
Instead of ToString
I'll have a ToText
which will return the value as a Text
. The manipulation will be performed, then placed and returned into a new object of the resulting type. Text
manipulation behavior becomes more isolated, and only the objects they represent are exposed in the system, as I've been trying to get to.
While I created the Text
and FluentTypes... I'd love for them to not be needed because I'll have gotten really effective at creating objects to represent all of the concepts in the code, not just a class pretending it's not a string.
Summary
Don't use primitives. Wrap them simply in objects. It's a step. It's not the final step. There's a lot more steps.
Gotta take that first step to take more steps - Stop Using Primitives.