From: Robert Klemme on
2010/4/16 Josh Cheek <josh.cheek(a)gmail.com>:
> On Thu, Apr 15, 2010 at 11:39 PM, Derek Cannon
> <novellterminator(a)gmail.com>wrote:

Derek,thanks for stepping in with good explanations!

> > What exactly is "modularity"?
>
> Think how unix commands are small with a specific function, but you can
> combine them in powerful ways. These small programs are modular.

I'd really like to stress this point of yours: for code to be properly
modularized it is essentially important that every single piece of
code (class, method) has a particular purpose and does _one_ thing
well. This one thing can be even as complex as "managing lists of
items" (class Array does that) or "convert to an integer" (method
#to_i does that). But "managing lists of items and send them to
PostScript printers" would not be modular. Class Array would be
bloated with printer control code that most people do no need most of
the time. Plus, you change printing code and suddenly list management
needs to change as well which could have negative side effects on
other code using class Array. Keeping things focused not only helps
reuse but also understanding (if you need to maintain code someone
else wrote you will see what I mean).

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

From: Derek Cannon on
Thanks Jesus and Robert for your responses.

> You can even modularize it more by adding a method that will do the
> parsing and output a complete initialized CourseController.
> #initialize then might have an empty argument list or a different
> list. Of course I am speculating a bit here since I do not know your
> application case's details.

To be more specific with you:

In my program, I'm getting data from an HTML file row by row. Each row
has 20 columns, and each of those columns makes up one variable in the
Course class. I'm using an HTML/CSS/XML parser known as "Nokogiri".

In CourseController, I have 4 methods for parsing the HTML:

def count_rows
# Returns total number of rows (by counting how many <tr> tags there
are)
end

def get_row(row)
# Returns an array of 20 elements, each being a column from the
specified row
# This is mainly focused around the code:
@doc.css("tr:nth-child(#{row}) .dddefault").each { temp.push(e) }
return temp
end

def collect_courses
# Returns an array of arrays of courses. E.g.: [[course1,data,data],
[course2,data,data], etc...]
# (Works by using total row count (@row) and the get_row method for
each course)
return all_courses
end

def get_courses
# Returns an array of Course instances, where each instance is a
unique course.
all_courses = collect_courses
all_courses.each { |i| temp.push(i) }
returns temp
end

In the CourseController constructor, my code is as follows:

def initialize(url)
@doc = Nokogiri::HTML(open(url))
@row = count_rows
@courses = get_courses
end

How in this case do I improve my code to use the self.read_file and
self.read_url methods? I can't entirely see how this would work, and
what would change.

And are this many methods acceptable for parsing the HTML or is it
better if I merge them to make one, clean method?

-- Derek
--
Posted via http://www.ruby-forum.com/.

From: Derek Cannon on
> And are this many methods acceptable for parsing the HTML or is it
> better if I merge them to make one, clean method?

I guess I'm ultimately asking here: What should be the criteria for
creating something in a new method?

Because in this case, I could really just combine count_rows, get_row,
collect_courses, and get_courses... They're not being used for any other
purpose but to ultimately serve get_courses.

--
Posted via http://www.ruby-forum.com/.

From: Robert Dober on
On Sat, Apr 17, 2010 at 10:10 AM, Derek Cannon
<novellterminator(a)gmail.com> wrote:
>> And are this many methods acceptable for parsing the HTML or is it
>> better if I merge them to make one, clean method?
>
> I guess I'm ultimately asking here: What should be the criteria for
> creating something in a new method?
>
> Because in this case, I could really just combine count_rows, get_row,
> collect_courses, and get_courses... They're not being used for any other
> purpose but to ultimately serve get_courses.
>
Given that certain people (YHS included) consider methods of a length
of more than ~10 lines very bad[1] you will re-factor your "one clean
method". Given that most of these folks consider long classes (and/or
source files) a problem too (for me 300 lines is a pain, I prefer 100)
you will get lots of modules to be mixed in. Sometimes I find that
this kind of decomposition is a joy and leads to a very modular and
readable design, sometimes, I have to admit, code fragmentation
becomes a pain too[2]. I guess there is no answer for "ultimately
asked questions" (forgive the pun please).
HTH
R.

[1] except the long case statement, which I try to avoid for that very reason ;)
[2] but I am a very bad large systems engineer


--
The best way to predict the future is to invent it.
-- Alan Kay

From: Derek Cannon on
> Given that certain people (YHS included) consider methods of a length
> of more than ~10 lines very bad[1] you will re-factor your "one clean
> method". Given that most of these folks consider long classes (and/or
> source files) a problem too (for me 300 lines is a pain, I prefer 100)
> you will get lots of modules to be mixed in.

Thanks for the info. Based on what you've said on classes, do you think
I should create another class for comparing the classes? For example:
Course (to hold individual course data), CourseController (to hold the
instantiated Courses), and CourseComparer (to provide methods to
determine if courses overlap, courses are compatible, etc). Does this
sound like better OOP?
--
Posted via http://www.ruby-forum.com/.