Beginner would like help with oo-modelling

I’m new to ruby and basically oop as well, but based on what I’ve seen
so far, ruby seems the way to understand and learn oop.

Now, I would like to write a cute little script that generates a ruler
in svg (or maybe ps, pdf as well).

Of course, it should do that in a way that lets the user pass
parameters, specifically a varying number and properties of
subdivisions.

So, let’s say the script has received the following data:

unit, length
label every nth unit
lines:
bold and long every unit
normal and medium every 0.5 units
thin and short every 0.1 units

Now, let’s model the object(s):

Should I split everything up into as little/independent ‘units’ as
possible? I would think so.

So a /ruler/ class consists of several /line/ and /label/ objects. Each
instance of line contains a position (relative to some origin), length
(alternatively, the second point [pair of coords] of the line), color
and width.

It could be similar with the labels.

Then, the /ruler/ class stores a number of lines and labels.

But how do they get there, and how are they ‘ordered’?
As each kind of line should later be put into a different group (so
manual editing of the SVG is easy) how do I store them? In an array,
hash?

And where should the methods be implemented? It’s probably good to have
the ruler assemble itself when created, by just passing all the
properties.
And then lateron just using a method that returns the SVG code.

So basically my problem comes down to this:

How do I store the /line/ objects, so that calculation is easy
(conflict: all types of line would be placed at 1 metric_unit for the
parameters given above) and iteration over the several kinds of lines
(for creating groups) is easy as well?

Feedback would be greatly appreciated, it all seems a bit fuzzy now, but
I hope the situation clarifies itself with some input and other points
of view…

thanks,

paper

It’s usually a good idea to separate out how something presents itself
from how it is stored. You mentioned that you want to render not just to
SVG, but perhaps to ps and PDF too? That makes me think it would be
sensible to have a RulerRenderer subclass with implementations for each
rendering method. The SVG renderer (and probably the others too) may be
well represented with a “template” - take a look at ERB.

In my opinion (would like to hear others)…

The most important thing I’ve learned about OO is that object
hierarchies are not fundamental. There is no right way to model a given
set of objects. If you try to find one, you will be engaging in
premature hierarchy building, and you’ll be wasting time.

Given some objects and a particular use for them, there are hierarchies
that work well. A good hierarchy will continue to work well as the
requirements for the object change.

In particular settings, there are known extremely good hierarchies.
These are known because so many people have gone up the learning curve
of building a hierarchy and refactoring it / starting again. Over time,
consensus about a sensible object hierarchy emerges. Some of the
patterns are examples (Model View Controller springs to mind).

I think that in this domain, you’ve limited opportunity for making
sensible use of OO modelling (please disagree everyone). There’s also a
danger that you will build a hierarchy of objects that doesn’t really
model anything particularly useful.

However: actual advice? Play about and see how far you get :slight_smile: Try
writing procedural code, and when it gets annoying, see how you can
introduce some objects that split the problem in to manageable chunks.
Go to a good book shop and look at a few books on patterns and OO
decomposition - get some that appeal to you.

Cheers,
Benj

sensible, I’m currently stuck, and I most likely would be stuck on the

As arrays apparently only support integer keys, and the order in which
the line elements are stored does not really matter, my guess is that a
hash using the position of each line (float) as keys, and the style of
line as value, plus another hash or array that contains just the
different styles might be a good approach.

Why do you need to store the lines and ticks and bits of ruler at all? I
don’t think you need to. What you need to store is what makes one ruler
unique (how long it is, what units it uses, how many gradations it has,
what its colour is, where the bold gradations are…). That’s the kind
of thing that you would put in to a ruler, probably.

But for starters (I’m not quite sure where your experience level is), I
don’t think you even know that you need that.

I would try to just generate the SVG for a fixed ruler. In fact, I’d
start by trying to generate the SVG for some parallel lines. 10 of them.
Of unit length. I’d use ERB, and I’d look up an ERB tutorial.

You’ll find info about ERB here:
http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html

Or, you could just do it in ruby (I don’t have a Ruby to hand to try
this with, so it will have errors I expect):

lines = 1…10

lines.each do |line_x|
puts “draw_line_from #{line_x}, 0 to #{line_x}, 1”
end

You’ll need lots more puts in there to get it to create actual SVG, and
I doubt SVG has a command “draw_line_from x,y to x,y”, so you’ll need to
fix that up too. Maybe the above is enough to get you started though.

Best of luck,
Ben

Benj,

thanks for your input!

The option of rendering different outputs is supposed to be part of The
Concept, but although you’re affirming my assumption that All Roads Lead
to Rome, my hopes for a specific hint to one of those roads are
disappointed now :slight_smile:

Even as I’m trying to discover OO ways of modeling that may not be even
sensible, I’m currently stuck, and I most likely would be stuck on the
procedural path as well. Actually, I have been playing and now I’ve
mostly run out of game ideas…

I would just like someone to push me into the right direction,
specifically addressing the matter of storing the line data (whether as
attribute or independent).

I’ve been thinking about using a relational approch using two [storage
units], one containing type and positional data of a line, while the
other just stores line-type related information as color, width, …

As arrays apparently only support integer keys, and the order in which
the line elements are stored does not really matter, my guess is that a
hash using the position of each line (float) as keys, and the style of
line as value, plus another hash or array that contains just the
different styles might be a good approach.

Then I could iterate with the step method to insert an element, if there
is none yet. Resulting in a ‘list’ with all lines.
I assume that I then could easily extract a specific type of line, fetch
the corresponding style information from the other list, and voilà ! -
generate what I want.

Could you kindly provide me with your thoughts about this approach? If
it is not doomed, I shall gain motivation and so will be able to try out
procedural and OO constellations, learning the wonderous workings of
arrays and hashes, and eventually improving the program, so everyone
will be able to create her/his badly-needed ruler…

I have access to books describing OO with UML, but maybe I can extract
the concept without having to ‘bother’ about UML yet.

[email protected] wrote:

In my opinion (would like to hear others)…

The most important thing I’ve learned about OO is that object
hierarchies are not fundamental. There is no right way to model a given
set of objects. If you try to find one, you will be engaging in
premature hierarchy building, and you’ll be wasting time.

Well, if there are no right ways, there certainly are wrong ways. I
would have a look at
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod and read each
of the articles for advice on object oriented design.

Pa Per wrote:

Then I could iterate with the step method to insert an element, if there

I have access to books describing OO with UML, but maybe I can extract
the concept without having to ‘bother’ about UML yet.

I like to stick with the metaphor as much as possible, as it makes it
easier when you come back to it after several months or years, or
someone else works on your code, to figure out what was going on.

In that vein, one question I have about your proposed storage mechanism
is: How will you know where the lines belong? I mean, if you store it
based on a hash where the key is the position, how will you remember the
position? Sure, you can get all the keys, but it seems like an extra
step that is not needed. It seems to me that a position is an attribute
of a line, and that information would be better suited there. As you
mention, the order doesn’t matter. But, that doesn’t mean a hash would
be better than an array, simply because it doesn’t take order into
account. If an array works and order doesn’t matter, don’t sort it. =)
It sounds like you are making it harder than it needs to be (though, it
still is simple, I just think arrays are “simpler” than hashes).

Pa Per wrote:

Sammy,
what do you mean by ‘sticking to the metaphor’ ? Haven’t heard that
expression before, I’m not a native speaker.

Well, when you are building a system, essentially you are modeling some
domain. So, take for instance, we want to model a person. So we might
have as attributes of a person:

Name
Hair color
Hair length
Eye Color

DNA sequence (this would likely be unique)

To me, it would make more sense to have DNA as an attribute inside the
person object, not as a reference in a hash. The way I understood your
description of using the hash, it would be something like this:

[“DNA sequence 3232” => person_object_1, “DNA sequence 3999” =>
person_object_2 … “DNA sequence 9882” => person_object_n]

and each person object would have Name, Hair color, Hair length, Eye
color … as attributes (not including the DNA sequence).

So, you’d “know” a person’s DNA sequence by getting the keys and seeing
which person object each key referred to. To me, it would make sense to
store this information in the object. Now, if you needed quick access
to search for a person based on their DNA, you might ALSO store it in a
hash as well, using the DNA as a key. But if you were just going to
iterate through them, an array would do just fine.

Basically, I got the idea that you weren’t storing a property that
belongs to a line (its position) within the line, and if you follow the
“metaphor” a line should have a position, among other attributes.

-Sam

Ok, now I understand what you mean. And you are right, for some reason I
totally got off the path I was following initially.
But the problem I’m trying to deal with right now would probably persist
when storing the information inside an object:

I’m currently using the num.step method to iterate from zero to the
length of the ruler, in order to calculate the positions. This creates
multiple types of lines on the same position, e.g.

| | | lines[0]
| | | | | | lines[1]
|||||||||||||||||||||||||||| lines[2]
0 5 10

lines indicate value, e.g. lines[2] = [1…n]

To prevent that, when adding a line (position) to lines, it is necessary
to iterate over the previous array(s), checking if the value-to-be is
already included (enum.include?).

I don’t like that approach, although it probably works. I have yet to
experiment with “following the metaphor”.

Alternatively, I would have to find a method to generate the positions
directly, like
0, 10, 20, 30
5, 15, 25, 35
1,2,3,4,6,7,8,9, …

But since the pattern depends on the parameter, I am not sure if a
reasonably short equation could be found.

Another thought that crossed my mind was to define the positions
recursively, e.g. “divide length into n sections, divide those into l
sections, …”
But I have not evaluated the pros and cons of this, regarding usability.
It probably is the same, in the end.

On the other hand, I figure that there is indeed a simple solution to
this.

For now, I’ll try to use classes and methods and learn on the way, I’ll
eventually find something that works well…

Thanks for the inspiration!

Ben,
thanks for your suggestion, but generating the SVG is not the problem
(whether with eruby, erb, or with help of rexml).

Sammy,
what do you mean by ‘sticking to the metaphor’ ? Haven’t heard that
expression before, I’m not a native speaker.

But thanks for your question: it really does not matter whether I use a
hash’s key or an array’s value to store the position.

I’ll try to take it from there, now it seems that experimenting could
actually result in something. Thanks folks!

On 10/26/06, [email protected] [email protected] wrote:

But since the pattern depends on the parameter, I am not sure if a
reasonably short equation could be found.

it’s quite short:

Aye, that would be the way to go. I can’t think of any reason why
you’d want to eat up all that memory holding all of the offsets when
you can calculate them relatively easily.

http://en.wikipedia.org/wiki/Arithmetic_series

On Fri, 27 Oct 2006, Pa Per wrote:

| | | | | | lines[1]
experiment with “following the metaphor”.

Alternatively, I would have to find a method to generate the positions
directly, like
0, 10, 20, 30
5, 15, 25, 35
1,2,3,4,6,7,8,9, …

But since the pattern depends on the parameter, I am not sure if a
reasonably short equation could be found.

it’s quite short:

 harp:~ > cat a.rb
 class TickGen
   include Enumerable
   def initialize a, step, b = nil
     @a, @step, @b = a, step, b
   end
   def each
     n = @a
     loop{
       yield n
       n += @step
       break if @b and n > @b
     }
   end
   def include? tick
     q, r = (tick - @a).divmod @step
     r.zero? and (@b.nil? or q <= @b)   #=> THE EQUATION
   end
   def to_a
     raise "infinitly big array" unless @b
     super
   end
   def to_ary() to_a end
   def | other
     (to_a | other.to_a).sort.uniq
   end
 end

 a = TickGen.new 0, 2, 10
 p a.to_a
 p a.include?(8)

 b = TickGen.new 1, 1, 10
 p b.to_a
 p b.include?(8)

 c = TickGen.new 1, 2, 10
 p c.to_a
 p c.include?(8)

 p( a | b | c )


 harp:~ > ruby a.rb
 [0, 2, 4, 6, 8, 10]
 true
 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 true
 [1, 3, 5, 7, 9]
 false
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

regards.

-a

On 2006-10-26 10:42:56 +0200, [email protected] said:

The most important thing I’ve learned about OO is that object
of building a hierarchy and refactoring it / starting again. Over time,
introduce some objects that split the problem in to manageable chunks.
Go to a good book shop and look at a few books on patterns and OO
decomposition - get some that appeal to you.

Cheers,
Benj

You can read this book , it’s very helpful…

Domain-Driven Design: Tackling Complexity in the Heart of Software
by Eric Evans

Publisher: Addison Wesley Professional
Pub Date: August 20, 2003
Print ISBN-10: 0-321-12521-5
Print ISBN-13: 978-0-321-12521-7
Pages: 560

Specific topics covered include:

I would like to just add this comment… when first hitting OOP, some
people tend to create objects based on real world objects, in the way
you are thinking of the ruler and its ticks.

If you keep breaking the data up in this way, you will find first of
all that you have many many interfaces getting in the way of actually
doing anything, and secondly that the objects themselves may not
actually suit what you are trying to do.

Try organising your problem like this… you have a ruler object, some
potential labelling objects and you want to put the results of that
interaction through one of several output objects. That is probably as
OO as you want to be with such a limited problem domain.

class Ruler
class Labeller
class Writer

ruler = Ruler.new(length, etc)
labellerBold = LabellerBold.new(ruler)
labellerEveryFiveUnits = LabellerEveryFiveUnits.new(ruler)

Writer writer = Writer.new
writer.write(labellerBold)
writer.write(labellerEveryFiveUnits)

See how its not real-world objects being modelled, but instead the
classes are based on units of functionality? If you want to create a
new way of labelling a ruler, its trival. If you want to create a new
way of writing out a bunch of labels, its trival. Over a long period
of maintenance, these are the things you are most likely to want to
add to the program.

unknown wrote:

it’s quite short:

I have to nag yet another time, but I don’t understand your code… that
is, I don’t see how it is different to iterating with the step method.

Could you please point out the advantages / the ‘trick’ ? Sorry I’m
missing it …

Writer writer = Writer.new

heh, surprised I didnt just type

Writer *writer = new Writer();

:wink:

All C++ and no Ruby makes Jack a dull boy. :frowning:

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs