Class attribute visibility Vs. Interface
Quote:
Originally Posted by
Jasper Bekkers
The thing is, if you make your private methods publicly accessible you know for sure that someone will err.
I know this should have been solved by the 'moron' by using and Adapter + factory or some other fancy way to abstract your library.
The developer is not supposed to know what functions are public or private, unless you specify it. That's why I believe specifying the visibility is part of the documentation and development process. The same goes for unit testing, exceptions… Moreover it's important to provide third-party developers with interfaces instead of a bunch of public functions that change every release. An interface never changes and if a redesign is required, then a new interface is provided.
Accessibility and listing elements in a message
I saw lastcraft and Wheeler are not using lists to enumerate elements. Know that it makes messages unaccessible to visually-impaired people for example. Using characters * and - is not a good idea, better use the message editor list feature :And thanks for posting :)
The Wheeler Coding Process™
Quote:
Originally Posted by
wheeler
thanks to all for the intellectual debate so far, I suppose it is a shame that there is not a set format to learning and coding PHP OOP but I guess we can blame that on the language itself for being so loose; there are so many ways to achieve the same thing, so naturally everyone develops their own interpretation. Must be one of those greatest strength, greatest weakness things.
Think the development kingdom as an ecosystem, a living organism, better have hundreds of species than a bunch of dead worms coding around :x. PHP OOP ? Seperate the language from the programming methodology. Pick your language, pick your method. Test Driven Development/eXtreme Programming ? Unified Process ? Wheeler Coding Process ? See you're already immortal, among the Gods of Development :cool:
Quote:
Originally Posted by
wheeler
of the db classes i've looked at, they tend to have a method to connect rather than having it in the constructor. But my thought is that I use the db on virtually every page, so it makes sense to always connect
Think simple. What's the aim of a constructor ? To build an object, not to connect to a database. You also shouldn't think of what you want but what others would want. For example I prefer to construct my object first then call its functions. Build a database object and connect to it. That way I have better control other the application flow. If the construction fails, I can report the problem. If it's a success, let's connect…
In the procedural programming paradigm it's important not to develop functions that do too many actions : construction, connection… It makes the code much more reusable. Fundamental rule : reusability. And of course is also works when OOPing :eye:
Quote:
Originally Posted by
wheeler
I don't yet have an error handling class to compliment any problems that may arise
I second what someones said about using exceptions. You can't just clutter your OO code with hundreds of error handling calls, tests…
Quote:
Originally Posted by
wheeler
I can't work out how I should handle and display an array of results
Check out the PEAR database packages and the way fetched results are handled as objects. The PHP 5 Iterator interface is really useful to parse a results set using foreach.
I also have some great online references on these subjects if you're interested : ActiveRecord, Object-Relational Mapping (ORM)…
Quote:
Originally Posted by
wheeler
'MySQL' might be a better class name than 'db'
MySQL, db… these are too generic names that anyone could pick. My advice is to prefix your class names, as PHP 4/5 lacks the namespace feature. It avoids conflicts with other classes, frameworks, your own projects… Why don't you coin some nice name for your project ? The Wheeler Framework ? An other solution is to prefix your classes with a short URL. For example if your project was hosted at "wheelerdb.sf.net" you would name your class "wheelerdb_sf_net_db". I know it's long but it's an example. I have a C++ and Java background so… it probably makes me an evil PHP 5 developer :lol:
About naming your class MySQL, I think it's a bad idea. What will happen if you decide to switch to PostgreSQL ? Don't make the assumption you'll ever stick to MySQL, PHP history. At first there was a bunch of PHP 4 functions, then some pseudo-classes emerged… then packages in some fruity framework… and now PDO. What's next ? :confused:
Quote:
Originally Posted by
wheeler
Despite all of that, i'm already loving writing "query()" instead of "mysql_query"! :)
Welcome to the VIP party of highly lazy but more efficient developers :D
Quote:
Originally Posted by
wheeler
PHP Code:
var $affected;
function affected()
{
$this->affected = mysql_affected_rows($this->conn);
return $this->affected;
}
You were right, your code lacks privacy. Better private the variable as no one is supposed to access it. It's also important to choose a naming convention. $affected and affected() ? Affected what ? Rows ? Then name your variable $affected_rows. What's the aim of the function ? Document it using PHPdoc : aim, parameters, returned value… What does it do ? It returns the affected rows ? Then name it something like get_affected_rows() or getAffectedRows() depending of your conventions. Remember that a function always perform an action. I think I mentionned in a previous post, maybe in an other thread…
If you don't document your code and choose self-explicit names, you'll never be able to understand your own code in a few months.
Quote:
Originally Posted by
wheeler
PHP Code:
## CONNECT ##
function __construct($username=NULL, $password=NULL, $db_name=NULL, $host='localhost', $port=3306)
{
$conn = mysql_connect($host . ':' . $port, $username, $password);
if (!$conn) exit('<p>' . ERROR_TXT . '</p>');
if (!mysql_select_db($db_name, $conn)) exit('<p>' . ERROR_TXT . '</p>');
// assign the db details (excluding password) for future reference
$this->username = $username;
$this->db_name = $db_name;
$this->host = $host;
$this->port = $port;
$this->conn = $conn; // create the db resource handler
}
Again using PHPdoc (/** */) instead of these ## comments. It specially useful for complex functions, your constructor is. It connects to the database, handle errors, select the database and initialize the attributes… Separate things, make things simpler. Use exceptions instead of if if if… What if you're not supposed to output HTML ? What if the developer wants to handle errors using his own system ?
Of course I'm a bit picky but It's important to think outside the box. It's easy to quick & dirty code and in a few months… you'll just flush the class :blush:
Quote:
Originally Posted by
wheeler
PHP Code:
## ERRORS ##
function getError()
{
$this->error = mysql_error($this->conn);
$this->errorno = mysql_errno($this->conn);
return 'Code: ' . $this->errorno . ' Text:' . $this->error;
}
Coding your own error handling system is a lot of fun. Don't hesitate to dig into the PEAR framework manual, its code too. All functions from the database package return an object for example. It can be the results set you just queried… or an error object. It makes coding a breeze.
Seperating the error handling from the database management is also important because you often have to reuse your error handling functions. Again, think reusability. Encapsulating them would allow you to define different methods : output HTML error messages, log them in a file…
About that function, again, it does too many things. It's a simple one so a good example. getError() initializes attributes, build up an error message and returns it. What if I need the error number ? What if I want to format the error message ? Is a getError() function really supposed to return a string ? What's an Error ? An object ? A code ? Again, see PEAR. In the object parallel dimension a develop would expect an object, not a string.
Sorry for the mess, I hope my reply makes sense, if not :injured:
"inter-class communication"
yep, I made that name up all by myself... i'm sure there is a technical term for it ;)
now that some basic ideas are starting to fall into place, I seem to have a real problem communicating between classes.
As an example, right now I have to:
a) instantiate a page class that handles header, footer, meta tags etc.
b) instantiate a session class that checks the permission level requirement of the current page and whether the user has sufficient privilege/is logged in
c) instantiate a database class to do typical database stuff
So on edit-account.php, say if I wanted to access a db method, I would have to go: $page->session->db->query("SELECT ..."); :nono:
These 3 classes need to do a certain amount of talking to one another. My approach is to have absolute bare minimum code on the "view" pages (though i'm still miles away from understanding MVC), so I want to instantiate a Page and have the session and databases setup straight away. The flow is:
1. create a new page eg. edit-account.php
2. right away require the page class, passing the required permission (eg. guest/member/admin)
3. calling the Session class in the Page __construct, and immediately determining if the user is authorised access
4. if authorised, instantiate DB class and connect right away, otherwise redirect to login.php
I understand that one of the gains of OOP is to create reusable code, and to abstract classes into a the most accurate possible definition (eg. a dog is a dog, is a canine, is an animal, if necessary I should burrow down to a dog class).
But without perhaps grasping exactly what I should be doing particularly with object-to-object communication, I have a sneaking suspicious I will end up with a pile of spaghetti... well I guess thats inevitable but at least it could be tasty, authentic spaghetti :)
Is the easy beginners way to communicate between objects to pass objects at __construct time? put in a require() mid-method? These seem unlikely but I can't think of any other alternatives...