Xavier Noria: The Code Gardener

Share this article

Xavier won the Ruby Hero
award in 2010

Xavier Noria (pronounced “sha – vee – aay” in Catalan) is very well known in the Ruby community. A self-employed Ruby developer from Barcelona, he’s also a member of the Rails core team and won the Ruby Hero award during RailsConf 2010. Many of you may have met him in person; he has presented at numerous Ruby conferences all across Europe this year.

But I’m most impressed by Xavier’s role as the “Code Gardener” – a phrase I took from a minor Rails commit he made over two years ago. You can read more about this commit in an article I wrote last year about my favorite Rails commits. Last week Xavier and I had a chance to talk for over an hour – read on to learn more about his background, what’s coming in Rails 4, his passion for documentation and most importantly his philosophy about the importance of small changes. I also got a chance to ask Xavier about how you can determine if a number is prime using a regular expression!

Getting started in Ruby

Q: How did you get started with Ruby and Rails?

12 years ago I started computer programming for a living; I was 30 years old at the time so I am late to the party. But I switched careers to do computer programming because I love it.

I worked professionally with Java for some time and also I did quite a lot of Perl in the research lab I was working in. I taught Perl in the University of Barcelona for 7 years in my spare time. In 2005 someone contacted me and asked: “Hey – is there anything new that has caught your attention?” In 2005 everybody was talking about Ruby on Rails and at first sight it looked like it deserved the attention. So I thought: “Yes – this Ruby on Rails thing looks promising.” I hadn’t done any Ruby programming professionally but I had played around with Ruby a little bit because I loved dynamic languages.

Then we tried Rails with a real project, not just doing a “hello world” application or anything like that, and we were so positively amazed about our experience with this little project that we thought you could found a company based on this technology. So we founded a Rails shop in 2006; we did only Rails. That was our brand: we were Rails specialists in Spain.

Q: You keep saying “we” – who were you working with?

With Agustín Cuenca. We did this first project in 2005, and then we founded ASPgems in 2006 with other partners. The company is still alive and doing well, but later I became independent and left in 2009.

Working on the Rails core team

Q: How did you get started contributing to Rails itself and become part of the core team?

I’ve been involved in open source for 10 years. I have some Perl modules in CPAN; I’ve always been helping in IRC, doing that sort of thing. In Rails, whenever I found something to fix, a bug or something, I always tried to contribute a patch – but I didn’t work with tickets or anything like that. When I needed something, I tried to contribute a patch or a fix or whatever.

The thing that got me involved in the Rails project itself was documentation. In general I think documentation in the Ruby culture is lacking. There’s a lot of room for improvement. And, in particular in Ruby on Rails I was not satisfied with the documentation we had. So Pratik Naik had this genius idea to create docrails. Docrails is a branch of Rails for quick doc fixes that is regularly cross-merged with master. At the beginning you got the commit bit to docrails just asking for it to Pratik, and nowadays it has public write access.

I was first in the line asking for the commit bit from Pratik, and then I started working on documentation like crazy. The documentation had a few axes to work on. One axis was the content itself, which was the most important thing. Then there were other things that are also important, like consistency in typography, etc. There were no conventions or guidelines; it was a real mess. I said earlier I started as a developer when I was 30 years old, but before that for some years I was a proofreader for math textbooks.

Q: Oh really?

So you know, I had my eye trained for this kind of thing. If this has to be in italics and it’s not in italics then I see it right away!

Q: I’d better take advantage of you! Can I send you a rough draft of my new eBook? I never realized you were a professional proofreader…

Yea I would love that!

So we set some documentation guidelines, and I started to apply these guidelines massively across the source code for Ruby on Rails. I did a lot of work and mostly without visibility – but I didn’t care. I was fixing something that I wanted to fix. Then occasionally I also worked with code. My ratio was perhaps 80/20 or something like that. The majority of my contributions were with documentation in those days. In the end people in the core team knew about this work, and I started to have closer contact with them and to have more opportunities to know the project from the inside. And eventually I got invited to be on the core team.

Q: Congratulations – that’s fantastic! What is like working on the core team? Is it fun? Difficult? Tiring?

It’s great! In the team there’s a fine balance between individuals and working as a team. It’s not written anywhere, but for some important things we try to discuss and reach a consensus, but for the most part we are left alone. Everybody in the core team works in the places that he is interested in. We have two places for communication – one is a room in Campfire; another one is a project in Basecamp.

Q: Do you ever actually talk with the team, either over Skype like we are now, or in person?

At least in my case, everything is written either in Campfire or Basecamp or very rarely in email. But I know for instance that José and Yehuda in the Rails 3 days paired a lot remotely.

Q: They actually worked together on individual features?

Yes. I don’t know nowadays whether there’s anyone doing that. But normally everything is written.

What’s coming in Rails 4

Q: A lot of people are wondering about what’s coming with Rails 4… I know we don’t have time to go through everything, but can you tell us a bit about it now?

It’s a major release – there’s a ton of stuff. In the last few days I’ve been going through the change logs in order to start preparing material for the release notes. Here are some highlights….

First, Ruby 1.9.3 is going to be required.

Q: … and that’s because you’re using syntax that’s only valid in 1.9.3?

There has been consensus that we want to focus on the latest stable version of Ruby only and not to spend any time with previous versions. So since this is a major version we are going to just go with 1.9.3. We are only going to “officially” support 1.9.3. It might be the case that your application also runs with 1.9.2, but you are on your own there. It’s not going to run with 1.8 – that’s for sure. There was a lot of code with conditionals that switched between 1.8 and 1.9 and all of that was removed.

Q: Oh I see. So your test suite only runs on 1.9.3?

Yes, that’s right.

And then there are a lot of new features also: something that I like is that we have switched to use the PATCH verb as a first class citizen in the set of HTTP verbs that we support.

Q: What does the PATCH verb do? Is it an update?

Yea the idea is that it does an update. In the past you did updates with the PUT verb but the semantics of PUT are creation or replacement of this entity I’m sending to you. In web programming, however, most of the time you are not sending the full resource. So now in forms that update a resource, in the “_method” hidden parameter you are going to get PATCH. But it’s still routed to update. PUT will continue to route to update, to make upgrading easier – all current requests are going to end up in the same place.

Q: What do developers need to know about that? Is it seamless? Does it happen transparently?

Yea, it should be seamless.

Something else that many people wanted to change is the control of mass-assignment of attributes. It was in the model layer; many people wanted to put it into the controller layer and that is going to happen in Rails 4. The feature is called strong parameters – mass-assignment still happens but you configure it in the controller layer. “attr_accessible” and “attr_protected” are out. They have been extracted into a plugin.

Another nice thing is the API for queues. You can hook several queues and have a uniform API to talk with them. In fact the mailers can send mail asynchronously in Rails 4, thanks to this API.

Q: Interesting…

Also, another one of the main highlights is support for what we call “Russian Doll caching.”

Q: Yes… I’ve seen some pictures of that recently. Can you explain that in a couple of minutes?

If you heavily cache all partials in a given view – say you have two or three levels of caching – and you are using a generational technique which is to put a time stamp so that keys auto-expire and everything. Now if you change the static content of one of the nested templates then you have to invalidate the parent containers. Before this feature was in, you had to do that manually somehow. This new feature in Rails 4 automates that for you, computing MD5 digests of the template contents.

Finally, Active Resource is out. It’s not being used a lot and will become a plugin.

There’s even more stuff, but those are a few highlights.

The Code Gardener

Q: Do you remember the article I wrote last year where I described you as a “code gardener?” I hope you’re not angry or upset about that… I hope it wasn’t offensive!

On the contrary, it’s unusual that someone highlights small contributions. I loved that comment from you.

Q: Do you really spend a lot of time your time doing that? Are you really a “code gardener?”

When something catches my attention I go and fix it. For me, I get equally excited about writing a big thing, about making this code uniform or about fixing that little typo. The thing is, if I am reading source code and I see a minor thing I just go and push the fix right away.

Q: So you are very detail oriented. If I imagine you in a garden pulling out weeds from the dirt – that is the sort of thing you like to do.

Xavier’s “code gardening” Rails commit
from two years ago

Yes, and I think that kind of contribution is important, because those kinds of details help to give shape to the code and to keep the code beautiful. If I see anything – whether it’s important, big, small – I don’t care, I just go edit and push.

I don’t qualify tickets in any way – for me fixing a typo is as important as fixing a bug or any other change. If someone sends patches like these, as long as they are not monster patches, I would accept right away. And that’s something I like a lot about docrails, because docrails promotes the idea that you can do this sort of thing.

Q: Let’s say there are people reading this who want to contribute to Rails but haven’t before? What would be a good way to get started contributing to the Rails project?

The easiest way is to go to GitHub and work on tickets. Working on tickets can mean many things: it could be preparing a patch that fixes something, it could be testing that an existing patch still passes, or whatever. If you are experienced in documentation then you can also go and search in the source code for places that are not properly documented. You can go and document those places. And also the Rails Guides can also always benefit from someone willing to contribute documentation. It’s a very, very important part of the project.

Ruby Conferences

Q: You’ve gone to many different conferences in the last few months: RailsClub Moscow, BaRuCo, RuLu 2012, RailsBerry and EuRuKo. What did you enjoy the most about these conferences?

Yea, I think it’s the year that I’ve traveled the most. I presented in all of them, except in EuRuKo where I did a workshop the day previous to the conference. So it’s been a fun year. All of the conferences have been amazing.

My motivation to go to conferences is to meet people. I like to attend the talks also, but, you know, the talks are not my main motivation to go.

Q: So it’s your time in the bar or pub afterwards that you enjoy the most?

I enjoy the breaks… I don’t party a lot – at 1am or something I go to the hotel to rest.

Q: 1am sounds very early for a Spaniard! I thought in Spain you’ve barely finished eating dinner by 1am…

Ha, ha – that’s true. But I like to go rested to the second day of the conference. There are two styles of conference schedules: one with a full morning of talks, and the other which is more sparse, with generous breaks of a half hour or more. I prefer this second style, where you have time to go and talk with people and have less presentations.

Q: Will you ever get a chance to come over to a conference in the US?

To be honest it’s too far for me. I’ve only been in the US once, and to be sincere I went only because the organizers “suggested” that I should attend… because I was going to receive the Ruby Hero award.

Q: Congratulations! That was a few years ago?

Yes, it was at RailsConf 2010 in Baltimore.

Regular expressions and prime numbers

Q: I don’t remember where I saw this, but recently I heard for the first time about how it’s possible to determine if a number is prime using a regular expression. Then I saw the one liners in your Math With Regular Expressions repo, like this one:

[gist id=”3860918″]

For these, by the way, I used Perl because one liners can be shorter in Perl. You could write the same thing in Ruby but you would have to use “gsub,” for example.

Q: It sounds bizarre and strange to me that you can determine whether a number is prime using a regex! Can you explain how in the world that works?

Ha ha yea – once you understand the regex you can say: “ah… it’s easy.” The genius idea for me was to ever think that you can solve this problem with a regular expression.

The story behind this is that many years ago, a Perl hacker called Abigail, wrote a one liner to check whether a given positive integer was prime. The idea behind it is the following: Let’s say you want to check whether 15 is prime. What you have to do is visualize 15 sticks – if the number is composite, then you can group evenly the sticks. That’s the vision. That’s the idea.

What the original regex from Abigail does, given a number like 15, is to construct a string with 15 ones. And then the regular expression uses the regex engine to try to evenly group the ones. You have to anchor and then try a group – and since you have backreferences and the quantifiers – you can easily break this into even groups, or not. So it’s a brute force thing, but it’s brilliant. So I’ve known about this technique for many years, but one day I decided to explore this technique and apply it to other problems.

Q: And that’s when you created the github repo.

Yes – all of these one liners exploit the same technique.

Thanks!

Q: Bueno; muchas gracias Xavier! Me alegro mucho haber hablado contigo…

Muy bien – igualmente – ha sido un placer.

Pat ShaughnessyPat Shaughnessy
View Author

Pat Shaughnessy writes a blog about Ruby development and recently self-published an eBook called Ruby Under a Microscope. When he's not at the keyboard, Pat enjoys spending time with his wife and two kids. Pat is also a fluent Spanish speaker and travels frequently to Spain to visit his wife's family.

Share this article
Read Next
Effortless Content Publishing: A Developer’s Guide to Adobe Experience Manager
Effortless Content Publishing: A Developer’s Guide to Adobe Experience Manager
SitePoint Sponsors
From Idea to Prototype in Minutes: Claude Sonnet 3.5
From Idea to Prototype in Minutes: Claude Sonnet 3.5
Zain Zaidi
Essential Plugins for WordPress Developers: Top Picks for 2024
Essential Plugins for WordPress Developers: Top Picks for 2024
SitePoint Sponsors
WebAssembly vs JavaScript: A Comparison
WebAssembly vs JavaScript: A Comparison
Kaan Güner
The Functional Depth of Docker and Docker Compose
The Functional Depth of Docker and Docker Compose
Vultr
How Top HR Agencies Build Trust Through Logo Designs
How Top HR Agencies Build Trust Through Logo Designs
Evan Brown
Leveraging Progressive Web Apps (PWAs) for Enhanced Mobile User Engagement
Leveraging Progressive Web Apps (PWAs) for Enhanced Mobile User Engagement
SitePoint Sponsors
10 Artificial Intelligence APIs for Developers
10 Artificial Intelligence APIs for Developers
SitePoint Sponsors
The Ultimate Guide to Navigating SQL Server With SQLCMD
The Ultimate Guide to Navigating SQL Server With SQLCMD
Nisarg Upadhyay
Retrieval-augmented Generation: Revolution or Overpromise?
Retrieval-augmented Generation: Revolution or Overpromise?
Kateryna ReshetiloOlexandr Moklyak
How to Deploy Apache Airflow on Vultr Using Anaconda
How to Deploy Apache Airflow on Vultr Using Anaconda
Vultr
Cloud Native: How Ampere Is Improving Nightly Arm64 Builds
Cloud Native: How Ampere Is Improving Nightly Arm64 Builds
Dave NearyAaron Williams
How to Create Content in WordPress with AI
How to Create Content in WordPress with AI
Çağdaş Dağ
A Beginner’s Guide to Setting Up a Project in Laravel
A Beginner’s Guide to Setting Up a Project in Laravel
Claudio Ribeiro
Enhancing DevSecOps Workflows with Generative AI: A Comprehensive Guide
Enhancing DevSecOps Workflows with Generative AI: A Comprehensive Guide
Gitlab
Creating Fluid Typography with the CSS clamp() Function
Creating Fluid Typography with the CSS clamp() Function
Daine Mawer
Comparing Full Stack and Headless CMS Platforms
Comparing Full Stack and Headless CMS Platforms
Vultr
7 Easy Ways to Make a Magento 2 Website Faster
7 Easy Ways to Make a Magento 2 Website Faster
Konstantin Gerasimov
Powerful React Form Builders to Consider in 2024
Powerful React Form Builders to Consider in 2024
Femi Akinyemi
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Ralph Mason
Sending Email Using Node.js
Sending Email Using Node.js
Craig Buckler
Creating a Navbar in React
Creating a Navbar in React
Vidura Senevirathne
A Complete Guide to CSS Logical Properties, with Cheat Sheet
A Complete Guide to CSS Logical Properties, with Cheat Sheet
Ralph Mason
Using JSON Web Tokens with Node.js
Using JSON Web Tokens with Node.js
Lakindu Hewawasam
How to Build a Simple Web Server with Node.js
How to Build a Simple Web Server with Node.js
Chameera Dulanga
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Beloslava Petrova
Crafting Interactive Scatter Plots with Plotly
Crafting Interactive Scatter Plots with Plotly
Binara Prabhanga
GenAI: How to Reduce Cost with Prompt Compression Techniques
GenAI: How to Reduce Cost with Prompt Compression Techniques
Suvoraj Biswas
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
Aurelio De RosaMaria Antonietta Perna
Quick Tip: How to Align Column Rows with CSS Subgrid
Quick Tip: How to Align Column Rows with CSS Subgrid
Ralph Mason
15 Top Web Design Tools & Resources To Try in 2024
15 Top Web Design Tools & Resources To Try in 2024
SitePoint Sponsors
7 Simple Rules for Better Data Visualization
7 Simple Rules for Better Data Visualization
Mariia Merkulova
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
SitePoint Team
Best Programming Language for AI
Best Programming Language for AI
Lucero del Alba
Quick Tip: How to Add Gradient Effects and Patterns to Text
Quick Tip: How to Add Gradient Effects and Patterns to Text
Ralph Mason
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Vultr
How to Optimize Website Content for Featured Snippets
How to Optimize Website Content for Featured Snippets
Dipen Visavadiya
Psychology and UX: Decoding the Science Behind User Clicks
Psychology and UX: Decoding the Science Behind User Clicks
Tanya Kumari
Build a Full-stack App with Node.js and htmx
Build a Full-stack App with Node.js and htmx
James Hibbard
Digital Transformation with AI: The Benefits and Challenges
Digital Transformation with AI: The Benefits and Challenges
Priyanka Prajapat
Quick Tip: Creating a Date Picker in React
Quick Tip: Creating a Date Picker in React
Dianne Pena
How to Create Interactive Animations Using React Spring
How to Create Interactive Animations Using React Spring
Yemi Ojedapo
10 Reasons to Love Google Docs
10 Reasons to Love Google Docs
Joshua KrausZain Zaidi
How to Use Magento 2 for International Ecommerce Success
How to Use Magento 2 for International Ecommerce Success
Mitul Patel
5 Exciting New JavaScript Features in 2024
5 Exciting New JavaScript Features in 2024
Olivia GibsonDarren Jones
Tools and Strategies for Efficient Web Project Management
Tools and Strategies for Efficient Web Project Management
Juliet Ofoegbu
Choosing the Best WordPress CRM Plugin for Your Business
Choosing the Best WordPress CRM Plugin for Your Business
Neve Wilkinson
ChatGPT Plugins for Marketing Success
ChatGPT Plugins for Marketing Success
Neil Jordan
Managing Static Files in Django: A Comprehensive Guide
Managing Static Files in Django: A Comprehensive Guide
Kabaki Antony
The Ultimate Guide to Choosing the Best React Website Builder
The Ultimate Guide to Choosing the Best React Website Builder
Dianne Pena
Exploring the Creative Power of CSS Filters and Blending
Exploring the Creative Power of CSS Filters and Blending
Joan Ayebola
How to Use WebSockets in Node.js to Create Real-time Apps
How to Use WebSockets in Node.js to Create Real-time Apps
Craig Buckler
Best Node.js Framework Choices for Modern App Development
Best Node.js Framework Choices for Modern App Development
Dianne Pena
SaaS Boilerplates: What They Are, And 10 of the Best
SaaS Boilerplates: What They Are, And 10 of the Best
Zain Zaidi
Understanding Cookies and Sessions in React
Understanding Cookies and Sessions in React
Blessing Ene Anyebe
Enhanced Internationalization (i18n) in Next.js 14
Enhanced Internationalization (i18n) in Next.js 14
Emmanuel Onyeyaforo
Essential React Native Performance Tips and Tricks
Essential React Native Performance Tips and Tricks
Shaik Mukthahar
How to Use Server-sent Events in Node.js
How to Use Server-sent Events in Node.js
Craig Buckler
Five Simple Ways to Boost a WooCommerce Site’s Performance
Five Simple Ways to Boost a WooCommerce Site’s Performance
Palash Ghosh
Elevate Your Online Store with Top WooCommerce Plugins
Elevate Your Online Store with Top WooCommerce Plugins
Dianne Pena
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Dianne Pena
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
Vultr
Enhance Your React Apps with ShadCn Utilities and Components
Enhance Your React Apps with ShadCn Utilities and Components
David Jaja
10 Best Create React App Alternatives for Different Use Cases
10 Best Create React App Alternatives for Different Use Cases
Zain Zaidi
Control Lazy Load, Infinite Scroll and Animations in React
Control Lazy Load, Infinite Scroll and Animations in React
Blessing Ene Anyebe
Building a Research Assistant Tool with AI and JavaScript
Building a Research Assistant Tool with AI and JavaScript
Mahmud Adeleye
Understanding React useEffect
Understanding React useEffect
Dianne Pena
Web Design Trends to Watch in 2024
Web Design Trends to Watch in 2024
Juliet Ofoegbu
Building a 3D Card Flip Animation with CSS Houdini
Building a 3D Card Flip Animation with CSS Houdini
Fred Zugs
How to Use ChatGPT in an Unavailable Country
How to Use ChatGPT in an Unavailable Country
Dianne Pena
An Introduction to Node.js Multithreading
An Introduction to Node.js Multithreading
Craig Buckler
How to Boost WordPress Security and Protect Your SEO Ranking
How to Boost WordPress Security and Protect Your SEO Ranking
Jaya Iyer
Understanding How ChatGPT Maintains Context
Understanding How ChatGPT Maintains Context
Dianne Pena
Building Interactive Data Visualizations with D3.js and React
Building Interactive Data Visualizations with D3.js and React
Oluwabusayo Jacobs
JavaScript vs Python: Which One Should You Learn First?
JavaScript vs Python: Which One Should You Learn First?
Olivia GibsonDarren Jones
13 Best Books, Courses and Communities for Learning React
13 Best Books, Courses and Communities for Learning React
Zain Zaidi
5 jQuery.each() Function Examples
5 jQuery.each() Function Examples
Florian RapplJames Hibbard
Implementing User Authentication in React Apps with Appwrite
Implementing User Authentication in React Apps with Appwrite
Yemi Ojedapo
AI-Powered Search Engine With Milvus Vector Database on Vultr
AI-Powered Search Engine With Milvus Vector Database on Vultr
Vultr
Understanding Signals in Django
Understanding Signals in Django
Kabaki Antony
Why React Icons May Be the Only Icon Library You Need
Why React Icons May Be the Only Icon Library You Need
Zain Zaidi
View Transitions in Astro
View Transitions in Astro
Tamas Piros
Getting Started with Content Collections in Astro
Getting Started with Content Collections in Astro
Tamas Piros
What Does the Java Virtual Machine Do All Day?
What Does the Java Virtual Machine Do All Day?
Peter Kessler
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Mayank Singh
Layouts in Astro
Layouts in Astro
Tamas Piros
.NET 8: Blazor Render Modes Explained
.NET 8: Blazor Render Modes Explained
Peter De Tender
Mastering Node CSV
Mastering Node CSV
Dianne Pena
A Beginner’s Guide to SvelteKit
A Beginner’s Guide to SvelteKit
Erik KückelheimSimon Holthausen
Brighten Up Your Astro Site with KwesForms and Rive
Brighten Up Your Astro Site with KwesForms and Rive
Paul Scanlon
Which Programming Language Should I Learn First in 2024?
Which Programming Language Should I Learn First in 2024?
Joel Falconer
Managing PHP Versions with Laravel Herd
Managing PHP Versions with Laravel Herd
Dianne Pena
Accelerating the Cloud: The Final Steps
Accelerating the Cloud: The Final Steps
Dave Neary
An Alphebetized List of MIME Types
An Alphebetized List of MIME Types
Dianne Pena
The Best PHP Frameworks for 2024
The Best PHP Frameworks for 2024
Claudio Ribeiro
11 Best WordPress Themes for Developers & Designers in 2024
11 Best WordPress Themes for Developers & Designers in 2024
SitePoint Sponsors
Top 10 Best WordPress AI Plugins of 2024
Top 10 Best WordPress AI Plugins of 2024
Dianne Pena
20+ Tools for Node.js Development in 2024
20+ Tools for Node.js Development in 2024
Dianne Pena
The Best Figma Plugins to Enhance Your Design Workflow in 2024
The Best Figma Plugins to Enhance Your Design Workflow in 2024
Dianne Pena
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Christopher Collins
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form