Peter's blog

blog about computers, science, and computer science

RSS Feed

Old Notebook, New Ubuntu (12.04 LTS on Dell Inspiron 6400)

Comments Off

Hard drive on my 6 year old laptop finally died, and I’ve decided to not restore an old Windows XP installation, but to go ahead and try the Ubuntu, which I only used before either as servers or as specialized computers (like media players / internet stations / etc), where not much of desktop user experience was necessary. Now we are talking about my personal laptop, where I spend most of my time as a user/blogger/etc, not as a programmer (I have another computer for work).

The laptop is Dell Inspiron 6400 and it has been in heavy use all these years — this is second time I’ve replaced the hard drive. An old work horse.

I’ve picked up Ubuntu 12.04 LTS; although 11.04 LTS would probably make a better choice for hardware that old, but Ubuntu 13 was on the horizon, so I though, the newer the better… nevermind. There was one thing that doesn’t allow me to make a claim Ubuntu as “out of the box” solution for that Inspiron, and that’s the wireless card, which didn’t work right away. Everything else looked just fine.

The caveat: the Broadcom 802.11 STA driver suggested by Ubuntu just blocked the network card, and had to be removed. If you ever try to install Ubuntu 12.04 LTS on Inspiron 6400, don’t even try to go with this driver. Do the following instead:

sudo apt-get remove --purge bcmwl-kernel-source
sudo apt-get install firmware-b43-installer

Found this on some Ubuntu forum… and didn’t even bother to dig into the details. Apparently the new Broadcom driver was in conflict with another one pre-built with the kernel or something, so the old driver had to be removed and I’ve picked up a newer one. It worked right away, and I just left it alone.

I said before, I would be better off with 11.04 because it might be less demanding to the hardware… but maybe not. I’ve never looked into “official” h/w requirements, and they always mention just the necessary minimum. That notebook of mine is not the newest piece of hardware, so it becomes sluggish from time to time… mostly when heavy scripting environments become involved — and modern UN*X (Ubuntu and Mac included) are all about Python, Ruby, and of course Java. (Interestingly, wasn’t once wasting computer resources one of the main accusations toward Windows from UNIX people?)

And another thing. I’ve installed Eclipse with PHP support, configured it for XDebug, and it all worked like a charm. Well, almost… :) Had to link my project source to /opt/www, but that’s all.

Evolution is finally here. Linux for human beings, minimum configuration required, and it even can print to Windows network shared printer. (It appears, Windows 7 has severe problems with sharing printers, but this is totally different story…)

Ruby again: Sinatra and MVC discussion

Comments Off

Although Ruby is mostly famous for Ruby-on-Rails framework, it’s not the only one existing in Ruby world.

The tutorial I mentioned before suggests Sinatra as introduction to Web development on Ruby. I gladly went into the open door, and what have I discovered…

  1. Easy to install (just another Ruby gem, duh)
  2. Not total MVC, but separates views from the logic (see my opinion below)
  3. Can be easily (!) deployed with CGI (and I love the “easy” part above all) – no tricks, no configuration to mess up, no Apache modules

Now, who said MVC is a holy cow? After all, the separation between Controllers and Model is somewhat vague (which leads to designs like MVVC), while the separation between Views and the logic is essential. When I build my CodeIgniter sites (and CI is just a ”by the book” MVC), my Models are merely convenience wrappers around CI DB manipulation calls. On the other hand, MVVM and MVP patterns were born because some web apps are so DB-driven, that Controller functionality is reduced to View Model or Presenter or whatever they call it (it might be just another name to name the same thing, but it also points out that in many case generic Controller turns into something more specific and close to either the Model or the View). The bottom line it, the separation of Views is mandatory, and Sinatra provides it, and then you can play with your Models/Controllers/whatevers as it pleases you.

For the beginning, you just start your Web app with ruby <your-app-name>.rb, as if you would start a normal Ruby script. This would be your development web server. At some point, Sinatra will produce a message like this:

[2012-07-30 11:44:36] INFO  WEBrick::HTTPServer#start: pid=24851 port=4567

Now you can start some browser on local box, and go to localhost:4567 — it will display your Web app.

To stop your development server, hit Ctrl-C, and it will say:

^C
== Sinatra has ended his set (crowd applauds)

;)

You can start creating your Sinatra app like described here, but I personally would suggest you to just put together the script and the Views directory. (Simplicity, remember?)

The “Hello World” start

Let’s take a look… Eventually it’s going to be the “Borg Attack” game on the Web, hence all the names.

Here is the code:

require "sinatra"
require "erb"

module Borgattack
  get '/' do
    greeting = "Hello, World!"
    erb :index, :locals => {:greeting => greeting} 
  end
end

require “sinatra” — brings Sinatra framework, and takes care of all the web server / http stuff.

require “erb” — is for your page handling, templates etc. Higher level stuff.

Now, something that I hate: the name erb is cryptic. But after having “gems”, “bundles”, and “sinatra” itself, it’s not a big deal to complain about, indeed. :)

Here is something that I love though: that line

erb :index, :locals => {:greeting => greeting}

is easy, understandable, transparent by all means. We call that erb thing (whatever it is, it separates views from the logic), it should load the index with the dictionary of variables which are processed in your View (the latter is standard technique in CI, Django, ASP.NET — probably in in every Web development framework).

A View is a template. (Hmm, here is another prove the separation of Views is essential: templates became popular long before the MVC pattern. Ever heard of PHP Smarty?) And Sinatra Views templates have their syntax (template code comes almost entirely from Zed Shaw’s example):

<html>
  <head>
    <title>Star Trek -- Attack of the Borg</title>
  </head>
  <body>
    <% if greeting %>
      <p>I just wanted to say <em style="color: green; font-size: 2em;"><%= greeting %></em>.
    <% else %>
      <em>Hello</em>, world!
    <% end %>
  </body>
</html>

So, again, we have some typical template language inside HTML files. It’s standard technique, and therefore it’s easy! Zero learning curve! If you are familiar with this stuff in general, you can start developing web sites using this Sinatra thing almost immediately!

Handling Forms – easy!

Next cool thing in Sinatra: forms. They’re probably done in most elegant way in Sinatra than I’ve ever seen anywhere. Here is how it works:

  • define “get” method for the form => will show your form.
  • define “post” method => handles the submitted form. params dictionary handles the submitted parameters / filled-up fields

That’s it! OMG, literally — that’s it! You can do forms in Sinatra now!

E.g

  get '/hello' do
    erb :hello
  end

  post '/hello' do
    greet = params[:greet] || "Hello"
    name = params[:name] || "Nobody"
    erb :index, :locals => {:greeting => "#{greet}, #{name}"}
  end

So easy, so good!

You can concentrate now on the task at hand, rather than on “learning the framework” overhead.

Templates

Again, it’s really easy! Most simple websites use just one template for all pages. You just put another file to the Views directory, named layout.erb, and it will be picked up by default.

layout.erb code:

<html>
  <head>
    <title>Star Trek -- Attack of the Borg</title>
  </head>
  <body>
  <h1>Star Trek -- Attack of the Borg</h1>
  <%= yield %>
  </body>
</html>

Then you can strip down your pages of the header and footer part. E.g. your index page:

<p><a href="/hello">Say Hello</a></p>

<% if greeting %>
  <p>I just wanted to say <em style="color: green; font-size: 2em;"><%= greeting %></em>.
<% else %>
  <em>Hello</em>, world!
<% end %>

I have to admit, I’m totally ecstatic, indeed! The code appears to be much more concise than even I have in CI. You might seriously consider Sinatra for small, non-static website development. In other words, it seems to be a good competitor for CodeIgniter.

“We are solving really complex problems here!

Comments Off

O, complexity, the god of so many IT and R&D departments! Thou providest people job security, self-esteem, and sometimes very nice bonuses (that’s in the case of financial institutions).

Recently I’ve heard that a company I used to work for couple of years ago, conducted massive lay-off, closing whole departments which were working on “very complicated software”, with a whole “process” of SDLC and automated testing and a lot of other things… It wasn’t public company, all right, it had a private owner, and the owner just wondered at some point, what are all those people are doing, except of spending his money in a complicated economy like we have today.

I’ve been through projects with a lot of legacy code, and I’ve been starting projects from scratch, big and small projects, in companies big and small, on different platforms, OS’s, frameworks, etc. The same pattern persists everywhere: people just love to over-complicate technical problems.

People might have different motivation, of course: some just try to make their boss happy, others crave “universal” solutions, but the result is always the same: in couple of years, normal turn-over of human resources creates a situation when nobody really can understand what’s going on with a huge amount of code, databases, scripts, and so on.

Complexity is bad.

It’s very bad. It’s something that removes the substance and replaces it with a “process” of “figuring out” the substance (if any). Financial instruments called “derivatives”, all those CDOs and CMOs were way more more complex than stocks or commodities, and we all know what happened to banks which had built their businesses around those instruments. But reports those banks were presenting along the way were never bad. They were, well… complex.

There is another term for complexity in software world: we call some designs “over-engineered”. In many cases the over-engineering is caused by an attempt to make design more flexible, universal, and thus is becomes very configurable and flexible and customizable… but 90% of that customization is never used.

In other cases, excessive complexity comes to existence, when the original design wasn’t well thought through. This is actually the more “classic” scenario, described in all the smart software engineering books, and as such, it’s not seen too often in serious big projects.

And complexity is created by people. Same people also fail to figure out later on, what that complex solution is doing. Managing complexity has very little to do with computer science and even computer engineering. It’s 90% psychological problem.

Typically, engineers have good intentions. They want to get their job done really well. They are trying to foresee any scenario, anything that might go bad. That’s why they try to keep things flexible. And to keep it flexible, they need a dynamic object management, and some universal platform running their business logic, and some tools which are “industry standard” for that platform, and so on, and so forth… Sooner or later it leads to spaghetti code or spaghetti configuration, or (most likely) to both.

My bottom line is: first, the complexity is bad, and second, complexity is created by people.

Some Rules of Thumb

It’s probably not enough to proclaim the holy principles of DRY (Don’t Repeat Yourself), KISS (keep it simple, stupid!) and YAGNI (you ain’t gonna need it!). We are serious people, all right, engineers, programmers, we are educated and all this, so let’s take a look on some concrete recommendations:

1. Solve Only the Problem At Hand. Don’t try to solve the problems of the entire world. Don’t try to look too far in the future (well, unless this is part of your requirements, of course). Most businesses today are short-sighted, and so are their business needs. If you are late because of planning something for “tomorrow” — well, there might not be any “tomorrow” for your project.

2. Use Simple Programming Techniques. It’s quite simple, all right: it should be a good reason, to use complex over simple, custom over standard, and so on. If you want to use multi-threading, double-check whether you really need it. If you want to create additional interface or implementation, to derive another class, use another level of encapsulation — make sure it’s really necessary.

  • avoid multithreading, unless the task at hand requires it
  • avoid adding extra levels of indirection
  • avoid adding classes
  • avoid adding functionality, unless real business needs demand it
  • avoid creating another table in your database
  • avoid creating another field in your table
  • avoid… just anything! be lazy! minimize the amount of your code!

3. Keep Your Design Simple, Your Components — As Detached As Possible. Meaning, while solving task at hand, don’t forget that it might change, if your clients change their mind. You won’t have a problem to “refactor” your code at any moment, if it may be easily decomposed to smaller components.

4. Neither DRY, KISS, or YAGNI are absolute principles. The Great Dao of Laziness is. If you can make something small, concise, serving its exact purpose – do it. Most complicated designs with “future needs” in mind end up so complicated that they don’t work for those future needs either, and then the whole thing requires some huge re-factoring to be performed. Remember: impossible to see the future is! (C) Yoda

And the last, but not the least:

5. Think twice before using 3rd party component. Use it only if its learning curve is minimal.

And of course, if you have on your agenda something which is not simple, elegant, easily maintainable design — feel free to print a hard copy of this article and toss it to garbage.

On C++11

Comments Off

When you have a lot of work to do, you are typically trying to avoid unexpected factors in your code. That’s why I’m a bit behind on C++11.

Well, I used couple of new things, like the new meaning of auto keyword and unordered_map (instead of old hash_map), but that’s about it. So I’m finally taking a look on the new features of C++11 (formerly known as C++0x).

lambdas

There are so many good things to say about C++11. Let’s start with what I believe is the symbol of C++0x/C++11, which is the lambda functions/expressions.

vector<int> v={10,22,11,3,14,9,4};
sort(v.begin(), v.end(), [] (int x, int y) { return (x < y); } );
string delim = "";
for_each(v.begin(), v.end(), [&delim] (int x) { cout << delim << x; delim=", "; });
cout << endl;

BTW, I’m totally ecstatic that you can use the << operator with std::string now. (It’s been a pain saying s.c_str() every time.) Also, I find lambda functions a cute mechanism, which might improve productivity for those who knows they are doing… and create more potential for spaghetti code by programmers who, well, know a lot of language features. :)

Also, I’m finally going to take more use of the <algorithm> header. :) To be honest, I rarely used all those convenient algorithms just because it’s been a pain in the neck defining a functor every time.

decltype

Next nice feature: decltype is a logical continuation of the new meaning of auto keyword. You just grab the type you need, even without an assignment. It’s probably hard to come up with a real-world example of using it though…

default and deleted

In my humble opinion, these two new keywords are just syntactic sugar, and their only purpose is to replace empty functions and prohibiting members by making them private out of public. On the other hand, why not.

Finally!

No, it’s not a keyword. Finally we’ve got nullptr and constructors delegations (this is something I craved for a long time!)

Constructor delegation is, in simple words, ability to call one constructor from another. I wanted to have it for a long time.

nullptr helps to distinguish between foo(int x) and foo(char* x). And yes, it’s a big deal of difference.

 

These are some simple and nice features found in C++11. Next time I’ll try to take a look on rvalue references and move semantics. Since C++’s primary niche today is high-performance system design, move semantics (as opposite to copy semantics) sounds very promising.

Ruby Structures and Lieutenant Commander Data

Comments Off

Unlike C, structures in Ruby can be generated on the fly, and unlike Perl, they still will be different from the Dictionaries.

Indeed, we are dealing with a higher level language here. There is no reason to worry about bytes and bits and CPU cycles. It’s all about usability, simplicity, maintainability, and so on.

Ruby Approach to Structures

So the whole idea of structures being in fact dictionaries with predefined keys sounds just right. After all, we access structure fields (as well as class data members) by name, so why should it be different than just a dictionary? On the other hand, when you deal with a structured data, you want some sort of predictability, in other words you want to know what kind of fields your data object might contain.

Here is Ruby approach:

#
# Struct is some sort of Class generator. It generates classes, and classes
# generate instances/objects. Very OO!
#
PersonData = Struct.new (:firstname, :lastname, :address, :zip)

#
# Now PersonData can instantiate an object / an instance of PersonData class:
#
joe = PersonData.new ("Joe", "Schmo", "12345 Bedford Avenue, Brooklyn, New York, NY", 11211)

Doin’ It On-the-Fly

We call Ruby or Pythonscripting languages just because they are interpreters. But thanks to JIT and similar techniques, the border between strictly compiled and strictly interpreted languages is fading. C/C++ are strictly compiled languages, but how about Java and C#? They use JIT technology, and apply some optimizations in run time. PHP, Python, Perl? Pre-compiling the code behind the scenes.

See, the reality is that computers are still getting faster, and they are already fast enough so the difference between “script” and native binary wouldn’t really matter for many applications. And interpreted languages have one distinctive advantage compiled languages have not:

 

A program written in interpreted language
can re-program itself.

 

That’s why the structures in Ruby can be defined during run time. Java’s and C#’s reflection (or whatever it’s called) is just a baby step toward self-programming programs. In C# or say Python the program can write a source file and compile/load it. Ruby takes some further steps in this direction: a program can define its own data structures. It can become adaptive to environment.

Of course, anything done in interpreted language can be done in compiled language too… it’s just much harder to do. On the other hand, an interpreted language with built-in abilities to do most of it work in run time (load modules, define data structures etc) is leading the way to programs which write other programs…

In this part we should start speculating whether robots will turn on humans some day… but of course they will. They are built to.

I guess, the question is, will a machine built and programmed as “good” turn on humans some day… I bet it won’t. There is a limit to self-programming flexibility of any program. Hell, there are some limits to what certain living person is capable of doing, and it depends a great deal on programming, i.e. education and social environment.

Simplicity

As I said before, when we can manage complex mechanisms simpler way, there is more potential for effectively handling more complex problems. In other words, there are more chances of ever implementing Lieutenant Commander Data in Ruby than in C.

Let’s C… oops, let’s see:

Data can reprogram his own code. You can do it in Ruby much easier than in C. Running Ruby program means, you have Ruby interpreter on the same machine, which means you can compile modules on the fly. Running compiled C program means nothing.

Data can learn new categories and even new abstractions. In Ruby, you can define new structures in run time, and it’s native in the language. In C you just can’t do that. In C++ (and also in C#, Perl, etc) you can imitate the idea of dynamic structures with hashes and dictionaries, but again, it’s a lower level of abstraction, Ruby makes it easier.

Data can run self-diagnostics. Ruby modules easy to be tested and fixed one by one; go and do it with a system written in C or C++.

Well, you’re getting the idea. ;)

Back to the real world… Lessons 48 and 49 of Zed Shaw’s book show how to build a simple language parser in Ruby. I hope there is some good NLP library out there. Just google Ruby NLP… Also, depending on how complicated the problem is, you might try integrating libraries written in other languages.

Filed under Scripting

Unit Testing

Comments Off

I went through the exercise, hoping to find something new about unit testing, some unique Ruby approach, perhaps. Well, I’ve figured out the suggested directory structure is the one you use for any Ruby Gem, so it’s always good to have some standard thing around.

When you deal with simple modules it’s always good to have some small unit testing routines around. But if your module is just a little bit not trivial, or if you want to integrate several modules together, a separate project would be useful. In fact, sometimes you end up building sort of project inside project.

So it’s nothing really new about unit testing, but the fact it becomes standard part of Ruby library. I can’t think of any other language standardizing software engineering practices, definitely not QA practices (because, frankly, who care about such a boring thing as testing?)

There was something similar in Python, when you could have a routine (sic! a routine, not a project) inside your Python module, under

if __name__ == "__main__":
    do_your_stuff()

but it’s not really the same. I’m not really familiar with Python Eggs (which are supposed to be the same as Ruby Gems or Perl packages), which probably should have some unit testing standard of their own, but it seems the Eggs gained much less popularity than Ruby Gems.

With Perl CPAN modules, adding test scripts is considered a good habit, but it doesn’t seem to be standardized with nice directory structures etc.

The bottom line is: it’s not even the language itself, but I like the way Ruby community is doing things. It’s implying better software engineering practices, which will naturally lead to larger base of well-tested modules and components, which will inevitably lead to language popularity.

It looks like Rake is relying on the Gem unit testing, too. Rake is something I still have to learn about; the whole idea of having a substitute to standard Make looks strange to me — but on the other hand, smarter language-specific Make aware of packaging and unit testing for this language, should be really cool.

The last but not the least about Ruby test/unit package: it has everything you want to run your unit tests. It runs all your test cases automatically, no need to write a main function; it counts the time it took to pass the tests, it tells you how many of them failed with errors, and so on.

peter@ubuntu01:~/ruby/automated-testing$ test/test_automated-testing.rb
Run options:

# Running tests:

...

Finished tests in 0.000599s, 5009.6017 tests/s, 11689.0707 assertions/s.

3 tests, 7 assertions, 0 failures, 0 errors, 0 skips
peter@ubuntu01:~/ruby/automated-testing$

Sounds like Ruby provides you not just the language, but also the best imaginable framework for libraries and unit testing and make and everything. Tell you what, I’m going to examine Ruby modules (gems or whatever) for networking (pretty sure they are there), GUI (depends, and they might be platform-dependent too), multithreading and IPC, etc… It quite may be I will discover an all-purpose development platform, not just Rails for Web apps.

Will keep blogging on it, too!

Project Skeleton Script

Comments Off

So I accepted the challenge and made my own “game”, just as an exercise. You can find it on the Github under https://github.com/peter1st/learning-ruby. Besides, I’ve started to finally use Github. :)

Now, let’s move on.

This page left me really excited: it gives you in a nutshell an idea of how you build a Gem.

By the way, Perl script parsing this stuff and changing NAME to the actual project name would come handy here, he-he… You can do it with Ruby, you say? Of course you can… but with Perl it’s probably much easier… Hey, wait a second. Why not a Perl script which is copying the whole directory structure, changing the directories/files names as well as strings inside the file.

Here you go then: build-from-skeleton script in my github repo. Enjoy.

I’m not going to dig now into gems and how I build them (will figure it out when I’m going to build one), but the rest of the book seems to be dedicated to the following topics:

  • automated testing in Ruby (Wow!)
  • advanced parsing (another Wow!)
  • web applications – using a framework called Sinatra, and not Rails as one (including myself) might think

Started to read Exercise 47… The automated testing lesson reminds me of nethack — the game we used to play when Unix terminals were more commonly available than X-windows, and Linus Torvalds still hadn’t written first kernel of Linux. :) Today is too late, but I’m definitely looking for it tomorrow.

 

Learning Ruby (still cont’d)

Comments Off

Now, let’s take a closer look to the real things…

OOP in Ruby

First of all, it’s good to have the ri utility. You type

ri Class

and you get a lot of explanations about OO stuff in Ruby. (if you type lowercase class, it will describe the .class property of an object.)

Let’s take a look on that info ri Class returns:

-------------------------------------------------- Class: Class < Module
     Classes in Ruby are first-class objects---each is an instance of
     class +Class+.

     When a new class is created (typically using +class Name ... end+),
     an object of type +Class+ is created and assigned to a global
     constant (+Name+ in this case). When +Name.new+ is called to create
     a new object, the +new+ method in +Class+ is run by default. This
     can be demonstrated by overriding +new+ in +Class+:

        class Class
           alias oldNew  new
           def new(*args)
             print "Creating a new ", self.name, "\n"
             oldNew(*args)
           end
         end

         class Name
         end

         n = Name.new

     _produces:_

        Creating a new Name

The first awesome thing that we can see right here is what seems to be the new overloading. However, I doubt it somehow. Maybe it’s just a clumsy way to write class’ constructor?

Doing a bit of googling, and voila: constructor in Ruby is called initialize() method. Base class can be referred as super — good, that’s OO classics.

Apparently, new overloading is indeed new overloading. It allows you to fake creation of an object, which might depend on new arguments… wait, wait, wait… this thing has a name, and this is an OO feature that doesn’t exist in C++… this, my friends, is VIRTUAL CONSTRUCTOR!!!

Oh my God…

I don’t know whether this is Mr. Matsumoto creation (that’s the guy who created Ruby), or a later one, but I don’t care either. This is absolutely genius thing. Love it. You maybe can live without it, but it come very handy, say, in de-serialization, when you need to re-create the object, but you don’t know which one it would be.

Unless I got it all wrong, it seems that Ruby brings to the table something I’ve never seen in any other programming language. Lovely, lovely thing!

What’s not totally clear to me (yet) is the relationship between Object, Class, and Module. Object seems to be the top super-class of all classes; it’s just the name which is confusing me, probably because of my C++ background. Apparently, in Ruby class instance is not called Object; this name is reserved for the top class.

Built-in Data Structures

Man, data structures ARE important.

I’ve seen so many people who cannot tell the actual difference between an array and a list… not even with hints.

Ok, so I’ve just learned that Ruby has Arrays and Hashes. Arrays are indexed and Hashes have keys. (Perl philosophy, again.) And you can use tags, again, like in Perl — there is only syntactic difference. All straightforward, clear, easy — love it.

What escapes me though is the question mark (?) operator. Maybe I was going too fast through the book, and missed the explanation. Let’s ask my friend Google… wow. It’s just part of the method name. The convention is to put ? at the end of the name of a method which returns boolean. Sort of asking question: is_a? respond_to? kind_of? Quite elegant idea.

Pointers to functions — just like in C

Back to Zed Shaw’s site / book.

Lesson #40 contains an interesting example:

cities = {'CA' => 'San Francisco',
  'MI' => 'Detroit',
  'FL' => 'Jacksonville'}

cities['NY'] = 'New York'
cities['OR'] = 'Portland'

def find_city(map, state)
  if map.include? state
    return map[state]
  else
    return "Not found."
  end
end

# ok pay attention!
cities[:find] = method(:find_city)

while true
  print "State? (ENTER to quit) "
  state = gets.chomp

  break if state.empty?

  # this line is the most important ever! study!
  puts cities[:find].call(cities, state)
end

cities is our little in-memory database of cities. But unlike strongly-typed languages (C, C++, C#), this container (the hash) might contain totally unrelated pieces of data, while the data is of different types and the keys are of different types and so on.

The code on the line 17 (just below the “pay attention” remark) is placing into the hash a new piece of data: pointer to the find_city method. It’s stored now under the key :find (it could be called :finding_method or :boo or whatever).

You are more than welcome to review this example which demonstrates the usage of method pointers (or whatever they are called in Ruby), and which is a cool game, too. :)

Due to examples it was another long post, I guess…

Filed under Scripting

Learning Ruby (cont’d)

Comments Off

So, Learning Ruby the Hard Way is apparently quite a useful site. It’s written for absolute beginners, and I”ll try to finish it today, but this is not the point. The author is obviously familiar with bunch of other programming languages, and most examples he’s bringing to reader’s attention are easy to remember as references to Python, C, etc.

E.g. “the syntax of function declarations is Python-ish”, while “file operations are C-ish”, with read and seek etc. And require is PHP-ish. Sort of mishmash, I’d better not confuse which keyword was taken from which language… :)

Syntax of functions return values is somewhat not obvious though. Old good return would probably do better… but it’s probably easier for new programming students.

So far I’ve learned Ruby supports the concept of modules. Not sure whether this is the only way to do OO in Ruby, but I wouldn’t be surprised. Let’s not rush into conclusions though.

Reading the code

Another lovely thing about that site / book: it’s teaching to read Ruby code. At least it give you couple of exercises on that. This is very useful for beginners, but experts should probably do it from time to time, too. From my experience, many years ago, this was quite hard for us new grads: we knew how to write code, but not really how to read it. It took some experience. Reading your own code is not the same.

Now, this might sound really stupid. Beginners’ katas in martial arts might seem stupid, too.

And the last but not the least, Mr Zed A. Shaw (the author of that book) is calling me a good programmer.

A good programmer assumes, like a good scientist, that there’s always some probability their code is wrong. Good programmers start from the premise that their software is broken and then work to rule out all possible ways it could be wrong before finally admitting that maybe it really is the other guy’s code.

Thank you Zed!

And you, managers and business people — don’t you confuse professionalism with lack of self-confidence! :)

Back to Ruby

It just escapes me why scripting people dislike STL-style names for list/array manipulation.

push_back/push_front, pop_back/pop_front – are clear, uniform, easy to remember.

push / pop are better; but shift / unshift seem to be originated from Perl’s shift. If you don’t have any previous background… well, who cares indeed.

Ok, I made it through the first half of this book.

Coding the logic: IF-statements

The syntax of logic statements is very concise: no {}, not then‘s, no Python-style colons (the latter, with all due respect to Python, is a bit weird). Reverse if‘s are also possible — it’s Perl feature, and I love it. Same with elsif. These small things actually make you coding faster.

Coding the logic: loops

First, I love for-loop with foreach semantics. It’s just natural. Shame C/C++ doesn’t have it (yea, new release, C++0x/11, I know).

Second, I love the idea of blocks, and this is entirely Ruby idea, for the best of my knowledge.

tools = ['hammer', 'saw', 'drill']
tools.each do |tool|
  puts "My tool: #{tool}"
end

It resembles C# idea of Enumerables; although Ruby was created first from chronological perspective, most of us, I assume, have heard of C# before we’ve heard of Ruby.

Anyway, I could also say:

for tool in tools
  puts "My tool: #{tool}"
end

and the effect would be the same.

for over arrays and while loop are trivial => easy to remember.

Oops’es

No equivalent to Pearl’s die function in Ruby? What is this Process.exit(0) javabberish?! :(

to_i() – oh my God, this is just a joke! why not to_int()?!

prompt is not exactly designed for programmers productivity… Fortunately, there are good Ruby libraries which allow you writing:

require "highline/import"
input = ask "Input text: "
puts "You entered the following text: "+input

Ah, this is better!

If the above didn’t work, you probably need to install appropriate library — and this is Perl-ish way, again:

sudo gem1.9.1 install highline

or just

sudo gem install highline

depending on your version (I have both 1.8 and 1.9 installed).

I should take a better look on that Highline library, ’cause it’s about saving time, and that’s exactly my intention.

Debugging

Mr. Zed A. Shaw is writing:

Tips For Debugging

  1. Do not use a “debugger”. A debugger is like doing a full-body scan on a sick person. You do not get any specific useful information, and you find a whole lot of information that doesn’t help and is just confusing.
  2. The best way to debug a program is to use puts or p to print out the values of variables at points in the program to see where they go wrong.
  3. Make sure parts of your programs work as you work on them. Do not write massive files of code before you try to run them. Code a little, run a little, fix a little.

Now, this is really pissing me off. I’ve met programmers who claimed to do all the debugging “by printf’s”. Apparently (and I’m talking from experience) those people never handled really large and/or complicated projects. As a matter of fact, this approach failed big time in my previous firm, while more sane approach prevailed: use debugger and debug prints when appropriate.

I realize that the target audience of the book in discussion is not exactly people like myself… but still — please. :)

Ok, this posting is growing too long.

Filed under Scripting

Learning Ruby

Comments Off

Giving a try to two Ruby tutorials: Learning Ruby the Hard Way and the Pragmatic Programmer Guide.

Just giving it a try. Hope to know the language in a week or so at least on the same level I know Python. Maybe even more — after all, I used Python primarily for research-style data analysis…

My ultimate goal here is to understand Ruby and RoR good enough to make my opinion on it. I’ve been told that RoR is extremely good for rapid website development (maybe even better than Django)… we’ll see.

After I’m done with Ruby, I’m going to learn jQuery quite seriously. The goal is the same: rapid website development. I have my coding abilities and can do anything on the server side, but right tool (rather libraries) for the front-end is still under question.

In parallel I’m working on some VB scripts and ASP.NET (rotten tomatoes in the air). That’s for business, rather than for pleasure. :) I doubt I will ever consider Microsoft tools seriously for my own websites though… for magnitude of reasons. :)