Missing Something

I am an amateur programmer, and I feel I am missing something. Whenever
I’ve tried to understand certain aspects of programming, I often feel I
am just “missing something.” And most instruction doesn’t help (usually
because of overly clever examples… like: Okay class, today we are
talking about classes. So we’ll use this class as an example. We’ll
create a “class” called “class” and since classes have members we’ll
create a member for each member of the class. Then we’ll create a
variable in the class called “class” where we’ll store how classy
everyone in the class is. Now… how many of you wear glasses?)

I really just want my programs to DO SOMETHING. And I am trying to
develop a sort of automated analog synthesizer that works with files in
the .wav format. So my question is… what is WRONG with something like
this?

#! usr/bin/env ruby
require ‘wavefile’
include Math

frames = (ARGV[0].to_f * 44100.0).to_i
volume = ARGV[1].to_f
freq = 44100.0 / (ARGV[2].to_f)
file = ARGV[3]
w = WaveFile.new(1, 44100, 16)

(0…frames).each do
|frame|
w.sample_data[frame] = sin(frame * 2.0 * PI / freq) * volume * 32767
end

w.save(file)

The code looks good, as a one-off quick-n-dirty get it done script
If this is going to be used by others, and possibly re-used as part of a
larger app
than you have to think of how easy is it to integrate, and how easy is
it
to change?

Some things to consider:
How is a user to know/learn what options are required/valid when running
the command?

What if you decide to add a GUI?

What if you wanted to process more than 1 file?

Thanks, Chris! I have spent time thinking about ALL of those things.
Your questions hit at the heart of the problem, and they hit me all at
once, all the time, and I don’t even know where to begin. This is a very
simple version of what I am doing. I have much more functionality in
other versions.

You hit the nail on the head with the first question. I never know when
to export details to functions. I never know when to bundle functions
into classes. I can’t even begin to imagine how I would do things like
modules or who knows what.

I have a help file that keys off of --help -h -? as an argument. That is
usually in there before the requires and includes.

if (ARGV[0…3] == “–help”)
print “bleah… bleah… bleah…”
exit 0
end

That’s for if I want the end product to be CLI and scripty. It would
work off of a file of some sort (.yaml) to feed in data.

The GUI option is fun, but unnecessary for what I want to do now. I
suppose I would try to link it all up with Shoes?

The “processing” more than one file question hits the heart of the
matter. First of all, this creates a file. The processing of files is a
whole separate thing (in my way of viewing this). I want the final thing
to be working on dozens, if not hundreds and thousands of objects. And
that’s where the “object orientation,” “classes,” “methods” and all that
enters in and it’s where I get lost. It’s all so arbitrary. I can define
anything to be anything. And the more I do, the more ideas I get until I
end up with a great big jumble that falls off the rails.

All of the stuff out there (the help stuff) is operating on
presumptions… unstated presumptions about what a User is trying to do.
I always get to this point and get lost, hopelessly lost. Thanks for
responding.

Am 19.11.2012 17:05, schrieb Chris H.:

What if you decide to add a GUI?

What if you wanted to process more than 1 file?

and:

What if you wanted to add functionality?

What if you wanted to parse and validate command line options?

What if you wanted to add tests for parts of your code?

But: for really simple tasks I would have no problem with
a script like yours.

Jesus -

You know exactly what I am getting at. Thank you for the reply. I will
keep slogging away and hoping it gets easier. I am glad to have
confirmation for what I suspected: That it is possible for a program to
organically develop out of a linear sort of stack-oriented approach. I
still don’t see the advantage to bundling methods with objects. I guess
I still think Commodore 64 style! I don’t see why I shouldn’t keep
methods and objects separate is what I am saying. Methods as functions
and objects as collections of arrays.

I am always doing things the hard way, knowing there is an easier way,
but not quite knowing what the easier way is.

I’ll answer a few of your questions, if you’re curious…

@w = WaveFile.new(1, 44100, 16) # don’t know what these numbers mean

1 - means “mono” or one channel.
44100 - is 44,100 frames per second (that’s the rate of a Compact Disc)
16 - is for 16 bit.

A .wav file is like a bitmap, it’s uncompressed. So they’re HUGE.
Basically, the file tells a speaker where to be 44,100 times a second to
an accuracy of 16 bits. The resting position of the speaker is 0. Fully
out is 32768 and fully in is 32767. A speaker is basically an air pump.

That’s it. Sound is really simple.

Later, for processing, you might have several different processing
algorithms (I have absolutely no clue about sound processing). You can
create a class for each processing:

That’s where things are slightly difficult. It is hard to distinguish
between what is processing, what is filtering and what is generating.
It’s all arbitrary, actually. The great thing about doing this in
software is that it’s all just moving numbers around. No wires, no
circuit boards, no keys, nothing. It’s very pure in a way. So, one is
always torn between what makes sense in the abstract, and what is
familiar to the end user.

Thank you for your attention and code samples, Jesus. I think this will
really help me organize my thinking.

  • Ron

Am 19.11.2012 19:26, schrieb Ron S.:

Jesus -

You know exactly what I am getting at. Thank you for the reply. I will
keep slogging away and hoping it gets easier. I am glad to have
confirmation for what I suspected: That it is possible for a program to
organically develop out of a linear sort of stack-oriented approach. I

Growing and restructuring / refactoring is the normal way.

still don’t see the advantage to bundling methods with objects. I guess
I still think Commodore 64 style! I don’t see why I shouldn’t keep
methods and objects separate is what I am saying. Methods as functions
and objects as collections of arrays.

One advantage: try working with functions that depend on half a dozen
of parameters (and need to be called with half a dozen of arguments)
and compare with a method that can simply use the instance variables.

[…]

Tip: for a nicer and more robust way to handle command line options
have a look at the OptionParser class.

On Mon, Nov 19, 2012 at 7:26 PM, Ron S. [email protected] wrote:

Jesus -

You know exactly what I am getting at. Thank you for the reply. I will
keep slogging away and hoping it gets easier. I am glad to have
confirmation for what I suspected: That it is possible for a program to
organically develop out of a linear sort of stack-oriented approach. I
still don’t see the advantage to bundling methods with objects.

Some interesting concepts about object orientation are among other
encapsulation and reusability.
If you build an object with a clean interface, the clients of the
object can forget about the internal implementation.
The advantages of this is that everything from the outside is easier,
and you are free to change the implementation without the external
code noticing (or failing).

When you have these objects with a defined behaviour and a clean
interface, they can be reused in scenarios that not even you
anticipated when you created them, and this is huge.

You should also read about the SOLID design principles and clean code,
which can be summarized with: a good design is one that is easy to
change.

Tomorrow, when you have to change some logic in your code or add some
behaviour, you would prefer that everything is in a single place, in
the expected place. You use a class, extend it or whatever in a
simple way and “magically” you have changed your software. All or most
of the SOLID principles involve removing duplication: when you have
the same code in two different places, the risks are huge. If you need
to change that piece of logic, you might forget one of the two (or
many) places, leading to bugs. Objects help with this thanks to the
encapsulation and reusability they provide.

I guess
I still think Commodore 64 style! I don’t see why I shouldn’t keep
methods and objects separate is what I am saying. Methods as functions
and objects as collections of arrays.

If the functions operate over a set of data, it’s better to have them
bundled with the data as a unit, it’s easier to reason about it,
change implementation, extract common behaviour with other parts of
the code, etc, etc.

I am always doing things the hard way, knowing there is an easier way,
but not quite knowing what the easier way is.

Well, don’t despair. These things take experience. It’s important to
read about this topics, and to see other’s code. A book that I liked a
lot was Clean Code from Robert C. Martin.

an accuracy of 16 bits. The resting position of the speaker is 0. Fully
out is 32768 and fully in is 32767. A speaker is basically an air pump.

That’s it. Sound is really simple.

Yep, sounds simple (pun intended)

familiar to the end user.
The idea is that you create object that represents the concepts that
are in your domain: a filter chain composed of filters (two classes),
a generating algorithm (a factory object), transformations, etc.

Thank you for your attention and code samples, Jesus. I think this will
really help me organize my thinking.

Keep at it, and read about object oriented concepts, there are good
articles and books out there.

Jesus.

On Mon, Nov 19, 2012 at 5:27 PM, Ron S. [email protected] wrote:

The “processing” more than one file question hits the heart of the
matter. First of all, this creates a file. The processing of files is a
whole separate thing (in my way of viewing this). I want the final thing
to be working on dozens, if not hundreds and thousands of objects. And
that’s where the “object orientation,” “classes,” “methods” and all that
enters in and it’s where I get lost. It’s all so arbitrary. I can define
anything to be anything. And the more I do, the more ideas I get until I
end up with a great big jumble that falls off the rails.

I think you should go step by step, little by little. Adding
functionality and looking for opportunities to reuse code. For
example, if you want to generate a file, and the process it, you can
start by defining a class that represents the file, so that you can
create such object and pass it around. Then you start thinking what
things can be responsibility of that class, things that you would tell
it to do, for example: save yourself in the filesystem. Create a
method for that. If you start this way, you will find yourself with
little reusable things that you can compose to perform more and more
complex logic.

For example:

class MyWaveFile
def initialize frames, frequency, volume, file_name
@frames, @frequency, @volume, @file_name = frames, frequency,
volume, file_name
@w = WaveFile.new(1, 44100, 16) # don’t know what these numbers mean
generate_samples
end

def generate_samples
(0…@frames).each do |frame|
@w.sample_data[frame] = sin(frame * 2.0 * PI / @freq) * @volume *
32767
end

def save
@w.save @file_name
end
end

Now you can:

wave_file = MyWaveFile.new frames, frequency, volume, file
wave_file.save

Later, for processing, you might have several different processing
algorithms (I have absolutely no clue about sound processing). You can
create a class for each processing:

class XProcessing
end
clas YProcessing
end

and apply the processings in order or whatever, passing your wave_file
around:

wave_file = MyWaveFile.new frames, frequency, volume, file
XProcessing.new.process wave_file
wave_file.save

If, for example, you see duplicated code in all processing classes,
try to extract it to a common class (for example, a parent class of
all processings). This way, reducing duplication, you end up with a
design for your system.

It’s difficult at the beggining, and depending on the domains can be
quite complex, but keep working at it and you’ll see that it gets
easier and easier.

Good luck !

Jesus.

Thank you so much, Jesus! You given me more practical advice AND theory
in a few posts than I’ve gotten from dozens of sites! And now the sites
are starting to make sense to boot. You’ve been a great help. Many
blessings on your house!

unknown wrote in post #1085232:

One advantage: try working with functions that depend on half a dozen
of parameters (and need to be called with half a dozen of arguments)
and compare with a method that can simply use the instance variables.

I am already there! It’s amazing how quickly the parameters list grows.
Then I realize that I could use fewer parameters, but have to repeat
code-snippets (let’s say you have parameters: x, y, z… but z is (10 *
x / y). You could pass z or just pass x and y but then you would have to
pepper the method with 10 * x / y all over the place.) What I do is pass
as few parameters as possible, and have local variables defined in the
method.

Tip: for a nicer and more robust way to handle command line options
have a look at the OptionParser class.

That is a built-in?

Thank you for replying Unknown!

Am 21.11.2012 13:23, schrieb Ron S.:

Tip: for a nicer and more robust way to handle command line options
have a look at the OptionParser class.

That is a built-in?

Yes, it is, see

http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html

You won’t have to install a gem.

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