# Separation of Records vs Classes > [!quote] [link](https://josipmisko.com/posts/c-sharp-class-vs-record) > The main difference between class and record type in C# is that a record has the main purpose of storing data, while class ==define responsibility==. *Everything is an object* has been the slogan of the earlier OOP languages (ex: [[Java]]). [^not-everything-is-an-object] `Class = Data + Object` has been the general philosophy. However, even though classes are powerful, in majority of use cases it's more useful to think of them as separate entities. [^not-everything-is-an-object]: This is not strictly true, as entities such as *methods* or *functions* were not first class citizens in Java. # Types of Objects It's useful to distinguish between *Records* and *Active Objects*. ## [Records](https://en.wikipedia.org/wiki/Record_(computer_science)) * Record behave like primitives, or collection of primitives or records. * basic collections like `list`, `map`, or `set` may be allowed. * Example: [[JSON]] * Immutable. Depending on the language * Can be immutable * Immutable by default * Default functionalities (see [[java.lang.Object]]) * `equals` and `hashCode` - may participate as a key in hash map. * lexicographic comparison * string representation * serialization * ... and much more ... * potentially stack allocatable * if this is just primitives, it's possible (C-struct semantic) * pointers and collections make this difficult; * example: [[Go]] structs > [!note] On Go Slices > It's annoying that slices cannot be used as map keys in Go, but `string` can; thus ## Resource This is a watered down introduction to [[Rust]]. By resource, I'm referring to a data type that has a clear lifecycle of *acquisition - usage - release*. **Examples**: * File handles * TCP Sockets * DB Connections, Sessions, Transactions * Request - Response lifecycle of a server. * Thread and Goroutines (or handles to them) * Semaphore / Locks * ⭐️ *Memory* (but this is a special one). ### What is special about resource? * Resources need to go through a lifecycle. * Normally requires a mutually exclusive access. * Leaking resources (i.e. not releasing them) is detrimental to the application in the long run. ### Memory The question here is, *is memory a resource*? In the theoretical sense, it is. But it is such a different type of resource that it should be treated separately. * Memory is fundamentally a different than other resources. It is largely homogeneous. Exact behaviors around memory allocation and deallocation is not important. Memory has a very complex ownership structure (pointers, refcount) which creates a very graph. Some memory is short-living and some are long living, which is a property exploited by [generational GCs](https://en.wikipedia.org/wiki/Tracing_garbage_collection#Generational_GC_(ephemeral_GC)) * caveat; it *is* important for certain domain, but these domains are already well aware of it and is very careful with memory. ex: embedded programming preallocating all the memory. * ACTUALLY, this is one of the greatest accomplishment of a GCs and managed runtimes. * Moreover, "leaking memory" may not even be the worst thing in these applications. Programs crash all the time (and we expect programs to crash). Programs stop and restart all the time too. * Other resources can be managed via GC too (with finalizers). However, this is risky because you don't control the exact timing and behavior of the resource de-allocation. ## Active Object There really is no good terminology for. Closest word to this is *Resource*. * *Class* * is an abstraction over these resources, while using other classes and records as dependencies. * has a lifecycle - this is the consequence of the fact that classes abstract over lifecycle. * Though, certain classes may piggy-back off the resources’ lifecycle. I.e. class is a wrapper on top of an already initialized resource and it assumes that the resource is available for the entire duration of the class’s lifecycle. * Some of this concept becomes more crisp if you’re in a language like Rust where the concept of ownership is built in to the language, but even outside of it it can be powerful. # Problems with the [[Floating Point Number]] Floating point introduces two problems, where `x == y` and `byte(x) == byte(y)` does not match. - +0 and -0 - these have different byte representation (different sign bit) but are equal values. - `NaN != NaN` - # Ideal Architecture (using the above notion) ## Problem OOP philosophy and design pattern is muddled by the fact that *records* and *Active objects* are treated under the same umbrella. ## Example: Polymorphism * Polymorphism is a hotly debated topic, but polymorphism (even in its best light) should be treated differently * Records * ⚠️⚠️ it *can* make sense. However, it adds a lot of contradiction - the problem of *Equals*, for example. The general consensus is to use composition (which has more well known semantics). Limited support of *mixins* can provide syntactic sugar for boilerplate properties without introducing semantical ambiguity. * Active Classes * ⚠️ it can make sense. However, code sharing via inheritance has been criticized. Abstract classes are at least designed to be used by inheritance. However, the general best practice is to push for interface-based abstraction instead. ## Example: serialization * records - ✅ make sense * Object graph is a tree * active classes - ❌ doesn't make sense to serialize active classes. * May be a DAG or a full graph. * Resources are environment specific (ex: open files handles cannot be meaningfully serialized). * java [[Serialization]]. * python pickle ## Example: deep copying * records - ✅ make sense * active classes - ❌ fundamentally doesn't make sense * Complex operation given that the object graph may be nontrivial; see serialization. * how deep should one go? * similar problem as the serialization. ## example: equality * records - ✅ make sense * active classes - ❌ *can* make sense, but what's the exact semantics you're expecting? * [[java.net.URL]] ## example: immutability * records - ✅ make sense * all records are immutable * python(`namedtuple`), C# * records can be immutable (frozen or unfrozen) * C++ * are there good examples of this? * active classes - ⚠️ situational * many interesting resources have corresponding states associated with them. * to represent lifecycle, additional states may be needed. RAII avoids some of this, but not all of it. Evaluating classic design patterns * adapter pattern * make sense for the Active Classes * for records, just perform a transformation (especially if immutability is guaranteed) may be valuable. ## Performance A case of [[Performance]]. Treating all objects to be heap allocated is simple; however, there's performance limitations to it. ## Solution * Records and Active classes are separate. # Other Examples ## [[ORM]] - In the [[Active Record]] pattern, every object implicitly has a reference to the session. Every attribute traversal (ex: `user.posts`) performs a DB query using the same session behind the scene. ## Exceptions Exception Type Hierarchy is quite useful for pattern matching. # Strange Cases ## Time date, datetime, timestamp, durations... https://docs.timetime.in/blog/js-dates-finally-fixed/ ### Timezones https://pkg.go.dev/time/tzdata ## URLs [[java.net.URL]]