Today I once again got through one chapter of "Reliable Extensions" with a lot more success than yesterday. For example, today's chapter, on object-oriented programming, domain-driven design, test-driven design and the Model-View-Control pattern, where I often referenced my "Hands-On with PHPUnit" book for additional information, was 40 pages. Yesterday's chapter was 8.
First off, I started the day with a revelation: I learn better when the rest of my life is in order. When the apartment looks decent and I have clean clothes to wear, healthy, home-made food to eat, groceries in the cupboard, a legally valid public-transportation ticket, and all errands run. Because then my head is clear for other things, like refreshing my knowledge of concepts important to OOP (object-oriented programming).
Objected-oriented-programming is a programming paradigm that assumes that processes in the world can be abstracted into and represented by models (or objects), and the relationships and interactions between those objects. Objects have relationships, just like in the real world: a car HAS a motor. A Volvo IS a car. A Smart WANTS TO BE a car... These relationships can be one-to-one (a car has ONE steering wheel), one-to-many (a car has FOUR - or more - wheels) or many-to-many: a City-Car is driven by MANY drivers, Michael Jordan drives MANY cars.
The objects closely or inseperably involved in a "has a" or "belongs to" relationship can be described as aggregates: for example, wheels, brakes and a motor belong together in a car. The car would constitute the "aggregate root object" since it represents its composite parts as belonging to a complete whole. An aggregate root object, just like a car, must be an individual object in the world. We call an object that can be an individual object in the real world an "entity". In contrast to an entity, a value ("value object") would be something like the color blue, or the number 1. Blue is blue - it wouldn't make sense to say that it was an individual in the world.
Another concept from the world of OOP is the idea of "services". Services are containers for actions that can't really be attributed to any object. A service should be "stateless", that is, it should have no internal status that can be changed or manipulated. A service is kind of like a verb, where objects are more like nouns: a car can have a state (in motion, at rest) whereas "to drive" can't really be talked about that way. A service usually receives an entity or a value object whose state it can manipulate or change.
In the world of software, which consists not of REAL objects, but of mere representations of objects, the act of keeping these objects around in the virtual world (in memory or on the hard drive) is known as "persisting". In the world of OOP, the act of persisting an object is the responsibility of "repositiories". A database could be called a repository. It's responsible for "remembering" an instantiated object and its state so that it can be used in a program with consistency.
Our object-representations (let's just call them objects so that I don't have to type so much) can be created with factories. A factory is something that builds complex objects and sets all their properties before giving out the complete object at the end for use. In OOP, we use either a factory or the "constructor" method of a class to create an aggregate root object and set all its properties with consistency.
Aggregate root objects and persistence are tied together in that every aggregate root has to have exactly one repository: something (even a virtual something) can only be in one place at one time. In Extbase (ay, there's the mark of the matter), we define an aggregate root by creating its repository first.
On to MVC: Model-View-Control. The MVC is a pattern that can be used when writing software that (when used sensibly) will make software easier to read, maintain, and develop further. This is because the MVC pattern seperates software functionalities into distinct areas of responsibility: the Model, the View and the Controller.
The model is responsible for encapsualting data, the logic of how the data is used, how it's accessed, and how it's persisted. The view is responsible for presenting data to the user. Finally, the controller is responsible for coordinating the interaction between the model and the view. It ONLY coordinates: the actual domain functionality is implemented in the model. In Extbase, the model is further structured into domain model (abstraction of the domain, its logic and rules), repository (database access), and validator (container for the "invariants of the model", whatever that means) .
This brings us to DDD: domain-driven-development. What's a doman, you ask? It's an area of special knowledge and specific processes that belong together. For example, a hospital (the domain) has admissions, appointments, examinations, surgeries, therapy, medications, medical records, etc. The goal of a software developer who wants to develop a program to make these processes easier (cheaper, faster, more reliable, less tedious, compliant with the law) for the people who work within the domain, is to understand the language of this area and these processes. In order to do this, she has to sit together with someone who knows the domain inside out (and does actual, competent WORK within it...) and together with them, develop a way of talking about this domain that both developer and domain expert can understand.
This way of talking about the domain that both developer and expert (and software user) can understand is called "ubiquitous language" and can be best made useful by developing a kind of dictionary, or glossary, of terms, that both developer and domain expert can refer to. This glossary can then be used by the developer to implement software that is easy to talk about with the expert/user and to check with them that the desired functionality has been correctly understood and implemented.
Here's a personal aside: I use the hospital example because it's the domain in which I have had over 10 years of experience developing software for. By this point, I'd consider myself both a developer of software as well as a domain expert for hospital administration processes. I got there by consistently asking to watch how my colleagues work, asking them to tell me all about the way they do things, and then asking them questions about things I didn't understand or weren't clear. I would then sketch out a step-by-step example of a program and go through it with them, asking them at each step if what we were talking about made sense and corresponded to the way they needed to get their job done. I would do this again and again until they were satisfied with what we had worked on together, and only then would I start programming.
Only when I did NOT do this (for example, when the domain expert believed that they could communicate with me indirectly about what they "needed" by telling my boss about it, or in an incomprehensible email, or via telepathy), or the domain "expert" did not actually do any real WORK in the area they were supposed to represent, that software "got developed" that was of no use to anyone. Domain-driven-design makes sense to me - it's the only way to possibly make something that someone's going to be happy with and actually use.
So I already have a good handle on - and years of experience with - domain-driven-design. What I lack an intuition for is TDD - test-driven-development. I'm familiar with the theory, which I refreshed today, and have started to implement it in baby-steps: trying to code the example and then checking out the code provided by the book to see how close it is, if I have the idea right, what's missing, what's totally wrong, what I've failed to understand or succeeded in getting right.
That made today a fun day. Just in time for the weekend.