Approximity blog home
267 to 286 of 597 articles InfoSyndicate: full/short

Zen Refactoring   24 May 05
[print link all ]
Alex Chaffee posted this to the xp-list.
 Yesterday I was pairing with Patrick, our new intern. He's great,
 smart as a whip, and willing to learn. (When I told him we write tests
 first, he laughed, incredulously, but then I said No, really, I'm
 actually serious, and he listened, and later, he said, Oh, now I see.)
 At the end of a long successful refactoring (turning a clutch of
 static methods into instance methods), we were sort of buzzing and
 didn't want to stop, were casting about for other refactorings to do
 in the same class. I suggested a technique I only just then gave a
 name to, that I've done occasionally on my own for a long time, but
 hadn't yet taught: Zen Refactoring.

 "Just let your eyes unfocus and scroll through the code and look for
 refactorings. Look for duplication; look for too-long or
 too-deeply-indented code blocks. When you notice something odd, don't
 read it, just select it, hit Extract Method (ctl-alt-M), and hit
 random keys for the name. Then focus your eyes again and see what
 you've done."

 I demonstrated. The first time we hit a bunch of print statements with
 repeated formatting -- it worked, but the refactoring was tedious,
 with marginal payoff. But the second time was golden. I saw a blurry
 if-else block; the first arm meandered for 15 or 20 deeply-indented
 lines, the second for fewer; their logic appeared opaque and disjoint.
 But after extracting the first block as a method, lo and behold:

 if (something() || other()) {
  customerId = sdlfjds(x, y, z);
  } else {
    user = someOtherExistingMethod();
    customerId = user.getUserId();
 }

 IDEA had figured out that the result of that meander was a single
 value, and returned it from the new method. It was instantly clear
 that we should rename the extracted method
 customerIdForSomethingOrOther", and extract the whole conditional as
 "getCustomerId". Shift-F6, ctl-alt-M, high five.

 Then it was Patrick's turn. Not quite as much of a slam-dunk but still
 a worthy refactoring. I can't wait to get an incredulous laugh from
 the next one I spring this on...

AutrijusRaisingPerl6IntoARealPuppy   18 May 05
[print link all ]
Perl6 in Haskell after 100 days .. :-) Enjoy the link redhanded.hobix.com/inspect/autrijusRaisingPerl6IntoARealPuppy.html

When talking to CEO and CFO types ..   16 May 05
[print link all ]
Ron Jeffries posted in the xp-list:
 When I talk with CEO and CFO types, I generally emphasize that XP /
 Agile projects focus on the delivery of running, tested, actual
 software, along the lines of my article /A Metric Leading to
 Agility/, http://www.xprogramming.com/xpmag/jatRtsMetric.htm

Good article about Tiger   08 May 05
[print link all ]
My girlfriend told me to get a computer that makes less noise .. so I took the opportunity to buy a Mac-Mini and to have a nice computer to play with :-).

Thanks to Sven for emailing me this link .. a good overview article about Tiger. arstechnica.com/reviews/os/macosx-10.4.ars

Nice graphics   06 May 05
[print link all ]
Joao made this nice graphics and posted it in his blog

Link of the day   04 May 05
[print link all ]
links.userfriendly.org/lotd/http://www.delltechforce.com/

Die Larry Ellison Puppe k?mpft gegen "Big Iron" und sagt "Let’s go in and kick some proprietory ass!"

ROTFL

Sin City Comic-to-Screen Comoparison   24 Apr 05
[print link all ]
Very nice link about a cool movie.

Seeing Metaclasses Clearly   19 Apr 05
[print link all ]
why wrote a nice article.
 I've written a very nuts+bolts article on metaclasses (aka virtual
 classes or metaobjects), since they still lurk under a shroud of fear
 and enigma.

whytheluckystiff.net/articles/seeingMetaclassesClearly.html

 I'm hoping this will help uncover the truth.  If anything is unclear,
 please report it.  Shed a light.

Collaborative Corporate Culture   19 Apr 05
[print link all ]
home.att.net/~geoffrey.slinker/maverick/CCC.html

300 engineers take forever writing anything   19 Apr 05
[print link all ]
Nice post by Elizabeth D. Rather
 Heh, that reminds me of a time in the late 70's, when IBM came out with a
 new "mini-computer".  We put Forth on it for a customer.  Our standard
 system came with a database capability, multitasker, multi-user support,
 lots of other features.  Another customer was considering this machine, and
 we made a presentation on our software.  Some IBM engineers were also there.
 They said, "This machine has only been on the market for a few months.  We
 have 300 engineers writing software for it in Boca Raton (Florida), and they
 only have a macro assembler and simple executive running so far.  How could
 you have done all this with only one engineer?"

 Well, I said something about having a standard design implemented in high
 level that was easy to port, but of course the real answer is that 300
 engineers would take forever writing anything!

Enterprise software   11 Apr 05
[print link all ]
Software development and software buying in big companies can be rather sick. This is a nice report about the madness in a common enterprise. link

I think I have to read my daily Dilbert now, before making yet another Powerpoint presentation for work, instead of fixing my bugs.

wee: More novel than popular   30 Mar 05
[print link all ]
Avi posted a nice entry about seaside, rails and wee.
 Rails ... doesn't have any novel ideas. I'm not
 trying to talk it down, that's just the reality of what
 Rails is -- it's not Seaside or Wee (and if it was it
 wouldn't be so popular anyway).

*More novel than popular; I can live with that.*

Making videos to show off your latest software   28 Mar 05
[print link all ]
xvidcap is a great tool to to capture things going on on an X-Windows display to either individual frames or an MPEG video.

A big thanks to Michael Neumann who pointed out this too to me. He made his great wee-videos with xvidcap.

Packet sniffing and replay   27 Mar 05
[print link all ]
I just came across this most useful ksnuffle. It will help us to automate some more work.

RubyScript2Exe 0.3.3 is released!   26 Mar 05
[print link all ]
RubyScript2Exe transforms your Ruby script into a standalone, compressed Windows, Linux or Max OS X (Darwin) executable. You can look at it as a "compiler". Not in the sense of a source-code-to-byte-code compiler, but as a "collector", for it collects all necessary files to run your script on an other machine: the Ruby script, the Ruby interpreter and the Ruby runtime library (stripped down for this script). Anyway, the result is the same: a standalone executable (application.exe). And that’s what we want!

gegroet, Erik V.

link

Rake 0.5.0 Released   26 Mar 05
[print link all ]
It has been a long time in coming, but we finally have a new version of Rake available.

Changes

  • Fixed bug where missing intermediate file dependencies could cause an abort with —trace or —dry-run. (Brian Chandler)
  • Recursive rules are now supported (Tilman Sauerbeck).
  • Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck).
  • Added warning option for the Test Task (requested by Eric Hodel).
  • The jamis rdoc template is only used if it exists.
  • Added fix for Ruby 1.8.2 test/unit and rails problem.
  • Added contributed rake man file. (Jani Monoses)
  • Fixed documentation that was lacking the Rake module name (Tilman Sauerbeck).

What is Rake

Rake is a build tool similar to the make program in many ways. But instead of cryptic make recipes, Rake uses standard Ruby code to declare tasks and dependencies. You have the full power of a modern scripting language built right into your build tool.

Availability

The easiest way to get and install rake is via RubyGems

  gem install rake    (you may need root/admin privileges)

Otherwise, you can get it from the more traditional places:

Home Page:rake.rubyforge.org/
Download:rubyforge.org/project/showfiles.php?group_id=50

Thanks

Lots of people provided input to this release. Thanks to Tilman Sauerbeck for numerous patches, documentation fixes and suggestions. And for also pushing me to get this release out. Also, thanks to Brian Chandler for the finding and fixing —trace/dry-run fix. That was an obscure bug. Also to Eric Hodel for some good suggestions.

— Jim Weirich

.. that sounds like real life   13 Mar 05
[print link all ]
I was once on a project where the customer realized only after 1.5 months that they want us to modify an application that does not even exist at that company. You really makes you wonder what goes on in big companies .. Great Dilbert comic

How to start a startup?   10 Mar 05
[print link all ]
Nice article by Paul Graham.

You need three things to create a successful startup: to start with good people, to make something customers actually want, and to spend as little money as possible. Most startups that fail do it because they fail at one of these. A startup that does all three will probably succeed.

And that’s kind of exciting, when you think about it, because all three are doable. Hard, but doable. And since a startup that succeeds ordinarily makes its founders rich, that implies getting rich is doable too. Hard, but doable.

If there is one message I’d like to get across about startups, that’s it. There is no magically difficult step that requires brilliance to solve.

A cool job announcement   07 Mar 05
[print link all ]
.. seen this in today’s ruby-talk
 #!/usr/bin/env ruby

 # Warning this is a job announcement!
 # Run it/Read it if you are interested.
 # Lack of comments and robust input handling are intentional.

 class Company
    attr_accessor :name, :location, :web_site, :description
    attr_accessor :available_jobs

    def initialize(name = nil, location = nil, web_site = nil)
      self.name = name
      self.location = location
      self.web_site = web_site
      self.available_jobs = Array.new
    end

    def ask_for_interview?(job_applicant)
      available_jobs.each do |ajob|
        return true if ajob.meets_requirements?(job_applicant)
      end
      false
    end

    def describe
      puts "Company  : #{name}"
      puts "Location : #{location}"
      puts "Web site : #{web_site}"
      puts "","Brief description :"
      puts description, ""
    end

    def announce_job_availability(good_match, not_so_good_match)
      return if available_jobs.empty?
      describe
      puts "Available jobs:"
      available_jobs.each_with_index do |job, idx|
        puts "", "#{idx + 1} ) #{job.name}", job.description, ""
      end

      job_applicant = ask_for_job_applicant_information
      return if job_applicant.nil?

      if ask_for_interview?( job_applicant )
        puts good_match
      else
        puts not_so_good_match
      end
    end

    def ask_for_job_applicant_information
      job_applicant = nil
      puts "Would you like to apply for a job? Y/N"
      res = gets.chomp
      if res =~ /Y/i
        msg = "Great!  Please follow the prompts to input your profile"
        msg<< " to see if there if a job matches."
        puts msg, ""
        job_applicant = JobApplicant.new_from_interactive_shell
      else
        puts "Well thanks for reading/running the program!  Good Bye!"
      end
      job_applicant
    end

 end

 class Job
    attr_accessor :name, :description, :requirements, :threshold
    def initialize(name = nil, description = nil,
                   threshold = 100, requirements = [] )
      self.name = name
      self.description = description
      self.requirements = requirements
      self.threshold = threshold
    end

    def meets_requirements?(job_applicant)
      points = 0
      requirements.each do |req|
        points += req.check_requirement(job_applicant)
      end
      points >= threshold
    end

 end

 class JobApplicant
    attr_accessor :name, :resume, :location
    attr_accessor :spoken_languages, :computer_languages_skills
    def initialize
      self.spoken_languages = Array.new
      self.computer_languages_skills = Array.new
    end

    def JobApplicant.new_from_interactive_shell
      applicant = JobApplicant.new
      puts "What is your name?"
       applicant.name = gets.chomp
      puts "Where do you live? (City, Country)"
      applicant.location = gets.chomp
      note = " [One entry per line.  Press CTRL-D to stop input] "
      puts "What languages do you speak?", note
      applicant.spoken_languages = readlines.map { |d| d.chomp }
      cq1 = "What computer languages are you proficient in?"
      cq2 = "And what other computer skills do you have?"
      puts cq1, cq2, note
      applicant.computer_languages_skills = readlines.map {|d| d.chomp }
      puts ""
      applicant
    end

 end

 class Requirement

    def initialize(points = 1, &proc)
      @points = points
      if proc
        @requirement_calc = proc
      else
        @requirement_calc = Proc.new { |x| true }
      end
    end

    def check_requirement(job_applicant)
      points = 0
      if @requirement_calc.call(job_applicant)
        points = @points
      end
      points
    end

 end

 ubit = Company.new("Ubit", "Tokyo, Japan", "http://ubit.com")
 ubit.description =<<EOF
 Ubit is a Japanese company focusing on mobile phone services and
 content aggregation both in Japan and abroad.
 EOF

 developer = Job.new("Software Developer")
 developer.description =<<EOF
 Become knowledgeable in the inner workings of our
 product platform and work as a team with other developers to implement
 new features and improve our current capabilities.  Ideally, you are
 willing to work under dynamic conditions and communicate well with
 others.
 EOF

 loose_find = lambda do |data, reg_match|
    data.find { |v| v =~ match }
 end

 reqs = Array.new
 reqs<< Requirement.new(25) do |ja|
   ja.spoken_languages.include?("English")
 end

 reqs<< Requirement.new(25) do |ja|
    ja.spoken_languages.include?("Japanese")
 end

 reqs<< Requirement.new(5) do |ja|
    sub = ["English", "Japanese"]
    (ja.spoken_languages - sub).size > 0
 end

 reqs<< Requirement.new(50) do |ja|
   ja.computer_languages_skills.include?("Ruby")
 end

 reqs<< Requirement.new(25) do |ja|
   ja.computer_languages_skills.include?("Databases")
 end

 reqs<< Requirement.new(10) do |ja|
   ja.computer_languages_skills.include?("Mobile Technologies")
 end

 reqs<< Requirement.new(5) do |ja|
   ja.computer_languages_skills.include?("*NIX")
 end

 reqs<< Requirement.new(5) do |ja|
   (ja.computer_languages_skills - ["Ruby", "Database"]).size > 0
 end

 reqs<< Requirement.new(25) do |ja|
   ja.location =~ /Japan/i
 end

 developer.requirements = reqs
 developer.threshold = 125

 ubit.available_jobs<< developer

 good_match =<<EOF
 Your profile looks promising!
 If you are interested in working with us,
 please send your resume to Zev Blut at rubyzbibd@ubit.com
 EOF

 nsgm =<<EOF
 Sorry, at the moment we are in need of people who meet our specific
 needs.  But if you feel that you can meet them then go ahead and send
 your resume to Zev Blut at rubyzbibd@ubit.com
 EOF

 ubit.announce_job_availability(good_match,nsgm)

 > Now that is just too cool :-)
 >
 > Cheers,
 > Tim

 Hi, I found a few ways to improve your program.

 --- tokyo_job.rb.orig   2005-03-07 12:41:23.457936200 -0500
 +++ tokyo_job.rb        2005-03-07 13:16:14.736811208 -0500
 @@ -101,11 +102,11 @@
       applicant.location = gets.chomp
       note = " [One entry per line.  Press CTRL-D to stop input] "
       puts "What languages do you speak?", note
 -    applicant.spoken_languages = readlines.map { |d| d.chomp }
 +    applicant.spoken_languages = readlines.map { |d| d.downcase.chomp }
       cq1 = "What computer languages are you proficient in?"
       cq2 = "And what other computer skills do you have?"
       puts cq1, cq2, note
 -    applicant.computer_languages_skills = readlines.map {|d| d.chomp }
 +    applicant.computer_languages_skills = readlines.map {|d|
 d.downcase.chomp }
       puts ""
       applicant
     end
 @@ -157,42 +158,55 @@

   reqs = Array.new
   reqs<< Requirement.new(25) do |ja|
 -  ja.spoken_languages.include?("English")
 +  ja.spoken_languages.include?("english")
   end

   reqs<< Requirement.new(25) do |ja|
 -  ja.spoken_languages.include?("Japanese")
 +  ja.spoken_languages.include?("japanese")
   end

   reqs<< Requirement.new(5) do |ja|
 -  sub = ["English", "Japanese"]
 +  sub = ["english", "japanese"]
     (ja.spoken_languages - sub).size > 0
   end

   reqs<< Requirement.new(50) do |ja|
 -  ja.computer_languages_skills.include?("Ruby")
 +  ja.computer_languages_skills.include?("ruby")
   end

   reqs<< Requirement.new(25) do |ja|
 -  ja.computer_languages_skills.include?("Databases")
 +  ja.computer_languages_skills.grep(/database/).size > 0 or
 +    ja.computer_languages_skills.grep(/\bdb\b/).size > 0
 +    ja.computer_languages_skills.grep(/sql/).size > 0
   end

   reqs<< Requirement.new(10) do |ja|
 -  ja.computer_languages_skills.include?("Mobile Technologies")
 +  ja.computer_languages_skills.include?("mobile technologies")
   end

   reqs<< Requirement.new(5) do |ja|
 -  ja.computer_languages_skills.include?("*NIX")
 +  ja.computer_languages_skills.grep(/linux|unix/).size > 0
   end

   reqs<< Requirement.new(5) do |ja|
 -  (ja.computer_languages_skills - ["Ruby", "Database"]).size > 0
 +  ja.computer_languages_skills.find_all do |lang|
 +    case lang
 +    when /ruby/, /database/, /\bdb\b/, /sql/
 +      false
 +    else
 +      true
 +    end
 +  end.size > 0
   end

   reqs<< Requirement.new(25) do |ja|
     ja.location =~ /Japan/i
   end

 +reqs<< Requirement.new(5) do |ja|
 +  ja.name =~ /Ben/i
 +end
 +
   developer.requirements = reqs
   developer.threshold = 125

 With these changes, it doesn't require '*NIX', but will accept "Linux"
 or "Unix", and it is a bit more accepting of various database keywords.
 (Oh yeah, and it assigns bonus points for cool names)

 Ben

 (P.S. !Japan, !Japanese, !"Mobile Technologies", and !currently_looking?
 but that was too much fun to pass up.  :)  )

ANN: IHelp 0.3.0   26 Feb 05
[print link all ]
Announcing the release of IHelp 0.3.0.

fhtr.org/projects/ihelp/ fhtr.org/projects/ihelp/doc/ fhtr.org/projects/ihelp/releases/ihelp-0.3.0.tar.gz

This release brings with it custom help renderers, which you can leverage to render help whenever you want, wherever you want and however you want.

Also included are a couple experimental renderers (no guarantees):

  • #rubydoc_org opens the corresponding ruby-doc.org class help file using the program defined in IHelp::WWW_BROWSER
  • #rubytoruby_src uses Ryan Davis’ RubyToRuby class to print out the source for the method.

blog.zenspider.com/archives/2005/02/rubytoruby.html for more info about RubyToRuby.

Ri bindings for interactive use from within Ruby. Does a bit of second-guessing (Instance method? Class method? Try both unless explicitly defined. Not found in this class? Try the ancestor classes.)

Goal is that help is given for all methods that have help.

Examples:

  require 'ihelp'

  a = "string"
  a.help
  a.help :reverse
  a.help :map
  String.help
  String.help :new
  String.help :reverse
  String.help :map
  String.instance_help :reverse
  String.instance_help :new # => No help found.
  a.help :new
  help "String#reverse"
  help "String.reverse"
  a.method(:reverse).help # gets help for Method
  help "Hash#map"

Custom help renderers: The help-method calls IHelp::Renderer’s method defined by IHelp.renderer with the RI info object. You can print help out the way you want by defining your own renderer method in IHelp::Renderer and setting IHelp.renderer to the name of the method.

 require 'ihelp'

 class IHelp::Renderer
   def print_name(info)
     puts info.full_name
   end
 end

 IHelp.renderer = :print_name
 [1,2,3].help:reject
 # Array#reject
 # => nil

 

Powered by Rublog