Fat Page Controllers?
Moderator: General Moderators
- volomike
- Forum Regular
- Posts: 633
- Joined: Wed Jan 16, 2008 9:04 am
- Location: Myrtle Beach, South Carolina, USA
Fat Page Controllers?
Is it typical, when you're on a tough deadline, to make fat page controllers and thin or few models, saving that for a later refactoring phase, such as phase 2 of a project? Because that's what I'm experiencing right now. I hope on a phase 2 to create domain models and then start refactoring by the patterns on this list:
http://en.wikipedia.org/wiki/Design_pat ... r_science)
(Great list with good explanations, FTW!)
And I think I "get" this Domain model stuff. I used to call them Entity Objects until I learned this term "Domain". I meant something that an end user might understand, such as Accounts, Users, Banks, Payments, Products, Catalog, Ads, etc. You implement them in your models subfolder so that you're not doing ORM or DB class calls from your page controllers. It's the first phase of making models, and then start refactoring from there.
For those who actually have time, I guess you'd whiteboard your entire set of design patterns and then start building something, or reuse a design pattern that worked for a particular project task, but I don't have that luxury right now.
http://en.wikipedia.org/wiki/Design_pat ... r_science)
(Great list with good explanations, FTW!)
And I think I "get" this Domain model stuff. I used to call them Entity Objects until I learned this term "Domain". I meant something that an end user might understand, such as Accounts, Users, Banks, Payments, Products, Catalog, Ads, etc. You implement them in your models subfolder so that you're not doing ORM or DB class calls from your page controllers. It's the first phase of making models, and then start refactoring from there.
For those who actually have time, I guess you'd whiteboard your entire set of design patterns and then start building something, or reuse a design pattern that worked for a particular project task, but I don't have that luxury right now.
Re: Fat Page Controllers?
It's not about having time, it's more about having experience and comfort level in applying those patterns. I always start with domain modeling, since it will reflect on almost everything interesting in the application - after all, most of the difference between applications is their domain logic, the rest is just reusable generic logic (for which hopefully, you have a good framework) or interface.
Encapsulating domain logic in models should save you time and effort not the other way around.
Encapsulating domain logic in models should save you time and effort not the other way around.
Re: Fat Page Controllers?
Maybe I am one of those people having too much time and thinking about how I can make my models fatter and controllers thinner
viewtopic.php?f=19&t=93011
I know what I want, my only problem is my limited ability to code it
viewtopic.php?f=19&t=93011
I know what I want, my only problem is my limited ability to code it
- volomike
- Forum Regular
- Posts: 633
- Joined: Wed Jan 16, 2008 9:04 am
- Location: Myrtle Beach, South Carolina, USA
Re: Fat Page Controllers?
This is probably why you're so darn fast on your projects. I recall reading a prior post from you about that and I was like, wow. Coding speed. Got to get me some of that.pytrin wrote:It's not about having time, it's more about having experience and comfort level in applying those patterns. I always start with domain modeling, since it will reflect on almost everything interesting in the application - after all, most of the difference between applications is their domain logic, the rest is just reusable generic logic (for which hopefully, you have a good framework) or interface.
Encapsulating domain logic in models should save you time and effort not the other way around.
Re: Fat Page Controllers?
Yeah, once all those "design patterns" and frameworks fell together for me, my productivity went through the roof. Almost all the repeating logic (approaching but never reaching the 100% limit) between my projects has been abstracted away, leaving just the domain logic and user interface to take care of. I would say approximately 60% of my time on projects now is spent implementing the UI (HTML/Javascript), 20% modeling the database and building models from it, and 20% creating the application flow logic.
True story, I'm in the process of closing a project now for rebuilding a site. The site was built three years ago by a shoddy web company that used their own proprietary framework (ugh..) and now has more security issues and bugs than you can imagine. I gave the client an estimate of 17 - 21 days for the completion of the project (mostly a mini-sites CMS with photo galleries and some shopping cart options). The client had some trouble believing my schedule estimate, he said - "the original project took 7 months to complete"
(Well I'd imagine it was so, if the company used that time to also build their terrible framework, and trying to use that framework to build the site...)
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: Fat Page Controllers?
Personally, my "productivity" at least in terms of intial development of a project took a nose dive.
I spend far more considering design, with each and every pattern I pick up on any given week or month or whatever.
That is time that I could spend "hammering" out code in a monolithic/transaction script manner but when design suffers the project suffers.
I think tools, like frameworks, scaffolding generators, etc will speed up your (MY) development but understanding of design patterns alone, not so much. Certainly experience plays a huge factor, even without knowledge of "formal" good design. Knowing what techniques, tools or technologies are best suited for a particular project, is what makes the biggest difference, IMHO.
Example: I have been out in terms of time by junior developers because their ignorance of good design let them focus strictly on getting the project finished ASAP, using horrible code libraries that I wouldn't consider using in a million years, but they were completely unaware of repercussions and just "got the job done".
Cheers,
Alex
I spend far more considering design, with each and every pattern I pick up on any given week or month or whatever.
That is time that I could spend "hammering" out code in a monolithic/transaction script manner but when design suffers the project suffers.
I think tools, like frameworks, scaffolding generators, etc will speed up your (MY) development but understanding of design patterns alone, not so much. Certainly experience plays a huge factor, even without knowledge of "formal" good design. Knowing what techniques, tools or technologies are best suited for a particular project, is what makes the biggest difference, IMHO.
Example: I have been out in terms of time by junior developers because their ignorance of good design let them focus strictly on getting the project finished ASAP, using horrible code libraries that I wouldn't consider using in a million years, but they were completely unaware of repercussions and just "got the job done".
Cheers,
Alex
Re: Fat Page Controllers?
Understanding design patterns AND having a good reusable implementation of it (ie, frameworks) is a big productivity boost. Design patterns are generally accepted good solutions to many common problems - if I have a good solution for most of my needs that I'm well familiar with, I don't need to solve those needs again - they're solved. More time spent on domain specific logic and UI.
- volomike
- Forum Regular
- Posts: 633
- Joined: Wed Jan 16, 2008 9:04 am
- Location: Myrtle Beach, South Carolina, USA
Re: Fat Page Controllers?
So how are you guys taking less time on helping your clients come to terms on their functional spec docs? I mean, a classic example is that I get a functional spec and it says, "Users need to be able to edit each of the sections of their profile." But then you find out after you've started the project that he wants it via AJAX, it needs a progress bar, and he wants expand and collapse effects for the section. As in, you go over a profile section, and edit button appears, you click Edit, the section collapses and re-expands with a progress bar, an AJAX request for the form occurs, the section collapses again and then re-expands with the form. And posting would be the reverse visual effect of that, but with updated content now that the form is posted. That sort of thing wasn't in the functional spec, but it's a contract over $10K that you've already started to get paid for, and so you feel obligated to just shrug your shoulders, go oh well, and get it done as fast as you can.
And for those of you who say they can build like a social networking site in 2 months, complete with AJAX, jQuery visual effects and doodads, and lots of cross-browser testing, all from your own code (except whatever ships with a framework like Skeleton or Zend) -- what kind of statement are you making when you hit that 2 months, let's say, and need another 2 to 3 weeks to complete it, but are paid by the hour? (Or, paid a fixed bid?) It's a tough thing to negotiate sometimes.
I think the next time I do a functional spec, I'm going to search on all the verb phrases, and especially "need to" and "needs to", or "should", and ask for more clarification on the finer details. Then, it would be ideal if the designer could draw every screen about 80% pixel perfect, then run it through the chopper so I get some XHTML templates, and then give it to me for me to worry about the web development. But I tried that on my last project and it didn't work.
And for those of you who say they can build like a social networking site in 2 months, complete with AJAX, jQuery visual effects and doodads, and lots of cross-browser testing, all from your own code (except whatever ships with a framework like Skeleton or Zend) -- what kind of statement are you making when you hit that 2 months, let's say, and need another 2 to 3 weeks to complete it, but are paid by the hour? (Or, paid a fixed bid?) It's a tough thing to negotiate sometimes.
I think the next time I do a functional spec, I'm going to search on all the verb phrases, and especially "need to" and "needs to", or "should", and ask for more clarification on the finer details. Then, it would be ideal if the designer could draw every screen about 80% pixel perfect, then run it through the chopper so I get some XHTML templates, and then give it to me for me to worry about the web development. But I tried that on my last project and it didn't work.
Re: Fat Page Controllers?
One of the most important parts of the project is the specification meeting with the client. I never accept a specification document blindly and always prefer to make my own after a face-to-face with the client, going over the entire requirements. During development, I try to have at least another meeting per week to see that we are still seeing eye-to-eye on the development direction.
Regarding things like later asking me to make things that are not specified in the requirements (changing a regular page refresh into an ajax request with a loading bar) - then depending on how long it will take me I'm likely to refuse without compensation. If it will take me more than two hours to make the change (or if there are plenty of small changes), then I stand my ground regarding costs. It's important to do this from the start - once the client understand that changes that might seem minor to him might have larger repercussions and will cost him money - the amount of unnecessary changes drops to an acceptable threshold.
I recently completed a project in which I was really diligent on the requirements, and the client cut some features due to his budget constraints. He later tried to push those features back in through the backdoor, and I had to remind him that he could have had those features, but he wasn't willing (and still unwilling) to pay for it.
Our time is valuable, we need to make clients understand that.
Regarding things like later asking me to make things that are not specified in the requirements (changing a regular page refresh into an ajax request with a loading bar) - then depending on how long it will take me I'm likely to refuse without compensation. If it will take me more than two hours to make the change (or if there are plenty of small changes), then I stand my ground regarding costs. It's important to do this from the start - once the client understand that changes that might seem minor to him might have larger repercussions and will cost him money - the amount of unnecessary changes drops to an acceptable threshold.
I recently completed a project in which I was really diligent on the requirements, and the client cut some features due to his budget constraints. He later tried to push those features back in through the backdoor, and I had to remind him that he could have had those features, but he wasn't willing (and still unwilling) to pay for it.
Our time is valuable, we need to make clients understand that.
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: Fat Page Controllers?
Getting the specs right the first time is near impossible...and probably one of the most difficult parts of SDLC. I feel your pain.That sort of thing wasn't in the functional spec, but it's a contract over $10K that you've already started to get paid for, and so you feel obligated to just shrug your shoulders, go oh well, and get it done as fast as you can.
My next bid is going to be like this...I hammer out the specs...we agree or make adjustments. I offer an estimate and start development. When a change is made by the client (like adding AJAX) that is a change that was not specified in the original spec document and therefore a re-estimate is required.I think the next time I do a functional spec, I'm going to search on all the verb phrases, and especially "need to" and "needs to", or "should", and ask for more clarification on the finer details. Then, it would be ideal if the designer could draw every screen about 80% pixel perfect, then run it through the chopper so I get some XHTML templates, and then give it to me for me to worry about the web development. But I tried that on my last project and it didn't work.
Changes happen in software...usually those changes are "feature requests" and occassionally those requests are "drop this feature" but in either case, it takes time which should cost money.
My biggest problem is keeping track of the specs document and keeping it sync'ed with the project...while allowing client collaboration...it's a tedious task and also takes time...time I don't normally account for in initial estimates, just like project planning, phone conversations, communications, etc...if I did my estimates would be a lot higher and I would likely lose bids to India or other such markets. This is the unfortunate reality of being a freelance developer I suppose.
Amen...my biggest failure as a freelance developer is with handling the business side of things. I never cared much for negotiating or wheeling and dealing and unfortunately that is an integral part of being a freelance developer. It seems so petty to charge someone for a phone conversation, but my problem now is I have 4 or 5 a week each of which last an hour which I am not paid for. Something is seriously wrong with that picture. On a per client basis, to them it's nothing as it's only an hour of their week, but add that up for me and it's a full day of pay unpaid per week.I recently completed a project in which I was really diligent on the requirements, and the client cut some features due to his budget constraints. He later tried to push those features back in through the backdoor, and I had to remind him that he could have had those features, but he wasn't willing (and still unwilling) to pay for it.
Our time is valuable, we need to make clients understand that
Ugh...we should start a support group for freelance developers...a coallition of freelance developers
Mike, you seem to have good business sense, I elect you as chairman of the board
Cheers,
Alex
Re: Fat Page Controllers?
I've noticed, that user requirements always change (in minority), so I put a 20% overtime after estimating the project in order to cover these changes without renegotiating - that keeps me and my client pleased and saves time.pytrin wrote:Regarding things like later asking me to make things that are not specified in the requirements (changing a regular page refresh into an ajax request with a loading bar) - then depending on how long it will take me I'm likely to refuse without compensation. If it will take me more than two hours to make the change (or if there are plenty of small changes), then I stand my ground regarding costs.
And yes - a list of detailed user reqirements (signed by the client) is a must!
There are 10 types of people in this world, those who understand binary and those who don't
Re: Fat Page Controllers?
I actually put 30% overhead in every project. I need that 30% to last the entire project though, so when a feature estimated at 2 hours for example, suddenly grows to 5 hours I usually give the client a price quote for the changes. It completely depends on the scope of the project and the stage you are at, and also on judging the type of client you are dealing with.I put a 20% overtime after estimating the project
That's very true. I've recently began a move to merge all of my freelance activities under a registered company with two other partners, so I could charge the extra maintenance of project management and other overheads. This time I will be positioned against other companies who do the same, and so hopefully this will have the desired effect.My biggest problem is keeping track of the specs document and keeping it sync'ed with the project...while allowing client collaboration...it's a tedious task and also takes time...time I don't normally account for in initial estimates, just like project planning, phone conversations, communications, etc...if I did my estimates would be a lot higher and I would likely lose bids to India or other such markets. This is the unfortunate reality of being a freelance developer I suppose.
- volomike
- Forum Regular
- Posts: 633
- Joined: Wed Jan 16, 2008 9:04 am
- Location: Myrtle Beach, South Carolina, USA
Re: Fat Page Controllers?
Here's a short scenario for you guys. Perhaps you can help me understand your design pattern on this one and then I think I can get the hang of it from there...
Photo upload with a profile scenario -- what would you be doing from the page controller with your models to implement the following?
1. I read an ID of the user from the cookie I created on their login.
2. I read whether they want the photo marked as private, or to reset to no photo -- two fields from a posted ajax form request coming in to me via $_POST.
3. I read the posted file name and its file extension.
4. if the file is not empty and if this is not a reset request (reset to no photo), then I check file extension. If not .jpg, .gif, or .png, I reject the request with an error message I post back over AJAX. In my case, all I have to do is do die('ERROR: The file extension is incorrect.') and the AJAX I have set up handles the response and parses it to display in an error box.
The part on # 4 is that I check if the file size is over x number of bytes from my central conf file that I have created, which is loaded up into a $Settings object with object properties.
5. If we receive a new file, or if this is a reset request, we then delete the original one out of the file system. I'll need to fire up the ORM to get that value so I know which one to delete.
6. We rename the uploaded file from /tmp into our designated photo space in uploads. I have a routine that handles this for me in a static class called Image, and it also does "smart cropping" to determine the general shape of the image and crop and/or optionally resize it into portrait mode in the size that I need.
7. I then use the ORM to write a new file into the profile field in the database table for this user, but before I do that, I can't have people guessing photo paths, so I use a special encoding scheme. The first part is a random 10 digit number and a dash. The second part is the ID number of the user (for me to visually find their photo if necessary, by hand) and a dash. The last part is a CRC (crc32()) on the first two so that I know the field isn't hacked. I then write the new file name into the table.
8. I run a special die() statement that I have composed that tells the AJAX on the receiving end to make a call to update that section of their profile so that it shows the new photo they have uploaded.
Photo upload with a profile scenario -- what would you be doing from the page controller with your models to implement the following?
1. I read an ID of the user from the cookie I created on their login.
2. I read whether they want the photo marked as private, or to reset to no photo -- two fields from a posted ajax form request coming in to me via $_POST.
3. I read the posted file name and its file extension.
4. if the file is not empty and if this is not a reset request (reset to no photo), then I check file extension. If not .jpg, .gif, or .png, I reject the request with an error message I post back over AJAX. In my case, all I have to do is do die('ERROR: The file extension is incorrect.') and the AJAX I have set up handles the response and parses it to display in an error box.
The part on # 4 is that I check if the file size is over x number of bytes from my central conf file that I have created, which is loaded up into a $Settings object with object properties.
5. If we receive a new file, or if this is a reset request, we then delete the original one out of the file system. I'll need to fire up the ORM to get that value so I know which one to delete.
6. We rename the uploaded file from /tmp into our designated photo space in uploads. I have a routine that handles this for me in a static class called Image, and it also does "smart cropping" to determine the general shape of the image and crop and/or optionally resize it into portrait mode in the size that I need.
7. I then use the ORM to write a new file into the profile field in the database table for this user, but before I do that, I can't have people guessing photo paths, so I use a special encoding scheme. The first part is a random 10 digit number and a dash. The second part is the ID number of the user (for me to visually find their photo if necessary, by hand) and a dash. The last part is a CRC (crc32()) on the first two so that I know the field isn't hacked. I then write the new file name into the table.
8. I run a special die() statement that I have composed that tells the AJAX on the receiving end to make a call to update that section of their profile so that it shows the new photo they have uploaded.
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: Fat Page Controllers?
Something about that would make me cautious. I never store anything in COOKIE unless I absolutely have to. User ID's are best stored in SESSION just incase you ever rely on that COOKIE variable directly somewhere by accident without checking other settings, a COOKIE is easily forged.I read an ID of the user from the cookie I created on their login.
Don't rely on the file type. Check the magic bytes or similar to confirm your dealing with an JPG and not a PHP script disguised as a JPG4. if the file is not empty and if this is not a reset request (reset to no photo), then I check file extension. If not .jpg, .gif, or .png, I reject the request with an error message I post back over AJAX. In my case, all I have to do is do die('ERROR: The file extension is incorrect.') and the AJAX I have set up handles the response and parses it to display in an error box.
Not sure I understand. Why can't people guess file paths? All they have to do is check the HTML source to figure out your scheme.but before I do that, I can't have people guessing photo paths, so I use a special encoding scheme. The first part is a random 10 digit number and a dash. The second part is the ID number of the user (for me to visually find their photo if necessary, by hand) and a dash. The last part is a CRC (crc32()) on the first two so that I know the field isn't hacked. I then write the new file name into the table.
Anyway, the model (strictly defined) would encompass the moving of the file to appropriate location, checking the type, size, and magic bytes, updating the database field, etc.
Uploading would be (IMHO) a controller action but is handled intrinsically by the browser. You would access the $_FILES['tmp_name'] inside the controller and assign that as well as the original file name (if needed -- but it sounds like you autogenerate?) to the model via parameters. In my framework, $_FILES is actually a composite of the REQUEST object so it's actually prepared before the controller layer however if you rely on superglobals and not objects, then I would suggest all this happen in the controller.
The action controller for an upload would be very lightweight, almost to th epoint where it wouldn't make sense to implement.
Code: Select all
$userID = (int)$_SESSION['userID'];
$temp = $_FILES['tmp_name'];
$model = new AccountModel();
$model->uploadPhoto($userID, $temp);
Code: Select all
$userID = (int)$_SESSION['userID'];
$temp = $_FILES['tmp_name'];
$model = new AccountModel();
if($ajax === TRUE){
$model->uploadPhoto($userID, $temp);
echo $model->getErrorMessage(); // NOTE: No redirection required in AJAX just echo the error message if any
}
else{
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$address = $_POST['address'];
$model->uploadAccount($userID, $temp, $fname, $lname, $address);
if($model->getErrorCode()){ // Return 0 on success 1> on failure
redirect('header: error.php?code='.$model->getErrorCode());
}
redirect('header: success.php');
}
Cheers,
Alex
- volomike
- Forum Regular
- Posts: 633
- Joined: Wed Jan 16, 2008 9:04 am
- Location: Myrtle Beach, South Carolina, USA
Re: Fat Page Controllers?
Thanks, PC Spectra, for looking at this. I think I get what you mean now. I basically take the "meat" of the hard work I was doing in the page controller, and make a decision whether it deals with generic input. If it does, then I could fatten the controller helper library (in my case Controller::blahblah) to handle this, or use the existing class methods that are there if I have them. If it doesn't and doesn't deal with output, then it goes into a model. I see you created a one-level model here with a domain model -- AccountModel. (Sidebar: Perhaps later on you could show me a case where you recently implemented a two-level model tree such as Bank, which holds Accounts and Transactions as children, for instance -- I would be curious to see how you implemented such a thing. I have my own notions, but I like to see what others have done.) And if it does deal with output, then I push the logic to the view.
On your other items:
> a COOKIE is easily forged
Not this one. Tee hee. Session vars occupy tmpfs (RAM + disk, because shared memory uses that, right?), and we want to conserve as much RAM as possible for everything else, such as database queries and so on, so we use encrypted and slightly compressed cookies instead, but only for storing very tiny things. Anything larger will be database I/O or, yes, we'll consider a Session var.
> Magic bytes.
I'll have to read up on that one. Didn't know I should do this, but you make sense.
> Guessing file paths.
The only photo they can find is their own. There is no way to find other file paths to see other profile photos. Not unless they reverse engineer the photo path scheme, and that requires an understanding of how and where I placed the crc32() check, which is hard to determine without seeing the original source. The source I provided here was just an example.
Again -- thanks.
On your other items:
> a COOKIE is easily forged
Not this one. Tee hee. Session vars occupy tmpfs (RAM + disk, because shared memory uses that, right?), and we want to conserve as much RAM as possible for everything else, such as database queries and so on, so we use encrypted and slightly compressed cookies instead, but only for storing very tiny things. Anything larger will be database I/O or, yes, we'll consider a Session var.
> Magic bytes.
I'll have to read up on that one. Didn't know I should do this, but you make sense.
> Guessing file paths.
The only photo they can find is their own. There is no way to find other file paths to see other profile photos. Not unless they reverse engineer the photo path scheme, and that requires an understanding of how and where I placed the crc32() check, which is hard to determine without seeing the original source. The source I provided here was just an example.
Again -- thanks.