Design Question - multiple XML parsers/ dependencies

(Mohit Sindhwani) #1

Hi Guys,

We have an API that returms XML and we'd like to build a client library for it so that we can use it in multiple projects. The current implementation uses Rexml for the parsing but we tried Ox and it's really fast(!!). However, since it's native, the installation doesn't always work as smoothly, especially on Windows. So, I wanted to see if we could support Ox if the user installs it and use Rexml as the normal way.

How should we organise such code? Would it basically be two internal implementations selected based on a parameter, or detection of the installation? Just want to get some ideas or a link to a best practice or somehing similar.

Thanks for any help!

Best Regards,
Mohit.

0 Likes

(Gerald Bauer) #2

Hello,

  See the multi_xml [1] and multi_json [2] for some "real world"
examples with sources [1a][2a].

Cheers.Prost.

[1] https://rubygems.org/gems/multi_xml
[2] https://rubygems.org/gems/multi_json
[1a] https://github.com/sferik/multi_xml
[2a] https://github.com/intridea/multi_json

0 Likes

(Marvin Gülker) #3

If #require fails, it raises a LoadError exception, which can be
rescued. This gives you the neccessary information for loading the
correct parts of your library without having to ask the user:

    begin
      require "ox"
      # ox is available
    rescue LoadError
      # ox is not available
    end

If you keep your library modular, you could then just load the correct
variant:

    begin
      require "ox"
      require_relative "your-library-with/ox"
    rescue LoadError
      require_relative "your-library-with/rexml"
    end

Gerald's suggestion with using a meta library that abstracts the actual
XML library in use is similar to this.

Alternatively, you could set some global piece of information using a
private API, e.g.

    begin
      require "ox"
      YourLibrary.ox_is_available = true
    rescue LoadError
      YourLibrary.ox_is_available = false
    end

···

Am 31. März 2019 um 14:31 Uhr +0800 schrieb Mohit Sindhwani:

How should we organise such code? Would it basically be two internal
implementations selected based on a parameter, or detection of the
installation? Just want to get some ideas or a link to a best practice or
somehing similar.

--
Blog: https://mg.guelker.eu

0 Likes

(Robert K.) #4

I am always a bit skeptical about these approaches (i.e. providing a
general wrapper) because you either have to agree on the least common
denominator of features or have to implement features in the wrapping
layer. In any case the wrapping layer needs to be updated whenever one
of the backend changes, which potentially creates a lot of maintenance
effort.

Also, especially with REXML in the mix I believe that had some quirks
related to encodings in the past. So generally testing effort will be
quite high. My 0.02€.

If only a few operations are used then the situation might look
different. Still you add one dimension to the test matrix because you
have to test all target system configuration combinations.

Kind regards

robert

···

On Sun, Mar 31, 2019 at 11:54 AM Gerald Bauer <gerald.bauer@gmail.com> wrote:

  See the multi_xml [1] and multi_json [2] for some "real world"
examples with sources [1a][2a].

[1] https://rubygems.org/gems/multi_xml
[2] https://rubygems.org/gems/multi_json
[1a] https://github.com/sferik/multi_xml
[2a] https://github.com/intridea/multi_json

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/

0 Likes

(Ryan Davis) #5

So use a binary gem that provides platform releases. There are probably many, but nokogiri is a safe choice:

  • 1.10.2 - March 25, 2019 (8.57 MB)
  • 1.10.2 - March 25, 2019 x64-mingw32 (5.59 MB)
  • 1.10.2 - March 25, 2019 java (5.46 MB)
  • 1.10.2 - March 25, 2019 x86-mingw32 (5.27 MB)

···

On Mar 30, 2019, at 23:31, Mohit Sindhwani <mo_mail@onghu.com> wrote:

However, since it's native, the installation doesn't always work as smoothly, especially on Windows. So, I wanted to see if we could support Ox if the user installs it and use Rexml as the normal way.

0 Likes

(Mohit Sindhwani) #6

Hi Robert.

Thanks!

I am always a bit skeptical about these approaches (i.e. providing a
general wrapper) because you either have to agree on the least common
denominator of features or have to implement features in the wrapping
layer. In any case the wrapping layer needs to be updated whenever one
of the backend changes, which potentially creates a lot of maintenance
effort.

You are right about this. I think if there are issues, we will need to make one or the other a prerequisite. For now, it's a case that we are moving out of REXML... but haven't decided if we want to force the dependency on ox.

Also, especially with REXML in the mix I believe that had some quirks
related to encodings in the past. So generally testing effort will be
quite high. My 0.02€.

Thanks! As above, REXML works for us... so, hopefully, the rest is easier still. Also, we are currently only parsing an XML file, so it might be easier still.

If only a few operations are used then the situation might look
different. Still you add one dimension to the test matrix because you
have to test all target system configuration combinations.

Yes, it is only a few operations. But you make an excellent point.

I think I have seen nokogiri mentioned a lot and if we were using Nokogiri, perhaps, I would have cared less. Just that ox seemed less popular but worked very well (and very fast) for our scenario. So, I was unsure if I should force that dependency also because ox installation is a bit difficult on Windows which is where we use it most.

Best Regards,
Mohit.

···

On 2019-4-1 5:33 PM, Robert Klemme wrote:

On Sun, Mar 31, 2019 at 11:54 AM Gerald Bauer <gerald.bauer@gmail.com> wrote:

0 Likes

(Mohit Sindhwani) #7

Dear Marvin,

Thanks, the sample is very useful! It does sound like a reasonable way to use it.

Best Regards,
Mohit.
2019-4-6 | 1:39 PM.

···

On 2019-3-31 10:05 PM, Marvin Gülker wrote:

Am 31. März 2019 um 14:31 Uhr +0800 schrieb Mohit Sindhwani:

How should we organise such code? Would it basically be two internal
implementations selected based on a parameter, or detection of the
installation? Just want to get some ideas or a link to a best practice or
somehing similar.

If #require fails, it raises a LoadError exception, which can be
rescued. This gives you the neccessary information for loading the
correct parts of your library without having to ask the user:

0 Likes

(Mohit Sindhwani) #8

Thanks, Gerald - I will take a look - this should be helpful.

Best Regards,
Mohit.
2019-4-6 | 10:50 PM.

···

On 2019-3-31 5:54 PM, Gerald Bauer wrote:

Hello,

   See the multi_xml [1] and multi_json [2] for some "real world"
examples with sources [1a][2a].

Cheers.Prost.

[1] https://rubygems.org/gems/multi_xml
[2] https://rubygems.org/gems/multi_json
[1a] https://github.com/sferik/multi_xml
[2a] https://github.com/intridea/multi_json

0 Likes

(Mohit Sindhwani) #9

Hi Ryan,

Thanks!

However, since it's native, the installation doesn't always work as smoothly, especially on Windows. So, I wanted to see if we could support Ox if the user installs it and use Rexml as the normal way.

So use a binary gem that provides platform releases. There are probably many, but nokogiri is a safe choice:

  • 1.10.2 - March 25, 2019 (8.57 MB)
  • 1.10.2 - March 25, 2019 x64-mingw32 (5.59 MB)
  • 1.10.2 - March 25, 2019 java (5.46 MB)
  • 1.10.2 - March 25, 2019 x86-mingw32 (5.27 MB)

I will check how Ox performs against nokogiri in our case. I stumbled across Ox and found it to be very fast (especially since we were using REXML at that point). It was a case of stumbling across somethig that worked well rather than searching and finding a prper well-researched solution. In any case, I think the responses have been very helpful and have taught me something new :slight_smile: even if I take the easier way out.

Best Regards,
Mohit.

···

On 2019-4-3 7:57 AM, Ryan Davis wrote:

On Mar 30, 2019, at 23:31, Mohit Sindhwani <mo_mail@onghu.com> wrote:

0 Likes