Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > The Chainsaw Infanticide Logger Manuever

Reply
Thread Tools

The Chainsaw Infanticide Logger Manuever

 
 
Zed A. Shaw
Guest
Posts: n/a
 
      08-24-2005
One of the things that's really great about agile languages is they give you the power to do anything. One of the most horrible things about agile languages is they give every other idiot the same power to stab you in the back with a rusty pitchfork.

I needed to do some simple logging. I made a Logger class and started writing to it. Hmm, my log messages sometimes have a format and sometimes they don't. Nothing I do fixes this.

Three hours later and half my sanity, I start to snoop through the libraries I've included, and I find this wonderfully horrible gem:

http://rafb.net/paste/results/0vADxJ56.html

Not only does this code re-open a class to do something that could *just as easily be done with subclassing*, but the author also TURNS OFF DOCUMENTATION with :nodoc: so that nobody knows about it. Great! So much for Principle Of Least Surprise. This is more like Principle Of Most Heinous Arsenic Injection.

I then trolled through a few more projects and found that this is common practice. The glue project does it. Glue even goes so far as to re-open the Logger class *just so it can turn it into a singleton*. Great Buddha the insanity is everywhere!

http://rafb.net/paste/results/yXNJvv50.html

What's wrong with you people? This is the absolute worst thing I've ever experienced in any language I've used. I thought having magic AspectJ crap silently move my code was bad. At least that stuff was documented and I could optionally turn it off. This can only be fixed with leprechaun backflips into a pool of jello while covered in chocolate. Translation: it can't be fixed easily and I shouldn't have to "fix" it since I didn't break it.

-- Please, think of the children before you re-open their parent with a damn chainsaw. --

I only re-open a class after I've tried every other option like subclassing, wrapping, etc. If nothing else works or is too much effort for the modification, then I DOCUMENT THE HELL out of my modification and try desperately to localize the change so that it doesn't hurt anyone else.

Alright, rant off. Please stop doing this. My appologies if I hurt anyone's feelings.

Zed A. Shaw
http://www.zedshaw.com/


 
Reply With Quote
 
 
 
 
Gavin Kistner
Guest
Posts: n/a
 
      08-24-2005
On Aug 23, 2005, at 10:06 PM, Zed A. Shaw wrote:
[... snip an awesome tirade...]

ROFLMAO. Well written

"Principle Of Most Heinous Arsenic Injection"...*giggle*

Thanks for the laugh. I agree with your sentiments, and the way
you've written them.


 
Reply With Quote
 
 
 
 
James Britt
Guest
Posts: n/a
 
      08-24-2005
Zed A. Shaw wrote:
...
> Alright, rant off. Please stop doing this. My appologies if I hurt anyone's feelings.
>


I take it you first tried to contact the author of the offending code
before ranting in public?

James


--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys


 
Reply With Quote
 
Nicholas Seckar
Guest
Posts: n/a
 
      08-24-2005
Zedas, here's concept as discussed in #ruby-lang... Take note that I've
reopened Logger.

class Logger
# Dictate the way in which this logger should format the messages
# it displays. This method requires a block. The block should return
# formatted strings given severity, timestamp, msg, progname.
#
# Useless example:
#
# logger = Logger.new
# logger.format do |severity, timestamp, msg, progname|
# "#{progname}@#{timestamp} - #{severity}::#{msg}"
# end
#
def format(&format_proc)
raise 'feed me a block dude' unless format_proc
@format_proc = format_proc
end

# hackish use of *args, give me some love
def format_message(*args)
@format_proc ? @format_proc.call(*args) : super(*args)
end
end


 
Reply With Quote
 
Eric Hodel
Guest
Posts: n/a
 
      08-24-2005
On 23 Aug 2005, at 21:06, Zed A. Shaw wrote:

> One of the things that's really great about agile languages is they
> give you the power to do anything. One of the most horrible things
> about agile languages is they give every other idiot the same power
> to stab you in the back with a rusty pitchfork.
>
> I needed to do some simple logging. I made a Logger class and
> started writing to it. Hmm, my log messages sometimes have a
> format and sometimes they don't. Nothing I do fixes this.
>
> Three hours later and half my sanity, I start to snoop through the
> libraries I've included, and I find this wonderfully horrible gem:
>
> http://rafb.net/paste/results/0vADxJ56.html


Oh? You think that's bad?

There's also this gem sitting right next to it.

def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, nil
begin
yield
ensure
$VERBOSE = old_verbose
end
end

So that things like this can be done:

silence_warnings { Customer = Struct.new("Customer", :name) }

instead of doing something simple like:

unless defined? Customer
Customer = Struct.new "Customer", :name
end

--
Eric Hodel - http://www.velocityreviews.com/forums/(E-Mail Removed) - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04



 
Reply With Quote
 
David Brady
Guest
Posts: n/a
 
      08-24-2005
Guys,

I don't understand. This is a feature of agile languages, not a
defect. Leaving the door open for chainsaw-wielding maniacs also leaves
the door open for gifted neurosurgeons.

I understand your frustration, and I feel your pain. But I am left with
a critical question:

Where were your unit tests?

Admittedly, silence_warnings might not be testable. You might have to
code review that to catch it. But then again, if *your* unit tests all
pass, then silence_warnings shouldn't affect you--especially if you test
the failure cases and assert that warnings were returned. Logger
integrity, however, should be straightforward.

I don't mean to come across like a heartless jerk or a TDD zealot. I am
neither. I am just looking at your pain and thinking, "why does this
have to hurt?"

-dB

--
David Brady
(E-Mail Removed)
I'm feeling really surreal today... OR AM I?



 
Reply With Quote
 
Bill Kelly
Guest
Posts: n/a
 
      08-24-2005
From: "Zed A. Shaw" <(E-Mail Removed)>
>
> I then trolled through a few more projects and found that this
> is common practice. The glue project does it. Glue even goes
> so far as to re-open the Logger class *just so it can turn it
> into a singleton*. Great Buddha the insanity is everywhere!


I was bitten recently by a change to the CGI module. I don't
think I can get to quite the same level of moral outrage on this
one because by comparison what I ran afoul of seems more like what
one would expect to be a legitimate leveraging of the Power of Ruby,
even in a library context: no global classes or constants were
being opened or modified. Something that I used to convert to a
String instance, was now still a String, but its singleton class had
been extended with additional features. Including some accompanying
instance variables, which is the part that bit me.

My code was littered with cgi['some_parameter'].to_s
because I'd long ago learned that CGI returned something as
a parameter value that acted like a String, but wasn't really.
I added the .to_s when fetching CGI parameters, because the values
I fetch eventually end up in objects which are serialized out to
a flat-file database with YAML.

A recent change to CGI that was--probably--for most intents and
purposes at least as good or better than the way it used to work
was apparently to make cgi['some_parameter'] now return a genuine
String - but one that had been extended with extra features.
Unfortunately, this had the effect of turning my .to_s calls into
no-op's. This had the ultimately semi-harmless but alarming and
baffling result of my database files beginning to show signs of
very strange bloat: objects that used to appear as simple strings
in the YAML, were now complex dumps of objects that included the
string value, but also these ancillary CGI parameters that were
hitchhiking on these extended String objects CGI was now returning
as parameter values.

I think it took me at least an hour and a half to track down the
cause. (Seemed like an eternity because I was working under a
deadline.)

To fix it, I did decide to open the String class with, well maybe
a small set of electric hedge trimmers. But I'm only dealing with
my private application here. If it were a library I were writing,
I'd go to prodigious lengths to try to not modify the global behavior
of Ruby. My cheesy application-level fix:

class String
# %%BWK -- this is a kludge to work around the CGI module extending
# String objects fetched from its parameters with some
# extra instance variables, which cause really verbose YAML
# to be output.
# I already was doing to_s on everything I fetched from
# the CGI parameters, thinking that was enough to give me
# a String without any extra baggage. This kludge forces
# my assumption to be a true one.
def to_s
String.new(self)
end
end

I'm not entirely sure what point I'm driving toward - because
really what CGI is doing seems to me in general like a pretty
reasonable use of Ruby. . . And yet it _bit_ me in a similar way to
what you reported about the Logger Maneuver.

I guess in general, Library Authors Take Note: Getting tricky in
your library can end up playing a trick on your users.


Regards,

Bill




 
Reply With Quote
 
Jeff Wood
Guest
Posts: n/a
 
      08-24-2005
My feelings are in-line with the review of Dave's session as OSCON @

http://raibledesigns.com/page/rd?ent...monday_morning

---QUOTE---

Classes are open: in Ruby, you can always add methods, attributes,
etc. to existing classes. For example, you can add an encrypt() method
to the String class. Isn't this dangerous? What if someone changes the
logic of + for math expressions. No, because if one of your
programmers overrides methods that breaks things - you take them out
in the parking lot and beat them with a rubber hose! The language
shouldn't prohibit us from doing powerful things.

---END QUOTE---

You shouldn't be afraid of having power. That's why you have tests.
You do have tests, right? ... right??? ... RIGHT !!?!?!?!??!

j.

On 8/24/05, Bill Kelly <(E-Mail Removed)> wrote:
> From: "Zed A. Shaw" <(E-Mail Removed)>
> >
> > I then trolled through a few more projects and found that this
> > is common practice. The glue project does it. Glue even goes
> > so far as to re-open the Logger class *just so it can turn it
> > into a singleton*. Great Buddha the insanity is everywhere!

>=20
> I was bitten recently by a change to the CGI module. I don't
> think I can get to quite the same level of moral outrage on this
> one because by comparison what I ran afoul of seems more like what
> one would expect to be a legitimate leveraging of the Power of Ruby,
> even in a library context: no global classes or constants were
> being opened or modified. Something that I used to convert to a
> String instance, was now still a String, but its singleton class had
> been extended with additional features. Including some accompanying
> instance variables, which is the part that bit me.
>=20
> My code was littered with cgi['some_parameter'].to_s
> because I'd long ago learned that CGI returned something as
> a parameter value that acted like a String, but wasn't really.
> I added the .to_s when fetching CGI parameters, because the values
> I fetch eventually end up in objects which are serialized out to
> a flat-file database with YAML.
>=20
> A recent change to CGI that was--probably--for most intents and
> purposes at least as good or better than the way it used to work
> was apparently to make cgi['some_parameter'] now return a genuine
> String - but one that had been extended with extra features.
> Unfortunately, this had the effect of turning my .to_s calls into
> no-op's. This had the ultimately semi-harmless but alarming and
> baffling result of my database files beginning to show signs of
> very strange bloat: objects that used to appear as simple strings
> in the YAML, were now complex dumps of objects that included the
> string value, but also these ancillary CGI parameters that were
> hitchhiking on these extended String objects CGI was now returning
> as parameter values.
>=20
> I think it took me at least an hour and a half to track down the
> cause. (Seemed like an eternity because I was working under a
> deadline.)
>=20
> To fix it, I did decide to open the String class with, well maybe
> a small set of electric hedge trimmers. But I'm only dealing with
> my private application here. If it were a library I were writing,
> I'd go to prodigious lengths to try to not modify the global behavior
> of Ruby. My cheesy application-level fix:
>=20
> class String
> # %%BWK -- this is a kludge to work around the CGI module extending
> # String objects fetched from its parameters with some
> # extra instance variables, which cause really verbose YAML
> # to be output.
> # I already was doing to_s on everything I fetched from
> # the CGI parameters, thinking that was enough to give me
> # a String without any extra baggage. This kludge forces
> # my assumption to be a true one.
> def to_s
> String.new(self)
> end
> end
>=20
> I'm not entirely sure what point I'm driving toward - because
> really what CGI is doing seems to me in general like a pretty
> reasonable use of Ruby. . . And yet it _bit_ me in a similar way to
> what you reported about the Logger Maneuver.
>=20
> I guess in general, Library Authors Take Note: Getting tricky in
> your library can end up playing a trick on your users.
>=20
>=20
> Regards,
>=20
> Bill
>=20
>=20
>=20
>=20



--=20
"So long, and thanks for all the fish"

Jeff Wood


 
Reply With Quote
 
Bill Kelly
Guest
Posts: n/a
 
      08-24-2005
From: "Jeff Wood" <(E-Mail Removed)>
>
> You shouldn't be afraid of having power. That's why you have tests.
> You do have tests, right? ... right??? ... RIGHT !!?!?!?!??!


Dudes, I do have tests. How in blazes would you write a test
to catch the problem I described? (Please show your work.
And why would you ever think to do so?

It's not being afraid of having power. In my own applications,
I'll exploit any and every cool capability of Ruby I feel like.

But when I personally write a module I view as a library I'd
like others to find useful, I take a decidedly more conservative
approach - deliberately.

Do you not consider libraries and applications different, where
Ruby's beloved Openness is concerned?


Regards,

Bill




 
Reply With Quote
 
Jeff Wood
Guest
Posts: n/a
 
      08-24-2005
The truely iterative & testing-complete way to build software is to
design and implement your tests before you write your code. When all
of your tests pass, you're done...

... If you built your system like that, you should have tests for each
and every action on your classes ... and the first time somebody elses
modifications has an affect on your functionality and expected output,
you should know about it.

j.

On 8/24/05, Bill Kelly <(E-Mail Removed)> wrote:
> From: "Jeff Wood" <(E-Mail Removed)>
> >
> > You shouldn't be afraid of having power. That's why you have tests.
> > You do have tests, right? ... right??? ... RIGHT !!?!?!?!??!

>=20
> Dudes, I do have tests. How in blazes would you write a test
> to catch the problem I described? (Please show your work.
> And why would you ever think to do so?
>=20
> It's not being afraid of having power. In my own applications,
> I'll exploit any and every cool capability of Ruby I feel like.
>=20
> But when I personally write a module I view as a library I'd
> like others to find useful, I take a decidedly more conservative
> approach - deliberately.
>=20
> Do you not consider libraries and applications different, where
> Ruby's beloved Openness is concerned?
>=20
>=20
> Regards,
>=20
> Bill
>=20
>=20
>=20
>=20



--=20
"So long, and thanks for all the fish"

Jeff Wood


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help using Chainsaw for Log4j jerry Java 5 06-06-2012 05:26 PM
Ruby's Logger vs ActiveRecord: no more Logger data output Georges Ko Ruby 4 07-26-2006 01:38 PM
why do i need to use org/apache/avalon/framework/logger/Logger to convert XSL-FO to PDF?? sachin XML 1 02-03-2006 09:58 PM
ruby's Logger conflict with Log4r's Logger cap Ruby 3 12-11-2005 03:44 PM
New Web Start version of log4j's Chainsaw V2 scott Java 0 05-24-2004 01:29 AM



Advertisments