Code Reuse

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

I agree, Subversion is a terrible tool for deployment. So, don't use it for deployment. Try something like the pear installer.

One big problem that I've seen before is trying to put too much under SCC. For example, trying to manage all of your libraries and tool dependencies with SCC. Personally, I never use externals, nor do I check in code libraries that I haven't written. Been there, done that, bad news.
Well, that's exactly what I was doing. I was under the impression that Subversion would cope with that. I bought a copy of the PEAR Installer Manifesto but it told me nothing. I couldn't find any basic PEAR installer tutorials for deploying applications.
If you want to be productive, you should be acquiring most of this code from third parties.
Well that really depends on the quality of that third party code. Certainly when it comes to third party code in PHP 97% of the time I can do a better job myself. I'm referring specifically to the lack of TDD practise.
Architectural code is where the action is in PHP right now. This code is moderately reusable.
I've seen foundation libraries before they nearly always seem superfluous to me, especially considering PHP's existing function library. So naturally the community is interested in architectural code.
Robert martin has a lot of writing on the relationship between deployment, dependencies and reuse in his book "Agile Software Development."
Do you mean this
The Release-Reuse Equivalency Principle - The granule of reuse is the granule of release
The Stable Dependencies Principle - Depend in the direction of stability
The Stable Abstractions Principle - A package should be as abstract as it is stable.
The Common Closure Principle - The classes in a package should be closed together against the same kinds of changes. A change that affects a closed package affects all the classes in that package and no other packages.
The Common Reuse Principle - The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all.
The acyclic dependencies principle - Allow no cycles in the package dependency graph
Where can I find more information about these?
I totally agree that OO code can be expensive to write. However, I find the big payoff not to be in development time, but in reliability. For me, OO code is easier to test and maintain.
Well if it's doing those things then it should be saving you time. The thing I was trying to do was generalize to the point that I'd achieve high level reusabilty. I was writing my own framework as I worked but I found that it couldn't be justified in a business sense. Basically this idea people have about writing their own frameworks is a bit wank. You won't save time by doing that.
arborint wrote:Because you are complaining about problems most people accept but that zealots argue about.
I'm thinking about it now in heignsight, I've wasted a lot of time, I think it's important I consider why.
As to your reuse problems, it is not clear whether you are any different that me -- except that you have higher expectations. I do get a fair about of reuse from my codebases, but that is more form getting similar problems to solve. Continuous upgrading is still a problem though.
Well the annoying thing is, as I outlined in my original post, there are probably ways to achieve what I want to achieve but it required more knowledge and experience on my part and the certain technologies need to mature a bit.
sike wrote:my current strategy is to get the project done and generalize only parts of my code base if i see similarities from previous projects (aka harvested frameworks). this works out ok thus far but i have to admit that the resulting "framework" is more of a library of building blocks for most of the projects i do.
Yes, I think this is what I should be doing. Well, that was my initial intention and then you read back the code and go "oh I can remove a dependency here" and "i'll improve the interface here" and before you know it you are spending weeks generalizing.
Selkirk
Forum Commoner
Posts: 41
Joined: Sat Aug 23, 2003 10:55 am
Location: Michigan

Post by Selkirk »

The PEAR installer isn't perfect, but its the tool we have. Its definitely getting better and installing applications is one of the stated use cases they are moving forward. I have the manifesto as well. What didn't you find missing?

There are always shell scripts and rsync.

Like I said, I would consider libraries like Swift Mailer and HTML purifier to be foundation libraries. I'm not talking about those over designed things that try to define a string class or something like that. The requirement for a test suite is good, but I think for many libraries it would be better to use a mature library with no test suite than an immature one with tests.

Yeah, Thats the book I meant. more reading here.
ole wrote:I was writing my own framework as I worked but I found that it couldn't be justified in a business sense. Basically this idea people have about writing their own frameworks is a bit wank. You won't save time by doing that.
Quoted for truth.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Well that really depends on the quality of that third party code. Certainly when it comes to third party code in PHP 97% of the time I can do a better job myself. I'm referring specifically to the lack of TDD practise.
More like 99.999% ;). Seriously though, it's gotten a lot better in the last two years.
The PEAR installer isn't perfect, but its the tool we have. Its definitely getting better and installing applications is one of the stated use cases they are moving forward. I have the manifesto as well. What didn't you find missing?
The PEAR2 Installer being developed: http://blog.pear.php.net/2007/06/03/mee ... installer/
I think PEAR's documentation is the big let down right now. To create a PEAR package is actually dead simple - but it's not presented in just one place - rather scattered across a few Manual locations.
Basically this idea people have about writing their own frameworks is a bit wank. You won't save time by doing that.
You save time by taking a free framework, using it constantly, tweaking it as required, and getting to know it inside and out. And you never move to another framework without a really good reason. The only good reason for writing a new framework is if you're learning by doing on your own time (honestly never saw a better OOP lesson than writing a framework ;)).
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

I'm closely following this discussion, but I'd like to pipe in about the PEAR installer: I've found this document to be quite useful in deploying PEAR for HTML Purifier. As usual, looking at existing code is quite helpful in figuring things like this out.

I've found that having live code load directly out of SVN does not cause very many major problems, only that: 1. performing the commit takes a while due to the large run-time of the post-commit hook and 2. the files are not updated instantaneously. The externals worked reasonably well too, although it's somewhat annoying to have to bump the directory numbers every time there's a version upgrade (I could make a shell script to do that though). What circumstances caused conflicts in svn:externals? Also, wouldn't it be possible to do a dry run first and throw warning bells if a conflict occurs? Deployment with Subversion, I think, is definitely possible.

I do agree, however, with your assessment on the expensiveness of merges. It sounds like you demand a measure of stability and parallel development that is difficult to do efficiently in Subversion. For me, Subversion has worked well, since my process usually entails develop develop develop TAG develop develop, etc. I feel your pain when it comes to maintaining two parallel branches, and that video made me seriously look at git (still wary about possible degradation of performance on Windows, so we'll see).

One final note: PEAR deployment is very coarse grained. You'll need to package, increment the version number, and re-publish every time you want a new version out, whereas version control can handle it with a mirror of a stable branch (something git does better than Subversion, but both can do).
Selkirk
Forum Commoner
Posts: 41
Joined: Sat Aug 23, 2003 10:55 am
Location: Michigan

Post by Selkirk »

One issue that is hard to solve if you are using SVN for deployment is that files might need to be placed differently in development and production systems, especially on complex systems. PEAR can do this.

For example, I generally place my test files next to the files they test in the directory structure. Many people create a separate, parallel test directory. I don't want to deploy my tests to the production server, but I do want to deploy them to a dev or test server. PEAR installer can handle that.

Another example is where files must be in a special location, such as your web server document root. If you have files to move to the document root from external packages, such as javascript, css, or images what do you do to deploy them with SVN?

One more issue is with include paths. Every extra include path you add slows down your application. Using SVN with externals may cause you to have a lengthy include path. On the other hand, with the PEAR installer, packages from multiple sources can be installed into a single repository with a single segment in the include path.
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

In my experience, SVN is a great tool for collaboration and versioned code history/backup. I won't touch any of the other features, nor can I see a reason to in most web development situations. If I'm feeling sassy, I'll deploy with a checkout. But that's it.

Externals sound like an invitation for broken code. I prefer to commit new versions of libraries et al once they've worked in a test environment, but never before.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

I keep thinking about this thread and I'm not sure why. I'm not sure why code reuse and svn are married in this thread, but what I can say is this...

As far as what I do, when it comes to code reuse, I would say that I follow the following thought process and best practices:

1. I need to accomplish or calculate something.
2. I ask myself if there is a slight possibility that I may ever need or could use this in a future project.
2A. If I think the code is reusable I'll encapsulate it into a self contained class which has as few dependencies and parameters as possible, even if some of the code in the class is a little redundant as far as the project as a whole goes.
2B. If I think the code is not reusable, I'll integrate it tightly into the application it's being developed for, ensuring that the class is not doing things that can or should be processed by a separate class or functions.
3. I design, code and test, repeating as necessary.
4. I finalize the code.

There are upsides and downsides to both branches in step 2. I'm happy and content with developing using this methodology. There are benefits and expenses to both and they are something learned with experience.

If you want to take it down to the nitty gritty it boils down to your experience, what you're developing and your personal preferences.

On a side note, I have a collection of small functions that I use in almost every project I work on that have saved me an immeasurable amount of time. I noticed that I was spending a lot of time creating forms and then validating the input, so to speed things up I wrote up functions to minimize what I have to do. The snippet below creates a dropdown menu. All I need to do is pass it a name and array of values. Validating against the array saves tons of time, is efficient and bulletproof. If validation fails in the form, the select menu will retain the selection so that the user doesn't need to select it again. Another thing that was always mundane to code.

Code: Select all

function method($method)
{
	return '_' . (strtoupper($method) == 'GET') ? 'GET' : 'POST';
}

function select($name, $values, $method = 'POST', $class = null, $auto_submit = false)
{
    $method = method($method);

    $form = '<select ' . (($class === null) ? '' : 'class="' . $class . '" ') . (($auto_submit) ? 'onchange="this.form.submit();" ': '') . 'name="' . $name . '">';
    foreach ($values as $key => $value)
    {
        $form .= (((isset(${$method}[$key])) ? trim(${$method}[$key]) : '') === (string) $key) ? '<option selected value="' . $key . '">' . $value . '</option>' : '<option value="' . $key . '">' . $value . '</option>';
    }
    $form .= "</select>";
    return $form;
}
A small piece of code can save a lot of time.

<ego>
I've never won an award on devnet, but I would now like to nominate myself for the coolest snippet of the year award. 8)
</ego>
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

I'm not sure why code reuse and svn are married in this thread
That's my fault.

Selkirk, you sum up the problems brilliantly there.

I wanted to be able to reuse as much as possible so I set up my subversion repository to work in a way that would implicitly package all my work. Maintaining old versions my libraries so I didn't have to be constrained by backwards compatibility was also important. Additionally because I was using Subversion as a deployment tool I wanted have all my servers (production and development) work off a single repository but each needed different things and none of them needed everything. I even went as far to separate the stuff under the document root into a "site" and the code outside of the document root into an "appLib". I did this because in 2 sense these things should be treated separately:
  1. you should be able to run the majority of the unit tests for a web application without any working web front-end
  2. you don't need to branch or tag the stuff within the document root
I linked all this stuff together with externals definitions.

So a checkout for my production server would link in a bunch of sites (only the ones required) using externals definitions, which would in turn link in their associated appLibs, which would in turn link in the libraries they depended upon. On paper it's elegant, complete, organised. Trouble is to get any kind of reliability for production you'll have to tag regularly and get your externals definitions to use those stable tags otherwise when you "svn update" on a production server you run the risk of getting unstable code. This means if you have to make a change to a library you'll have to update your externals definitions for the appLib, the site and the servers in question and you run into this problem of whether you should retag, just update the tag or refer to them with a revision number. So if you got one line wrong somewhere it could take 7 minutes to get that change up and running, naturally you'll skip the staging and go straight to production - then things get really bad. These externals definitions have to be written manually and are easy to get wrong. The whole time you are dealing with loads of copies of the same, very slightly different, code. Did you know you can put your code into conflict by having differing externals definitions?

I spent a week rethinking the inclusion strategy for my framework because Subversion had mucked up what it was relying on. I had specific functionality that depended on being able to dynamically load classes by their names all over the place, it was the basis of my dependency injection implementation that was driving my front controller, string formatting operations and other things. I never did figure that out.
In my version control company policy document I wrote:The advantage of this project layout is that each entity can be developed and branched separately and then be brought together to form a working whole.
Yes, but at what cost?! It's simply not worth it. I was pushing subversion way beyond it's original intended usage.

I'm using FTP and no version control at the moment. It's not perfect but it's not hell on earth either. :P

I didn't even address the issue of version controlling Apache Configurations that could be customized at checkout/update time to be made server specific or the problem that big files (such as video) that I routinely deal with can't realistically be put under version control.
I've never won an award on devnet, but I would now like to nominate myself for the coolest snippet of the year award.
I can't believe you've never won an award! Anyway, I've written that exact same function before, myself, and yes it is very useful. Not sure about the method() function, how about a couple of constants instead?
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

ole wrote:how about a couple of constants instead?
I wanted it to be reusable ;)

I'm not entirely sure why you brought up constants. To me that's just another thing to add and maintain in a config file. Honestly, I figured that there would come a time when another function would need to check the method to verify it, for instance if I wanted to add REQUEST or maybe even something out there like SESSION or COOKIE.

So I created a separate method function. Since it's basically a 1 liner it's not going to hurt and will make changes easier should the need arrive.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Hmm your right.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

This is actually an example of extremely robust code as well. The $method variable would never be supplied by an end user so some could argue there is no reason to check it. The functions that depend on it could all just assume that it's correct and use it as is.

As a developer, if you used that code to write something and pulled up the page, it either would work perfectly or not at all.

You have not only saved development time, but you also don't have to worry about bugs creeping up. It takes me longer to write code like this, but if I were to run some numbers, I would venture to guess that my bugs per line are far lower than average, and not having to unit test saves loads of time as well..
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

The Subversion discussion is something of a detour ;).
One issue that is hard to solve if you are using SVN for deployment is that files might need to be placed differently in development and production systems, especially on complex systems. PEAR can do this.
Who's actually using Subversion to regularly deploy? Has anyone used Phing or ant?

I would prefer to use PEAR, Phing and rsync in some combination. The two P's can easily export from a tagged revision on Subversion you wish to deploy, Phing can organise, test and create a build (including PEAR packages if needed), and rsync just does it's thing. The whole deal can be scripted. Checking out directly from Subversion just adds the problem of forcing Subversion to hold all the keys to deployment (correct directory structure, file naming, configuration, etc.) which has rarely been a good idea and is outside Subversion's scope.

I think here is where some of the later Externals biting went off the rails - Externals are great for updating tagged external libraries so you can ensure the app as a whole works (in development), but the directory structure resulting should not be considered final - use Phing or ant to re-organise prior to deployment/release as needed (e.g. reduce include paths, set relative/absolute path includes, file amendments via Regex, whatever else). Once you're doing that Externals are a no-brainer. So long as the External committers are tagging releases and applying bug fixes to the release branch.
Kieran Huggins wrote:Externals sound like an invitation for broken code.
Only if improperly used or depended on for too much. Besides you're connecting to another subversion repository - you can have a favourite tag/branch/revision to link to for stability. One assumes we're not deploying with a Trunk External :). You could even just use Phing/ant to organise external exports at build time.
thinsoldier
Forum Contributor
Posts: 367
Joined: Fri Jul 20, 2007 11:29 am
Contact:

Post by thinsoldier »

You're projects sound 1,000 times more complex than anything I ever did. (care to link to any?)

On my 3 dozen small websites I've done in the last 3 years I've had pretty good re-use of our code. Probably because all the site's are on the same server and we have a single directory full of function files that are automatically accessible to all sites on the server and are pretty well documented.

But yes, very application specific code is really only reusable within that 1 applications site.

As for 3rd party libraries we only use simple stand-alone things where we don't have to worry much about dependencies. Like PHPMailer and getID3

I've never used subversion. I think I saw a video of someone using it once through a command line interface and that just turned me off.
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

There's TortoiseSVN which integrates with the Windows file manager. Not that it's perfect, but it's not the command line.

I would recommend you use it for versioned code backups, if nothing else. Collaboration is where it really shines.

I also use it to sync code between my laptop and desktop. When I need to get out of the house for a while I'll do a quick checkout and go to the Starbucks patio for a while.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

This is an interesting discussion because it touches on how and why people use different tools. I have found recently that I use Subversion less and CVS more -- mainly because the built in support for CVS in Eclipse and that I tend now to use it only as a repository.

Other tools do the other things better. I just stopped seeing the need to reinstall some Subversion client or resetup a Subversion repository when CVS was already installed and did what I needed. The switch to PDT was the last nail in the coffin. The CVS clients even handle some of the multistep gyrations to move things around that were once the reason to use Subversion.
(#10850)
Post Reply