result of low level PDF experiment

10 views
Skip to first unread message

Gregory Brown

unread,
Jan 10, 2010, 1:08:15 PM1/10/10
to Prawn
I sat down this morning with a goal of getting
http://github.com/sandal/pdf to draw a line, and almost succeeded.
However, this took me several hours, even when cargo-culting a lot of
Prawn code.

What I realized is that this is going to take a ton of effort. If we
cut corners by copying a lot of what Prawn does, we'll get a good
division line between the user and developer level APIs, but we won't
get the benefit of a fresh start. If we start fresh, unless someone
has full time work available to donate, we're not going to be able to
finish this and have it up to a reasonable level of stability within
the next few months.

Of course, by doing this little exercise, I learned a lot of places
Prawn could improve, even at the most basic level. I have a good
sense of some refactorings that can be done. Here are a few thoughts

* I would like to rename Prawn::Document to Prawn::BasicDocument, then
create a new Prawn::Document class that inherits from it. We could
then move higher level features across the dividing line, and merge
Prawn::Internals into BasicDocument. Anything public on BasicDocument
would form our "developer API", and Document is our "user AP

* I'd like to either modularize or create a class for page related
operations. There's too many *_page_* methods, and I'm looking for a
way to condense that.

* I'm considering moving the tests over to contest
(http://github.com/citrusbyte/contest). While test/spec let us dodge
a bullet when RSpec was having 1.9 compatibility issues, it's neither
test-unit not RSpec, and I think that's source of some confusion.
Every switch I made in sandal/pdf to contest looked good to me. This
would also give me an opportunity to comprehensively review and
refactor our tests, a step that needs to be taken before 1.0 anyway.

* I'm considering using Prawn::Document.extensions for a number of the
features we mix in. This would allow disabling features you don't
need on Prawn::Document or a subclass of it.

These are my initial thoughts. I feel like spending time on
refactoring Prawn might be more productive than creating our PDF
kernel library, given that we have a timeline of a couple months, not
another year or two.
If folks are in agreement here, I'll fire up a refactor branch and
begin on my major changes, merging once they're stable and reviewed by
the community.

-greg

Daniel Nelson

unread,
Jan 10, 2010, 3:16:56 PM1/10/10
to prawn...@googlegroups.com
> * I would like to rename Prawn::Document to Prawn::BasicDocument, then
> create a new Prawn::Document class that inherits from it.   We could
> then move higher level features across the dividing line, and merge
> Prawn::Internals into BasicDocument.  Anything public on BasicDocument
> would form our "developer API", and Document is our "user AP

What about parallel hierarchies: Prawn::Document and
Prawn::Dev::Document, Prawn::Text and Prawn::Dev::Text, etc.? That
would make it clear where people should look if they are just using
Prawn versus if they are extending Prawn.

-Daniel

Gregory Brown

unread,
Jan 10, 2010, 3:36:17 PM1/10/10
to prawn...@googlegroups.com

It's a possibility... but it seems a bit heavy handed to me. I feel
like Document is our core end user API, and the rest of the features
are pretty much implicitly developer APIs anyway.... But I could be
convinced. Can you give me some examples of where you see useful
division lines there?

RNHurt

unread,
Jan 11, 2010, 6:17:58 AM1/11/10
to Prawn
On Jan 10, 1:08 pm, Gregory Brown <gregory.t.br...@gmail.com> wrote:
> ...snip...

> * I would like to rename Prawn::Document to Prawn::BasicDocument, then
> create a new Prawn::Document class that inherits from it.   We could
> then move higher level features across the dividing line, and merge
> Prawn::Internals into BasicDocument.  Anything public on BasicDocument
> would form our "developer API", and Document is our "user AP

I like this; it seems straightforward and clean.

> * I'd like to either modularize or create a class for page related
> operations.  There's too many *_page_* methods, and I'm looking for a
> way to condense that.

This sounds good as well.

> * I'm considering moving the tests over to contest
> (http://github.com/citrusbyte/contest).   While test/spec let us dodge
> a bullet when RSpec was having 1.9 compatibility issues, it's neither
> test-unit not RSpec, and I think that's source of some confusion.
> Every switch I made in sandal/pdf to contest looked good to me.   This
> would also give me an opportunity to comprehensively review and
> refactor our tests, a step that needs to be taken before 1.0 anyway.

I'm not sure what contest brings to the table, but tests are my weak
spot. :/

> * I'm considering using Prawn::Document.extensions for a number of the
> features we mix in.   This would allow disabling features you don't
> need on Prawn::Document or a subclass of it.

Excellent. By making Prawn even more lightweight this would increase
its usefulness immensely. My project requires only the basics and
needs to run in an embedded environment so this feature would be great
for me. :)

Gregory Brown

unread,
Jan 11, 2010, 8:03:58 AM1/11/10
to prawn...@googlegroups.com
On Mon, Jan 11, 2010 at 6:17 AM, RNHurt <rnh...@gmail.com> wrote:

> I'm not sure what contest brings to the table, but tests are my weak
> spot.  :/

It's more what it doesn't bring to the table. It's so small it fits
in your test_helper.rb file, but provides contexts and full sentence
test cases. That's pretty much all I need from a testing framework,
modulo mocks, which we've been using Mocha for anyway.

Lenny Marks

unread,
Jan 11, 2010, 10:10:15 AM1/11/10
to prawn...@googlegroups.com

Are there still known 1.9 compatibility issues with RSpec? I admit to
being confused by the rspec-ish specs. I had never come across test-
spec before. I for one have a strong preference for Vanilla RSpec(even
without mocha). Its simple and familiar(I'm sure some would argue the
same for test-unit) but among other reasons I think RSpec is more
natural at documenting behavior.

-lenny

> * I'm considering using Prawn::Document.extensions for a number of the
> features we mix in. This would allow disabling features you don't
> need on Prawn::Document or a subclass of it.
>
> These are my initial thoughts. I feel like spending time on
> refactoring Prawn might be more productive than creating our PDF
> kernel library, given that we have a timeline of a couple months, not
> another year or two.
> If folks are in agreement here, I'll fire up a refactor branch and
> begin on my major changes, merging once they're stable and reviewed by
> the community.
>
> -greg

> --
> You received this message because you are subscribed to the Google
> Groups "Prawn" group.
> To post to this group, send email to prawn...@googlegroups.com.
> To unsubscribe from this group, send email to prawn-ruby+...@googlegroups.com
> .
> For more options, visit this group at http://groups.google.com/group/prawn-ruby?hl=en
> .
>
>

Gregory Brown

unread,
Jan 11, 2010, 10:21:49 AM1/11/10
to prawn...@googlegroups.com
On Mon, Jan 11, 2010 at 10:10 AM, Lenny Marks <le...@aps.org> wrote:

> Are there still known 1.9 compatibility issues with RSpec? I admit to being

> confused by the rspec-ish specs. I had never come across test-spec before. I


> for one have a strong preference for Vanilla RSpec(even without mocha). Its
> simple and familiar(I'm sure some would argue the same for test-unit) but
> among other reasons I think RSpec is more natural at documenting behavior.

RSpec is probably 1.9 compatible by now. I've used pretty much every
test framework Ruby has to offer, and at the end of the day, I prefer
the bits with less moving parts. RSpec syntax is liked by some, but
not by all. I think Prawn is a library in which the ability for
RSpec to capture high level business language is less important...

This isn't an open debate though. Either we'll move to contest or
we'll stick with test/spec for the foreseeable future. I trust
everyone who hacks on Prawn to be adaptable when it comes to testing
frameworks, since this is a bit of an advanced project to begin with.

-greg

Daniel Nelson

unread,
Jan 11, 2010, 12:39:23 PM1/11/10
to prawn...@googlegroups.com
>> What about parallel hierarchies:  Prawn::Document and
>> Prawn::Dev::Document, Prawn::Text and Prawn::Dev::Text, etc.? That
> It's a possibility... but it seems a bit heavy handed to me.   I feel
> like Document is our core end user API, and the rest of the features
> are pretty much implicitly developer APIs anyway....    But I could be
> convinced.   Can you give me some examples of where you see useful
> division lines there?

Prawn::Text contains a couple developer methods that need to be
publicly accessible so they remain visible to extensions. For example,
draw_text_at (which we discussed as a developer method to replace the
current text_at so that text_at can become a user method and the :at
option removed from the text method) and process_text_options need to
be public so that extensions like Text::Box can access them. This
could be remedied by making the significant change of making Text into
a class of its own, rather than a mixin. Then things like TextBox
could simply extend the Text class.

The transformation_matrix method submitted by Michaël as the
foundation of the rotate, scale, skew, and translate methods is
similar.

Best,

Daniel

Gregory Brown

unread,
Jan 11, 2010, 12:51:02 PM1/11/10
to prawn...@googlegroups.com
On Mon, Jan 11, 2010 at 12:39 PM, Daniel Nelson <dnel...@gmail.com> wrote:
>>> What about parallel hierarchies:  Prawn::Document and
>>> Prawn::Dev::Document, Prawn::Text and Prawn::Dev::Text, etc.? That
>> It's a possibility... but it seems a bit heavy handed to me.   I feel
>> like Document is our core end user API, and the rest of the features
>> are pretty much implicitly developer APIs anyway....    But I could be
>> convinced.   Can you give me some examples of where you see useful
>> division lines there?
>
> Prawn::Text contains a couple developer methods that need to be
> publicly accessible so they remain visible to extensions. For example,
> draw_text_at (which we discussed as a developer method to replace the
> current text_at so that text_at can become a user method and the :at
> option removed from the text method) and process_text_options need to
> be public so that extensions like Text::Box can access them. This
> could be remedied by making the significant change of making Text into
> a class of its own, rather than a mixin. Then things like TextBox
> could simply extend the Text class.

This is worth experimenting with, though I think that I prefer
Prawn::Core::* to Prawn::Dev::* as it'll re-use an existing term.
If this sounds acceptable, I'll start trying to bust out
Prawn::Core::Document, and you can work on doing something nice with
Text.

-greg

Daniel Nelson

unread,
Jan 11, 2010, 1:14:07 PM1/11/10
to prawn...@googlegroups.com
Prawn::Core sounds much better than Dev. I presume these should go
into a "core" directory?

Cheers,

Daniel

Gregory Brown

unread,
Jan 11, 2010, 1:25:43 PM1/11/10
to prawn...@googlegroups.com
On Mon, Jan 11, 2010 at 1:14 PM, Daniel Nelson <dnel...@gmail.com> wrote:
> Prawn::Core sounds much better than Dev. I presume these should go
> into a "core" directory?

Yep. lib/prawn/core/*.rb

Daniel

unread,
Jan 16, 2010, 6:30:13 AM1/16/10
to Prawn
> This is worth experimenting with, though I think that I prefer
> Prawn::Core::* to Prawn::Dev::* as it'll re-use an existing term.
> If this sounds acceptable, I'll start trying to bust out
> Prawn::Core::Document, and you can work on doing something nice withText.

Hello Greg,

I've broken out the developer text methods into Prawn::Core::Text.
Note that I have not yet removed the :at option from text() because I
don't want to break anything during the extraction of the developer
API. If you still agree that extracting the text(:at => ...) option
out into text_at, then I will patch that after we decide on this
experiment with the Prawn::Core APIs.

http://github.com/Bluejade/prawn/commit/6d71346d525222e3eb51bee436a769719478104d

Best,

Daniel

Gregory Brown

unread,
Jan 16, 2010, 10:30:40 AM1/16/10
to prawn...@googlegroups.com
On Sat, Jan 16, 2010 at 6:30 AM, Daniel <dnel...@gmail.com> wrote:

> I've broken out the developer text methods into Prawn::Core::Text.
> Note that I have not yet removed the :at option from text() because I
> don't want to break anything during the extraction of the developer
> API. If you still agree that extracting the text(:at => ...) option
> out into text_at, then I will patch that after we decide on this
> experiment with the Prawn::Core APIs.

I am okay with this change and would prefer it sooner than later. So
go ahead and add it once you've merged the new code.

> http://github.com/Bluejade/prawn/commit/6d71346d525222e3eb51bee436a769719478104d

Looks great, please merge into master. When including modules, it'd
be desireable to use their fully qualified names, i.e. include
Prawn::Core::Text.
I'm sure that I've been inconsistent about that, but we might want to
get in the habit of doing that.

As for the refactorings, rather than "completing" the experiment and
then merging it all in at once, I want to incrementally bring in as
many as possible between now and 0.8.

I think the rough plan of attack is that if you've got a refactor that
we've discussed between the 4 of us (or on this list) before, go ahead
and code it up, and then as long as you can get peer review from at
least one of us, go ahead and merge.

This is going to create a shit-ton of turbulence on master, but I
don't want to freeze core for minor featurework or bugs, and I think
this is the only way to prevent a hellish merge.

Reply all
Reply to author
Forward
0 new messages