SlideShare una empresa de Scribd logo
1 de 110
Descargar para leer sin conexión
PHP without PHP
                           The Philosophy of
                           Good Architecture
                                                                   terry chay
                                                        2010-03-10T09:30+0500
                                                                      Confoo
                                                            Montreal, Canada




Thursday, March 18, 2010
An obscure but ubiquitous design pattern in PHP development is known as Funky Caching. Using real architectural examples as a lens to look at this one simple
PHP design pattern, we see how we can design web architectures that are "organic, democratic, and lasting…"
Funky Caching
                              Prologue #1




Thursday, March 18, 2010

Two prologues
aka




Thursday, March 18, 2010

Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument
line in your apache.conf. What this does is tell the webserver to redirect all missing files to a
PHP script called “error.php” in your directory root. You then create this handler:

Reference:
http://derickrethans.nl/errorhandling/rasmus-trick.html
http://lerdorf.com/tips.pdf
aka
                           ErrorDocument trick




Thursday, March 18, 2010

Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument
line in your apache.conf. What this does is tell the webserver to redirect all missing files to a
PHP script called “error.php” in your directory root. You then create this handler:

Reference:
http://derickrethans.nl/errorhandling/rasmus-trick.html
http://lerdorf.com/tips.pdf
aka
                           ErrorDocument trick

                           Smarter Caching




Thursday, March 18, 2010

Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument
line in your apache.conf. What this does is tell the webserver to redirect all missing files to a
PHP script called “error.php” in your directory root. You then create this handler:

Reference:
http://derickrethans.nl/errorhandling/rasmus-trick.html
http://lerdorf.com/tips.pdf
aka
                           ErrorDocument trick

                           Smarter Caching

                           … Rasmus’s Trick (Stig’s trick)




Thursday, March 18, 2010

Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument
line in your apache.conf. What this does is tell the webserver to redirect all missing files to a
PHP script called “error.php” in your directory root. You then create this handler:

Reference:
http://derickrethans.nl/errorhandling/rasmus-trick.html
http://lerdorf.com/tips.pdf
aka
                           ErrorDocument trick

                           Smarter Caching

                           … Rasmus’s Trick (Stig’s trick)




Thursday, March 18, 2010

Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument
line in your apache.conf. What this does is tell the webserver to redirect all missing files to a
PHP script called “error.php” in your directory root. You then create this handler:

Reference:
http://derickrethans.nl/errorhandling/rasmus-trick.html
http://lerdorf.com/tips.pdf
aka
                           ErrorDocument trick

                           Smarter Caching

                           … Rasmus’s Trick (Stig’s trick)



                           Go into apache.conf (or .htaccess) and

                               ErrorDocument 404 /error.php




Thursday, March 18, 2010

Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument
line in your apache.conf. What this does is tell the webserver to redirect all missing files to a
PHP script called “error.php” in your directory root. You then create this handler:

Reference:
http://derickrethans.nl/errorhandling/rasmus-trick.html
http://lerdorf.com/tips.pdf
Error.PHP
                $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']
                $basepath = dirname(__FILE__).DIR_SEP;
                 
                // Test to see if you can work with it
                if (false) { //…EDIT…
                    //output a 404 page
                    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips
                    return;
                }
                 
                // Generate the file
                // …EDIT…
                $data = 'something';
                 
                // Don't send 404 back, send 200 OK because this is a pretty smart 404
                // not a clueless one! http://www.urbandictionary.com/define.php?term=404
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                //Show the file
                echo $data;
                 
                //Store the page to bypass PHP on the next request. Use a temp file with a
                // link trick in order to avoid race conditions between concurrent PHP
                // processes.
                $tmpfile = tempnam($basepath.'tmp','fc');
                $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter
                fputs($fp, $data);
                fclose($fp);
                @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race
                unlink($tmpfile);




Thursday, March 18, 2010

What does this trick do? Basically, when a file doesn’t exist, it gives an opportunity for PHP to
create the data and return it instead of a 404 error page.

The code above is pretty canonical, the only exceptions are where you branch to show the
default error page…

syntax highlighting code:
php_value highlight.string '#b02c04'
php_value highlight.comment '#8e98a6'
php_value highlight.keyword '#96ad53'
#php_value highlight.bg '#f1f7d7'
php_value highlight.default '#524e37'
php_value highlight.html '#95ad53'
Error.PHP
                $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']
                $basepath = dirname(__FILE__).DIR_SEP;
                 
                // Test to see if you can work with it
                if (false) { //…EDIT…
                    //output a 404 page
                    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips
                    return;
                }
                 
                // Generate the file
                // …EDIT…
                $data = 'something';
                 
                // Don't send 404 back, send 200 OK because this is a pretty smart 404
                // not a clueless one! http://www.urbandictionary.com/define.php?term=404
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                //Show the file
                echo $data;
                 
                //Store the page to bypass PHP on the next request. Use a temp file with a
                // link trick in order to avoid race conditions between concurrent PHP
                // processes.
                $tmpfile = tempnam($basepath.'tmp','fc');
                $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter
                fputs($fp, $data);
                fclose($fp);
                @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race
                unlink($tmpfile);




Thursday, March 18, 2010

What does this trick do? Basically, when a file doesn’t exist, it gives an opportunity for PHP to
create the data and return it instead of a 404 error page.

The code above is pretty canonical, the only exceptions are where you branch to show the
default error page…

syntax highlighting code:
php_value highlight.string '#b02c04'
php_value highlight.comment '#8e98a6'
php_value highlight.keyword '#96ad53'
#php_value highlight.bg '#f1f7d7'
php_value highlight.default '#524e37'
php_value highlight.html '#95ad53'
Error.PHP
                $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']
                $basepath = dirname(__FILE__).DIR_SEP;
                 
                // Test to see if you can work with it
                if (false) { //…EDIT…
                    //output a 404 page
                    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips
                    return;                                  Ceheck
                }
                 
                // Generate the file
                // …EDIT…
                $data = 'something';
                 
                // Don't send 404 back, send 200 OK because this is a pretty smart 404
                // not a clueless one! http://www.urbandictionary.com/define.php?term=404
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                //Show the file
                echo $data;
                 
                //Store the page to bypass PHP on the next request. Use a temp file with a
                // link trick in order to avoid race conditions between concurrent PHP
                // processes.
                $tmpfile = tempnam($basepath.'tmp','fc');
                $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter
                fputs($fp, $data);
                fclose($fp);
                @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race
                unlink($tmpfile);




Thursday, March 18, 2010

…and where you generate the actual data to render to the user.
Error.PHP
                $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']
                $basepath = dirname(__FILE__).DIR_SEP;
                 
                // Test to see if you can work with it
                if (false) { //…EDIT…
                    //output a 404 page
                    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips
                    return;
                }
                 
                // Generate the file
                // …EDIT…
                $data = 'something';
                 
                // Don't send 404 back, send 200 OK because this is a pretty smart 404
                // not a clueless one! http://www.urbandictionary.com/define.php?term=404
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                //Show the file
                echo $data;
                 
                //Store the page to bypass PHP on the next request. Use a temp file with a
                // link trick in order to avoid race conditions between concurrent PHP
                // processes.
                $tmpfile = tempnam($basepath.'tmp','fc');
                $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter
                fputs($fp, $data);
                fclose($fp);
                @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race
                unlink($tmpfile);




Thursday, March 18, 2010

At the bottom is where the magic happens. It places the generated file directly into the web
server path. What this means is that the next request to the same web resource goes directly
for that resource without starting up this code and regenerating the data.

Reference:
404 defined: http://en.wikipedia.org/wiki/HTTP_404
404 discussion: http://www.alistapart.com/articles/perfect404/
404 examples: http://www.plinko.net/404/
HTTP codes: http://www.urbandictionary.com/define.php?term=404
PHP without PHP



Thursday, March 18, 2010

PHP never gets instantiated after the first request!

At that point it truly becomes PHP without PHP.
Paradigms
                            Prologue #2




Thursday, March 18, 2010
Code Complete
             The metaphor of Code as
             construction comes from this
             book…


             We            now   know         this         is
             fundamentally wrong…




Thursday, March 18, 2010
About the book and the metaphor.

The foundation of Steve McConnell’s seminal text, Code Complete, was that software development should be based around the paradigm
of construction. But that was fundamentally flawed because of the mythical man-month—the “man-month” term itself originally coming
from construction work. We now know McConnell was wrong and software isn’t construction, it is engineering. And we’re called “software
engineers,” not “software workers” for this reason: we’re engineers, not construction workers.
Mythical Man Month
                                      reorganize notes
                                      too much text

             “man-month” is a term from
             construction work


             The premise is that man and
             months are interchangeable.


             This means that in order to
             reach a deadline I simply add
             more people to the project.




Thursday, March 18, 2010

Rhe foundation of Steve McConnell’s seminal text, Code Complete, was that software
development should be based around the paradigm of construction. But that was
fundamentally flawed because of the mythical man-month—the “man-month” term itself
originally coming from construction work. We now know McConnell was wrong and software
isn’t construction, it is engineering. And we’re called “software engineers,” not “software
workers” for this reason: we’re engineers, not construction workers.
too much text




Thursday, March 18, 2010
paritionable
                                                   with training
                                                   traning + communication
                                                   unpartitionable




                                           20




                                                                             Time to COmplete Title
                           too much text   15




                                           10




                                           5




                                                Number of People




Thursday, March 18, 2010
paritionable
                                                                                  with training
                                                                                  traning + communication
                                                                                  unpartitionable




                                                                          20




                                                                                                            Time to COmplete Title
            First consider something like
            p a i n t i n g a f e n c e : e v e r y t h i n g much text
                                                            too i s       15

            partionable (man-month).


                                                                          10




                                                                          5




                                                                               Number of People




Thursday, March 18, 2010
paritionable
                                                                                  with training
                                                                                  traning + communication
                                                                                  unpartitionable




                                                                          20




                                                                                                            Time to COmplete Title
            First consider something like
            p a i n t i n g a f e n c e : e v e r y t h i n g much text
                                                            too i s       15

            partionable (man-month).



            …add a constant time for training.                            10




                                                                          5




                                                                               Number of People




Thursday, March 18, 2010
paritionable
                                                                                  with training
                                                                                  traning + communication
                                                                                  unpartitionable




                                                                          20




                                                                                                            Time to COmplete Title
            First consider something like
            p a i n t i n g a f e n c e : e v e r y t h i n g much text
                                                            too i s       15

            partionable (man-month).



            …add a constant time for training.                            10



            …add communication cost: n(n-1)/2.
                                                                          5




                                                                               Number of People




Thursday, March 18, 2010
paritionable
                                                                                  with training
                                                                                  traning + communication
                                                                                  unpartitionable




                                                                          20




                                                                                                            Time to COmplete Title
            First consider something like
            p a i n t i n g a f e n c e : e v e r y t h i n g much text
                                                            too i s       15

            partionable (man-month).



            …add a constant time for training.                            10



            …add communication cost: n(n-1)/2.
                                                                          5

            Compare to the unpartitionable
            (single man)




                                                                               Number of People




Thursday, March 18, 2010
paritionable
                                                                                  with training
                                                                                  traning + communication
                                                                                  unpartitionable




                                                                          20




                                                                                                            Time to COmplete Title
            First consider something like
            p a i n t i n g a f e n c e : e v e r y t h i n g much text
                                                            too i s       15

            partionable (man-month).



            …add a constant time for training.                            10



            …add communication cost: n(n-1)/2.
                                                                          5

            Compare to the unpartitionable
            (single man)



            Adding people to a late project
            makes it later!                                                    Number of People




Thursday, March 18, 2010
Engineer and
                                        graphics




                               Architect


Thursday, March 18, 2010

Software as Engineering vs. other. My title at Tagged is currently “software architect.” And I
have a “radical” idea that maybe titles are that way because they mean something. Meaning
that if I’m hired as a software architect then I should think like an architect and find my
inspiration from architecture.
1 Fallingwater
                           organic, democratic, plasticity, continuity




Thursday, March 18, 2010

So lets find our inspiration from architecture and see how it explains the Funky Caching
pattern through three buildings. the first is one known as Fallingwater.

References:
Fallingwater logo from: http://www.fallingwater.org/
Thursday, March 18, 2010

In Eastern mountain range of the United States there is a house that is CANTILEVERed 40 feet
above a waterfall. This is one of the most famous buildings by American architect, FRANK
LLOYD WRIGHT. In 1991 it was voted as the best all-time work of American architecture by
the American Institute of Architects. Even though it is OVER 80KM from the nearest city
people over a MILLION PEOPLE have traveled to see it.

Reference:
Image from http://commons.wikimedia.org/wiki/File:Falling_Water_01.jpg
Wikipedia: http://en.wikipedia.org/wiki/Fallingwater
Frank Lloyd Wright: http://franklloydwright.org/Home.html
…including me
Thursday, March 18, 2010

Yes, including me as a kid. The day it was built, TIME MAGAZINE wrote about it. Because it
was a quintessential example of ORGANIC ARCHITECTURE of FLW.

References:
Der Spiegel: http://en.wikipedia.org/wiki/Der_Spiegel
Hatchway Staircase                          View at the main (living room) level, from the
                                                                                bridge (from east)




Thursday, March 18, 2010

A staircase connects the house directly to the stream below. The stream and waterfall,
although not seen, can be heard in all parts of the house. The HATCHWAY that consists of
SLIDING GLASS DOORS and the bottom step has no support from below. (FLOAT above like
the water floats)

References:
http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/06E-hatchway-
fallingwater.html
Beyond the glass                        Fallingwater: Living room terraces and glass
                                                                            walls (from east).




Thursday, March 18, 2010

WINDOWS WRAP AROUND THE ENTIRE BUILDING so that the building MERGES with the
surrounding GREENERY. Similarly the TUNGSTEN LIGHTING and the glasses compliments the
FALL FOLIAGE of the region…
Fall Foliage                                       View from lookout, downstream.




Thursday, March 18, 2010

This is the VIEW that FLW planned for the house.

References:
http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/F1SW-fallingwater-in-
fall.html
Fall Foliage       View from lookout, downstream.




Thursday, March 18, 2010
No barriers                                   Detail: corner window at the guest house,
                                                                               from southeast.




Thursday, March 18, 2010

Panes of glass are caulked directly to each other and to the steel frame or stone walls to
further symbolize the lack of barriers between the construction and the surrounding nature.

References:
http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/34SE-guest-house-
window.html
Existing tree                                   The trellis over the driveway is built to
                                                                           accommodate a tree.




Thursday, March 18, 2010

The driveway trellis has a semi-circular cutaway to accommodate an existing tree.

References:
http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/15-tree-in-trellis-
fallingwater.html
Local quarry                                   Living room, west (downstream) side, from
                                                                                     southeast




Thursday, March 18, 2010

The stone floor in the living room, quarried from local rocks

http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/livingroom-
fallingwater.html
Existing boulder                                 Living room fireplace and hearth, looking
                                                               from kitchen door to south windows




Thursday, March 18, 2010

The rock in the foreground is is an original boulder not disturbed from it’s original position.

References:
http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/7-living-room-fireplace-
hearth.php
Existing boulder                                 Living room fireplace and hearth, looking
                                                               from kitchen door to south windows




Thursday, March 18, 2010

The rock in the foreground is is an original boulder not disturbed from it’s original position.

References:
http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/7-living-room-fireplace-
hearth.php
Thursday, March 18, 2010

From details like these to the whole view taken in at once, one gets a feeling that, in spite of
the SHARP HORIZONTAL AND VERTICAL LINES of the building, the whole lives in harmony with
its environment "instead of lording above [it] in an isolated spot as a man-made imposition.”
Why is this building as recognizable as any NATURAL WONDER?
Philosophy
           organic,


           democratic,


           plasticity,


           continuity.




Thursday, March 18, 2010

Surveyed the grounds before building. Organic: "form follows function." Wright argued that
"form and function are one." Democratic “design should accommodate needs” Plasticity:
“physical element should remove barriers.” Continuity “element should be part of nature”
Why on PHP?



Thursday, March 18, 2010

How prevalent is funky caching? Every time you visit PHP.NET, you use it (need to get the
order of needle-haystack by typing http://php.net/strstr). A cynic would say, because PHP is
so SLOW TO EXECUTE, it needs solutions like this to perform well. The problem with this
argument is that NO WEB LANGUAGE OUTPERFORMS STATIC SERVERS. Becase it trades off
speed of execution with SPEED FOR EASE OF DEVELOPMENT. As Andrei mentioned earlier, that
is fundamental to its design. In fact, all dynamically-typed scripting languages make this
tradeoff.
Harmony with Environment




Thursday, March 18, 2010

The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater
—lives in harmony with its environment. The environment is an APACHE WEB SERVER,
persistent data store in the form of a RELATIONAL DATABASE, and the demands of large-
scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument
handler built into Apache? Would this solution exist if we didn't persist content on a
(relatively) slow data store like a database? Would this solution exist if the consumer didn't
demand millisecond response time for dynamic content?
Harmony with Environment

                            Apache web server: ErrorDocument




Thursday, March 18, 2010

The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater
—lives in harmony with its environment. The environment is an APACHE WEB SERVER,
persistent data store in the form of a RELATIONAL DATABASE, and the demands of large-
scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument
handler built into Apache? Would this solution exist if we didn't persist content on a
(relatively) slow data store like a database? Would this solution exist if the consumer didn't
demand millisecond response time for dynamic content?
Harmony with Environment

                            Apache web server: ErrorDocument

                            Customer-centric: Performance
                            paramount




Thursday, March 18, 2010

The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater
—lives in harmony with its environment. The environment is an APACHE WEB SERVER,
persistent data store in the form of a RELATIONAL DATABASE, and the demands of large-
scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument
handler built into Apache? Would this solution exist if we didn't persist content on a
(relatively) slow data store like a database? Would this solution exist if the consumer didn't
demand millisecond response time for dynamic content?
Harmony with Environment

                            Apache web server: ErrorDocument

                            Customer-centric: Performance
                            paramount

                            Relational Database: Slow
                            persistence




Thursday, March 18, 2010

The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater
—lives in harmony with its environment. The environment is an APACHE WEB SERVER,
persistent data store in the form of a RELATIONAL DATABASE, and the demands of large-
scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument
handler built into Apache? Would this solution exist if we didn't persist content on a
(relatively) slow data store like a database? Would this solution exist if the consumer didn't
demand millisecond response time for dynamic content?
Harmony with Environment

                            Apache web server: ErrorDocument

                            Customer-centric: Performance
                            paramount

                            Relational Database: Slow
                            persistence

                            Harmony with PHP itself…




Thursday, March 18, 2010

The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater
—lives in harmony with its environment. The environment is an APACHE WEB SERVER,
persistent data store in the form of a RELATIONAL DATABASE, and the demands of large-
scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument
handler built into Apache? Would this solution exist if we didn't persist content on a
(relatively) slow data store like a database? Would this solution exist if the consumer didn't
demand millisecond response time for dynamic content?
write text to talk about
                                     it




        Architecture of PHP                                       Modern web architecture




Thursday, March 18, 2010

The language itself. PHP is a component of A WHOLE SYSTEM. It’s glue code.
PHP is “Cheap”
                                         graphcis money
                                         shorten quote

                           “A project done in Java will cost 5 times
                           as much, take twice as long, and be
                           harder to maintain than a project done
                           in a scripting language such as PHP or
                           Perl.”

                                                          —Phillip Greenspun




Thursday, March 18, 2010

developer time and resources
PHP is “Scalable”
                           “That a Java servlet performs better
                                          graphics notes?
                                          shortne quote
                           than a PHP script, under optimal
                           conditions [has] nothing to do with
                           scalability. The point is can your
                           application continue to deliver
                           consistent performance as volume
                           increases. PHP delegates all the ‘hard
                           stuff’ to other systems.”

                                                   —Harry Fuecks




Thursday, March 18, 2010

shared-nothing architecture
PHP is “Pragmatic”
                           “PHP is not about purity in CS
                                          graphics
                                          shorten quote
                           principles or architecture; it is about
                           solving the ugly web problem with an
                           admittedly ugly, but extremely
                           functional and convenient solution. If
                           you are looking for purity, you are in
                           the wrong boat. Get out now before
                           you get hit by a wet cat!”

                                                     —Rasmus Lerdorf




Thursday, March 18, 2010

designed to solve the web problem

Could this "ugly, but extremely functional and convenient" web language have been built to
solve anything other than the ugly web problem?
2 Bellefield Towers
                                   Design Hubris




Thursday, March 18, 2010

One block from where my mother used to work, on the corner of Fifth Avenue and Bellefield
in Pittsburgh, stands a strange sight…
make video of wpaking
                                                   towards?




Thursday, March 18, 2010
If you weren’t in PITTSBURGH IN THE LATE 1980’s you wouldn’t have understood how his could have happened. On this ground
once stood the original Bellefield church built in the 1880’s. Since its CONGREGATION HAD BEEN MOVED further down Fifth
Avenue, the building was sold a century later to developers trying to exploit the new business attracted by the PITTSBURGH
SUPERCOMPUTING CENTER. They wanted to level it and build a new building, but were blocked when people mobilized to SAVE
THE OLD TOWER. The developer then proceeded to honor this by DEMOLISH EVERYTHING BUT THE TOWER and building the
ironically-named “Bellefield Towers” next to it.
Gothic Romanesque architecture                The current Bellefield Church (two blocks
                                                                                          away)




Thursday, March 18, 2010

This is the current Bellefield Church and an example of city architecture of which the tower is
one of them…
Other city towers                               Allegheny Courthouse Main Tower & Four
                                                           Tower Types at Jail (and other towers)




Thursday, March 18, 2010

The center is the county courthouse and jail, the top right is the local Korean church, and the
bottom right is a private residence in the same neighborhood.
Tower of
                           Learning
                 Within spitting distance of
                     Bellefield Towers




Thursday, March 18, 2010
redo builds
                                       break out slides
                                       quots




        Carnegie Library                                  Most iconic moment in baseball history




Thursday, March 18, 2010

The photo at the top is was taken from the Cathedral of learning (previous slide).
redo builds
                                       break out slides
                                       quots




        Carnegie Library                                  Most iconic moment in baseball history




Thursday, March 18, 2010

The photo at the top is was taken from the Cathedral of learning (previous slide).
Why is Bellefield
                           Towers so Ugly?


Thursday, March 18, 2010

When faced with a gorgeous 100-year old example of the area’s architecture, INSTEAD OF WORKING
WITH THE ENVIRONMENT like Frank Lloyd Wright did with Fallingwater—in the same area of
Pennsylvania no less!—the developer simply sawed it off! The CURVED MODERN ARCHITECTURE of the
TOWERS of the latter serves only to emphasize how it was built with no consideration of the
surrounding environment. I GREW UP WATCHING THIS HAPPEN and it is a LIFE LESSON IN
ARCHITECTURAL HUBRIS.
Design Hubris?
                                        break out slides, graphics




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
Design Hubris?
                           Frameworks (almost by definition)
                                        break out slides, graphics




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
Design Hubris?
                           Frameworks (almost by definition)
                                        break out slides, graphics
                           Develop in the PHP community?




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
Design Hubris?
                           Frameworks (almost by definition)
                                        break out slides, graphics
                           Develop in the PHP community?

                           Take over an existing project?




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
Design Hubris?
                           Frameworks (almost by definition)
                                        break out slides, graphics
                           Develop in the PHP community?

                           Take over an existing project?

                           Limitations of Site Operations?
                           Hosting? or Virtual hosting?




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
Design Hubris?
                           Frameworks (almost by definition)
                                        break out slides, graphics
                           Develop in the PHP community?

                           Take over an existing project?

                           Limitations of Site Operations?
                           Hosting? or Virtual hosting?

                           Business needs trump programmer
                           desire?




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
Design Hubris?
                           Frameworks (almost by definition)
                                        break out slides, graphics
                           Develop in the PHP community?

                           Take over an existing project?

                           Limitations of Site Operations?
                           Hosting? or Virtual hosting?

                           Business needs trump programmer
                           desire?

                           Dealt with a user request?




Thursday, March 18, 2010

“I’m a developer, I can make the software conform to my needs.”
Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made
imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
add slideshow




                                …at Tagged
Thursday, March 18, 2010

cover cube story, (where cubes are good- Yahoo, sales, user QA), cover waterfall process
…at Tagged                       break out slides




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
…at Tagged                       break out slides




                                   Cubes




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
…at Tagged                       break out slides




                                   Cubes
                           Waterfall process




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
…at Tagged                       break out slides




                                   Cubes
                           Waterfall process
                              Oracle RAC




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
…at Tagged                       break out slides




                                   Cubes
                           Waterfall process
                              Oracle RAC
                                     Java




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
…at Tagged                       break out slides




                                   Cubes
                           Waterfall process
                              Oracle RAC
                                     Java
                                    PHP4




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
…at Tagged                       break out slides




                                   Cubes
                           Waterfall process
                              Oracle RAC
                                     Java
                                    PHP4
                           Zend Accelerator




Thursday, March 18, 2010
When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation,
Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development
process.
Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer
MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had
outgrown the cube-space.
Rework




Thursday, March 18, 2010
Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
Rework
                   From the Founders of 37
                           Signals




Thursday, March 18, 2010
Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
Rework
                   From the Founders of 37
                           Signals




Thursday, March 18, 2010
Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
Rework
                   From the Founders of 37
                           Signals


                  Last Book: “Getting Real”




Thursday, March 18, 2010
Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
Rework




Thursday, March 18, 2010
- cliche ridden with few examples “Hannah Montanta” reach for you dreams
- “would rather be celebrities than businesspeople.”
- 'Meetings are toxic.' In reality, good meetings are good and bad meetings are not good (generalization)
- “Planning, they say, is not recommended” - only applies to their business
- “They need to stop behaving like children.”
- “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions,
the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
Rework
             “Not Just Bad,
             but dangerous”




Thursday, March 18, 2010
- cliche ridden with few examples “Hannah Montanta” reach for you dreams
- “would rather be celebrities than businesspeople.”
- 'Meetings are toxic.' In reality, good meetings are good and bad meetings are not good (generalization)
- “Planning, they say, is not recommended” - only applies to their business
- “They need to stop behaving like children.”
- “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions,
the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
Rework
             “Not Just Bad,
             but dangerous”
                               —John Vincent, Leon
                                     Restaurants




Thursday, March 18, 2010
- cliche ridden with few examples “Hannah Montanta” reach for you dreams
- “would rather be celebrities than businesspeople.”
- 'Meetings are toxic.' In reality, good meetings are good and bad meetings are not good (generalization)
- “Planning, they say, is not recommended” - only applies to their business
- “They need to stop behaving like children.”
- “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions,
the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
Solutions Consider
                                              Environment


Thursday, March 18, 2010
Why? Because that is the environment and your solutions have to work within that environment. Anything else is architectural hubris.
Let’s say it is the early days of social networking and you join a company that is using Java/J2EE instead of PHP, or Oracle instead of MySQL, or they’re using Perl/Mason instead of your
favorite (PHP) framework, as Marco mentioned earlier—there are so many to choose from that the number is second only to Java.
Do you go in and say your experience building a CMS or e-store trumps their experience working on a nascent social network? Do you replace all the Java engineers with PHP ones? Do you
replace MySQL with Oracle? Do you rewrite the site from scratch using your favorite framework?
I’m not saying that in all these instances these architects shouldn’t have made the decisions they did. I am not qualified to answer that since I didn’t work at these places.
But what I do know was that in the vast majority of cases, people went in without considering the existing environment. I do know the dynamics of a Facebook.com is different from the
dynamics of Gamespot.com or Amazon.com. I do know a social network is different from a CMS or e-store. And all these solutions are very different from ones in enterprise.
Like building Fallingwater without getting an adequate survey done, every day people make the mistake of not looking before acting. They try to make PHP look like Java with dollar signs,
as Luke mentioned earlier. They expected the environment to conform to their reality so they can lord over it with “some isolated man-made imposition.”
3 Golden Gate Bridge
                                 The Design Pattern




Thursday, March 18, 2010

I’ve long since moved from the woods of Western Pennsylvania to the San Francisco
Peninsula. I am fortunate that my weekly run passes with a near-constant view of the most
recognizable architecture in the American West:

References:
Image licensed from: http://www.istockphoto.com/file_closeup.php?id=6091847
design build
                           quote of goldne gate
                           bridge




Thursday, March 18, 2010

my weekend run
quote from emperor
                                        norton




                             the other bridge
Thursday, March 18, 2010

What’s interesting is that there are much longer spans in the country and the world. Even in
the same city, there exists a beautiful bridge that is both longer and of more utility. And yet
this bridge represents the icon of San Francisco and of the state as a whole.
quotes of sf




Thursday, March 18, 2010
Thursday, March 18, 2010
Same problem,
              different pattern
                 Original design was hybrid
                  cantilever-suspension.
                     Replaced by purse
                        suspension




Thursday, March 18, 2010

The original design was for a hybrid cantilever and suspension structure. But it was replaced
with a pure suspension design because the former was deemed too ugly. A pure suspension
of this length had never been attempted before.
Art Deco                                  quote of art deco
                                                                      movemebnt



                     Bridge Tower, Lighting,
                      pedestrial walkway




Thursday, March 18, 2010
Irving Morrow designed the bridge tower, lighting, and pedestrian walkways with an entirely Art Deco decorative influence.
International
                        Orange
                  Rust colored like the
               environment it lives in … and
                          safe.




Thursday, March 18, 2010

The bridge was painted in a specially formulated anti-rust paint in International Orange on demand
from locals. The War Department, and others. The Navy alone originally demanded it be painted black
with yellow stripes to assure visibility with passing ships. The rust-colored paint evokes the hills of
Marin to the north as well as the setting sun. It is natural and visible enough to be safe.
Part of the
                             whole




Thursday, March 18, 2010
rust-colored suspension-only art deco structure It becomes an icon. Every week I pass by it and am inspired and
thankful I can live in so beautiful a city.
Design Patterns
                      Defined           shorten quote




Thursday, March 18, 2010

This quote is the origin of “design pattern.”
Design Patterns
                      Defined                  shorten quote

           “Each pattern describes a
           problem which occurs over
           and             over   again   in    our
           environment, and then
           describes the core of the
           solution to that problem, in
           such a way that you can use
           this solution a million times
           over, without ever doing it
           the same way twice.”



Thursday, March 18, 2010

This quote is the origin of “design pattern.”
Certainly iconic                                                Me in front of both icons




Thursday, March 18, 2010

But how are we to know which way to do it? Or even if it is the right pattern to be using in our
situation? The answer is found in how both a house in Pennsylvania and a bridge in San Francisco
represent ultimate expressions of architecture. They are wholly appropriate for the environment
in which they stand.
blend transition in
                                      stages




        Never the same way twice                                 How do you know which one?
                                                                 How do you know which way?




Thursday, March 18, 2010

A cantilever is wholly appropriate to create the floating look of Fallingwater, but that same
pattern would disrupted the naturalness of the Golden Gate Bridge. When choosing between a
singleton and a global variable, which pattern to use is determined by the environment.
Funky Caching again

                           “search for the closest matching valid
                           URL and redirect, and use attempted
                           url text as a DB keyword lookup”

                                                     —Rasmus Lerdorf




Thursday, March 18, 2010

the first is in Rasmus’s talk and you can see PHP.NET in others.
cleanup text




Thursday, March 18, 2010
At my previous company, we had the problem where images are stored on the database but need to be generated in multiple sizes and thumbnails
and streamed fast to the user. Previews and thumbnails can be dynamically and instantly generated from border parts, primary graphics, colors,
and sample font and text and then stored statically on a server using this method. Stuff may be stored in normal form on the database, but
representations built dynamically and served statically
Thursday, March 18, 2010
Address complaint about storing in database…Not all images are stored in the database. In fact, at Tagged, not a single image is stored on a database. However, at Plaxo, the admin tool
to manage ecard content requires the assets be done by a non-developer but the only way of pushing out filesystem changes is through change control and there is little need of user
generated content. In fact, outside e-cards, the entire Plaxo address book database (including the thumbnail photo of yourself) is stored in a database. I’m not the architect of that, nor do
I see much a problem with it.
What I point out you CAN now get away with putting image content on the database again with this trick. That’s pretty impressive because different assets on a site (statics, javascripts,
web pages, user data, application, back-end, corporate site, customer support, etc) are usually managed on an ad hoc basis optimized for the task at hand. Not all of them can resort to
using a filesystem push or web tier restart.
Javascript and CSS
                                      put a graphic or some
                                      text




                           compiling & caching


Thursday, March 18, 2010

Recently, Tagged has run across the very same performance (size and number) issues in
Javascript. The solution: Funky caching hooked up to a javascript compressor powered by a
Java service back-end to dynamically catenate and compress javascripts into a unique URL on
demand.
Thursday, March 18, 2010
We recently imported 1/64th of our production data over to the staging environment for testing, but the user’s images would
take too much time and disk space to import. We could just link the images, but then tester’s didn’t know which ones they
uploaded and which ones were proxied from the live website. The solution was to spend an hour writing a Funky Caching Proxy.
If the image was missing, the ErrorDocument handler would try to grav the image from the production website and add a
watermark.
Thursday, March 18, 2010

Since this is only for testing, there is no need to waste disk space by storing the created file.
The performance hit of real-time generation of redundant requests is unnoticeable to Quality
Assurance.
<?php

                $watermark = '3129080702_c4e76f71d7_o.png';
                $dead_url = 'http://example.com/dead_image.png';
                 
                // {{{ start_image($filename, &$data)
                /**
                * Creates a gd handle for a valid file
                * @param $filename string the file to get
                * @param $data array the imagesize
                * @return resource GD handle
                */
                function start_image($filename, &$data) {
                    $data = @getimagesize($filename);
                    if (empty($data)) { return null; }
                    $data['ratio'] = $data[0]/$data[1];   expand callouts
                    switch($data[2]) {
                        case IMG_GIF: return imagecreatefromgif($filename);
                        case 3: //problem where IMG_PNG is not bound correctly for my install
                        case IMG_PNG: return imagecreatefrompng($filename);
                        case IMG_JPG: return imagecreatefromjpeg($filename);
                        case IMG_WBMP: return imagecreatefromwbmp($filename);
                        case IMG_XPM: return imagecreatefromxbm($filename);
                    }
                    return null;
                }   
                // }}}
                $requestimg = $_SERVER['REDIRECT_URL'];
                if (!$_SERVER['QUERY_STRING']) {
                    // redirect user to invalid image
                    tag_http::redirect($dead_url);
                    return '';
                }
                // grab image to temp {{{
                $ch = curl_init($_SERVER['QUERY_STRING']);
                $tempfile = tempnam('/tmp', 'prod_remote_');
                $fp = f_open($tempfile, 'w'); //again delete the "_"
                curl_setopt($ch, CURLOPT_FILE, $fp);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_exec_($ch); //delete the final "_"
                curl_close($ch);
                fclose($fp);
                // }}}
Thursday, March 18, 2010
<?php

                $watermark = '3129080702_c4e76f71d7_o.png';
                $dead_url = 'http://example.com/dead_image.png';
                 
                // {{{ start_image($filename, &$data)
                /**
                * Creates a gd handle for a valid file
                * @param $filename string the file to get
                * @param $data array the imagesize
                * @return resource GD handle
                */
                function start_image($filename, &$data) {
                    $data = @getimagesize($filename);
                    if (empty($data)) { return null; }
                    $data['ratio'] = $data[0]/$data[1];   expand callouts
                    switch($data[2]) {
                        case IMG_GIF: return imagecreatefromgif($filename);
                        case 3: //problem where IMG_PNG is not bound correctly for my install
                        case IMG_PNG: return imagecreatefrompng($filename);
                        case IMG_JPG: return imagecreatefromjpeg($filename);
                        case IMG_WBMP: return imagecreatefromwbmp($filename);
                        case IMG_XPM: return imagecreatefromxbm($filename);
                    }
                    return null;
                }   
                // }}}
                $requestimg = $_SERVER['REDIRECT_URL'];
                if (!$_SERVER['QUERY_STRING']) {
                    // redirect user to invalid image
                    tag_http::redirect($dead_url);
                    return '';
                }
                // grab image to temp {{{
                $ch = curl_init($_SERVER['QUERY_STRING']);
                $tempfile = tempnam('/tmp', 'prod_remote_');
                $fp = f_open($tempfile, 'w'); //again delete the "_"
                curl_setopt($ch, CURLOPT_FILE, $fp);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_exec_($ch); //delete the final "_"
                curl_close($ch);
                fclose($fp);
                // }}}
Thursday, March 18, 2010
<?php

                $watermark = '3129080702_c4e76f71d7_o.png';
                $dead_url = 'http://example.com/dead_image.png';
                 
                // {{{ start_image($filename, &$data)
                /**
                * Creates a gd handle for a valid file
                * @param $filename string the file to get
                * @param $data array the imagesize
                * @return resource GD handle
                */
                function start_image($filename, &$data) {
                    $data = @getimagesize($filename);
                    if (empty($data)) { return null; }
                    $data['ratio'] = $data[0]/$data[1];
                    switch($data[2]) {
                        case IMG_GIF: return imagecreatefromgif($filename);
                        case 3: //problem where IMG_PNG is not bound correctly for my install
                        case IMG_PNG: return imagecreatefrompng($filename);
                        case IMG_JPG: return imagecreatefromjpeg($filename);
                        case IMG_WBMP: return imagecreatefromwbmp($filename);
                        case IMG_XPM: return imagecreatefromxbm($filename);
                    }
                    return null;
                }   
                // }}}
                $requestimg = $_SERVER['REDIRECT_URL'];
                if (!$_SERVER['QUERY_STRING']) {
                    // redirect user to invalid image
                    tag_http::redirect($dead_url);
                    return '';
                }
                // grab image to temp {{{
                $ch = curl_init($_SERVER['QUERY_STRING']);
                $tempfile = tempnam('/tmp', 'prod_remote_');
                $fp = f_open($tempfile, 'w'); //again delete the "_"
                curl_setopt($ch, CURLOPT_FILE, $fp);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_exec_($ch); //delete the final "_"
                curl_close($ch);
                fclose($fp);
                // }}}
Thursday, March 18, 2010
<?php

                $watermark = '3129080702_c4e76f71d7_o.png';
                $dead_url = 'http://example.com/dead_image.png';
                 
                // {{{ start_image($filename, &$data)
                /**
                * Creates a gd handle for a valid file
                * @param $filename string the file to get
                * @param $data array the imagesize
                * @return resource GD handle
                */
                function start_image($filename, &$data) {
                    $data = @getimagesize($filename);
                    if (empty($data)) { return null; }
                    $data['ratio'] = $data[0]/$data[1];
                    switch($data[2]) {
                        case IMG_GIF: return imagecreatefromgif($filename);
                        case 3: //problem where IMG_PNG is not bound correctly for my install
                        case IMG_PNG: return imagecreatefrompng($filename);
                        case IMG_JPG: return imagecreatefromjpeg($filename);
                        case IMG_WBMP: return imagecreatefromwbmp($filename);
                        case IMG_XPM: return imagecreatefromxbm($filename);
                    }
                    return null;
                }   
                // }}}
                $requestimg = $_SERVER['REDIRECT_URL'];
                if (!$_SERVER['QUERY_STRING']) {
                    // redirect user to invalid image
                    tag_http::redirect($dead_url);
                    return '';
                }
                // grab image to temp {{{
                $ch = curl_init($_SERVER['QUERY_STRING']);
                $tempfile = tempnam('/tmp', 'prod_remote_');
                $fp = f_open($tempfile, 'w'); //again delete the "_"
                curl_setopt($ch, CURLOPT_FILE, $fp);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_exec_($ch); //delete the final "_"
                curl_close($ch);
                fclose($fp);
                // }}}
Thursday, March 18, 2010
<?php

                $watermark = '3129080702_c4e76f71d7_o.png';
                $dead_url = 'http://example.com/dead_image.png';
                 
                // {{{ start_image($filename, &$data)
                /**
                * Creates a gd handle for a valid file
                * @param $filename string the file to get
                * @param $data array the imagesize
                * @return resource GD handle
                */
                function start_image($filename, &$data) {
                    $data = @getimagesize($filename);
                    if (empty($data)) { return null; }
                    $data['ratio'] = $data[0]/$data[1];
                    switch($data[2]) {
                        case IMG_GIF: return imagecreatefromgif($filename);
                        case 3: //problem where IMG_PNG is not bound correctly for my install
                        case IMG_PNG: return imagecreatefrompng($filename);
                        case IMG_JPG: return imagecreatefromjpeg($filename);
                        case IMG_WBMP: return imagecreatefromwbmp($filename);
                        case IMG_XPM: return imagecreatefromxbm($filename);
                    }
                    return null;
                }   
                // }}}
                $requestimg = $_SERVER['REDIRECT_URL'];
                if (!$_SERVER['QUERY_STRING']) {
                    // redirect user to invalid image
                    tag_http::redirect($dead_url);
                    return '';
                }
                // grab image to temp {{{
                $ch = curl_init($_SERVER['QUERY_STRING']);
                $tempfile = tempnam('/tmp', 'prod_remote_');
                $fp = f_open($tempfile, 'w'); //again delete the "_"
                curl_setopt($ch, CURLOPT_FILE, $fp);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_exec_($ch); //delete the final "_"
                curl_close($ch);
                fclose($fp);
                // }}}
Thursday, March 18, 2010
// configure image and dimensions {{{
                $size_data = array();
                $im = start_image($tempfile, $size_data);
                if (!$im) {
                    unlink($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // get watermark information {{{
                $wm_data = array();
                $wm = start_image($watermark, $wm_data);
                if (!$wm) {
                    unlink ($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // add watermark {{{
                if ($size_data['ratio']> $wm_data['ratio']) {
                    // image is wider format than the watermark
                    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);
                    $dst_x = ($size_data[0] - $new_smaller_dim)/2;
                    $dst_y = 0;
                    $dst_w = $new_smaller_dim;
                    $dst_h = $size_data[1];
                } else {
                    // image is taller format than the watermark
                    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);
                    $dst_x = 0;
                    $dst_y = ($size_data[1] - $new_smaller_dim)/2;
                    $dst_w = $size_data[0];
                    $dst_h = $new_smaller_dim;;
                }
                imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                header(sprintf('Content-type: %s',$size_data['mime']));
                // }}}
                switch ($size_data[2]) {
                    case IMG_GIF: imagegif($im); break;
                    case 3: case IMG_PNG: imagepng($im); break;
                    case IMG_JPG: imagejpeg($im); break;
                    case IMG_WBMP: imagewbmp($im); break;
                    case IMG_XPM: imagexbm($im); break;
                }
                imagedestroy($wm);
                imagedestroy($im);
                unlink($tempfile);
Thursday, March 18, 2010
// configure image and dimensions {{{
                $size_data = array();
                $im = start_image($tempfile, $size_data);
                if (!$im) {
                    unlink($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // get watermark information {{{
                $wm_data = array();
                $wm = start_image($watermark, $wm_data);
                if (!$wm) {
                    unlink ($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // add watermark {{{
                if ($size_data['ratio']> $wm_data['ratio']) {
                    // image is wider format than the watermark
                    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);
                    $dst_x = ($size_data[0] - $new_smaller_dim)/2;
                    $dst_y = 0;
                    $dst_w = $new_smaller_dim;
                    $dst_h = $size_data[1];
                } else {
                    // image is taller format than the watermark
                    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);
                    $dst_x = 0;
                    $dst_y = ($size_data[1] - $new_smaller_dim)/2;
                    $dst_w = $size_data[0];
                    $dst_h = $new_smaller_dim;;
                }
                imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                header(sprintf('Content-type: %s',$size_data['mime']));
                // }}}
                switch ($size_data[2]) {
                    case IMG_GIF: imagegif($im); break;
                    case 3: case IMG_PNG: imagepng($im); break;
                    case IMG_JPG: imagejpeg($im); break;
                    case IMG_WBMP: imagewbmp($im); break;
                    case IMG_XPM: imagexbm($im); break;
                }
                imagedestroy($wm);
                imagedestroy($im);
                unlink($tempfile);
Thursday, March 18, 2010
// configure image and dimensions {{{
                $size_data = array();
                $im = start_image($tempfile, $size_data);
                if (!$im) {
                    unlink($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // get watermark information {{{
                $wm_data = array();
                $wm = start_image($watermark, $wm_data);
                if (!$wm) {
                    unlink ($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // add watermark {{{
                if ($size_data['ratio']> $wm_data['ratio']) {
                    // image is wider format than the watermark
                    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);
                    $dst_x = ($size_data[0] - $new_smaller_dim)/2;
                    $dst_y = 0;
                    $dst_w = $new_smaller_dim;
                    $dst_h = $size_data[1];
                } else {
                    // image is taller format than the watermark
                    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);
                    $dst_x = 0;
                    $dst_y = ($size_data[1] - $new_smaller_dim)/2;
                    $dst_w = $size_data[0];
                    $dst_h = $new_smaller_dim;;
                }
                imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                header(sprintf('Content-type: %s',$size_data['mime']));
                // }}}
                switch ($size_data[2]) {
                    case IMG_GIF: imagegif($im); break;
                    case 3: case IMG_PNG: imagepng($im); break;
                    case IMG_JPG: imagejpeg($im); break;
                    case IMG_WBMP: imagewbmp($im); break;
                    case IMG_XPM: imagexbm($im); break;
                }
                imagedestroy($wm);
                imagedestroy($im);
                unlink($tempfile);
Thursday, March 18, 2010
// configure image and dimensions {{{
                $size_data = array();
                $im = start_image($tempfile, $size_data);
                if (!$im) {
                    unlink($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // get watermark information {{{
                $wm_data = array();
                $wm = start_image($watermark, $wm_data);
                if (!$wm) {
                    unlink ($tempfile);
                    tag_http::redirect($dead_url);
                    return;
                }
                // }}}
                // add watermark {{{
                if ($size_data['ratio']> $wm_data['ratio']) {
                    // image is wider format than the watermark
                    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);
                    $dst_x = ($size_data[0] - $new_smaller_dim)/2;
                    $dst_y = 0;
                    $dst_w = $new_smaller_dim;
                    $dst_h = $size_data[1];
                } else {
                    // image is taller format than the watermark
                    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);
                    $dst_x = 0;
                    $dst_y = ($size_data[1] - $new_smaller_dim)/2;
                    $dst_w = $size_data[0];
                    $dst_h = $new_smaller_dim;;
                }
                imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);
                header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
                header(sprintf('Content-type: %s',$size_data['mime']));
                // }}}
                switch ($size_data[2]) {
                    case IMG_GIF: imagegif($im); break;
                    case 3: case IMG_PNG: imagepng($im); break;
                    case IMG_JPG: imagejpeg($im); break;
                    case IMG_WBMP: imagewbmp($im); break;
                    case IMG_XPM: imagexbm($im); break;
                }
                imagedestroy($wm);
                imagedestroy($im);
                unlink($tempfile);
Thursday, March 18, 2010
Beyond Funky
                             Caching


Thursday, March 18, 2010

With a bit of creativity this concept can apply to modern applications where instead of
caching on the filesystem, you cache in memcache; instead of bypassing the application
server, you bypass the web servers themselves with a content distribution network; instead of
serving static content from the edge, you serve dynamic pages.
Whether to use it and how to use it is always determined by the environment.
San Francisco                                          quotes of san francisco?




                     Looking around you for
                           inspiration




Thursday, March 18, 2010
I hope this tour helps you see software development in a different way—that finding solutions are about using the right solution in a manner that fits with the environment.
Even then I realize that we can’t architect structures that work as harmoniously together as a city such as San Francisco. Story of Rounded Rectangles…

Bill Atkinson worked mostly at home, but whenever he made significant progress he rushed in to Apple to show it off to anyone who would appreciate it. This time, he
visited the Macintosh offices at Texaco Towers to show off his brand new oval routines, which were implemented using a really clever algorithm. Bill had added new code to
QuickDraw (which was still called LisaGraf at this point) to draw circles and ovals very quickly. That was a bit hard to do on the Macintosh, since the math for circles usually
involved taking square roots, and the 68000 processor in the Lisa and Macintosh didn't support floating point operations. But Bill had come up with a clever way to do the
circle calculation that only used addition and subtraction, not even multiplication or division, which the 68000 could do, but was kind of slow at.

Bill's technique used the fact the sum of a sequence of odd numbers is always the next perfect square (For example, 1 + 3 = 4, 1 + 3 + 5 = 9, 1 + 3 + 5 + 7 = 16, etc). So
he could figure out when to bump the dependent coordinate value by iterating in a loop until a threshold was exceeded. This allowed QuickDraw to draw ovals very quickly.

Bill fired up his demo and it quickly filled the Lisa screen with randomly-sized ovals, faster than you thought was possible. But something was bothering Steve Jobs. "Well,
circles and ovals are good, but how about drawing rectangles with rounded corners? Can we do that now, too?"

"No, there's no way to do that. In fact it would be really hard to do, and I don't think we really need it". I think Bill was a little miffed that Steve wasn't raving over the fast
ovals and still wanted more.

Steve suddenly got more intense. "Rectangles with rounded corners are everywhere! Just look around this room!". And sure enough, there were lots of them, like the
whiteboard and some of the desks and tables. Then he pointed out the window. "And look outside, there's even more, practically everywhere you look!". He even persuaded
Thanks!
                                 resize




                             tychay@php.net
                           terrychay.com/blog

Thursday, March 18, 2010

Más contenido relacionado

La actualidad más candente

Php File Operations
Php File OperationsPhp File Operations
Php File Operations
mussawir20
 
Php tutorial(w3schools)
Php tutorial(w3schools)Php tutorial(w3schools)
Php tutorial(w3schools)
Arjun Shanka
 

La actualidad más candente (19)

PHP NOTES FOR BEGGINERS
PHP NOTES FOR BEGGINERSPHP NOTES FOR BEGGINERS
PHP NOTES FOR BEGGINERS
 
Multisite Van Dyk Walkah
Multisite Van Dyk WalkahMultisite Van Dyk Walkah
Multisite Van Dyk Walkah
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHP
 
PHP POWERPOINT SLIDES
PHP POWERPOINT SLIDESPHP POWERPOINT SLIDES
PHP POWERPOINT SLIDES
 
Sa
SaSa
Sa
 
New PHP Exploitation Techniques
New PHP Exploitation TechniquesNew PHP Exploitation Techniques
New PHP Exploitation Techniques
 
File system
File systemFile system
File system
 
Filesystem Abstraction with Flysystem
Filesystem Abstraction with FlysystemFilesystem Abstraction with Flysystem
Filesystem Abstraction with Flysystem
 
Php File Operations
Php File OperationsPhp File Operations
Php File Operations
 
Mengembalikan data yang terhapus atau rusak pada hardisk menggunakan ubuntu
Mengembalikan data yang terhapus atau rusak pada hardisk menggunakan ubuntuMengembalikan data yang terhapus atau rusak pada hardisk menggunakan ubuntu
Mengembalikan data yang terhapus atau rusak pada hardisk menggunakan ubuntu
 
Php tutorial(w3schools)
Php tutorial(w3schools)Php tutorial(w3schools)
Php tutorial(w3schools)
 
Introduction to php web programming - get and post
Introduction to php  web programming - get and postIntroduction to php  web programming - get and post
Introduction to php web programming - get and post
 
Introducation to php for beginners
Introducation to php for beginners Introducation to php for beginners
Introducation to php for beginners
 
Using PHP
Using PHPUsing PHP
Using PHP
 
Php mysql
Php mysqlPhp mysql
Php mysql
 
Php with my sql
Php with my sqlPhp with my sql
Php with my sql
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop Notes
 
Php talk
Php talkPhp talk
Php talk
 
Php Tutorial | Introduction Demo | Basics
 Php Tutorial | Introduction Demo | Basics Php Tutorial | Introduction Demo | Basics
Php Tutorial | Introduction Demo | Basics
 

Similar a PHP Without PHP—Confoo

On secure application of PHP wrappers
On secure application  of PHP wrappersOn secure application  of PHP wrappers
On secure application of PHP wrappers
Positive Hack Days
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 

Similar a PHP Without PHP—Confoo (20)

Key features PHP 5.3 - 5.6
Key features PHP 5.3 - 5.6Key features PHP 5.3 - 5.6
Key features PHP 5.3 - 5.6
 
Remote File Inclusion / Local File Inclusion [Attack and Defense Techniques]
Remote File Inclusion / Local File Inclusion [Attack and Defense Techniques]Remote File Inclusion / Local File Inclusion [Attack and Defense Techniques]
Remote File Inclusion / Local File Inclusion [Attack and Defense Techniques]
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Php mysql ppt
 
On secure application of PHP wrappers
On secure application  of PHP wrappersOn secure application  of PHP wrappers
On secure application of PHP wrappers
 
Php intro
Php introPhp intro
Php intro
 
PHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source ProjectPHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source Project
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Justmeans power point
Justmeans power pointJustmeans power point
Justmeans power point
 
Learning of Php and My SQL Tutorial | For Beginners
Learning of Php and My SQL Tutorial | For BeginnersLearning of Php and My SQL Tutorial | For Beginners
Learning of Php and My SQL Tutorial | For Beginners
 
Php My SQL Tutorial | beginning
Php My SQL Tutorial | beginningPhp My SQL Tutorial | beginning
Php My SQL Tutorial | beginning
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
Php mysql training-in-mumbai
Php mysql training-in-mumbaiPhp mysql training-in-mumbai
Php mysql training-in-mumbai
 
Php hacku
Php hackuPhp hacku
Php hacku
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 

Más de terry chay

Más de terry chay (15)

2019-03 PHP without PHP Architecture @ Confoo
2019-03 PHP without PHP Architecture @ Confoo2019-03 PHP without PHP Architecture @ Confoo
2019-03 PHP without PHP Architecture @ Confoo
 
2019-03 Recomendation Engine @ Confoo
2019-03 Recomendation Engine @ Confoo2019-03 Recomendation Engine @ Confoo
2019-03 Recomendation Engine @ Confoo
 
2019-02 The Recommendation Engine @ SunshinePHP
2019-02 The Recommendation Engine @ SunshinePHP2019-02 The Recommendation Engine @ SunshinePHP
2019-02 The Recommendation Engine @ SunshinePHP
 
2017-11 Recommendation Engine @ RaiseMe
2017-11 Recommendation Engine @ RaiseMe2017-11 Recommendation Engine @ RaiseMe
2017-11 Recommendation Engine @ RaiseMe
 
2009-02 Oops!
2009-02 Oops!2009-02 Oops!
2009-02 Oops!
 
2013-08 10 evil things - Northeast PHP Conference Keynote
2013-08 10 evil things - Northeast PHP Conference Keynote2013-08 10 evil things - Northeast PHP Conference Keynote
2013-08 10 evil things - Northeast PHP Conference Keynote
 
10 Evil(ish) Things and how they relate to Features Engineering at the WMF
10 Evil(ish) Things and how they relate to Features Engineering at the WMF10 Evil(ish) Things and how they relate to Features Engineering at the WMF
10 Evil(ish) Things and how they relate to Features Engineering at the WMF
 
2011 07 Tales of Virality—OSCON
2011 07 Tales of Virality—OSCON2011 07 Tales of Virality—OSCON
2011 07 Tales of Virality—OSCON
 
2011 07 Living without your Linemen—OSCON
2011 07 Living without your Linemen—OSCON2011 07 Living without your Linemen—OSCON
2011 07 Living without your Linemen—OSCON
 
PHP Without PHP—Automattic
PHP Without PHP—AutomatticPHP Without PHP—Automattic
PHP Without PHP—Automattic
 
Broken Jewel—Automattic
Broken Jewel—AutomatticBroken Jewel—Automattic
Broken Jewel—Automattic
 
Photo to Finished
Photo to FinishedPhoto to Finished
Photo to Finished
 
Tales of Virality—Automattic
Tales of Virality—AutomatticTales of Virality—Automattic
Tales of Virality—Automattic
 
Chinese Proverbs—PHP|tek
Chinese Proverbs—PHP|tekChinese Proverbs—PHP|tek
Chinese Proverbs—PHP|tek
 
PHP Without PHP—IPC
PHP Without PHP—IPCPHP Without PHP—IPC
PHP Without PHP—IPC
 

Último

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Último (20)

Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 

PHP Without PHP—Confoo

  • 1. PHP without PHP The Philosophy of Good Architecture terry chay 2010-03-10T09:30+0500 Confoo Montreal, Canada Thursday, March 18, 2010 An obscure but ubiquitous design pattern in PHP development is known as Funky Caching. Using real architectural examples as a lens to look at this one simple PHP design pattern, we see how we can design web architectures that are "organic, democratic, and lasting…"
  • 2. Funky Caching Prologue #1 Thursday, March 18, 2010 Two prologues
  • 3. aka Thursday, March 18, 2010 Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  • 4. aka ErrorDocument trick Thursday, March 18, 2010 Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  • 5. aka ErrorDocument trick Smarter Caching Thursday, March 18, 2010 Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  • 6. aka ErrorDocument trick Smarter Caching … Rasmus’s Trick (Stig’s trick) Thursday, March 18, 2010 Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  • 7. aka ErrorDocument trick Smarter Caching … Rasmus’s Trick (Stig’s trick) Thursday, March 18, 2010 Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  • 8. aka ErrorDocument trick Smarter Caching … Rasmus’s Trick (Stig’s trick) Go into apache.conf (or .htaccess) and ErrorDocument 404 /error.php Thursday, March 18, 2010 Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  • 9. Error.PHP $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL'] $basepath = dirname(__FILE__).DIR_SEP;   // Test to see if you can work with it if (false) { //…EDIT…     //output a 404 page     include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips     return; }   // Generate the file // …EDIT… $data = 'something';   // Don't send 404 back, send 200 OK because this is a pretty smart 404 // not a clueless one! http://www.urbandictionary.com/define.php?term=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $data;   //Store the page to bypass PHP on the next request. Use a temp file with a // link trick in order to avoid race conditions between concurrent PHP // processes. $tmpfile = tempnam($basepath.'tmp','fc'); $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile); Thursday, March 18, 2010 What does this trick do? Basically, when a file doesn’t exist, it gives an opportunity for PHP to create the data and return it instead of a 404 error page. The code above is pretty canonical, the only exceptions are where you branch to show the default error page… syntax highlighting code: php_value highlight.string '#b02c04' php_value highlight.comment '#8e98a6' php_value highlight.keyword '#96ad53' #php_value highlight.bg '#f1f7d7' php_value highlight.default '#524e37' php_value highlight.html '#95ad53'
  • 10. Error.PHP $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL'] $basepath = dirname(__FILE__).DIR_SEP;   // Test to see if you can work with it if (false) { //…EDIT…     //output a 404 page     include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips     return; }   // Generate the file // …EDIT… $data = 'something';   // Don't send 404 back, send 200 OK because this is a pretty smart 404 // not a clueless one! http://www.urbandictionary.com/define.php?term=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $data;   //Store the page to bypass PHP on the next request. Use a temp file with a // link trick in order to avoid race conditions between concurrent PHP // processes. $tmpfile = tempnam($basepath.'tmp','fc'); $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile); Thursday, March 18, 2010 What does this trick do? Basically, when a file doesn’t exist, it gives an opportunity for PHP to create the data and return it instead of a 404 error page. The code above is pretty canonical, the only exceptions are where you branch to show the default error page… syntax highlighting code: php_value highlight.string '#b02c04' php_value highlight.comment '#8e98a6' php_value highlight.keyword '#96ad53' #php_value highlight.bg '#f1f7d7' php_value highlight.default '#524e37' php_value highlight.html '#95ad53'
  • 11. Error.PHP $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL'] $basepath = dirname(__FILE__).DIR_SEP;   // Test to see if you can work with it if (false) { //…EDIT…     //output a 404 page     include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips     return; Ceheck }   // Generate the file // …EDIT… $data = 'something';   // Don't send 404 back, send 200 OK because this is a pretty smart 404 // not a clueless one! http://www.urbandictionary.com/define.php?term=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $data;   //Store the page to bypass PHP on the next request. Use a temp file with a // link trick in order to avoid race conditions between concurrent PHP // processes. $tmpfile = tempnam($basepath.'tmp','fc'); $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile); Thursday, March 18, 2010 …and where you generate the actual data to render to the user.
  • 12. Error.PHP $filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL'] $basepath = dirname(__FILE__).DIR_SEP;   // Test to see if you can work with it if (false) { //…EDIT…     //output a 404 page     include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips     return; }   // Generate the file // …EDIT… $data = 'something';   // Don't send 404 back, send 200 OK because this is a pretty smart 404 // not a clueless one! http://www.urbandictionary.com/define.php?term=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $data;   //Store the page to bypass PHP on the next request. Use a temp file with a // link trick in order to avoid race conditions between concurrent PHP // processes. $tmpfile = tempnam($basepath.'tmp','fc'); $fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile); Thursday, March 18, 2010 At the bottom is where the magic happens. It places the generated file directly into the web server path. What this means is that the next request to the same web resource goes directly for that resource without starting up this code and regenerating the data. Reference: 404 defined: http://en.wikipedia.org/wiki/HTTP_404 404 discussion: http://www.alistapart.com/articles/perfect404/ 404 examples: http://www.plinko.net/404/ HTTP codes: http://www.urbandictionary.com/define.php?term=404
  • 13. PHP without PHP Thursday, March 18, 2010 PHP never gets instantiated after the first request! At that point it truly becomes PHP without PHP.
  • 14. Paradigms Prologue #2 Thursday, March 18, 2010
  • 15. Code Complete The metaphor of Code as construction comes from this book… We now know this is fundamentally wrong… Thursday, March 18, 2010 About the book and the metaphor. The foundation of Steve McConnell’s seminal text, Code Complete, was that software development should be based around the paradigm of construction. But that was fundamentally flawed because of the mythical man-month—the “man-month” term itself originally coming from construction work. We now know McConnell was wrong and software isn’t construction, it is engineering. And we’re called “software engineers,” not “software workers” for this reason: we’re engineers, not construction workers.
  • 16. Mythical Man Month reorganize notes too much text “man-month” is a term from construction work The premise is that man and months are interchangeable. This means that in order to reach a deadline I simply add more people to the project. Thursday, March 18, 2010 Rhe foundation of Steve McConnell’s seminal text, Code Complete, was that software development should be based around the paradigm of construction. But that was fundamentally flawed because of the mythical man-month—the “man-month” term itself originally coming from construction work. We now know McConnell was wrong and software isn’t construction, it is engineering. And we’re called “software engineers,” not “software workers” for this reason: we’re engineers, not construction workers.
  • 17. too much text Thursday, March 18, 2010
  • 18. paritionable with training traning + communication unpartitionable 20 Time to COmplete Title too much text 15 10 5 Number of People Thursday, March 18, 2010
  • 19. paritionable with training traning + communication unpartitionable 20 Time to COmplete Title First consider something like p a i n t i n g a f e n c e : e v e r y t h i n g much text too i s 15 partionable (man-month). 10 5 Number of People Thursday, March 18, 2010
  • 20. paritionable with training traning + communication unpartitionable 20 Time to COmplete Title First consider something like p a i n t i n g a f e n c e : e v e r y t h i n g much text too i s 15 partionable (man-month). …add a constant time for training. 10 5 Number of People Thursday, March 18, 2010
  • 21. paritionable with training traning + communication unpartitionable 20 Time to COmplete Title First consider something like p a i n t i n g a f e n c e : e v e r y t h i n g much text too i s 15 partionable (man-month). …add a constant time for training. 10 …add communication cost: n(n-1)/2. 5 Number of People Thursday, March 18, 2010
  • 22. paritionable with training traning + communication unpartitionable 20 Time to COmplete Title First consider something like p a i n t i n g a f e n c e : e v e r y t h i n g much text too i s 15 partionable (man-month). …add a constant time for training. 10 …add communication cost: n(n-1)/2. 5 Compare to the unpartitionable (single man) Number of People Thursday, March 18, 2010
  • 23. paritionable with training traning + communication unpartitionable 20 Time to COmplete Title First consider something like p a i n t i n g a f e n c e : e v e r y t h i n g much text too i s 15 partionable (man-month). …add a constant time for training. 10 …add communication cost: n(n-1)/2. 5 Compare to the unpartitionable (single man) Adding people to a late project makes it later! Number of People Thursday, March 18, 2010
  • 24. Engineer and graphics Architect Thursday, March 18, 2010 Software as Engineering vs. other. My title at Tagged is currently “software architect.” And I have a “radical” idea that maybe titles are that way because they mean something. Meaning that if I’m hired as a software architect then I should think like an architect and find my inspiration from architecture.
  • 25. 1 Fallingwater organic, democratic, plasticity, continuity Thursday, March 18, 2010 So lets find our inspiration from architecture and see how it explains the Funky Caching pattern through three buildings. the first is one known as Fallingwater. References: Fallingwater logo from: http://www.fallingwater.org/
  • 26. Thursday, March 18, 2010 In Eastern mountain range of the United States there is a house that is CANTILEVERed 40 feet above a waterfall. This is one of the most famous buildings by American architect, FRANK LLOYD WRIGHT. In 1991 it was voted as the best all-time work of American architecture by the American Institute of Architects. Even though it is OVER 80KM from the nearest city people over a MILLION PEOPLE have traveled to see it. Reference: Image from http://commons.wikimedia.org/wiki/File:Falling_Water_01.jpg Wikipedia: http://en.wikipedia.org/wiki/Fallingwater Frank Lloyd Wright: http://franklloydwright.org/Home.html
  • 27. …including me Thursday, March 18, 2010 Yes, including me as a kid. The day it was built, TIME MAGAZINE wrote about it. Because it was a quintessential example of ORGANIC ARCHITECTURE of FLW. References: Der Spiegel: http://en.wikipedia.org/wiki/Der_Spiegel
  • 28. Hatchway Staircase View at the main (living room) level, from the bridge (from east) Thursday, March 18, 2010 A staircase connects the house directly to the stream below. The stream and waterfall, although not seen, can be heard in all parts of the house. The HATCHWAY that consists of SLIDING GLASS DOORS and the bottom step has no support from below. (FLOAT above like the water floats) References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/06E-hatchway- fallingwater.html
  • 29. Beyond the glass Fallingwater: Living room terraces and glass walls (from east). Thursday, March 18, 2010 WINDOWS WRAP AROUND THE ENTIRE BUILDING so that the building MERGES with the surrounding GREENERY. Similarly the TUNGSTEN LIGHTING and the glasses compliments the FALL FOLIAGE of the region…
  • 30. Fall Foliage View from lookout, downstream. Thursday, March 18, 2010 This is the VIEW that FLW planned for the house. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/F1SW-fallingwater-in- fall.html
  • 31. Fall Foliage View from lookout, downstream. Thursday, March 18, 2010
  • 32. No barriers Detail: corner window at the guest house, from southeast. Thursday, March 18, 2010 Panes of glass are caulked directly to each other and to the steel frame or stone walls to further symbolize the lack of barriers between the construction and the surrounding nature. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/34SE-guest-house- window.html
  • 33. Existing tree The trellis over the driveway is built to accommodate a tree. Thursday, March 18, 2010 The driveway trellis has a semi-circular cutaway to accommodate an existing tree. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/15-tree-in-trellis- fallingwater.html
  • 34. Local quarry Living room, west (downstream) side, from southeast Thursday, March 18, 2010 The stone floor in the living room, quarried from local rocks http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/livingroom- fallingwater.html
  • 35. Existing boulder Living room fireplace and hearth, looking from kitchen door to south windows Thursday, March 18, 2010 The rock in the foreground is is an original boulder not disturbed from it’s original position. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/7-living-room-fireplace- hearth.php
  • 36. Existing boulder Living room fireplace and hearth, looking from kitchen door to south windows Thursday, March 18, 2010 The rock in the foreground is is an original boulder not disturbed from it’s original position. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/7-living-room-fireplace- hearth.php
  • 37. Thursday, March 18, 2010 From details like these to the whole view taken in at once, one gets a feeling that, in spite of the SHARP HORIZONTAL AND VERTICAL LINES of the building, the whole lives in harmony with its environment "instead of lording above [it] in an isolated spot as a man-made imposition.” Why is this building as recognizable as any NATURAL WONDER?
  • 38. Philosophy organic, democratic, plasticity, continuity. Thursday, March 18, 2010 Surveyed the grounds before building. Organic: "form follows function." Wright argued that "form and function are one." Democratic “design should accommodate needs” Plasticity: “physical element should remove barriers.” Continuity “element should be part of nature”
  • 39. Why on PHP? Thursday, March 18, 2010 How prevalent is funky caching? Every time you visit PHP.NET, you use it (need to get the order of needle-haystack by typing http://php.net/strstr). A cynic would say, because PHP is so SLOW TO EXECUTE, it needs solutions like this to perform well. The problem with this argument is that NO WEB LANGUAGE OUTPERFORMS STATIC SERVERS. Becase it trades off speed of execution with SPEED FOR EASE OF DEVELOPMENT. As Andrei mentioned earlier, that is fundamental to its design. In fact, all dynamically-typed scripting languages make this tradeoff.
  • 40. Harmony with Environment Thursday, March 18, 2010 The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater —lives in harmony with its environment. The environment is an APACHE WEB SERVER, persistent data store in the form of a RELATIONAL DATABASE, and the demands of large- scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument handler built into Apache? Would this solution exist if we didn't persist content on a (relatively) slow data store like a database? Would this solution exist if the consumer didn't demand millisecond response time for dynamic content?
  • 41. Harmony with Environment Apache web server: ErrorDocument Thursday, March 18, 2010 The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater —lives in harmony with its environment. The environment is an APACHE WEB SERVER, persistent data store in the form of a RELATIONAL DATABASE, and the demands of large- scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument handler built into Apache? Would this solution exist if we didn't persist content on a (relatively) slow data store like a database? Would this solution exist if the consumer didn't demand millisecond response time for dynamic content?
  • 42. Harmony with Environment Apache web server: ErrorDocument Customer-centric: Performance paramount Thursday, March 18, 2010 The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater —lives in harmony with its environment. The environment is an APACHE WEB SERVER, persistent data store in the form of a RELATIONAL DATABASE, and the demands of large- scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument handler built into Apache? Would this solution exist if we didn't persist content on a (relatively) slow data store like a database? Would this solution exist if the consumer didn't demand millisecond response time for dynamic content?
  • 43. Harmony with Environment Apache web server: ErrorDocument Customer-centric: Performance paramount Relational Database: Slow persistence Thursday, March 18, 2010 The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater —lives in harmony with its environment. The environment is an APACHE WEB SERVER, persistent data store in the form of a RELATIONAL DATABASE, and the demands of large- scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument handler built into Apache? Would this solution exist if we didn't persist content on a (relatively) slow data store like a database? Would this solution exist if the consumer didn't demand millisecond response time for dynamic content?
  • 44. Harmony with Environment Apache web server: ErrorDocument Customer-centric: Performance paramount Relational Database: Slow persistence Harmony with PHP itself… Thursday, March 18, 2010 The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright's Fallingwater —lives in harmony with its environment. The environment is an APACHE WEB SERVER, persistent data store in the form of a RELATIONAL DATABASE, and the demands of large- scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument handler built into Apache? Would this solution exist if we didn't persist content on a (relatively) slow data store like a database? Would this solution exist if the consumer didn't demand millisecond response time for dynamic content?
  • 45. write text to talk about it Architecture of PHP Modern web architecture Thursday, March 18, 2010 The language itself. PHP is a component of A WHOLE SYSTEM. It’s glue code.
  • 46. PHP is “Cheap” graphcis money shorten quote “A project done in Java will cost 5 times as much, take twice as long, and be harder to maintain than a project done in a scripting language such as PHP or Perl.” —Phillip Greenspun Thursday, March 18, 2010 developer time and resources
  • 47. PHP is “Scalable” “That a Java servlet performs better graphics notes? shortne quote than a PHP script, under optimal conditions [has] nothing to do with scalability. The point is can your application continue to deliver consistent performance as volume increases. PHP delegates all the ‘hard stuff’ to other systems.” —Harry Fuecks Thursday, March 18, 2010 shared-nothing architecture
  • 48. PHP is “Pragmatic” “PHP is not about purity in CS graphics shorten quote principles or architecture; it is about solving the ugly web problem with an admittedly ugly, but extremely functional and convenient solution. If you are looking for purity, you are in the wrong boat. Get out now before you get hit by a wet cat!” —Rasmus Lerdorf Thursday, March 18, 2010 designed to solve the web problem Could this "ugly, but extremely functional and convenient" web language have been built to solve anything other than the ugly web problem?
  • 49. 2 Bellefield Towers Design Hubris Thursday, March 18, 2010 One block from where my mother used to work, on the corner of Fifth Avenue and Bellefield in Pittsburgh, stands a strange sight…
  • 50. make video of wpaking towards? Thursday, March 18, 2010 If you weren’t in PITTSBURGH IN THE LATE 1980’s you wouldn’t have understood how his could have happened. On this ground once stood the original Bellefield church built in the 1880’s. Since its CONGREGATION HAD BEEN MOVED further down Fifth Avenue, the building was sold a century later to developers trying to exploit the new business attracted by the PITTSBURGH SUPERCOMPUTING CENTER. They wanted to level it and build a new building, but were blocked when people mobilized to SAVE THE OLD TOWER. The developer then proceeded to honor this by DEMOLISH EVERYTHING BUT THE TOWER and building the ironically-named “Bellefield Towers” next to it.
  • 51. Gothic Romanesque architecture The current Bellefield Church (two blocks away) Thursday, March 18, 2010 This is the current Bellefield Church and an example of city architecture of which the tower is one of them…
  • 52. Other city towers Allegheny Courthouse Main Tower & Four Tower Types at Jail (and other towers) Thursday, March 18, 2010 The center is the county courthouse and jail, the top right is the local Korean church, and the bottom right is a private residence in the same neighborhood.
  • 53. Tower of Learning Within spitting distance of Bellefield Towers Thursday, March 18, 2010
  • 54. redo builds break out slides quots Carnegie Library Most iconic moment in baseball history Thursday, March 18, 2010 The photo at the top is was taken from the Cathedral of learning (previous slide).
  • 55. redo builds break out slides quots Carnegie Library Most iconic moment in baseball history Thursday, March 18, 2010 The photo at the top is was taken from the Cathedral of learning (previous slide).
  • 56. Why is Bellefield Towers so Ugly? Thursday, March 18, 2010 When faced with a gorgeous 100-year old example of the area’s architecture, INSTEAD OF WORKING WITH THE ENVIRONMENT like Frank Lloyd Wright did with Fallingwater—in the same area of Pennsylvania no less!—the developer simply sawed it off! The CURVED MODERN ARCHITECTURE of the TOWERS of the latter serves only to emphasize how it was built with no consideration of the surrounding environment. I GREW UP WATCHING THIS HAPPEN and it is a LIFE LESSON IN ARCHITECTURAL HUBRIS.
  • 57. Design Hubris? break out slides, graphics Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 58. Design Hubris? Frameworks (almost by definition) break out slides, graphics Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 59. Design Hubris? Frameworks (almost by definition) break out slides, graphics Develop in the PHP community? Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 60. Design Hubris? Frameworks (almost by definition) break out slides, graphics Develop in the PHP community? Take over an existing project? Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 61. Design Hubris? Frameworks (almost by definition) break out slides, graphics Develop in the PHP community? Take over an existing project? Limitations of Site Operations? Hosting? or Virtual hosting? Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 62. Design Hubris? Frameworks (almost by definition) break out slides, graphics Develop in the PHP community? Take over an existing project? Limitations of Site Operations? Hosting? or Virtual hosting? Business needs trump programmer desire? Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 63. Design Hubris? Frameworks (almost by definition) break out slides, graphics Develop in the PHP community? Take over an existing project? Limitations of Site Operations? Hosting? or Virtual hosting? Business needs trump programmer desire? Dealt with a user request? Thursday, March 18, 2010 “I’m a developer, I can make the software conform to my needs.” Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  • 64. add slideshow …at Tagged Thursday, March 18, 2010 cover cube story, (where cubes are good- Yahoo, sales, user QA), cover waterfall process
  • 65. …at Tagged break out slides Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 66. …at Tagged break out slides Cubes Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 67. …at Tagged break out slides Cubes Waterfall process Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 68. …at Tagged break out slides Cubes Waterfall process Oracle RAC Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 69. …at Tagged break out slides Cubes Waterfall process Oracle RAC Java Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 70. …at Tagged break out slides Cubes Waterfall process Oracle RAC Java PHP4 Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 71. …at Tagged break out slides Cubes Waterfall process Oracle RAC Java PHP4 Zend Accelerator Thursday, March 18, 2010 When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC powered the back-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process. Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  • 72. Rework Thursday, March 18, 2010 Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
  • 73. Rework From the Founders of 37 Signals Thursday, March 18, 2010 Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
  • 74. Rework From the Founders of 37 Signals Thursday, March 18, 2010 Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
  • 75. Rework From the Founders of 37 Signals Last Book: “Getting Real” Thursday, March 18, 2010 Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
  • 76. Rework Thursday, March 18, 2010 - cliche ridden with few examples “Hannah Montanta” reach for you dreams - “would rather be celebrities than businesspeople.” - 'Meetings are toxic.' In reality, good meetings are good and bad meetings are not good (generalization) - “Planning, they say, is not recommended” - only applies to their business - “They need to stop behaving like children.” - “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions, the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
  • 77. Rework “Not Just Bad, but dangerous” Thursday, March 18, 2010 - cliche ridden with few examples “Hannah Montanta” reach for you dreams - “would rather be celebrities than businesspeople.” - 'Meetings are toxic.' In reality, good meetings are good and bad meetings are not good (generalization) - “Planning, they say, is not recommended” - only applies to their business - “They need to stop behaving like children.” - “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions, the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
  • 78. Rework “Not Just Bad, but dangerous” —John Vincent, Leon Restaurants Thursday, March 18, 2010 - cliche ridden with few examples “Hannah Montanta” reach for you dreams - “would rather be celebrities than businesspeople.” - 'Meetings are toxic.' In reality, good meetings are good and bad meetings are not good (generalization) - “Planning, they say, is not recommended” - only applies to their business - “They need to stop behaving like children.” - “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions, the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
  • 79. Solutions Consider Environment Thursday, March 18, 2010 Why? Because that is the environment and your solutions have to work within that environment. Anything else is architectural hubris. Let’s say it is the early days of social networking and you join a company that is using Java/J2EE instead of PHP, or Oracle instead of MySQL, or they’re using Perl/Mason instead of your favorite (PHP) framework, as Marco mentioned earlier—there are so many to choose from that the number is second only to Java. Do you go in and say your experience building a CMS or e-store trumps their experience working on a nascent social network? Do you replace all the Java engineers with PHP ones? Do you replace MySQL with Oracle? Do you rewrite the site from scratch using your favorite framework? I’m not saying that in all these instances these architects shouldn’t have made the decisions they did. I am not qualified to answer that since I didn’t work at these places. But what I do know was that in the vast majority of cases, people went in without considering the existing environment. I do know the dynamics of a Facebook.com is different from the dynamics of Gamespot.com or Amazon.com. I do know a social network is different from a CMS or e-store. And all these solutions are very different from ones in enterprise. Like building Fallingwater without getting an adequate survey done, every day people make the mistake of not looking before acting. They try to make PHP look like Java with dollar signs, as Luke mentioned earlier. They expected the environment to conform to their reality so they can lord over it with “some isolated man-made imposition.”
  • 80. 3 Golden Gate Bridge The Design Pattern Thursday, March 18, 2010 I’ve long since moved from the woods of Western Pennsylvania to the San Francisco Peninsula. I am fortunate that my weekly run passes with a near-constant view of the most recognizable architecture in the American West: References: Image licensed from: http://www.istockphoto.com/file_closeup.php?id=6091847
  • 81. design build quote of goldne gate bridge Thursday, March 18, 2010 my weekend run
  • 82. quote from emperor norton the other bridge Thursday, March 18, 2010 What’s interesting is that there are much longer spans in the country and the world. Even in the same city, there exists a beautiful bridge that is both longer and of more utility. And yet this bridge represents the icon of San Francisco and of the state as a whole.
  • 83. quotes of sf Thursday, March 18, 2010
  • 85. Same problem, different pattern Original design was hybrid cantilever-suspension. Replaced by purse suspension Thursday, March 18, 2010 The original design was for a hybrid cantilever and suspension structure. But it was replaced with a pure suspension design because the former was deemed too ugly. A pure suspension of this length had never been attempted before.
  • 86. Art Deco quote of art deco movemebnt Bridge Tower, Lighting, pedestrial walkway Thursday, March 18, 2010 Irving Morrow designed the bridge tower, lighting, and pedestrian walkways with an entirely Art Deco decorative influence.
  • 87. International Orange Rust colored like the environment it lives in … and safe. Thursday, March 18, 2010 The bridge was painted in a specially formulated anti-rust paint in International Orange on demand from locals. The War Department, and others. The Navy alone originally demanded it be painted black with yellow stripes to assure visibility with passing ships. The rust-colored paint evokes the hills of Marin to the north as well as the setting sun. It is natural and visible enough to be safe.
  • 88. Part of the whole Thursday, March 18, 2010 rust-colored suspension-only art deco structure It becomes an icon. Every week I pass by it and am inspired and thankful I can live in so beautiful a city.
  • 89. Design Patterns Defined shorten quote Thursday, March 18, 2010 This quote is the origin of “design pattern.”
  • 90. Design Patterns Defined shorten quote “Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” Thursday, March 18, 2010 This quote is the origin of “design pattern.”
  • 91. Certainly iconic Me in front of both icons Thursday, March 18, 2010 But how are we to know which way to do it? Or even if it is the right pattern to be using in our situation? The answer is found in how both a house in Pennsylvania and a bridge in San Francisco represent ultimate expressions of architecture. They are wholly appropriate for the environment in which they stand.
  • 92. blend transition in stages Never the same way twice How do you know which one? How do you know which way? Thursday, March 18, 2010 A cantilever is wholly appropriate to create the floating look of Fallingwater, but that same pattern would disrupted the naturalness of the Golden Gate Bridge. When choosing between a singleton and a global variable, which pattern to use is determined by the environment.
  • 93. Funky Caching again “search for the closest matching valid URL and redirect, and use attempted url text as a DB keyword lookup” —Rasmus Lerdorf Thursday, March 18, 2010 the first is in Rasmus’s talk and you can see PHP.NET in others.
  • 94. cleanup text Thursday, March 18, 2010 At my previous company, we had the problem where images are stored on the database but need to be generated in multiple sizes and thumbnails and streamed fast to the user. Previews and thumbnails can be dynamically and instantly generated from border parts, primary graphics, colors, and sample font and text and then stored statically on a server using this method. Stuff may be stored in normal form on the database, but representations built dynamically and served statically
  • 95. Thursday, March 18, 2010 Address complaint about storing in database…Not all images are stored in the database. In fact, at Tagged, not a single image is stored on a database. However, at Plaxo, the admin tool to manage ecard content requires the assets be done by a non-developer but the only way of pushing out filesystem changes is through change control and there is little need of user generated content. In fact, outside e-cards, the entire Plaxo address book database (including the thumbnail photo of yourself) is stored in a database. I’m not the architect of that, nor do I see much a problem with it. What I point out you CAN now get away with putting image content on the database again with this trick. That’s pretty impressive because different assets on a site (statics, javascripts, web pages, user data, application, back-end, corporate site, customer support, etc) are usually managed on an ad hoc basis optimized for the task at hand. Not all of them can resort to using a filesystem push or web tier restart.
  • 96. Javascript and CSS put a graphic or some text compiling & caching Thursday, March 18, 2010 Recently, Tagged has run across the very same performance (size and number) issues in Javascript. The solution: Funky caching hooked up to a javascript compressor powered by a Java service back-end to dynamically catenate and compress javascripts into a unique URL on demand.
  • 97. Thursday, March 18, 2010 We recently imported 1/64th of our production data over to the staging environment for testing, but the user’s images would take too much time and disk space to import. We could just link the images, but then tester’s didn’t know which ones they uploaded and which ones were proxied from the live website. The solution was to spend an hour writing a Funky Caching Proxy. If the image was missing, the ErrorDocument handler would try to grav the image from the production website and add a watermark.
  • 98. Thursday, March 18, 2010 Since this is only for testing, there is no need to waste disk space by storing the created file. The performance hit of real-time generation of redundant requests is unnoticeable to Quality Assurance.
  • 99. <?php $watermark = '3129080702_c4e76f71d7_o.png'; $dead_url = 'http://example.com/dead_image.png';   // {{{ start_image($filename, &$data) /** * Creates a gd handle for a valid file * @param $filename string the file to get * @param $data array the imagesize * @return resource GD handle */ function start_image($filename, &$data) {     $data = @getimagesize($filename);     if (empty($data)) { return null; }     $data['ratio'] = $data[0]/$data[1]; expand callouts     switch($data[2]) {         case IMG_GIF: return imagecreatefromgif($filename);         case 3: //problem where IMG_PNG is not bound correctly for my install         case IMG_PNG: return imagecreatefrompng($filename);         case IMG_JPG: return imagecreatefromjpeg($filename);         case IMG_WBMP: return imagecreatefromwbmp($filename);         case IMG_XPM: return imagecreatefromxbm($filename);     }     return null; }    // }}} $requestimg = $_SERVER['REDIRECT_URL']; if (!$_SERVER['QUERY_STRING']) {     // redirect user to invalid image     tag_http::redirect($dead_url);     return ''; } // grab image to temp {{{ $ch = curl_init($_SERVER['QUERY_STRING']); $tempfile = tempnam('/tmp', 'prod_remote_'); $fp = f_open($tempfile, 'w'); //again delete the "_" curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec_($ch); //delete the final "_" curl_close($ch); fclose($fp); // }}} Thursday, March 18, 2010
  • 100. <?php $watermark = '3129080702_c4e76f71d7_o.png'; $dead_url = 'http://example.com/dead_image.png';   // {{{ start_image($filename, &$data) /** * Creates a gd handle for a valid file * @param $filename string the file to get * @param $data array the imagesize * @return resource GD handle */ function start_image($filename, &$data) {     $data = @getimagesize($filename);     if (empty($data)) { return null; }     $data['ratio'] = $data[0]/$data[1]; expand callouts     switch($data[2]) {         case IMG_GIF: return imagecreatefromgif($filename);         case 3: //problem where IMG_PNG is not bound correctly for my install         case IMG_PNG: return imagecreatefrompng($filename);         case IMG_JPG: return imagecreatefromjpeg($filename);         case IMG_WBMP: return imagecreatefromwbmp($filename);         case IMG_XPM: return imagecreatefromxbm($filename);     }     return null; }    // }}} $requestimg = $_SERVER['REDIRECT_URL']; if (!$_SERVER['QUERY_STRING']) {     // redirect user to invalid image     tag_http::redirect($dead_url);     return ''; } // grab image to temp {{{ $ch = curl_init($_SERVER['QUERY_STRING']); $tempfile = tempnam('/tmp', 'prod_remote_'); $fp = f_open($tempfile, 'w'); //again delete the "_" curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec_($ch); //delete the final "_" curl_close($ch); fclose($fp); // }}} Thursday, March 18, 2010
  • 101. <?php $watermark = '3129080702_c4e76f71d7_o.png'; $dead_url = 'http://example.com/dead_image.png';   // {{{ start_image($filename, &$data) /** * Creates a gd handle for a valid file * @param $filename string the file to get * @param $data array the imagesize * @return resource GD handle */ function start_image($filename, &$data) {     $data = @getimagesize($filename);     if (empty($data)) { return null; }     $data['ratio'] = $data[0]/$data[1];     switch($data[2]) {         case IMG_GIF: return imagecreatefromgif($filename);         case 3: //problem where IMG_PNG is not bound correctly for my install         case IMG_PNG: return imagecreatefrompng($filename);         case IMG_JPG: return imagecreatefromjpeg($filename);         case IMG_WBMP: return imagecreatefromwbmp($filename);         case IMG_XPM: return imagecreatefromxbm($filename);     }     return null; }    // }}} $requestimg = $_SERVER['REDIRECT_URL']; if (!$_SERVER['QUERY_STRING']) {     // redirect user to invalid image     tag_http::redirect($dead_url);     return ''; } // grab image to temp {{{ $ch = curl_init($_SERVER['QUERY_STRING']); $tempfile = tempnam('/tmp', 'prod_remote_'); $fp = f_open($tempfile, 'w'); //again delete the "_" curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec_($ch); //delete the final "_" curl_close($ch); fclose($fp); // }}} Thursday, March 18, 2010
  • 102. <?php $watermark = '3129080702_c4e76f71d7_o.png'; $dead_url = 'http://example.com/dead_image.png';   // {{{ start_image($filename, &$data) /** * Creates a gd handle for a valid file * @param $filename string the file to get * @param $data array the imagesize * @return resource GD handle */ function start_image($filename, &$data) {     $data = @getimagesize($filename);     if (empty($data)) { return null; }     $data['ratio'] = $data[0]/$data[1];     switch($data[2]) {         case IMG_GIF: return imagecreatefromgif($filename);         case 3: //problem where IMG_PNG is not bound correctly for my install         case IMG_PNG: return imagecreatefrompng($filename);         case IMG_JPG: return imagecreatefromjpeg($filename);         case IMG_WBMP: return imagecreatefromwbmp($filename);         case IMG_XPM: return imagecreatefromxbm($filename);     }     return null; }    // }}} $requestimg = $_SERVER['REDIRECT_URL']; if (!$_SERVER['QUERY_STRING']) {     // redirect user to invalid image     tag_http::redirect($dead_url);     return ''; } // grab image to temp {{{ $ch = curl_init($_SERVER['QUERY_STRING']); $tempfile = tempnam('/tmp', 'prod_remote_'); $fp = f_open($tempfile, 'w'); //again delete the "_" curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec_($ch); //delete the final "_" curl_close($ch); fclose($fp); // }}} Thursday, March 18, 2010
  • 103. <?php $watermark = '3129080702_c4e76f71d7_o.png'; $dead_url = 'http://example.com/dead_image.png';   // {{{ start_image($filename, &$data) /** * Creates a gd handle for a valid file * @param $filename string the file to get * @param $data array the imagesize * @return resource GD handle */ function start_image($filename, &$data) {     $data = @getimagesize($filename);     if (empty($data)) { return null; }     $data['ratio'] = $data[0]/$data[1];     switch($data[2]) {         case IMG_GIF: return imagecreatefromgif($filename);         case 3: //problem where IMG_PNG is not bound correctly for my install         case IMG_PNG: return imagecreatefrompng($filename);         case IMG_JPG: return imagecreatefromjpeg($filename);         case IMG_WBMP: return imagecreatefromwbmp($filename);         case IMG_XPM: return imagecreatefromxbm($filename);     }     return null; }    // }}} $requestimg = $_SERVER['REDIRECT_URL']; if (!$_SERVER['QUERY_STRING']) {     // redirect user to invalid image     tag_http::redirect($dead_url);     return ''; } // grab image to temp {{{ $ch = curl_init($_SERVER['QUERY_STRING']); $tempfile = tempnam('/tmp', 'prod_remote_'); $fp = f_open($tempfile, 'w'); //again delete the "_" curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec_($ch); //delete the final "_" curl_close($ch); fclose($fp); // }}} Thursday, March 18, 2010
  • 104. // configure image and dimensions {{{ $size_data = array(); $im = start_image($tempfile, $size_data); if (!$im) {     unlink($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // get watermark information {{{ $wm_data = array(); $wm = start_image($watermark, $wm_data); if (!$wm) {     unlink ($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // add watermark {{{ if ($size_data['ratio']> $wm_data['ratio']) {     // image is wider format than the watermark     $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);     $dst_x = ($size_data[0] - $new_smaller_dim)/2;     $dst_y = 0;     $dst_w = $new_smaller_dim;     $dst_h = $size_data[1]; } else {     // image is taller format than the watermark     $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);     $dst_x = 0;     $dst_y = ($size_data[1] - $new_smaller_dim)/2;     $dst_w = $size_data[0];     $dst_h = $new_smaller_dim;; } imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]); header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); header(sprintf('Content-type: %s',$size_data['mime'])); // }}} switch ($size_data[2]) {     case IMG_GIF: imagegif($im); break;     case 3: case IMG_PNG: imagepng($im); break;     case IMG_JPG: imagejpeg($im); break;     case IMG_WBMP: imagewbmp($im); break;     case IMG_XPM: imagexbm($im); break; } imagedestroy($wm); imagedestroy($im); unlink($tempfile); Thursday, March 18, 2010
  • 105. // configure image and dimensions {{{ $size_data = array(); $im = start_image($tempfile, $size_data); if (!$im) {     unlink($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // get watermark information {{{ $wm_data = array(); $wm = start_image($watermark, $wm_data); if (!$wm) {     unlink ($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // add watermark {{{ if ($size_data['ratio']> $wm_data['ratio']) {     // image is wider format than the watermark     $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);     $dst_x = ($size_data[0] - $new_smaller_dim)/2;     $dst_y = 0;     $dst_w = $new_smaller_dim;     $dst_h = $size_data[1]; } else {     // image is taller format than the watermark     $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);     $dst_x = 0;     $dst_y = ($size_data[1] - $new_smaller_dim)/2;     $dst_w = $size_data[0];     $dst_h = $new_smaller_dim;; } imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]); header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); header(sprintf('Content-type: %s',$size_data['mime'])); // }}} switch ($size_data[2]) {     case IMG_GIF: imagegif($im); break;     case 3: case IMG_PNG: imagepng($im); break;     case IMG_JPG: imagejpeg($im); break;     case IMG_WBMP: imagewbmp($im); break;     case IMG_XPM: imagexbm($im); break; } imagedestroy($wm); imagedestroy($im); unlink($tempfile); Thursday, March 18, 2010
  • 106. // configure image and dimensions {{{ $size_data = array(); $im = start_image($tempfile, $size_data); if (!$im) {     unlink($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // get watermark information {{{ $wm_data = array(); $wm = start_image($watermark, $wm_data); if (!$wm) {     unlink ($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // add watermark {{{ if ($size_data['ratio']> $wm_data['ratio']) {     // image is wider format than the watermark     $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);     $dst_x = ($size_data[0] - $new_smaller_dim)/2;     $dst_y = 0;     $dst_w = $new_smaller_dim;     $dst_h = $size_data[1]; } else {     // image is taller format than the watermark     $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);     $dst_x = 0;     $dst_y = ($size_data[1] - $new_smaller_dim)/2;     $dst_w = $size_data[0];     $dst_h = $new_smaller_dim;; } imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]); header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); header(sprintf('Content-type: %s',$size_data['mime'])); // }}} switch ($size_data[2]) {     case IMG_GIF: imagegif($im); break;     case 3: case IMG_PNG: imagepng($im); break;     case IMG_JPG: imagejpeg($im); break;     case IMG_WBMP: imagewbmp($im); break;     case IMG_XPM: imagexbm($im); break; } imagedestroy($wm); imagedestroy($im); unlink($tempfile); Thursday, March 18, 2010
  • 107. // configure image and dimensions {{{ $size_data = array(); $im = start_image($tempfile, $size_data); if (!$im) {     unlink($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // get watermark information {{{ $wm_data = array(); $wm = start_image($watermark, $wm_data); if (!$wm) {     unlink ($tempfile);     tag_http::redirect($dead_url);     return; } // }}} // add watermark {{{ if ($size_data['ratio']> $wm_data['ratio']) {     // image is wider format than the watermark     $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);     $dst_x = ($size_data[0] - $new_smaller_dim)/2;     $dst_y = 0;     $dst_w = $new_smaller_dim;     $dst_h = $size_data[1]; } else {     // image is taller format than the watermark     $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);     $dst_x = 0;     $dst_y = ($size_data[1] - $new_smaller_dim)/2;     $dst_w = $size_data[0];     $dst_h = $new_smaller_dim;; } imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]); header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); header(sprintf('Content-type: %s',$size_data['mime'])); // }}} switch ($size_data[2]) {     case IMG_GIF: imagegif($im); break;     case 3: case IMG_PNG: imagepng($im); break;     case IMG_JPG: imagejpeg($im); break;     case IMG_WBMP: imagewbmp($im); break;     case IMG_XPM: imagexbm($im); break; } imagedestroy($wm); imagedestroy($im); unlink($tempfile); Thursday, March 18, 2010
  • 108. Beyond Funky Caching Thursday, March 18, 2010 With a bit of creativity this concept can apply to modern applications where instead of caching on the filesystem, you cache in memcache; instead of bypassing the application server, you bypass the web servers themselves with a content distribution network; instead of serving static content from the edge, you serve dynamic pages. Whether to use it and how to use it is always determined by the environment.
  • 109. San Francisco quotes of san francisco? Looking around you for inspiration Thursday, March 18, 2010 I hope this tour helps you see software development in a different way—that finding solutions are about using the right solution in a manner that fits with the environment. Even then I realize that we can’t architect structures that work as harmoniously together as a city such as San Francisco. Story of Rounded Rectangles… Bill Atkinson worked mostly at home, but whenever he made significant progress he rushed in to Apple to show it off to anyone who would appreciate it. This time, he visited the Macintosh offices at Texaco Towers to show off his brand new oval routines, which were implemented using a really clever algorithm. Bill had added new code to QuickDraw (which was still called LisaGraf at this point) to draw circles and ovals very quickly. That was a bit hard to do on the Macintosh, since the math for circles usually involved taking square roots, and the 68000 processor in the Lisa and Macintosh didn't support floating point operations. But Bill had come up with a clever way to do the circle calculation that only used addition and subtraction, not even multiplication or division, which the 68000 could do, but was kind of slow at. Bill's technique used the fact the sum of a sequence of odd numbers is always the next perfect square (For example, 1 + 3 = 4, 1 + 3 + 5 = 9, 1 + 3 + 5 + 7 = 16, etc). So he could figure out when to bump the dependent coordinate value by iterating in a loop until a threshold was exceeded. This allowed QuickDraw to draw ovals very quickly. Bill fired up his demo and it quickly filled the Lisa screen with randomly-sized ovals, faster than you thought was possible. But something was bothering Steve Jobs. "Well, circles and ovals are good, but how about drawing rectangles with rounded corners? Can we do that now, too?" "No, there's no way to do that. In fact it would be really hard to do, and I don't think we really need it". I think Bill was a little miffed that Steve wasn't raving over the fast ovals and still wanted more. Steve suddenly got more intense. "Rectangles with rounded corners are everywhere! Just look around this room!". And sure enough, there were lots of them, like the whiteboard and some of the desks and tables. Then he pointed out the window. "And look outside, there's even more, practically everywhere you look!". He even persuaded
  • 110. Thanks! resize tychay@php.net terrychay.com/blog Thursday, March 18, 2010

Notas del editor

  1. An obscure but ubiquitous design pattern in PHP development is known as Funky Caching. Using real architectural examples as a lens to look at this one simple PHP design pattern, we see how we can design web architectures that are &amp;quot;organic, democratic, and lasting…&amp;quot;
  2. Two prologues
  3. Often attributed to Rasmus, but actually invented by Stig First you create an ErrorDocument line in your apache.conf. What this does is tell the webserver to redirect all missing files to a PHP script called “error.php” in your directory root. You then create this handler: Reference: http://derickrethans.nl/errorhandling/rasmus-trick.html http://lerdorf.com/tips.pdf
  4. What does this trick do? Basically, when a file doesn’t exist, it gives an opportunity for PHP to create the data and return it instead of a 404 error page. The code above is pretty canonical, the only exceptions are where you branch to show the default error page… syntax highlighting code: php_value highlight.string &apos;#b02c04&apos; php_value highlight.comment &apos;#8e98a6&apos;php_value highlight.keyword &apos;#96ad53&apos;#php_value highlight.bg &apos;#f1f7d7&apos;php_value highlight.default &apos;#524e37&apos;php_value highlight.html &apos;#95ad53&apos;
  5. … and where you generate the actual data to render to the user.
  6. At the bottom is where the magic happens. It places the generated file directly into the web server path. What this means is that the next request to the same web resource goes directly for that resource without starting up this code and regenerating the data. Reference: 404 defined: http://en.wikipedia.org/wiki/HTTP_404 404 discussion: http://www.alistapart.com/articles/pe rfect404/ 404 examples: http://www.plinko.net/ 404/ HTTP codes: http://www.urbandictionary.com/define.php?te rm=404
  7. PHP never gets instantiated after the first request! At that point it truly becomes PHP without PHP.
  8. About the book and the metaphor. The foundation of Steve McConnell’s seminal text, Code Complete , was that software development should be based around the paradigm of construction. But that was fundamentally flawed because of the mythical man-month —the “man-mon th” term itself originally coming from construction work. We now know McConnell was wrong and software isn’t construction, it is engineering . And we’re called “software engine ers,” not “software workers” for this reason: we’re engineers, not construction workers.
  9. Rhe foundation of Steve McConnell’s seminal text, Code Complete , was that software development should be based around the paradigm of construction. But that was fundamentally flawed because of the mythical man-month —the “man-mon th” term itself originally coming from construction work. We now know McConnell was wrong and software isn’t construction, it is engineering . And we’re called “software engine ers,” not “software workers” for this reason: we’re engineers, not construction workers.
  10. Software as Engineering vs. other. My title at Tagged is currently “software architect.” And I have a “radical” idea that maybe titles are that way because they mean something. Meaning that if I’m hired as a software architect then I should think like an architect and find my inspiration from architecture.
  11. So lets find our inspiration from architecture and see how it explains the Funky Caching pattern through three buildings. the first is one known as Fallingwater. References: Fallingwater logo from: http://www.fallingwater.org /
  12. In Eastern mountain range of the United States there is a house that is CANTILEVERed 40 feet above a waterfall. This is one of the most famous buildings by American architect, FRANK LLOYD WRIGHT. In 1991 it was voted as the best all-time work of American architecture by the American Institute of Architects. Even though it is OVER 80KM from the nearest city people over a MILLION PEOPLE have traveled to see it. Reference: Image from http://commons.wikimedia.org/wiki/File:Falling_Water_01.jpg Wikipedia: http://en.wikipedia.org/wiki/Fallingwater Frank Lloyd Wrigh t: http://franklloydwright.org/Home.html
  13. Yes, including me as a kid. The day it was built, TIME MAGAZINE wrote about it. Because it was a quintessential example of ORGANIC ARCHITECTURE of FLW. References: Der Spiegel: http://en.wikipedia.org/wiki/Der_Spiegel
  14. A staircase connects the house directly to the stream below . The stream and waterfall, although not seen, can be heard in all parts of the house. The HATCHWAY that consists of SLIDING GLASS DOORS and the bottom step has no support from below. (FLOAT above like the water floats) References: http://wright-house.com/frank-lloyd-wright/fallingwater-p ictures/06E-hatchway-fallingwater.html
  15. WINDOWS WRAP AROUND THE ENTIRE BUILDING so that the building MERGES with the surrounding GREENERY. Similarly the TUNGSTEN LIGHTING and the glasses compliments the FALL FOLIAGE of the region…
  16. This is the VIEW that FLW planned for the house. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/F1SW-fallingwater-in-fall.html
  17. Panes of glass are caulked directly to each other and to the steel frame or stone walls to further symbolize the lack of barriers between the construction and the surrounding nature. References: http://wright-house.co m/frank-lloyd-wright/fallingwater-pictures/34SE-guest-house-window.html
  18. The driveway trellis has a semi-circular cutaway to accommodate an existing tree . References: http://wright-house.com/frank-lloyd-wright/fallingwater -pictures/15-tree-in-trellis-fallingwater.html
  19. The stone floor in the living room , quarried from local rocks http://wright-hous e.com/frank-lloyd-wright/fallingwater-pictures/livingroom-fallingwater.html
  20. The rock in the foreground is is an original boulder not disturbed from it’s original position. References: http://wright-house.com/frank-lloyd-wright/fallingwater-pictures/7-living-room-fireplace-hearth.php
  21. From details like these to the whole view taken in at once, one gets a feeling that, in spite of the SHARP HORIZONTAL AND VERTICAL LINES of the building, the whole lives in harmony with its environment &amp;quot;instead of lording above [it] in an isolated spot as a man-made imposition.” Why is this building as recognizable as any NATURAL WONDER?
  22. Surveyed the grounds before building. Organic: &amp;quot;form follows function.&amp;quot; Wright argued that &amp;quot;form and function are one.&amp;quot; Democratic “design should accommodate needs” Plasticity: “physical element should remove barriers.” Continuity “element should be part of nature”
  23. How prevalent is funky caching? Every time you visit PHP.NET, you use it (need to get the order of needle-haystack by typing http://php.net/strstr ). A cynic would say, because PHP is so SLOW TO EXECUTE, it needs solutions like this to perform well. The problem with this argument is that NO WEB LANGUAGE OUTPERFORMS STATIC SERVERS. Becase it trades off speed of execution with SPEED FOR EASE OF DEVELOPMENT. As Andrei mentioned e arlier , that is fundamental to its design. In fact, all dynamically-typed scripting languages make this tradeoff.
  24. The ubiquity of this trick in the PHP world is because it—like Frank Lloyd Wright&apos;s Fallingwater—lives in harmony with its environment. The environment is an APACHE WEB SERVER, persistent data store in the form of a RELATIONAL DATABASE, and the demands of large-scale, CONSUMER-CENTRIC web sites. Would this solution exist without an ErrorDocument handler built into Apache? Would this solution exist if we didn&apos;t persist content on a (relatively) slow data store like a database? Would this solution exist if the consumer didn&apos;t demand millisecond response time for dynamic content?
  25. The language itself. PHP is a component of A WHOLE SYSTEM. It’s glue code.
  26. developer time and resources
  27. shared-nothing architecture
  28. designed to solve the web problem Could this &amp;quot;ugly, but extremely functional and convenient&amp;quot; web language have been built to solve anything other than the ugly web problem?
  29. One block from where my mother used to work, on the corner of Fifth Avenue and Bellefield in Pittsburgh, stands a strange sight…
  30. References: Map of Pitt: http://www.tour.pitt.edu/documents/map200506.pdf
  31. If you weren’t in PITTSBURGH IN THE LATE 1980’s you wouldn’t have understood how his could have happened . On this ground once stood the original Bellefield church built in the 1880’s. Since its CONGREGATION HAD BEEN MOVED further down Fifth Avenue, the building was sold a century later to developers trying to exploit the new business attracted by the PITTSBURGH SUPERCOMPUTING CENTER. They wanted to level it and build a new building, but were blocked when people mobilized to SAVE THE OLD TOWER. The developer then proceeded to honor this by DEMOLISH EVERYTHING BUT THE TOWER and building the ironically-named “Bellefield Towers” next to it.
  32. This is the current Bellefield Church and an example of city architecture of which the tower is one of them…
  33. The center is the county courthouse and jail, the top right is the local Korean church, and the bottom right is a private residence in the same neighborhood.
  34. The photo at the top is was taken from the Cathedral of learning (previous slide).
  35. When faced with a gorgeous 100-year old example of the area’s architecture, INSTEAD OF WORKING WITH THE ENVIRONMENT like Frank Lloyd Wright did with Fallingwater—in the same area of Pennsylvania no less!—the developer simply sawed it off! The CURVED MODERN ARCHITECTURE of the TOWERS of the latter serves only to emphasize how it was built with no consideration of the surrounding environment. I GREW UP WATCHING THIS HAPPEN and it is a LIFE LESSON IN ARCHITECTURAL HUBRIS.
  36. “ I’m a developer, I can make the software conform to my needs.”Oh really? That sounds a lot like trying to “lord over the environment with an isolated man-made imposition.” “But what I mean is it’s all man-made in software, there is no environment.”
  37. cover cube story, (where cubes are good- Yahoo, sales, user QA), cover waterfall process
  38. When I joined my current company, they had a couple services written in Java, only Zend Accelerator could code cache their PHP 4 installation, Oracle RAC power ed the bac k-end and development occurred by engineers working in cubes with a relatively heavyweight waterfall development process.Even though I prefer Python to Java for services, we’ve increased our Java development to around 40% of our code base! Even though I prefer MySQL to Oracle, we still use Oracle as our back-end. Even the transition to the open office occurred after it became apparent the company had outgrown the cube-space.
  39. Book on management by the founders of 37 Signals. Their last book was “Getting Real” about web business.
  40. - cliche ridden with few examples “Hannah Montanta” reach for you dreams - “would rather be celebrities than businesspeople.” - &apos;Meetings are toxic.&apos; In reality, good meetings are good and bad meetings are not good (generalization) - “Planning, they say, is not recommended” - only applies to their business - “They need to stop behaving like children.” - “Outside money is plan”, about why you should never take on third-party investors.37signals reveals that it took money from Bezos Expeditions, the VC company that invests on behalf of the Amazon founder, Jeff Bezos, in 2006.
  41. Why? Because that is the environment and your solutions have to work within that environment. Anything else is architectural hubris. Let’s say it is the early days of social networking and you join a company that is using Java/J2EE instead of PHP, or Oracle instead of MySQL, or they’re using Perl/Mason instead of your favorite (PHP) framework, as Marco m entioned earlier —there are so many to choose from that the number is second only to Java.Do you go in and say your experience building a CMS or e-store trumps their experien ce working on a nascent social network? Do you replace all the Java engineers with PHP ones? Do you replace MySQL with Oracle? Do you rewrite the site from scratch using your favorite framework? I’m not saying that in all these instances these architects shouldn’t have made the decisions they did. I am not qualified to answer that since I didn’t work at these places.But what I do know was that in the vast majority of cases, people went in without considering the existing environment. I do know the dynamics of a Facebook.com is different from the dynamics of Gamespot.com or Amazon.com. I do know a social network is different from a CMS or e-store. And all these solutions are very different from ones in enterprise .Like building Fallingwate r without get ting an adequate survey done, every day people make the mistake of not looking before acting. They try to make PHP look like Java with dollar signs, as Luke mentioned earlier . They expected the environ ment to conform to their reality so they can lord over it with “some isolated man-made imposition.”
  42. I’ve long since moved from the woods of Western Pennsylvania to the San Francisco Peninsula. I am fortunate that my weekly run passes with a near-constant view of the most recognizable architecture in the American West : References: Image licensed from: http://www.istockphoto.com/file_closeup.php?id=6091847
  43. my weekend run
  44. What’s interesting is that there are much longer spans in the country and the world. Even in the same city, there exists a beautiful bridge that is both longer and of more utility. And yet this bridge represents the icon of San Francisco and of the state as a whole.
  45. The original design was for a hybrid cantilever and suspension structure. But it was replaced with a pure suspension design because the former was deemed too ugly. A pure suspension of this length had never been attempted before.
  46. Irving Morrow designed the bridge tower, lighting, and pedestrian walkways with an entirely Art Deco decorative influence.
  47. The bridge was painted in a specially formulated anti-rust paint in International Orange on demand from locals. The War Department, and others. The Navy alone originally demanded it be painted black with y ellow stripes to assure visibility with passing ships . The rust-colored p aint evokes the hills of Marin to the north as well as the setting sun. It is natural and visible enough to be safe.
  48. rust-colored suspension-only art deco structure It becomes an icon. Every week I pass by it and am inspired and thankful I can live in so beautiful a city.
  49. This quote is the origin of “design pattern.”
  50. But how are we to know which way to do it? Or even if it is the right pattern to be using in our situation? The answer is found in how both a house in Pennsylvania and a bridge in San Francisco represent ultimate expressions of architecture. They are wholly appropriate for the environment in which they stand.
  51. A cantilever is wholly appropriate to create the floating look of Fallingwater, but that same pattern would disrupted the naturalness of the Golden Gate Bridge. When choosing between a singleton and a global variable, which pattern to use is determined by the environment.
  52. the first is in Rasmus’s talk and you can see PHP.NET in others.
  53. At my previous company, we had the problem where images are stored on the database but need to be generated in multiple sizes and thumbnails and streamed fast to the user. Previews and thumbnails can be dynamically and instantly generated from border parts, primary graphics, colors, and sample font and text and then stored statically on a server using this method. Stuff may be stored in normal form on the database, but representations built dynamically and served statically
  54. Address complaint about storing in database…Not all images are stored in the database. In fact, at Tagged, not a single image is stored on a database. However, at Plaxo, the admin tool to manage ecard content requires the assets be done by a non-developer but the only way of pushing out filesystem changes is through change control and there is little need of user generated content. In fact, outside e-cards, the entire Plaxo address book database (including the thumbnail photo of yourself) is stored in a database. I’m not the architect of that, nor do I see much a problem with it.What I point out you CAN now get away with putting image content on the database again with this trick. That’s pretty impressive because different assets on a site (statics, javascripts, web pages, user data, application, back-end, corporate site, customer support, etc) are usually managed on an ad hoc basis optimized for the task at hand. Not all of them can resort to using a filesystem push or web tier restart.
  55. Recently, Tagged has run across the very same performance (size and number) issues in Javascript. The solution: Funky caching hooked up to a javascript compressor powered by a Java service back-end to dynamically catenate and compress javascripts into a unique URL on demand.
  56. We recently imported 1/64th of our production data over to the staging environment for testing, but the user’s images would take too much time and disk space to import. We could just link the images, but then tester’s didn’t know which ones they uploaded and which ones were proxied from the live website. The solution was to spend an hour writing a Funky Caching Proxy. If the image was missing, the ErrorDocument handler would try to grav the image from the production website and add a watermark .
  57. Since this is only for testing, there is no need to waste disk space by storing the created file. The performance hit of real-time generation of redundant requests is unnoticeable to Quality Assurance.
  58. With a bit of creativity this concept can apply to modern applications where instead of caching on the filesystem, you cache in memcache; instead of bypassing the application server, you bypass the web servers themselves with a content distribution network ; instead of serving static content from the edge, you serve dynamic pages.Whether to use it and how to use it is always determined by the environment.
  59. I hope this tour helps you see software development in a different way—that finding solutions are about using the right solution in a manner that fits with the environment. Even then I realize that we can’t architect structures that work as harmoniously together as a city such as San Francisco. Story of Rounded Rectangles… Bill Atkinson worked mostly at home, but whenever he made significant progress he rushed in to Apple to show it off to anyone who would appreciate it. This time, he visited the Macintosh offices at Texaco Towers to show off his brand new oval routines, which were implemented using a really clever algorithm. Bill had added new code to QuickDraw (which was still called LisaGraf at this point) to draw circles and ovals very quickly. That was a bit hard to do on the Macintosh, since the math for circles usually involved taking square roots, and the 68000 processor in the Lisa and Macintosh didn&apos;t support floating point operations. But Bill had come up with a clever way to do the circle calculation that only used addition and subtraction, not even multiplication or division, which the 68000 could do, but was kind of slow at. Bill&apos;s technique used the fact the sum of a sequence of odd numbers is always the next perfect square (For example, 1 + 3 = 4, 1 + 3 + 5 = 9, 1 + 3 + 5 + 7 = 16, etc). So he could figure out when to bump the dependent coordinate value by iterating in a loop until a threshold was exceeded. This allowed QuickDraw to draw ovals very quickly. Bill fired up his demo and it quickly filled the Lisa screen with randomly-sized ovals, faster than you thought was possible. But something was bothering Steve Jobs. &amp;quot;Well, circles and ovals are good, but how about drawing rectangles with rounded corners? Can we do that now, too?&amp;quot; &amp;quot;No, there&apos;s no way to do that. In fact it would be really hard to do, and I don&apos;t think we really need it&amp;quot;. I think Bill was a little miffed that Steve wasn&apos;t raving over the fast ovals and still wanted more. Steve suddenly got more intense. &amp;quot;Rectangles with rounded corners are everywhere! Just look around this room!&amp;quot;. And sure enough, there were lots of them, like the whiteboard and some of the desks and tables. Then he pointed out the window. &amp;quot;And look outside, there&apos;s even more, practically everywhere you look!&amp;quot;. He even persuaded Bill to take a quick walk around the block with him, pointing out every rectangle with rounded corners that he could find. When Steve and Bill passed a no-parking sign with rounded corners, it did the trick. &amp;quot;OK, I give up&amp;quot;, Bill pleaded. &amp;quot;I&apos;ll see if it&apos;s as hard as I thought.&amp;quot; He went back home to work on it. Bill returned to Texaco Towers the following afternoon, with a big smile on his face. His demo was now drawing rectangles with beautifully rounded corners blisteringly fast, almost at the speed of plain rectangles. When he added the code to LisaGraf, he named the new primitive &amp;quot;RoundRects&amp;quot;. Over the next few months, roundrects worked their way into various parts of the user interface, and soon became indispensable.