Related
I have been searching for an answer in this topic but I haven’t been able to find a satisfactory one like in other topics, where the consensus is solid.
The situation
To keep things simple: I am implementing a custom Dependency Injection Container into one of my current projects (I know, I should use an already built one, but I’m doing it with learning purposes; so answers like ‘use this func of that container…’ are not useful) and I’ve stumbled a problem with instantiation of new elements inside a collection.
The problem
Imagine that I have a complex object, for example a car. This car has several dependencies (engine, axis, seats, airbags…) that have, at the same time, their own dependencies, and so on.
It is not a big issue to make the DiC (via autowiring or using a config file) build the object graph and inject all the dependencies with a simple line of code like:
$car = $container->get(‘car’);
The problem arrives when I build a CarCollection, which is a simple class that wraps an array of cars. The issue comes when I try to use a method that populates the collection with all the cars that exist in the database. It’s obvios that the collection should be able to create the Car objects on the fly when we call the “getAll” method from the database.
The code would be something like this:
public function populate(array $filters) {
$all_data = $this->dao->getAll($filters); // Call the data access object to query all cars.
foreach($all_data as $data) {
$new_object = $this->container(‘car’); // create a template object
$new_object->setData($data); // set the info.
$this->items[] = $new_object; // Add to the collection.
}
}
If car was not such a complex object it would be easier, because I could pass the car fqcn as a parameter for carCollection and use it in every iteration. But that’s not possible for a very complex object (or if I want to instantiate different sub types of the object - for example: lorry, pick-up, van…- depending on information from the database).
The question.
Regarding the collection being aware about the container: does not it break the purpose of the DIC phylosophy?
I guess not on one side, because I am using PSR\Container to type hint the container I pass to the collection (which loosens the coupling). But it breaks the idea that the container should not be coupled with the domain model at all.
The only alternative that I have thought about is substituting the creation of one new object for each iteration with a cloning from a prototype object that lives in the collection as a property. But we all know cloning in php can get really tricky and very difficult to debug (Or worse: very difficult to even know that there is a problem going on).
Similar issue.
PS: I have the same problem when I try to do lazy loading using Porxy objects: I need the proxy objects to have access to the container if I want to instantiate the full object later, which also breaks the principles of a DiC.
Thank you all.
I think the core of your issue comes down to this:
The issue comes when I try to use a method that populates the collection with all the cars that exist in the database.
The composition of object graphs of application components should be independent of any I/O, as described here and here by Mark Seemann. This means that the structure of those object graphs can't (and shouldn't) change based on changes in your database.
It seems to me that your Car object is a Domain Object, rather than a (Domain) Service. It would, therefore, be better suited to return a collection of Car instances from a service, rather than injecting the collection directly into one of your application components.
I need the proxy objects to have access to the container if I want to instantiate the full object later, which also breaks the principles of a DiC.
It's generally considered to be a bad practice to let application code depend on the DI Container. This a a pattern known as the Service Locator anti-pattern. There are many reasons why Service Locator is considered to be a bad idea, but it's important to understand that the list of downsides of Service Locator do not apply when the DI Container is used in the application's startup path (a.k.a. the Composition Root). A DI Container used within the Composition Root, is not an implementation of the Service Locator anti-pattern.
When your proxy classes are defined within the Composition Root, it's perfectly fine to let them depend on the DI Container and you won't violate any software principle or practice.
I have a bunch of Domain Objects and I am using overloading to get and set properties.
My form filters are comprehensive. If properties of the wrong type or value sneak through, I am confident that I can pick them up in the mapper. Worst case scenario is that the database throws an exception which I can catch.
In this instance, should I worry about getters and setters in the domain object?
As a best practice, you should always "catch what you can" before you get to the database. Though it may seem as if a round-trip isn't a big deal, they are expensive. Objects have to be created on the server, application pool resources managed, and so much more. Do all the validation you can, though it's tedious, before you get to the database.
The reason you rely on the database to throw exceptions is to ensure its integrity via other forms of access (e.g. import scripts), not to leverage it for your application (which is capable of catching and handling them gracefully).
The final benefit of building the get and set operations is that you can fully encapsulate these bounds checks so that you only have to write the code once, you're going in the right direction!
Well there is no good answer in my opinion for it.
If you do it, you can be 100% sure the value returned is of type x. Otherwise you depend on the data layer for the right stuff.
I check the values, but that is mostly because I like the defensive programming approuch (everything outside the scope is evil and should not be trusted). The domain object is outside the scope of the mapper, so you are not sure what you get.
Next if you make an api of some kind and use the domain objects again out of scope so check the values.
conclusion it depends on the code style you like. So you could implement the getters and settets or just direct to the values.
Although I recommend use at least getters and setters for the case you need to change how values are handeld (array needs to become object for example)
Defining explicit 'getters and setters' will allow you to implement the correct encapsulation for your domain model.
From a setting point of view, this would be type checking for complex values. Then you can perform any validation that is applicable in the context of the domain model.
When the domain model is persisted, this "validation" is really to ensure the values are stored correctly. The only concern the mapper would have is to cast the simple (scalar) values to the correct format (i.e dates etc). These operations tend to be database specific and would probably be better suited within the mapper.
In my application design, I usually map objects to the important tables in the database. The objects then handle everything relating to that data (including linkage tables). So I for example have built an Activity object, with properties like name and due_date, methods like load() and save(), and also methods like getParent(), getContributors() and getTeam(), which return (arrays of) other objects. Is this 'bad' OOP because it violates the Single Responsibility Principle?
It depends on the situation and the exact code you have: Your design might touch multiple responsibilities and still be a pretty nice OOP and maintainable.
Do you handle load() and save() in each class with similar code? Or do you delegate the task within load() and save() to other objects that are used for this functionality in several classes? That would be half-what following SRP and still be according to your design.
If not, your code really seems a bit smelly. To check whether it covers multiple responsibilities, ask yourself: what could cause changes to my class? In your situation, I would at least try to refactor the similar code in load() and save() in different classes to reach the situation described above, so that
maintainability is greatly improved,
you still do not need to change your clients' code.
Well .. its hard to tell at this stage. You could pastbin the whole class , but ..
Yes , it looks like bad OOP. You have same class responsible for interaction with database and domain logic. This creates two, completely different reasons for class to change.
You might benefit from exploring DataMapper pattern.
Maybe I'll just kick in the dark with this (cause I'm not an expert) but:
Methods load() and save() inside domain objects is called Active Record (Another description). This is not bad (altough I dislike it) because people that will maybe work after or with you will have less problems figuring out how to persist those objects.
About other methods. It's not that bad if it's in objects domain and it represents objects behaviour. If designed well it can be very good. Domain driven design encourages using rich domain model which is opposite of anemic domain model. An anemic domain model has domain objects that only have properties and getters and setters. So as long as it's in domain of your object, putting additional methods in it is not considered bad.
This is as far as I understand those concept from the books and articles I've read..
Hope it helps..
What you describe is an ActiveRecord and it's well known that it violates SRP. Also, ActiveRecord only works well when the table rows match the object closely. Once Impedance Mismatch gets too big, it will make changes to the system more difficult later.
It's not necessarily bad OOP, but it is a form of Technical Debt because of the lack of separation between persistence logic and domain logic. Violating any of the SOLID principles will usually lead to hard to change code, fragile code, non-reusable code.
A few of those debts are not an issue. It's when those debt accumulate interest, e.g. when they start to ripple into other design decisions. In other words, when you notice that it gets more difficult to change the system, try to pay back some debts, e.g. refactor to a more maintainable solution.
I think it's important to stop thinking that Model should be only layer between logic and database. Model can work with database and with other models, all logic should be in Models.
I think there is two ways:
your Model could return array of ID's in getContributors() method, and you could create new object (Factory maybe), which will convert these ID's to objects.
your Model could return array of objects, but without using new keyword, but through the Factory or Dependencies Container (I prefer DC).
I just started practicing TDD in my projects. I'm developing a project now using php/zend/mysql and phpunit/dbunit for testing. I'm just a bit distracted on the idea of encapsulation and the test driven approach. My idea behind encapsulation is to hide access to several object functionalities. To make it more clear, private and protected functions are not directly testable(unless you will create a public function to call it).
So I end up converting some private and protected functions to public functions just to be able to test them. I'm really violating the principles of encapsulation to give way to micro function testability. Is this the correct way of doing it?
There is a pretty standard answer to this in TDD circles. If there is functionality in a class that you both want hidden and directly tested, you should sprout a class with that functionality. This is a great example of how TDD improves your design.
In the original class, that extraneous functionality is gone, wrapped within the sprouted class, so the original class' design is simpler, and better conforms to the Single Responsibility Principle. In the sprouted class, the extracted functionality is its raison d'etre, therefore it's appropriate for it to be public, and therefore it's testable without test-only modifications.
With respect there Carl Manaster's fine answer, there are some drawbacks you should at least consider before embarking on the path Carl suggested.
The most significant of which is this: we use encapsulation to minimise the number of potential dependencies that carry the greatest probability of change propagation. In your case, you have encapsulated private methods inside your class: they are not available to other classes and thus there are no potential dependencies on them: the cost of any changes you make to them is minimised and has a low probablility of propagation to other classes.
It seems that Carl suggests moving some private methods from your class into a new class, and making those methods public (so that you can test them). (Incidentally, why not just make them public in the original class?)
By doing this, you remove the barrier to other classes' forming dependencies on those methods, which will potentially increase the cost of chaging those methods should any other class take to using them.
You may judge this down-side minor and a worthwhile price to pay for being able to test your private methods, but at least be aware of it. In a small number of cases, it may indeed be worthwhile, but if you institute this throughout your code-base then you'll drastically increase the probability that these dependencies will form, increasing the cost of your maintenance cycle to an unknown degree.
For these reasons, I disagree with Carl that his suggestion is, ” … a great example of how TDD improves your design.”
Furthermore, he states, ”In the original class, that extraneous functionality is gone, wrapped within the sprouted class, so the original class' design is simpler, and better conforms to the Single Responsibility Principle.”
I would argue that the functionality being moved is not at all, ”Extraneous.” Also, ”Simpler,” is a not well-defined: it certainly may be the case that a class's simplicity is inversely proportional to its size but that does not mean that a system of simplest-possible classes will be the simplest possible system: if this were the case, all classes would contain only one method and a system would have an enormous number of classes; the removal of this hierarchical layer of multiple-methods-within-classes, it could be argued, would make the system much more complicated.
The Single Responsibility Principle (SRP) is, furthermore, notoriously subjective and entirely dependent on the level of abstraction of the observer. It is not at all the case that removing a method from a class automatically improves its conformity to the SRP. A Printer class, with 10 methods, has the single responsibility of printing at the level of abstraction of the class. One of its methods may be checkPrinterConnected() and one may be checkPaper(); at the method level, these are clearly separate responsibilities, but they do not automatically suggest that the class should be broken down into further classes.
Carl finishes, ”In the sprouted class, the extracted functionality is its raison d'etre, therefore it's appropriate for it to be public, and therefore it's testable without test-only modifications.” A functionality's importance (it's raison-d'etre-ness) is not the basis for the appropriateness of its being public. The basis for the appropriateness of functionality's being public is the minimising of the interface exposed to the client such that the class's functionality is available for use while the client's independence of the functionality's implementation is maximised. Of course, if you are moving just one method into the sprouted class, then it has to be public. If you are moving more than one method, however, you must make those methods public which are essential to the client's successful use of the class: these public methods may be far less important than some of the private methods from which you wish to shield your client. (In any case, I'm not at a fan of this, ”Raison-d'etre,” phrase as the importance of a method is also not well-defined.)
An alternative approach to Carl's suggest depends on how large you envisage your system to grow. If it will grow to fewer than a few thousand classes, then you might consider having a script to copy your source code to a new directory, change all occurances of, ”private” to, ”public” in that copied source and then write your tests against the copied source. This has the down-side of the time it takes to copy the code but the benefit of preserving encapsulation your original source yet making all the methods testable in the copied version.
Below is the script I use for this purpose.
Regards,
Ed Kirwan
!/bin/bash
rm -rf code-copy
echo Creating code-copy ...
mkdir code-copy
cp -r ../www code-copy/
for i in find code-copy -name "*php" -follow; do
sed -i 's/private/public/g' $i
done
php run_tests.php
I have just read a great article on letting mock objects drive you design:
http://www.mockobjects.com/files/usingmocksandtests.pdf
When Carl says "you should sprout a class with that functionality", the author of this article explain how your tests can guide you, through the use of mock objects, how you can design your class so you 1) don't need to worry about not being able to test private parts, and more importantly 2) how this will improve your design by (I'll paraphrase Carls quote) discovering collaborators and roles with the right responsibility.
The author takes you through an example step by step to make his point very clear.
Here's another article with the same approach:
http://www.methodsandtools.com/archive/archive.php?id=90
A quote:
Many who start with TDD struggle with
getting a grip on dependencies. To
test an object, you exercise some
behaviour and then verify whether an
object is in an expected state.
Because OO design focuses on
behaviour, the state of an object is
usually hidden (encapsulated). To be
able to verify if an object behaves
like expected, you sometimes need to
access the internal state and
introduce special methods to expose
this state, like a getter method or a
property that retrieves the internal
state.
Apart from not wanting objects
cluttering their interfaces and
exposing their private parts, we
neither want to introduce unnecessary
dependencies with such extra getters.
Our tests will become too tightly
coupled and focused on implementation
details.
A group of agile software development
pioneers from the United Kingdom were
also struggling with this back in
1999. They had to add additional getter methods to validate the state
of objects. Their manager didn't like
all this breaking of encapsulation and
declared: I want no getters in the
code! (Mackinnon et al., 2000 &
Freeman et al., 2004)
The team came up with the idea to
focus on interactions rather than
state. They created a special object
to replace the collaborators of
objects under test. These special
objects contained specifications for
expected method calls. They called
these objects mock objects, or mocks
for short. The original ideas have
been refined, resulting in several
mock object frameworks for all common
programming languages: Java (jMock,
EasyMock, Mockito), .NET (NMock,
RhinoMocks), Python (PythonMock,
Mock.py, Ruby (Mocha, RSpec), C++
(mockpp, amop). See
www.mockobjects.com for more
information and links.
I'm currently rewriting an e-shop - but only the client side, i.e. the CMS remains mostly in tact. I am not using a pre-built framework, as the system has to retain backwards compatibility with the CMS and I have to have full freedom of the structure of code.
The new system is purely MVC based and I have a Bootstrapper which loads controllers based on the current uri and the latter use models for the real work - both with sessions and the database.
tl;dr It's my first project without a pre-built framework.
I am very inexperienced when it comes to design patterns. I know how do most of the popular ones work but have had never put them to use.
Now I am suspecting code smells because all of my models are classes that consist purely of static methods. I can find no advantages of doing them in a different manner. I routinely need some of the methods in various places through out the code. I.e. I need to fetch the logged in user in the main layout, check user rights to see current page in the bootstraper, display user panel by the controller. I'd need to re-instantiate an object each time or keep a global one if I wasn't using statics. There also won't be a need for more than one such class at a time.
I must be missing something, because even though I use OOP, some my classes are just meaningless containers for their methods (and sometimes a couple of private variables). I could have just been using PHP4 and simple functions.
Any comments or advice would be highly appreciated.
EDIT: in spite of all these educated answers, I remain unconvinced. Even though it's most probably because of my lack of experience, I still don't foresee anything going wrong with the current setup. I mean I don't even fathom a situation where I'd have any inconveniences due to the code architecture as it is now. I hope I don't get a harsh lesson when it's too late to change anything...
You are right, it's a code smell and everybody will tell you it's baaaad.
So here I suggest rather to make a self-assessment of the severity of the problem:
Do you have classes with many getter and setter?
Are your static functions like the one below?
If yes, try to move the logic in the class MyClass that will be already way more OO. That's a classic mistake from procedural/scripting world.
static void myMethod( MyClass anObject )
{
// get value from anObject
// do some business logic
// set value of anObject
}
Do you have a lot of global state, such as data you fetch from the current session?
If yes, make an assessment whether you want to change it. The OO way would be to pass the session down the call chain. But in practice, it's convenient to access the session as a global object. But it impedes testability. Try to remove some global state and turn that into regular object that you pass and manipulate in methods.
Make this assessment, and try to identify utility classes, services classes and the business objects. Utility class are helper classes with utility methods (e.g. formatting, conversion, etc.) which can be static. Service class do some business logic but they should be stateless and one instance suffice. Business objects are user, products, article, etc. is where you must concentrate your effort. Try to turn plain data into objects with embed some behavior.
Have a look at should entity be dumb. Even if it's for java, the concepts are general.
EDIT
Here is my analysis based on your comment:
You don't have a domain model with entities. You manipulate the database directly.
What you call your model, is what I call services and is where you perform the business logic that manipulate data. Service classes are stateless, which is correct. As you pointed out in the question, you then either need to constantly re-create them, create one global instance, or use static methods.
The OO paradigm would say that you should try to have a domain model where you map your database with entities. At least have an anemic domain model where entities are dull data container that are loaded/persisted in database. Then the OO paradigm would also say to put a bit of logic in the entities if possible.
It would also say to turn the services into objects to ease composition and reuse. If it was the case you could for instance wrap all services with an interceptor to start/stop transactions or do some security check, which you won't be able to do with static methods.
What you describe (no entities + stateless procedural services) is not considered a great OO design. I would suggest you introduce an anemic domain model at least and DAO. Regarding the sateless procedural services, this is actually the reality of many web applications -- if you don't need more you can stick to it.
My 2 cents
If you are mainly only using static classes then you've really taken out the object out of object oriented programming. I am not saying you are doing things incorrectly, I am saying maybe your system shouldn't lend itself to OOP. Maybe it is a simple app that requires some basic utility functions (sends email, etc). In this case most of your code becomes very procedural.
If you are dealing with databases you could have a static db class, and a simple business layer, and your php app interacts with your business layer which in turn interacts with your database layer. This becomes your typical 3-tier architecture (some people like to refer to this as 4 t-iers and seperate the actual database from the data layer, same thing).
If you are not really calling methods that require an object than what is the point of all of these static classes, just a question to ask yourself.
One thing you may notice is that if you plan on doing any kind of unit testing with mocking/stubbing you are probably going to have a hard time since static classes and methods are not easy to mock, stub or test.
I would be cautious about using static variables and classes in web applications. If you really must share an instance between users, then it should be ok to have a single instance (lookup "Singleton" design pattern).
However, if you trying to maintain state across pages, you should do this through either utilising the ViewState or by using the Session object.
If you were to have a global static variable, you could have a situation where concurrent users are fighting to update the same value.
Short answer: It's ok but you are foregoing the benefits of OOP.
One reasoning behind using objects is that most of the time there is more than one type of object that performs a role. For example you can swap your DBVendor1 data access object with a DBVendor2 data access object that has the same interface. This especially handy if you are using unit tests and need to swap objects that do real work with dummy objects (mocks and stubs). Think of your objects with the same interface as Lego bricks with different colors that fit together and are easily interchangeable. And you simply can't do that with static objects.
Of course, the increased flexibility of the objects comes at a price: The initialization of the objects and putting them together is more work (like you wrote) and leads to more code and objects that put together other objects. This is where creational design patterns like builder and factory come into play.
If you want to go that route, I advise you to read about dependency injection and using a DI framework.
Technically there is nothing wrong in doing it. But practically you are loosing lot of the benefits of object oriented programming. Also write the code/functionality where it belong to.. for example:
user.doSomeTask()
on the user object makes more sense than
UserUtils.doSomeTask(User user)
Using OOP concepts you abstract the functionality where it belongs to and in future it helps you change your code, extend the functionality more easily than using the static methods.
There are advantages to using static methods. One being that since you cannot inherit them they perform better. But using them all of the time limits you. The whole OOP paradigm
is based on re-usability of base classes thorough the use of inheritance.