4 ms·
Ideally the choices you make would fit the domain. However for very large projects that have existed for a long time, three things happen. 1. Requirements chan
by crimsonalucard 7y ago
Ideally the choices you make would fit the domain. However for very large projects that have existed for a long time, three things happen.
1. Requirements change and this causes a change in primitives.
2. Small errors in design and scope creep in because objects allow you to mistakenly scope functions with the wrong piece of data, over a long time these small errors accumulate into something called technical debt. I call it inevitable.
3. Correct design principles appear after the project is complete, often because the design solution to the problem domain is unknown. You may have segregated you data and functions in the wrong scope because you simply didn't know what your program would end up doing when your finished.
By forcing your data and functions into groupings like this you lose flexibility of composition, you take away the future proof of your design. Too often programmers realize that the lines of segregation of their designs are wrong or have changed. They see a function that should have been universal but is trapped on an object mutating data so they're forced to make a similar method on a another object and they just call it a trade off between technical debt and time.
This happens all the time on large projects because the concept of the object as a primitive is wrong. The primitives are data and functions, not the two combined into an object.
Without that arbitrary artificial line called an object drawn around data and objects your code can react instantly to design changes. You can change a function without damaging the entire context the function relies on because it has no context in the first place, functions are independent and modular from context; methods are inexlorably tangled with state. And therefore when the time comes to inevitably change your program, you create technical debt to get around the immoveability of your methods.
I understand the need to place everything under a single primitive type and while this is ideal it only works if primitives can compose; of which objects can't. You will see across mathematics the quest for an elegant assembly language and simplified language to describe the field first began with set theory than transitioned to category theory. In both theories the dichotomy between function and data remains solid, if they couldn't unify for theoretical math then it likely says something about the primitives of the universe and your designs as well.
- AnimalMuppet 7y agoIf you separate functions and data, do you keep related data in clusters, or do you keep it as primitives? If you keep it in clusters, then you have all the same problems. Your functions depend on the structure of the clusters; if they change (for all of the reasons you describe), then the functions are broken just as much as if they were grouped with the data in objects. On the other hand, if you keep the data as primitives, then you have a lot of primitives scattered all over the place, some of which have to maintain relationships with each other, even though they're not grouped. That gets difficult to manage, no matter how nicely everything composes. You object that mathematics doesn't group things like this. Well, programming is not a purely mathematical activity - it's an engineering one. So even if your observation is accurate, it is not all that relevant.
- crimsonalucard 7y ago>If you separate functions and data, do you keep related data in clusters, or do you keep it as primitives? The data exists in primitives. And yes you are correct, you eventually need to group this data, but the data must exist in both forms, both as a primitive and both organized. But when you start out building your program you start with primitives at the root and you build up the organization. Allow me to elucidate. Think of the way your program is organized. You have layers of logic from the lowest level that's primitive to the highest level that's organized and closest to the user. Let's say you build an App that's a phonebook and prints the addresses of people. You can break the data into two primitives at the lowest later: Person and Address. Then in the next layer you compose Person and Address into PersonWithAddress. Much more organized, but then let's say Companies are added to your design. Now all you have to do is add a company primitive to your design and create a composition called CompanyWithAddress at the next layer of logic. If you decided to group your primitives immediately and define a Person with address attributes included, you would get design problems later on. Think about what happens when the company is introduced but no Address primitive exists. You're either going to create the Address primitive and have the Person data structure forever keep redundant attributes, or you have redundant address attributes in Company. How would you then define a function FindAllNeighboringAddresses when addresses exists in a fractured/redundant state in your program? Obviously this is a trivial example, but the same type of problem happens all the time in a more complicated way on projects much more complex than this. When a team encounters such a problem they either add more technical debt, or rewrite a huge portion of the program, or rewrite everything. Choosing the right primitives are a critical part of design. The entire purpose of primitives is for Maximum flexibility so that you can organize your program to do whatever you want it to do. Objects as a primitive will lock your organization into a specific purpose way to early and often incorrectly. Objects are a bad primitive for this and other reasons. >You object that mathematics doesn't group things like this. Well, programming is not a purely mathematical activity - it's an engineering one. So even if your observation is accurate, it is not all that relevant. This is a philosophical argument. Either way historically speaking the foundations of all of software and programming comes from the field of mathematics. It is formally defined both algorithmically and computationally from lambda calculus, von neumann machines to decidability. One can argue that the entire field is a sub field of mathematics. Additionally, if the definition of mathematics is simply the creation of axioms and deriving theorems and statements from a set of axioms, than programing is the Exact same thing. You are literally assigning values to things and deriving new values (theorems) from your initial set of values (axioms). Unlike other fields labeled with "engineering" the output of a computer is highly, highly deterministic. That is why also unlike other engineering fields, programming is the subject of formal mathematical analysis more-so than almost every other engineering field out there.