<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>pragone.com</title>
	
	<link>http://pragone.com</link>
	<description>desarrollo, comunidad y monetización</description>
	<lastBuildDate>Sun, 29 May 2011 01:12:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Pragonecom" /><feedburner:info uri="pragonecom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Maintainability and Shareability… The hidden demons</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/eNRZu0f4gWk/121</link>
		<comments>http://pragone.com/proyectos/maintainability-scalability-and-shareability-the-hidden-demons/121#comments</comments>
		<pubDate>Sun, 29 May 2011 01:12:49 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Chamaleon Framework]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=121</guid>
		<description><![CDATA[When you&#8217;re learning to code, you normally focus on making the thing do what you want it to do. Once you have that under control, you focus on making it work faster and more efficient. Then you actually start to more actively use and design patterns and you start to appreciate their beauty. And that&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;re learning to code, you normally focus on making the thing do what you want it to do. Once you have that under control, you focus on making it work faster and more efficient. Then you actually start to more actively use and design patterns and you start to appreciate their beauty.</p>
<p>And that&#8217;s it for most people, at that point you&#8217;re probably a senior developer with good coding practices. But that&#8217;s definitely not the end of the road. Depending on your work you may actually have to think a lot on Scalability and that opens up another world of possibilities that still now a days is not &#8220;solved&#8221;, and everyday there&#8217;s a new framework, persistence layer or caching technology seeing the day of light.</p>
<p>But, still, the road continues with what I think are often forgotten or non-priority concerns: Maintainability and Shareability</p>
<h2>Maintainability</h2>
<p>Hasn&#8217;t it happened to you that you look back to code that you wrote a year ago and go: &#8220;ok, why did I do this THAT way?&#8221;, or even worse, you look at some one else&#8217;s code and just don&#8217;t get what did they do&#8230; This is what I refer to with maintainability: The ability to maintain and evolve an existing code base.</p>
<p>For this I&#8217;d stress three good practices that can help keep your code maintainable:</p>
<p><em><strong>Keep it real: </strong></em>The best way to make your code maintainable is to keep it close to the business needs. In this sense Domain Driven Design is a powerful tool because it creates a common language that enables developers and business experts to communicate effectively, and as a side effect allows the developer (when in doubt) to go ask a business expert what is the code doing and is therefore great for maintenance.</p>
<p><em><strong>Be verbose:</strong></em> Verbosity goes a long way into helping understand what code does. When I say verbosity, logging is of course the first thing that comes to mind, but the concept expands also to having correctly named variables, methods, classes, etc. But there&#8217;s more, in these days where everybody uses IoC and DI frameworks like Spring, sometimes it&#8217;s hard to follow how things are wired together; don&#8217;t take me wrong, I like the @Autowired annotation, but I don&#8217;t like so much @Component/@Service. I prefer to declare beans explicitly in the .xml files.<br />
It&#8217;s a bit like the when you&#8217;re studying and writing things down actually helps a lot to memorize and understand them.</p>
<p><em><strong>Refactor:</strong></em> Last, but not least, one the best practices for maintainability of code is to do continuous and incremental refactoring, because honestly it&#8217;s not always possible to do it right the first time (because of time constrains, changing business rules, being human, etc).</p>
<h2>Shareability</h2>
<p>Shareability is the next step. While maintainability allows you to evolve a code base with the business needs, shareability is what allows your code to be able to accommodate not only your specific needs, but other team&#8217;s and other businesses&#8217; needs without making the code base a mess.</p>
<p>A great example of this is the Spring framework itself: The way concerns are isolated and interfaces are defined makes the framework amazingly flexible for a very wide range of uses.</p>
<p>This is the most complex level of abstraction to achieve as it implies distilling the essence of each peace of code, carefully designing interconnections and thinking of uses you haven&#8217;t thought possible. But it&#8217;s also the most &#8220;fulfilling&#8221; level of coding: If you&#8217;ve ever had to implement a new feature and you&#8217;re afraid it may be a big change because it deviates a lot from the existing use cases, but it turns out that the solution fits naturally in the existing code, then you&#8217;ve just experiences shareability saving the day.</p>
<p>Is this last &#8220;level of coding&#8221; what has been driving my attention lately, and where I&#8217;ve spent some time thinking of alternatives.</p>
<p>In following posts I&#8217;ll describe a programming paradigm and framework I&#8217;m developing that I think helps you get to this level of coding.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/TeGS_nu-Nx_jDVvJm50EL0kXJ4E/0/da"><img src="http://feedads.g.doubleclick.net/~a/TeGS_nu-Nx_jDVvJm50EL0kXJ4E/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/TeGS_nu-Nx_jDVvJm50EL0kXJ4E/1/da"><img src="http://feedads.g.doubleclick.net/~a/TeGS_nu-Nx_jDVvJm50EL0kXJ4E/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/eNRZu0f4gWk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/proyectos/maintainability-scalability-and-shareability-the-hidden-demons/121/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://pragone.com/proyectos/maintainability-scalability-and-shareability-the-hidden-demons/121</feedburner:origLink></item>
		<item>
		<title>Distributed configuration of an OSGI app with ZooKeeper</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/h8fUxSf-3RI/110</link>
		<comments>http://pragone.com/interesante/distributed-configuration-of-an-osgi-app-with-zookeeper/110#comments</comments>
		<pubDate>Fri, 15 Oct 2010 13:07:20 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Interesante]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=110</guid>
		<description><![CDATA[So, I&#8217;m working on an application using the OSGI environment. As with any app that will see  the light of day and run in a production environment you need to make it both scalable and fault tolerant. OSGI implementations like Equinox are very well tested and stable, but a hard drive can always go bad, [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;m working on an application using the OSGI environment. As with any app that will see  the light of day and run in a production environment you need to make it both scalable and fault tolerant.</p>
<p>OSGI implementations like Equinox are very well tested and stable, but a hard drive can always go bad, or the cleaning lady could always unplug a network cable, so you&#8217;re never really fault tolerant unless you&#8217;re able to run your app in more than one machine.</p>
<p>Sometimes it&#8217;s as simple as deploying the code to another machine and running it. Sadly, most of the times it&#8217;s not that simple.</p>
<p>Creating an OSGI app that will run in several servers is not a trivial task, as I started to do it, I immediately found one typical example of something that&#8217;s very simple when done in one machine and rather complex when you need to do it in multiple machines: Configuration.</p>
<p>OSGI already defines a Configuration Admin Service to manage the configuration of your services. Yet it doesn&#8217;t say anything about distributed configuration. I started to look around and the best I found was this thread called &#8220;<a title="Bridge between zookeeper and OSGI configuration admin" href="http://www.apacheserver.net/Bridge-between-zookeeper-and-OSGI-configuration-admin-at174771.htm" target="_blank">Bridge between zookeeper and OSGI configuration admin</a>&#8220;.</p>
<p>With that piece of software you&#8217;re able to maintain your services configuration in Apache ZooKeeper, and any change in it will be automagically distributed to all servers running your system.</p>
<p>Definitely worth a look.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/8PZwzEqSya39ONH0-XCmLBjUw0U/0/da"><img src="http://feedads.g.doubleclick.net/~a/8PZwzEqSya39ONH0-XCmLBjUw0U/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/8PZwzEqSya39ONH0-XCmLBjUw0U/1/da"><img src="http://feedads.g.doubleclick.net/~a/8PZwzEqSya39ONH0-XCmLBjUw0U/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/h8fUxSf-3RI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/interesante/distributed-configuration-of-an-osgi-app-with-zookeeper/110/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://pragone.com/interesante/distributed-configuration-of-an-osgi-app-with-zookeeper/110</feedburner:origLink></item>
		<item>
		<title>Welcome to OSGI land</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/gF_eitdDEvI/93</link>
		<comments>http://pragone.com/proyectos/welcome-to-osgi-land/93#comments</comments>
		<pubDate>Sun, 08 Aug 2010 01:26:42 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[OSGI]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=93</guid>
		<description><![CDATA[Lately I&#8217;ve been able to play around with loads of new technologies/frameworks (new to me, of course). Among these I should probably mention: JGroups, Hazelcast, Neo4J&#8230; But the one I&#8217;m working more these days is OSGI. I find OSGI particularly interesting because it solves one of the big drawbacks I saw to development in Java: [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been able to play around with loads of new technologies/frameworks (new to me, of course). Among these I should probably mention: <a title="JGroups: Reliable unicast and multicast" href="http://www.jgroups.org" target="_blank">JGroups</a>, <a title="Hazelcast: Distributed data store" href="http://www.hazelcast.com" target="_blank">Hazelcast</a>, <a title="Neo4J: No-SQL graph database" href="http://neo4j.org" target="_blank">Neo4J</a>&#8230; But the one I&#8217;m working more these days is <a title="OSGI: Open Services Gateway Initiative" href="http://www.osgi.org" target="_blank">OSGI</a>.</p>
<p>I find OSGI particularly interesting because it solves one of the big drawbacks I saw to development in Java: deployment and management of component versioning (something that&#8217;s not a problem in scripting languages like PHP).</p>
<p>Yet, the learning curve in OSGI is particularly steep, I guess because it&#8217;s really becoming mainstream just recently, so I thought I would share what an OSGI novice has been able to learn about it in a week of development and a lot of reading (and I mean a LOT).</p>
<h2>What is OSGI? And what is it for?</h2>
<p>OSGI itself is &#8220;just&#8221; a set of specifications about how you can go about building highly modularized, dynamic applications. That&#8217;s why when you got to the <a title="OSGI Alliance Web Site" href="http://www.osgi.org" target="_blank">OSGI Alliance web site</a> the only download you&#8217;ll find are the <a title="OSGI Specifications" href="http://www.osgi.org/Specifications/HomePage" target="_blank">specs</a>. Take the chance and download them, store them somewhere (you&#8217;ll need them&#8230; just not now).</p>
<p>So if OSGI is &#8220;just&#8221; a compendium of specifications, how do I use it?</p>
<p>You need to get your hands on one of the implementations/frameworks. The base for every OSGI App is an OSGI Framework. Its on top of that you build your OSGI Application.</p>
<p>The main open source OSGI Frameworks are:</p>
<ul>
<li><a title="Eclipse Equinox project" href="http://www.eclipse.org/equinox/" target="_blank">Eclipse Equinox</a>: Is Eclipse Foundation&#8217;s version of it. It serves as the base for the popular <a title="Eclipse IDE" href="http://www.eclipse.org/" target="_blank">Eclipse IDE</a>, which is in itself an OSGI application.</li>
<li><a title="Apache Felix OSGI Framework" href="http://felix.apache.org/site/index.html" target="_blank">Apache Felix</a>: Is Apache Foundation&#8217;s implementation. It&#8217;s also very used by a lot of people.</li>
<li><a title="Knoplerfish: OSGI framework" href="http://www.knopflerfish.org/" target="_blank">Knoplerfish</a>: Is another Open Source OSGI &#8220;service platform&#8221;. I think it&#8217;s quite used too, but I don&#8217;t think you can compare it&#8217;s community to any of the previous two.</li>
</ul>
<p>Once you have one of these up and running you can start bulding/deploying bundles to it&#8230; but what is an OSGI bundle?</p>
<p>An OSGI bundle is the main building block of an OSGI application. To better understand it let&#8217;s dive deeper into how OSGI works.</p>
<h2>How does OSGI works?</h2>
<p>In Java, every Class is brought to live by a <a title="ClassLoader API" href="http://download.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html" target="_blank">ClassLoader</a>. Whenever you use a class (whether its one you&#8217;ve built or a java.lang one), a ClassLoader is used to fetch it from a directory or JAR in your ClassPath and load it in the JVM.</p>
<p>A ClassLoader can only load a class once, and that&#8217;s why when you modify a class in a stand alone app you need to restart the JVM for the changes to take effect. To overcome this &#8220;limitation&#8221;, the OSGI frameworks create several ClassLoaders (one per bundle), if you need to reload the classes in a bundle, the Framework disposes the ClassLoader associated with the bundle and creates a new one. OSGI Frameworks are not the only ones that use this mechanism, Servlet Containers (like Tomcat or Jetty) do the same, and that&#8217;s how you can reload servlets without taking down the web server.</p>
<p>This sounds like a great idea, but it must be handled with a lot of care. For example, when several ClassLoaders are used you could end up with more than one Singleton, and static variables of one class having different values depending on the ClassLoader you use. To make matters even worse, the Java 2 platform silently introduced the concept of Thread Context ClassLoader (A ClassLoader that&#8217;s associated with a Thread and not necessarily used to load the classes used in it).</p>
<p>A good article on this topic is: <a title="ClassLoaders and Context ClassLoaders" href="http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html" target="_blank">Find a way out of the ClassLoader maze</a>.</p>
<p>But no tool is good or bad in itself, it all depends on how you use it, and this is where the Specs of OSGI come into play establishing a well defined way to manage ClassLoaders. And this is how bundles where born.</p>
<h2>What is a bundle?</h2>
<p>A bundle is the minimum unit of reloadable content, and <em>&#8220;is comprised of Java classes and other resources, which together can provide functions to end users&#8221;</em> (OSGI R4 Core Specs, page 27). In practice a bundle is a Jar file with a special META-INF/MANIFEST.MF. In this manifest, the bundle specifies what packages (as  in java.lang) it exposes to other bundles, what packages it needs from other bundles, an optional Activator class (to customize the life cycle of the bundle) and many other things.</p>
<p>But let&#8217;s create a simple bundle to understand this better. Our TestBundle is a Jar with this content:</p>
<ul>
<li>META-INF/MANIFEST.MF</li>
<li>com/testbundle/Activator.class</li>
<li>com/testbundle/exported/Concatenator.class</li>
</ul>
<p>The manifest contains the following:</p>
<pre>Manifest-Version: 1.0
Bnd-LastModified = 1281229346082
Build-Jdk = 1.6.0_20
Built-By = pragone
Bundle-Activator = com.testbundle.Activator
Bundle-ManifestVersion = 2
Bundle-Name = testbundle
Bundle-SymbolicName = com.testbundle.testbundle
Bundle-Version = 0.0.1.SNAPSHOT
Created-By = Apache Maven Bundle Plugin
Export-Package = com.testbundle;uses:="org.osgi.framework",com.testbundle.exported
Import-Package = org.osgi.framework;version="1.2"
Tool = Bnd-0.0.357</pre>
<pre><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;">The important parts here are:</span></pre>
<ul>
<li>Import-Package: indicates what packages this bundle needs to function, particularly org.osgi.framework is a package that is always  provided by the OSGI Framework</li>
<li>Export-Package. indicates what packages owned by this bundle are made available to other bundles. e.g. com.testbundle.exported</li>
<li>Bundle-Activator: the name of a class that implements <a title="BundleActivator API" href="http://www.osgi.org/javadoc/r4v42/org/osgi/framework/BundleActivator.html" target="_blank">org.osgi.framework.BundleActivator</a></li>
</ul>
<p>The code of the activator is pretty simple:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="color: #961a65;">package</span> com.testbundle;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="color: #961a65;">import</span> org.osgi.framework.BundleActivator;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="color: #961a65;">import</span> org.osgi.framework.BundleContext;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="color: #961a65;">public</span> <span style="color: #961a65;">class</span> Activator <span style="color: #961a65;">implements</span> BundleActivator {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="white-space: pre;"> </span><span style="color: #961a65;">public</span> <span style="color: #961a65;">void</span> start(BundleContext context) <span style="color: #961a65;">throws</span> Exception {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3b3df5;"><span style="color: #000000;"><span style="white-space: pre;"> </span>System.</span><span style="color: #032fc3;">out</span><span style="color: #000000;">.println(</span>&#8220;Test Bundle starting&#8221;<span style="color: #000000;">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="white-space: pre;"> </span>}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="white-space: pre;"> </span><span style="color: #961a65;">public</span> <span style="color: #961a65;">void</span> stop(BundleContext context) <span style="color: #961a65;">throws</span> Exception {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3b3df5;"><span style="color: #000000;"><span style="white-space: pre;"> </span>System.</span><span style="color: #032fc3;">out</span><span style="color: #000000;">.println(</span>&#8220;Test Bundle stopping&#8221;<span style="color: #000000;">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;"><span style="white-space: pre;"> </span>}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco;">}</p>
<p>To &#8220;execute&#8221; this bundle do the following:</p>
<ol>
<li>Download an OSGI framework. Let&#8217;s use Equinox for this examples. Get org.eclipse.osgi_&lt;version&gt;.jar from  <a title="Download Equinox" href="http://download.eclipse.org/equinox/" target="_blank">http://download.eclipse.org/equinox/</a> (I&#8217;m using version 3.6)</li>
<li>Save the jar file to a new directory in, say, your desktop. Let&#8217;s assume this directory is called &#8220;&lt;DESKTOP&gt;/osgi&#8221;</li>
<li>Download the test bundle source code from <a title="Downloade testbundle.tgz" href="http://pragone.com/osgi/tesbundle.tgz" target="_self">here</a>. Untar/Unzip it to a location of your liking.</li>
<li>In a terminal/command prompt, go to the folder where the content of the bundle was unpacked and type: &#8220;mvn package&#8221; (This assumes you have <a title="Maven Dependency Manager" href="http://maven.apache.org/" target="_blank">Maven</a> installed. If you don&#8217;t&#8230; what are you waiting for, go get it)</li>
<li>Once Maven has finished execution, a new folder called target will be created and in it a file called: testbundle-&lt;VERSION&gt;.jar, copy this file to the &#8220;&lt;DESKTOP&gt;/osgi&#8221; folder.</li>
<li>Still on the terminal/command prompt go to the &#8220;&lt;DESKTOP&gt;/osgi&#8221; folder and type:<br />
java -jar org.eclipse.osgi_&lt;version&gt;.jar -console</li>
<li>You should see a &#8220;osgi&gt;&#8221; prompt. type:<br />
install file:testbundle-&lt;VERSION&gt;.jar</li>
<li>Now type:<br />
start 1</li>
<li>You should see a message indicating: <em>&#8220;Test Bundle starting&#8221;</em></li>
</ol>
<p>That&#8217;s it, you just got your first OSGI app up and running.</p>
<p>Now let&#8217;s try some Class updating magic. Go into the source code if the TestBundle and modify the source of Activator.java changing the two System.out.println from:</p>
<pre>System.out.println("Test Bundle starting"); -- to --&gt; System.out.println("New Test Bundle starting");</pre>
<p>and</p>
<pre>System.out.println("Test Bundle stopping"); -- to --&gt; System.out.println("New Test Bundle stopping");</pre>
<p>repeat steps 4 and 5 from above in a new terminal and then in the terminal running our OSGI app type:</p>
<pre>osgi&gt; update 1</pre>
<p>You should see:</p>
<pre>Test Bundle stopping
New Test Bundle starting</pre>
<p>Nice, huh?, the old version was stopped, the new jar loaded and the new version was started. Now that&#8217;s what I call a Hot Deployment.</p>
<h2>What&#8217;s next?</h2>
<p>In the next articles, I&#8217;ll talk about the BundleContext, bundle Services, Service Trackers, Tools when working with OSGI and resources</p>

<p><a href="http://feedads.g.doubleclick.net/~a/B3g7Igwhpfry7Mm5qzBC6lAFMaM/0/da"><img src="http://feedads.g.doubleclick.net/~a/B3g7Igwhpfry7Mm5qzBC6lAFMaM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/B3g7Igwhpfry7Mm5qzBC6lAFMaM/1/da"><img src="http://feedads.g.doubleclick.net/~a/B3g7Igwhpfry7Mm5qzBC6lAFMaM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/gF_eitdDEvI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/proyectos/welcome-to-osgi-land/93/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://pragone.com/proyectos/welcome-to-osgi-land/93</feedburner:origLink></item>
		<item>
		<title>Las nuevas tecnologías para la escalabilidad</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/VdZGVuOy4s8/81</link>
		<comments>http://pragone.com/interesante/las-nuevas-tecnologias-para-la-escalabilidad/81#comments</comments>
		<pubDate>Sun, 10 May 2009 15:26:55 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Interesante]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[desarrollo programming]]></category>
		<category><![CDATA[funcional]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[voldemort]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=81</guid>
		<description><![CDATA[Ultimamente, he estado viendo algunas nuevas tecnologías que se enfocan en la escalabilidad. Estamos en un momento realmente interesante de la evolución de las tecnologías Web, lo que más me llama la atención es que ya no basta con simplemente ver cómo optimizar o hacer el &#8220;fine tunning&#8221; de los sistemas que cualquier desarrollador conoce [...]]]></description>
			<content:encoded><![CDATA[<p>Ultimamente, he estado viendo algunas nuevas tecnologías que se enfocan en la escalabilidad. Estamos en un momento realmente interesante de la evolución de las tecnologías Web, lo que más me llama la atención es que ya no basta con simplemente ver cómo optimizar o hacer el &#8220;fine tunning&#8221; de los sistemas que cualquier desarrollador conoce ya, sino que es hora de, incluso, revisar los conceptos más básicos: siguen siendo las bases de datos relacionales las más apropiadas?, son los lenguajes Orientados a Objetos lo mejor?</p>
<p>Por supuesto, si tu página web sólo sirve unos pocos miles de impresiones al día o a la hora, no tienes grandes problemas y muchas de estas preguntas son simplemente irrelevantes por el bien de un desarrollo ágil, pero si comienzas a hablar de páginas con tráfico considerable es posible que te encuentres con problemas para los que no haya soluciones ampliamente conocidas.</p>
<p>Trataré de escribir algunos artículos más exponiendo mi punto de vista sobre algunas de las tecnologías que ya conocemos y sus alternativas. Por el momento simplemente les dejo con algunos enlaces que pueden resultarles interesantes:</p>
<h2>Lenguajes de programación:</h2>
<p></p>
<ul>
<li><a title="Is the Supremacy of Object-Oriented Programming Over?" rel="nofollow" href="http://blog.objectmentor.com/articles/2009/04/20/is-the-supremacy-of-object-oriented-programming-over" target="_blank">Is the Supremacy of Object-Oriented Programming Over?</a>: [EN] Un artículo realmente interesante que habla sobre las limitación de POO para ciertos problemas y plantea si es la hora de reintroducir lenguajes de programación funcionales por sus mejores condiciones para el manejo concurrente de tareas.</li>
<li><a title="Erlang programming language" href="http://www.erlang.org/" target="_blank">Erlang</a> [EN] (<a title="Erlang" href="http://es.wikipedia.org/wiki/Erlang" target="_blank">Wiki</a> [ES]): Un &#8220;nuevo&#8221; lenguaje de programación creado por Ericsson que es particularmente bueno para el manejo de tareas concurrentes y distribuidas. Es la base para algunos de los proyectos más interesantes que han salido últimamente.</li>
<li><a title="Clojure" href="http://clojure.org/" target="_blank">Clojure</a> [EN]: Otro lenguaje de programación funcional que vive dentro de la JVM</li>
</ul>
<h2>Persistencia / Bases de datos:</h2>
<p></p>
<ul>
<li><a title="Distributed key-value stores" href="http://www.metabrew.com/article/anti-rdbms-a-list-of-distributed-key-value-stores/" target="_blank">Anti-RDBMS a list of distributed key-value stores</a> [EN]: Un buen artículo en el que se presenta una lista con algunas de las alternativas existentes a bases de datos relacionales. Particularmente interesantes son <a title="Project Voldemort" href="http://project-voldemort.com/" target="_blank">Project Voldemort</a> y <a title="Apache CouchDB" href="http://en.wikipedia.org/wiki/CouchDB" target="_blank">CouchDB</a>.</li>
<li><a title="BigTable" href="http://labs.google.com/papers/bigtable-osdi06.pdf" target="_blank">BigTable</a> [EN,PDF] y <a title="MapReduce" href="http://es.wikipedia.org/wiki/MapReduce" target="_blank">MapReduce</a> [EN]: Desarrollados por Google, conceptualmente la base para la implementación de algunos de los sistemas de persistencia mencionados en el artículo anterior.</li>
<li><a title="Data consistency" href="http://www.allthingsdistributed.com/2008/12/eventually_consistent.html" target="_blank">Eventually Consistent</a> [EN]: un artículo interesante en el que se plantea la pregunta de: es necesaria la consistencia de la data siempre? o por razones de performance nos podemos permitir inconsistencias temporales?</li>
</ul>
<ul>
<li><a title="Gigaspaces" href="http://www.gigaspaces.com/" target="_blank">Gigaspaces</a> [EN]: Tecnología muy interesante que se enfoca en mantener todo en memoria y olvidarte de la persistencia (ya se encarga Gigaspaces de ello).</li>
<li><a title="TokuDB" href="http://www.tokutek.com/" target="_blank">TokuDB</a> [EN]: Un nuevo <em>storage engine</em> para MySQL, basado en lo que <a href="http://www.tokutek.com/" target="_blank">Tokutek</a> llama <em>Fractal Trees &#8482;</em>, o como lo llama el MIT <a title="Fractal tree indexing" href="http://supertech.csail.mit.edu/cacheObliviousBTree.html" target="_blank">&#8220;Cache-Oblivious Trees&#8221;</a> [EN]</li>
</ul>
<h2>Búsqueda de texto / Indexación de información:</h2>
<p></p>
<ul>
<li><a title="Sphinx, Full-text search engine" href="http://www.sphinxsearch.com/" target="_blank">Sphinx</a> [EN]: Un <em>FullText Search Engine</em>, con un performance excelente aunque con una lista limitada de funcionalidades.</li>
<li><a title="Solr" href="http://lucene.apache.org/solr/" target="_blank">Solr</a> [EN]: Un nuevo <em>FullText Search Engine</em> de Apache que encapsula a Lucene y provee algunas funcionalidades extra como el preprocesamiento de la data a indexar.</li>
</ul>
<p>Espero los enlaces les sean de interés, trataré de escribir algo más de detalle al respecto.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/4IQprOF8oEWfajm6KrIV9mZaS20/0/da"><img src="http://feedads.g.doubleclick.net/~a/4IQprOF8oEWfajm6KrIV9mZaS20/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/4IQprOF8oEWfajm6KrIV9mZaS20/1/da"><img src="http://feedads.g.doubleclick.net/~a/4IQprOF8oEWfajm6KrIV9mZaS20/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/VdZGVuOy4s8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/interesante/las-nuevas-tecnologias-para-la-escalabilidad/81/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://pragone.com/interesante/las-nuevas-tecnologias-para-la-escalabilidad/81</feedburner:origLink></item>
		<item>
		<title>eBay Anuncios…. it’s live!</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/A6xrPKdbS-I/78</link>
		<comments>http://pragone.com/proyectos/ebay-anuncios-its-live/78#comments</comments>
		<pubDate>Sun, 08 Mar 2009 20:37:28 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=78</guid>
		<description><![CDATA[Finalmente, luego de un par de meses de arduo trabajo los nuevos sitios de eBay Anuncios, eBay Pisos y de eBay Coches están al aire y funcionando&#8230; todavía quedan algunos pequeños detalles que resolver, pero nada que sea demasiado impactante para la experiencia del usuario en las nuevas páginas. Ha sido un proyecto como ninguno [...]]]></description>
			<content:encoded><![CDATA[<p>Finalmente, luego de un par de meses de arduo trabajo los nuevos sitios de <a title="eBay Anuncios. Compra y venta de artículos nuevos y de segunda mano" href="http://www.ebayanuncios.es" target="_blank">eBay Anuncios</a>, <a title="eBay Pisos, alquiler y compra de pisos, chalets y otros" href="http://www.ebaypisos.es" target="_blank">eBay Pisos</a> y de <a title="eBay Coches. Coches y motos, nuevos y de segunda mano" href="http://www.ebaycoches.es" target="_blank">eBay Coches</a> están al aire y funcionando&#8230; todavía quedan algunos pequeños detalles que resolver, pero nada que sea demasiado impactante para la experiencia del usuario en las nuevas páginas.</p>
<p>Ha sido un proyecto como ninguno en mi carrera profesional. El día 2 de Enero de este año empezó su vida como proyecto y cerca del 14 de Enero empezó de forma oficial su desarrollo. En poco menos de dos meses hemos construido una nueva plataforma desde cero (pues no hemos podido aprovechar prácticamente nada del código de Loquo).</p>
<p>Esta nueva plataforma resuelve la mayoría de las limitaciones que Loquo tiene: Un excelente motor de búsquedas; Soporte para atributos flexibles; Mejor soporte para I18N y muchos más.</p>
<p>De aquí mis felicitaciones, no sólo a mi equipo de desarrollo que ha respondido de una forma excelente frente a la presión con un constante buen ánimo y energía, sino a todos los integrantes del equipo: CS, OM/DM, SEO/SEM, al equipo de Liderago  y al equipo de Site Operations de Marktplaats.</p>
<p>Todas las partes han desempeñado su papel de forma magistral&#8230; y, debo decirlo, haber tenido una team-meeting el 3 de Marzo a las 2:00 (a.m.) cuando el sitio empezó a estar &#8220;live&#8221;, y que prácticamente todo el equipo estuviera ahí asegurándose de que su parte estuviera bien ha sido una experiencia genial de integración <img src='http://pragone.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Me siento honrado de trabajar con este equipo.</p>
<p>Es un momento excelente y un proyecto muy especial.</p>
<p>Gracias a todos <img src='http://pragone.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/DjLoWT4tpl1uxHASk2JAN7IR_Kc/0/da"><img src="http://feedads.g.doubleclick.net/~a/DjLoWT4tpl1uxHASk2JAN7IR_Kc/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/DjLoWT4tpl1uxHASk2JAN7IR_Kc/1/da"><img src="http://feedads.g.doubleclick.net/~a/DjLoWT4tpl1uxHASk2JAN7IR_Kc/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/A6xrPKdbS-I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/proyectos/ebay-anuncios-its-live/78/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://pragone.com/proyectos/ebay-anuncios-its-live/78</feedburner:origLink></item>
		<item>
		<title>Comida Venezolana: El Güero</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/vD_ZoNRFwH4/69</link>
		<comments>http://pragone.com/interesante/comida-venezolana-el-guero/69#comments</comments>
		<pubDate>Sun, 09 Nov 2008 11:54:46 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Interesante]]></category>
		<category><![CDATA[arepa]]></category>
		<category><![CDATA[cachapa]]></category>
		<category><![CDATA[comida]]></category>
		<category><![CDATA[guasacaca]]></category>
		<category><![CDATA[madrid]]></category>
		<category><![CDATA[restaurante]]></category>
		<category><![CDATA[venezuela]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=69</guid>
		<description><![CDATA[Hace un par de semanas unos amigos nos invitaron a otro sitio de comida Venezolana, que debo decir ha estado incluso mejor que el anterior: El Güero, comida venezolana en Madrid. Tienen una carta muy amplia de comida venezolana (y una carta de comida Mexicana que no ha probado pero de seguro que está muy [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_73" class="wp-caption alignright" style="width: 198px"><img class="size-full wp-image-73" title="El Güero" src="http://pragone.com/wp-content/uploads/2008/11/guero.jpeg" alt="El Güero" width="188" height="294" /><p class="wp-caption-text">El Güero</p></div>
<p>Hace un par de semanas unos amigos nos invitaron a otro sitio de comida Venezolana, que debo decir ha estado incluso mejor que el anterior: <a title="El Güero, comida venezolana" href="http://www.elguero.es" target="_blank">El Güero, comida venezolana en Madrid</a>.</p>
<p>Tienen una carta muy amplia de comida venezolana (y una carta de comida Mexicana que no ha probado pero de seguro que está muy buena).</p>
<p>Lo mejor de todo: Tienen unos quesitos muy buenos: Queso de mano, Guayanés, Telita, etc. Si te quieres tomar una Polar o una Malta lo puedes hacer también&#8230; en fin, la verdad es que excelente totalmente. Además de que la atención es muy buena y te hacen sentir en casa <img src='http://pragone.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Luego de haber ido un par de veces, mi favorita es la <a title="¿Qué es una arepa pelúa?" href="http://es.wikipedia.org/wiki/Arepa#Variantes" target="_blank"><strong>Arepa pelúa</strong></a>: el guiso de carne mechada es genial&#8230; sobre todo cuando lo acompañas con la <a title="Guasacaca, comida típica venezolana" href="http://es.wikipedia.org/wiki/Guasacaca" target="_blank">guasacaca</a> que te dan y la salsita picante. Yo que soy de Caracas, me senti en el granjero del este <img src='http://pragone.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: left;">Merecen una mensión especial también las <a title="Empanadas" href="http://es.wikipedia.org/wiki/Empanada" target="_blank">empanaditas</a>, las <a title="Cachapas" href="http://es.wikipedia.org/wiki/Cachapa" target="_blank">cachapas</a>, las <a title="Tajadas" href="http://es.wikipedia.org/wiki/Tajada" target="_blank">tajadas</a> con queso, los <a title="Tequeños" href="http://es.wikipedia.org/wiki/Teque%C3%B1os" target="_blank">tequeños</a>, el papelón con limón, el jugo de parchita&#8230; y ahora en época decembrina las <a title="Hallacas, comida típica Venezolana" href="http://es.wikipedia.org/wiki/Hallaca" target="_blank">hallacas</a> (que no las he probado, pero de seguro lo haré&#8230; se pueden encargar).</p>
<div id="attachment_70" class="wp-caption aligncenter" style="width: 310px"><a href="http://pragone.com/wp-content/uploads/2008/11/imgp1063.jpg"><img class="size-medium wp-image-70" title="Tajadas con Queso" src="http://pragone.com/wp-content/uploads/2008/11/imgp1063-300x225.jpg" alt="Tajadas con Queso" width="300" height="225" /></a><p class="wp-caption-text">Tajadas con Queso</p></div>
<p>La verdad no tomé muchas fotos (estaba muy ocupado comiendo hasta reventar <img src='http://pragone.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ), pero aquí les dejo un par de joyas que sé que les encantarán (si consigo otras fotos las montaré luego):</p>
<p style="text-align: center;"><a href="http://pragone.com/wp-content/uploads/2008/11/imgp1064.jpg"><img class="size-medium wp-image-71 aligncenter" title="Las salsas" src="http://pragone.com/wp-content/uploads/2008/11/imgp1064-300x225.jpg" alt="Guasacaca y Salsa Picante." width="300" height="225" /></a></p>
<p>Aquí les dejo también el menú de El Güero:</p>
<div id="attachment_72" class="wp-caption aligncenter" style="width: 504px"><a href="http://pragone.com/wp-content/uploads/2008/11/guero2.jpeg"><img class="size-full wp-image-72" title="Menú de El Güero" src="http://pragone.com/wp-content/uploads/2008/11/guero2.jpeg" alt="Menú de El Güero" width="494" height="756" /></a><p class="wp-caption-text">Menú de El Güero</p></div>
<p>En fin, un sitio que les recomiendo ampliamente.</p>
<p>Asegúrense de fimar el libro de visitas anotando su email y les notificarán de cosas nuevas como por ejemplo cuando salen las hallacas, etc. También pueden <a title="Blog de El Güero, comida venezolana" href="http://elgueromadrid.blogspot.com/2008/04/creacin-del-blog.html" target="_blank">visitar su Blog</a>.</p>
<p>La dirección: C/ Emigrantes, 2. 28043, Madrid.</p>
<p>Saludos y disfruten.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/JFz0XmnA3LTMfcL7AzPx8Xk5YDM/0/da"><img src="http://feedads.g.doubleclick.net/~a/JFz0XmnA3LTMfcL7AzPx8Xk5YDM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/JFz0XmnA3LTMfcL7AzPx8Xk5YDM/1/da"><img src="http://feedads.g.doubleclick.net/~a/JFz0XmnA3LTMfcL7AzPx8Xk5YDM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/vD_ZoNRFwH4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/interesante/comida-venezolana-el-guero/69/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://pragone.com/interesante/comida-venezolana-el-guero/69</feedburner:origLink></item>
		<item>
		<title>Da’ Gusto: Comida Venezolana en Madrid</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/FntIJUMaHK8/65</link>
		<comments>http://pragone.com/interesante/da-gusto-comida-venezolana-en-madrid/65#comments</comments>
		<pubDate>Sat, 23 Aug 2008 13:57:43 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Interesante]]></category>
		<category><![CDATA[arepa]]></category>
		<category><![CDATA[batido]]></category>
		<category><![CDATA[comida]]></category>
		<category><![CDATA[da gusto]]></category>
		<category><![CDATA[dagusto]]></category>
		<category><![CDATA[guanabana]]></category>
		<category><![CDATA[madrid]]></category>
		<category><![CDATA[parchita]]></category>
		<category><![CDATA[patacon]]></category>
		<category><![CDATA[tamarindo]]></category>
		<category><![CDATA[venezuela]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=65</guid>
		<description><![CDATA[Hoy hemos ido a desayunar a un sitio muy bueno de comida Venezolana. Se llama &#8220;Da&#8217; Gusto&#8221;. Tenían arepas, patacones, tequeños, unos batidos geniales y malta. Es dueño es un maracucho muy simpático (aunque no recuerdo el nombre ahora). Nos sentimos como en casa cuando luego de traernos un jugo de Tamarindo, vino con el [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy hemos ido a desayunar a un sitio muy bueno de comida Venezolana. Se llama &#8220;Da&#8217; Gusto&#8221;.</p>
<div id="attachment_66" class="wp-caption aligncenter" style="width: 310px"><a href="http://pragone.com/wp-content/uploads/2008/08/dsc_0414.jpg"><img class="size-medium wp-image-66" title="Da' Gusto: Comida Venezolana en Madrid" src="http://pragone.com/wp-content/uploads/2008/08/dsc_0414-300x201.jpg" alt="Da' Gusto: Comida Venezolana en Madrid" width="300" height="201" /></a><p class="wp-caption-text">Da&#39; Gusto: Comida Venezolana en Madrid</p></div>
<p>Tenían arepas, patacones, tequeños, unos batidos geniales y malta.</p>
<p>Es dueño es un maracucho muy simpático (aunque no recuerdo el nombre ahora). Nos sentimos como en casa cuando luego de traernos un jugo de Tamarindo, vino con el pote de la licuadora para echar el fondito <img src='http://pragone.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div id="attachment_67" class="wp-caption aligncenter" style="width: 310px"><a href="http://pragone.com/wp-content/uploads/2008/08/dsc_0419_2.jpg"><img class="size-medium wp-image-67" title="Da Gusto: Sentirse como en casa" src="http://pragone.com/wp-content/uploads/2008/08/dsc_0419_2-300x201.jpg" alt="Da Gusto: Sentirse como en casa" width="300" height="201" /></a><p class="wp-caption-text">Da Gusto: Sentirse como en casa</p></div>
<p>En fin&#8230; muy recomendable. Yo me pedí un de carne mechada y estaba genial.</p>
<p>La dirección es:</p>
<p>Avda. De los Poblados, 131<br />
28025, Madrid</p>
<p>Telef: 913 410 731 / 622 431 583</p>
<p>En fin&#8230; muy bueno.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/3vprzwxexWbDQgpXUl6NxvELFRU/0/da"><img src="http://feedads.g.doubleclick.net/~a/3vprzwxexWbDQgpXUl6NxvELFRU/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/3vprzwxexWbDQgpXUl6NxvELFRU/1/da"><img src="http://feedads.g.doubleclick.net/~a/3vprzwxexWbDQgpXUl6NxvELFRU/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/FntIJUMaHK8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/interesante/da-gusto-comida-venezolana-en-madrid/65/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://pragone.com/interesante/da-gusto-comida-venezolana-en-madrid/65</feedburner:origLink></item>
		<item>
		<title>SVD e Indices para búsquedas en espacios de altas dimensiones</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/Wb-kM6bJTG8/55</link>
		<comments>http://pragone.com/proyectos/svd-e-indices-para-busquedas-en-espacios-de-altas-dimensiones/55#comments</comments>
		<pubDate>Wed, 13 Aug 2008 23:17:42 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[delta-tree]]></category>
		<category><![CDATA[detección spam]]></category>
		<category><![CDATA[imágenes]]></category>
		<category><![CDATA[reducción dimensional]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[SVD]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=55</guid>
		<description><![CDATA[Como comenté en un articulo anterior sobre la detección de Spam en Imágenes, uno de los métodos es la identificación de imágenes duplicadas o casi duplicadas (Near-duplicate detection). Este proceso consiste de dos partes: La creación de un LSH (Locality Sensitive Hash), es decir, crear una especie de &#8220;firma&#8221; que tenga la propiedad de que [...]]]></description>
			<content:encoded><![CDATA[<p>Como comenté en un articulo anterior sobre la <a title="Detección de Spam en Imágenes" href="http://pragone.com/proyectos/deteccion-de-spam-en-imagenes/54" target="_blank">detección de Spam en Imágenes</a>, uno de los métodos es la identificación de imágenes duplicadas o casi duplicadas (Near-duplicate detection).</p>
<p>Este proceso consiste de dos partes:</p>
<ol>
<li>La creación de un LSH (Locality Sensitive Hash), es decir, crear una especie de &#8220;firma&#8221; que tenga la propiedad de que dos imágenes que se parezcan tengan dos firmas parecidas y que dos imágenes que no se parezcan tengan firmas diferentes.</li>
<li>Tener estas firmas en una base de datos para dada una &#8220;firma&#8221; buscar si hay alguna otra imagen cuya firma se parezca lo suficiente.</li>
</ol>
<p>Existen muchas formas de crear la firma, por ejemplo con el uso de <a title="Haar Wavelet" href="http://en.wikipedia.org/wiki/Haar_wavelet" target="_blank">Haar Wavelet</a>, Histogramas de colores, etc. Sin embargo, la parte de la búsqueda es la realmente complicada.</p>
<p>Una firma, puede consistir de 128, 200 o más números enteros. Estas firmas pueden ser vistas como un vector de tantas dimensiones como números la compongan, y de ahí que el título del artículo se refiera a espacios de alta dimensionalidad.</p>
<p>Debido a que buscar los duplicados de una imagen particular (imagen query) es encontrar algún otro &#8220;vector&#8221; en una base de datos cuya distancia a la imagen query sea menor a cierto umbral, estas búsquedas no son manejables con un sistema de base de datos convencional (No sin recorrer toda la base de datos a cada consulta y calcular la distancia de la imagen query con todas las imágenes de la BBDD).</p>
<p>Sin embargo, hay alternativas. La mayoría de ellas tienen que ver con reducciones dimensionales, es decir tratar de representar en menos dimensiones (con menos números) los mismos datos. Esto resulta bastante bien cuando la data es dispersa, ya que probablemente muchas dimensiones no aporten casi información (por ejemplo, en las estructuras de datos utilizadas para la detección de Spam con SVM (Support Vector Machines) en la que cada palabra es una dimensión y el valor de esa dimensión es la cantidad de veces que aparece la palabra en el texto.</p>
<p>Pero cuando la data no es esparcida, los métodos que se basan exclusivamente en reducciones dimensionales no son tan atractivos.</p>
<p>Es por esto que la propuesta descrita en: <a title="Indexing high-dimensional data for efficient in-memory similarity search" href="http://ieeexplore.ieee.org/Xplore/login.jsp?url=/iel5/69/30208/01388245.pdf?temp=x" target="_blank">Indexing High-Dimensional Data for Efficient In-Memory Similarity Search</a> resulta muy interesante.</p>
<p>En este paper se propone la creación de una estructura llamada un delta-tree, en el que los niveles superiores (más cercanos a la raíz) son de dimensiones menores que los inferiores (de hecho las &#8220;hojas&#8221; del árbol son los datos sin ninguna reducción dimensional).</p>
<p>Lo que más me llamó la atención fue la forma en la que se realiza la reducción dimensional: <a title="SVD: Singula Value Decomposition" href="http://http://en.wikipedia.org/wiki/Singular_value_decomposition" target="_blank">SVD:  Singular Value Decomposition</a>. Esta técnica te permite reducir la dimensionalidad de la data con una propiedad interesante:</p>
<p>Dados dos puntos x1 y x2 en el espacio m-dimensional de origen, y dados y1 y y2 sus &#8220;versiones reducidas&#8221;  en el espacio n-dimensional (con n &lt; m),</p>
<p>d(x1,x2) ≤ d(y1,y2), donde d(a,b) es la distancia que hay entre a y b.</p>
<p>De esta forma se puede recorrer el árbol, descartando las ramas que ya se encuentran muy lejos (por encima del umbral) con menos dimensiones (y por lo tanto menos cálculos) y centrar la búsqueda en las dimensiones superiores en un espacio mucho menor.</p>
<p>Esto me parecía muy bueno para ser verdad, así que me instalé <a title="Scilab: Open Source MatLab" href="http://www.scilab.org" target="_blank">SciLab</a> que es un excelente reemplazo gratis  de Matlab (as in beer and in speech), hice una prueba de esta reducción dimensional y comprobé la regla de las distancias empíricamente.</p>
<p>Creé de forma aleatoria una matriz de datos (50 puntos), cada uno de ellos en un espacio de 20 dimensiones, la reduje a 15, 10 y 5 dimensiones y comparé las distancias entre los puntos entre las distintas dimensiones y obtuve gráficos como este:</p>
<div id="attachment_60" class="wp-caption aligncenter" style="width: 510px"><a href="http://pragone.com/wp-content/uploads/2008/08/corr15.gif"><img class="size-full wp-image-60" title="Correlación con una reducción a 15 dimensiones" src="http://pragone.com/wp-content/uploads/2008/08/corr15.gif" alt="Correlación con una reducción a 15 dimensiones" width="500" height="333" /></a><p class="wp-caption-text">Correlación con una reducción a 15 dimensiones</p></div>
<p>Un punto de este gráfico se obtiene de la siguiente forma:</p>
<p>Coordenada x = distancia entre los puntos xi y xj en el espacio original (20 dimensiones)</p>
<p>Coordenada y = distancia entre los puntos xi y xj en el espacio reducido (15 dimensiones en este caso)</p>
<p>Como se puede ver existe una gran cercanía de estos puntos a la recta y=x (la correlación de los puntos en la gráfica de 15 dimensiones es de 0.95), con lo que se puede ver que hay una correlación entre las distancias en el espacio original y el espacio reducido.</p>
<p>Haciendo lo mismo con 10 y luego 5 dimensiones obtuve:</p>
<div id="attachment_61" class="wp-caption aligncenter" style="width: 510px"><a href="http://pragone.com/wp-content/uploads/2008/08/comp10.gif"><img class="size-full wp-image-61" title="Correlación con una reducción a 10 dimensiones" src="http://pragone.com/wp-content/uploads/2008/08/comp10.gif" alt="Correlación con una reducción a 10 dimensiones" width="500" height="333" /></a><p class="wp-caption-text">Correlación con una reducción a 10 dimensiones</p></div>
<p>Como es lógico se redujo más la correlación pues se pierde más información en la reducción dimensional, pero sigue habiendo una fuerte relación entre las distancias en ambos espacios.</p>
<p>Y, finalmente, con una reducción a 5 dimensiones obtuve:</p>
<div id="attachment_62" class="wp-caption aligncenter" style="width: 510px"><a href="http://pragone.com/wp-content/uploads/2008/08/comp5.gif"><img class="size-full wp-image-62" title="Correlación con una reducción a 5 dimensiones" src="http://pragone.com/wp-content/uploads/2008/08/comp5.gif" alt="Correlación con una reducción a 5 dimensiones" width="500" height="333" /></a><p class="wp-caption-text">Correlación con una reducción a 5 dimensiones</p></div>
<p>En el que la correlación si bien existe es bastante débil.</p>
<p>Sin embargo, incluso en este escenario en el que se pierde tanta información por la reducción dimensional, logré verificar que se mantiene la asumpción sobre que las distancias en menores dimensiones son menores que en mayores dimensiones, y por lo tanto el esquema propuesto sirve.</p>
<p>No conozco ningún manejador de base de datos que pudiere utilizar para representar esto&#8230; así que supongo que tendré que crear uno <img src='http://pragone.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/PTkED4I7ksP0MSKiMieD7F2XzkE/0/da"><img src="http://feedads.g.doubleclick.net/~a/PTkED4I7ksP0MSKiMieD7F2XzkE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/PTkED4I7ksP0MSKiMieD7F2XzkE/1/da"><img src="http://feedads.g.doubleclick.net/~a/PTkED4I7ksP0MSKiMieD7F2XzkE/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/Wb-kM6bJTG8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/proyectos/svd-e-indices-para-busquedas-en-espacios-de-altas-dimensiones/55/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://pragone.com/proyectos/svd-e-indices-para-busquedas-en-espacios-de-altas-dimensiones/55</feedburner:origLink></item>
		<item>
		<title>Detección de Spam en imágenes</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/EDJN6psK3qQ/54</link>
		<comments>http://pragone.com/proyectos/deteccion-de-spam-en-imagenes/54#comments</comments>
		<pubDate>Sat, 09 Aug 2008 14:18:01 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[detección de duplicados]]></category>
		<category><![CDATA[image spam]]></category>
		<category><![CDATA[investigación]]></category>
		<category><![CDATA[loquo]]></category>
		<category><![CDATA[LSH]]></category>
		<category><![CDATA[near-duplicate]]></category>
		<category><![CDATA[OCR]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[spam imágenes]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=54</guid>
		<description><![CDATA[Aprovecho mientras tengo al SciLab entrenando una ANN (Artificial Neural Network) para contarles sobre las últimas investigaciones que estoy haciendo. En Loquo, buena parte de mi labor se centra no solo en el desarrollo de producto, sino en la investigación e innovación en la plataforma. El primer fruto que logramos fue la creación del sistema [...]]]></description>
			<content:encoded><![CDATA[<p>Aprovecho mientras tengo al <a title="Scilab: Open Source MatLab" href="http://www.scilab.org" target="_blank">SciLab</a> entrenando una <a title="ANN: Artificial Neural Network [EN]" href="http://en.wikipedia.org/wiki/Artificial_neural_network" target="_blank">ANN (Artificial Neural Network)</a> para contarles sobre las últimas investigaciones que estoy haciendo.</p>
<p>En Loquo, buena parte de mi labor se centra no solo en el desarrollo de producto, sino en la investigación e innovación en la plataforma.</p>
<p>El primer fruto que logramos fue la creación del sistema de detección de duplicados. Este sistema ha tenido un impacto muy positivo en el sitio, logrando mejorar la calidad del contenido y por lo tanto la experiencia del usuario.</p>
<p>Claro está, los spammers no se iban a quedar de brazos cruzados y, como era lógico, han evolucionado sus técnicas.</p>
<p>Primero, se fueron por la ruta de colocar texto oculto (cuyo color se parece mucho al color de fondo), así que sacamos un sistema que elimina el texto oculto (utilizando un cálculo que toma en consideración la percepción de los colores para el ojo humano). Luego, colocaron texto muy pequeño&#8230; y también lo eliminamos.</p>
<p>Ahora, simplemente colocan textos aleatorios de forma visible y colocan toda la información &#8220;de verdad&#8221; en imágenes.</p>
<p>Por supuesto, colocar esta información en las imágenes las hace prácticamente indetectables&#8230; ¿o no? <img src='http://pragone.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Pues es en eso en lo que estoy trabajando ahora. En luchar contra el Spam en Imágenes.</p>
<h3>Problemas para la detección de Spam en Imágenes</h3>
<p>La detección de Spam en imágenes es particularmente retadora porque una imágen no es más que un conjunto de pixels, cada uno de un color. A diferencia del texto en el que cada palabra tiene un sentido particular, un pixel o linea no tiene ningún significado como tal.Además, las imágenes son información bidimensional, mientras que el texto es de una sola dimensión&#8230;</p>
<p>En fin, es un problema mucho más complicado, así que..</p>
<h3>¿Cómo afrontar el problema de detección de Spam en Imágenes?</h3>
<p>Como siempre, en problemas complejos, no hay una solución sencilla. El sistema que tengo en mente tiene dos módulos principales:</p>
<ul>
<li>Análisis de la imagen: En este se busca extraer información de la imagen para tratar de reconocer si una imágen particular es Spam o no.</li>
<li>Detección de imágenes duplicadas: En este otro, lo que se busca es saber si una imagen se parece a otra que ya se encuentre en el sistema y que haya sido identificada como Spam.</li>
</ul>
<p>Cada una de estas tareas es todo un reto pues consisten de procesamientos altamente complicados, con lo cual escalarlo a una plataforma con tantos visitantes como lo es Loquo (más de 5.5 millones de Usuarios únicos al mes) es un problema doblemente complicado.</p>
<h3>Análisis de la Imagen</h3>
<p>Este sistema consiste en la extracción de información a partir de una imágen.</p>
<p>Evidentemente, la información más &#8220;sencilla&#8221; de extraer son los textos que se encuentren embebidos en la imágen a través de uso de un software <a title="OCR: Optical Character Recognition [EN]" href="http://en.wikipedia.org/wiki/Optical_character_recognition" target="_blank">OCR (Optical Character Recognition)</a>.</p>
<p>Para esto se deben hacer dos pasos:</p>
<ol>
<li><strong>Document Layout Analysis:</strong> Este primer paso consiste en identificar en una imagen las áreas que probablemente contienen texto.</li>
<li><strong>OCR:</strong> Luego, las áreas con alta probabilidad de contener texto son pasadas al software OCR para ver qué es capaz de reconocer.</li>
</ol>
<p>Otra forma de analizar la imagen sería intentar extraer información sobre los objetos que componen la imagen. Este es un proceso aún más complicado, pero podría servir, para, por ejemplo, reconocer si en una imagen hay una pistola o algún otro elemento prohibido.</p>
<h3>Detección de imágenes duplicadas</h3>
<p>Este sistema busca identificar si una imagen dada se parece lo suficiente a alguna otra imagen de una base de datos.</p>
<p>Evidentemente la forma trivial es simplemente compara los hashes de los archivos (MD5 o SHA1). Pero esto sólo sirve para reconocer que se trata del mismo archivo. Basta cambiar un pixel en la imagen y este sistema sería inválido. Por esto, la forma correcta de atajar este problema es con &#8220;Near-Duplicate Image Detection&#8221;.</p>
<p>El sistema de Near-Duplicate Image Detection consiste en crear una especie de Hash a partir de la imagen, pero de tal forma que si dos imágenes se parecen, sus respectivos Hashes también se parezcan. (Esto se conoce como <a title="LSH: Locality Sensitive Hashing [EN]" href="http://en.wikipedia.org/wiki/Locality_sensitive_hashing" target="_blank">LSH: Locality Sensitive Hashing</a>.</p>
<p>En próximos artículos comentaré un poco sobre los avances logrados en cada una de estas áreas.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/seED-JUfHlMfV05Cwvm52UNNPBY/0/da"><img src="http://feedads.g.doubleclick.net/~a/seED-JUfHlMfV05Cwvm52UNNPBY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/seED-JUfHlMfV05Cwvm52UNNPBY/1/da"><img src="http://feedads.g.doubleclick.net/~a/seED-JUfHlMfV05Cwvm52UNNPBY/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/EDJN6psK3qQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/proyectos/deteccion-de-spam-en-imagenes/54/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://pragone.com/proyectos/deteccion-de-spam-en-imagenes/54</feedburner:origLink></item>
		<item>
		<title>Integrar phpBB3 con tu sitio. (2da integración, 1ra parte)</title>
		<link>http://feedproxy.google.com/~r/Pragonecom/~3/3ah9MOZk6Ks/52</link>
		<comments>http://pragone.com/proyectos/integrar-phpbb3-con-tu-sitio-2da-integracion-1ra-parte/52#comments</comments>
		<pubDate>Tue, 10 Jun 2008 21:22:33 +0000</pubDate>
		<dc:creator>pragone</dc:creator>
				<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[integración]]></category>
		<category><![CDATA[integrar]]></category>
		<category><![CDATA[interfaz]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpbb]]></category>
		<category><![CDATA[phpbb3]]></category>
		<category><![CDATA[registro]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[usuario]]></category>

		<guid isPermaLink="false">http://pragone.com/?p=52</guid>
		<description><![CDATA[Este artículo es parte de un conjunto de artículos/tutoriales sobre cómo integrar phpBB3 con otro sistema. Puedes ir al artículo principal sobre cómo integrar phpBB3 con tu sitio para ver las distintas formas de integración Este es el segundo artículo o tutorial de la serie sobre cómo integrar phpBB3 con tu sitio. phpBB3 es un [...]]]></description>
			<content:encoded><![CDATA[<div style="border:1px solid darkgray; width:95%; margin: 10px; padding: 6px; background-color:#ddddaa">Este artículo es parte de un conjunto de artículos/tutoriales sobre cómo integrar phpBB3 con otro sistema.<br />
Puedes ir al artículo principal sobre <a style="text-decoration:underline; font-weight:bold" title="tutoriales para integrar phpBB3 con tu sitio" href="http://pragone.com/proyectos/integracion-de-phpbb3-con-tu-sitio/47">cómo integrar phpBB3 con tu sitio</a> para ver las distintas formas de integración</div>
<p>Este es el segundo artículo o tutorial de la serie sobre cómo <a title="Tutorial sobre cómo integrar phpBB3 con tu sitio" href="http://pragone.com/proyectos/integracion-de-phpbb3-con-tu-sitio/47" target="_blank">integrar phpBB3</a> con tu sitio.</p>
<p><a title="phpBB un software de foro gratuito" href="http://www.phpbb.com" target="_blank">phpBB3</a> es un excelente paquete de foros gratuito, escrito en PHP+MySQL. Debido a su gran utilidad y al hecho de que es de código abierto (free as in beer and speech), una de las cosas que muchos queremos hacer es integrarlo con algún otro sistema que tengamos, para poder ofrecer la excelente funcionalidad del foro, sin que esto complique la experiencia del usuario en el sitio.</p>
<p>En este artículo se trata la segunda integración descrita en el artículo: <a title="tutoriales para integrar phpBB3 con tu sitio" href="http://pragone.com/proyectos/integracion-de-phpbb3-con-tu-sitio/47">cómo integrar phpBB3 con tu sitio</a>:</p>
<h3>Al crear un usuario en el otro sistema, automáticamente se crea un usuario en phpBB3 y hacer login en uno de ellos automáticamente te loguea en el otro.</h3>
<p>Esta es una integración un poco más compleja que la anterior y por lo tanto la divido en dos partes. En esta hablo sobre cómo hacer para que al registrar a un usuario en &#8220;el otro sistema&#8221; (el que no es phpBB3), automáticamente quede registrado en el foro. La segunda parte la dejo para otro artículo por ser un poco más compleja y depender de la configuración de los dos sitios (si están o no en el mismo dominio o subdominio).</p>
<h3>La idea básica</h3>
<p>phpBB3 está muy bien hecho, el código es muy modular y es fácil de navegar. Por esto, cuando estudiamos cómo hace phpBB3 la creación de un nuevo usuario nos encontramos con lo que buscamos en el archivo includes/ucp/ucp_register.php [<a title="Source code at code.phpbb.com" href="http://code.phpbb.com/repositories/entry/5/tags/release_3_0_1/phpBB/includes/ucp/ucp_register.php?rev=8499" target="_blank">code</a>] (luego de sortear mucho código de validación).</p>
<p>Para crear un nuevo usuario nos bastaría con este código:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">/* GetUserIp: 
	 *
	 * Taken from: http://forums.whirlpool.net.au/forum-replies-archive.cfm/976380.html
	 *
	 */</span>
&nbsp;
	<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'IN_PHPBB'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$phpbb_root_path</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">defined</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'PHPBB_ROOT_PATH'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? PHPBB_ROOT_PATH <span style="color: #339933;">:</span> <span style="color: #0000ff;">'./'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$phpEx</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strrchr</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$phpbb_root_path</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'common.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$phpEx</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$phpbb_root_path</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'includes/functions_user.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$phpEx</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$phpbb_root_path</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'includes/functions_module.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$phpEx</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">function</span> GetUserIP<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_X_FORWARDED_FOR'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_X_FORWARDED_FOR'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_CLIENT_IP'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_CLIENT_IP'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REMOTE_ADDR'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">getenv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP_X_FORWARDED_FOR'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #990000;">getenv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP_X_FORWARDED_FOR'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">getenv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP_CLIENT_IP'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #990000;">getenv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP_CLIENT_IP'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">getenv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'REMOTE_ADDR'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000088;">$user_name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'paolo123'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$user_pass</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'shh123'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$user_email</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'usuario@servidor.de.correo'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$user_lang</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'es'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$user_ip</span> <span style="color: #339933;">=</span> GetUserIP<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'SELECT group_id
		FROM '</span> <span style="color: #339933;">.</span> GROUPS_TABLE <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;
		WHERE group_name = 'REGISTERED'
			AND group_type = &quot;</span> <span style="color: #339933;">.</span> GROUP_SPECIAL<span style="color: #339933;">;</span>
	<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sql_fetchrow</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sql_freeresult</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">trigger_error</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'NO_GROUP'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000088;">$group_id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'group_id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// Utilizamos el uso horario del foro</span>
	<span style="color: #000088;">$is_dst</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'board_dst'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>	
	<span style="color: #000088;">$timezone</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'board_timezone'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// Reunimos toda la data del nuevo usuario</span>
	<span style="color: #000088;">$user_row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">'username'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$user_name</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_password'</span>		<span style="color: #339933;">=&gt;</span> phpbb_hash<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_pass</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_email'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$user_email</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'group_id'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$group_id</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_timezone'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span>float<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$timezone</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_dst'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$is_dst</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_lang'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$user_lang</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_type'</span>		<span style="color: #339933;">=&gt;</span> USER_NORMAL<span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_actkey'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_ip'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$user_ip</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_regdate'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_inactive_reason'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'user_inactive_time'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// Register user...</span>
	<span style="color: #000088;">$user_id</span> <span style="color: #339933;">=</span> user_add<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_row</span><span style="color: #339933;">,</span> <span style="color: #000088;">$cp_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// This should not happen, because the required variables are listed above...</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_id</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">trigger_error</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'NO_USER'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">E_USER_ERROR</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Este código crea un usuario con nombre &#8216;paolo123&#8242; y clave &#8216;shh123&#8242;. Este será un usuario idéntico a cualquier otro usuario que se haya registrado siguiendo el proceso normal del foro. </p>
<h3>Consideraciones finales</h3>
<p>Importante indicar que este código está pensado para ejecutar en un archivo que estuviera en la carpeta raíz del foro, por lo que si no es este el caso, habría que modificar la declaración del principio que dice: <code>$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';</code> cambiando el &#8216;./&#8217; por la ruta relativa o absoluta de la carpeta raíz del foro.</p>
<p><strong>Importante:</strong> Crear el usuario de esta forma, salta todas las verificaciones que hay normalmente en el foro, por lo que es importante asegurarse de que todos los datos son válidos.</p>
<p>La forma de integrar este código con tu sistema la dejo a discreción del usuario, ya que variaría mucho dependiendo del sistema desde el que se invoque&#8230; lo único que hay que tener presente son los datos que necesita este código para ejecutar: <code>$user_name, $user_pass, $user_email, $user_lang</code> y <code>$user_ip</code>.</p>
<p>En el próximo artículo de esta &#8220;serie&#8221; trataré el tema de la segunda parte de esta integración: el manejo de sesiones&#8230; Cómo hacer que cuando un usuario se identifique en uno de los sistemas, quede identificado en el otro también.</p>
<p>Espero les sirva.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/EvSUcxTL2ygfEHmSjDWKQpIN2zA/0/da"><img src="http://feedads.g.doubleclick.net/~a/EvSUcxTL2ygfEHmSjDWKQpIN2zA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/EvSUcxTL2ygfEHmSjDWKQpIN2zA/1/da"><img src="http://feedads.g.doubleclick.net/~a/EvSUcxTL2ygfEHmSjDWKQpIN2zA/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/Pragonecom/~4/3ah9MOZk6Ks" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pragone.com/proyectos/integrar-phpbb3-con-tu-sitio-2da-integracion-1ra-parte/52/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		<feedburner:origLink>http://pragone.com/proyectos/integrar-phpbb3-con-tu-sitio-2da-integracion-1ra-parte/52</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 1.368 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-13 21:24:57 -->

