🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.java
Article #384

Re: Refactoring book + one to many implementation

#384
From: Jason Trenouth
Date: Mon, 15 Nov 1999 00:00
106 lines
5551 bytes
On Sun, 14 Nov 1999 15:47:01 -0800, Mark Fussell <mark.fussell@chimu.com>
wrote:


> If Martin had factored the method to match exactly what he wrote, we
> would instead get:
> 
>     public void setCustomer (Customer customer) {
>         unlinkFromCurrentCustomer();
>         myCustomer = customer;
>         linkToCurrentCustomer();
>     }
> 
>     protected void unlinkFromCurrentCustomer() {
>         if (myCustomer != null) myCustomer.friendOrders().remove(this);
>     }
> 
>     protected void linkToCurrentCustomer() {
>         if (myCustomer != null) myCustomer.friendOrders().add(this);
>     }
> 
> This is now very descriptive, matches the narrative exactly, and is very
> unlikely to allow a misreading or miscopying.  Although it would be
> somewhat unusual (i.e. not main-stream) to have methods this short in
> Java, that is no reason to not use this approach when it would help
> readability and maintainability.  The above is a very Smalltalk (i.e.
> Superior :-) way of writing code, and I highly suggest getting [Beck 97]
> for examples of this type of cleanup.  Although you would have to deal
> with another syntax you may not be familiar with, the patterns/idioms
> and transformations described in [Beck 97] are universal to all OO
> languages.

Since this thread has touched on readability issues that might affect
maintenance, and also touched on alternative languages like Object Pascal and
Smalltalk, I thought I'd post the equivalent snippet of Dylan for general
interest:

8<----------------------------------------------------------------------

define method set-customer (order :: <order>, customer :: <customer>) => ()
  unlink-from-current-customer(order);
  my-customer(order) := customer;
  link-to-current-customer(order);
end method;

define method unlink-from-current-customer (order :: <order>) => ()
  if (my-customer(order))
    remove!(friend-orders(my-customer(order)), order);
  end if;
end method;

define method link-to-current-customer (order :: <order>) => ()
  if (my-customer(order))
    add!(friend-orders(my-customer(order)), order);
  end if;
end method;

8<----------------------------------------------------------------------

Some points about the code: 

+ Dylan used begin/end style syntax instead of {} to help readability. The bit
after the word "end" is optional. You can say "end", "end method", or even
"end method link-to-current-customer" but the latter _is_ checked if you do
use that form.

+ Dylan is case-insensitive so case cannot be used to distinguish identifiers.
Extra characters _must_ be used.

+ Dylan identifiers can contain a wider variety of characters than C or Java.
Current conventions that help provide visual cues include <> for classes, and
! for some destructive operations. "-" is conventionally used to separate
words within identifiers for readability.

+ Dylan uses ":=" for assignment to avoid confusion with equality testing.

+ Dylan has generalized booleans as well as an explicit <boolean> type. This
means that conditional expressions evaluating to non-false values are treated
as true. eg "if (my-customer(order))" is equivalent to
"if (my-customer(order) ~= #f)". "#f" is Dylan's literal false value. #f is
general used were "null" would be in languages like Java.

+ "x :: y" means "x has type y". This used in the method syntax for
specializing arguments and variable binding syntax. Dylan is dynamically typed
and most type declarations are optional. If present they help the compiler
produce more efficient code and/or insert checks.

+ "=> ()" means there are no return values. Dylan methods can return multiple
values. This declaration is optional.

+ Dylan uses a generalization of message-passing to multiple arguments. A
corollary of this is that all arguments are explicit. There is no hidden
"this" parameter.

+ Dylan has a "." notation for calling functions e.g. "order.my-customer" and
"my-customer(order)" are equivalent, but I've only used the latter above.

+ "Fields" (called "slots" in Dylan) cannot be accessed outside of the object
system as if they are variables. Instead all accesses must go via accessor
methods. E.g. the field access "myCustomer" in Java becomes
"my-customer(order)" in Dylan. This means field access and local variables
can't get confused.

There's more about Dylan at http://www.functionalobjects.com

__Jason
Technical Details
Message-ID: <ivgvOGT6VgwsF0A90FtfZhBbNZ3U@4ax.com>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <80hvjs$1pqi$1@otis.netspace.net.au> <382C8CEE.39347C17@chimu.com> <80iicf$od1$1@nnrp1.deja.com> <382D1653.EF337931@chimu.com> <80krmj$7sp$1@nnrp1.deja.com> <382E0AD4.79C1F9C5@chimu.com> <80ndoh$sh7$1@nnrp1.deja.com> <382F49F5.388F27E5@chimu.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f5d71,da48a4987570047e
X-Google-Attributes: gidf5d71,public
X-Google-Thread: 10d6db,da48a4987570047e
X-Google-Attributes: gid10d6db,public
X-Google-Thread: fbe9c,da48a4987570047e
X-Google-Attributes: gidfbe9c,public
X-Google-Thread: 114809,da48a4987570047e
X-Google-Attributes: gid114809,public
From: Jason Trenouth <jason@harlequin.com>
Subject: Re: Refactoring book + one to many implementation
Date: 1999/11/15
Message-ID: <ivgvOGT6VgwsF0A90FtfZhBbNZ3U@4ax.com>
X-Deja-AN: 548808659
Cache-Post-Path: cnn!unknown@bagheera
Content-Transfer-Encoding: 7bit
References: <80hvjs$1pqi$1@otis.netspace.net.au> <382C8CEE.39347C17@chimu.com> <80iicf$od1$1@nnrp1.deja.com> <382D1653.EF337931@chimu.com> <80krmj$7sp$1@nnrp1.deja.com> <382E0AD4.79C1F9C5@chimu.com> <80ndoh$sh7$1@nnrp1.deja.com> <382F49F5.388F27E5@chimu.com>
Content-Type: text/plain; charset=us-ascii
Organization: The Harlequin Group
Mime-Version: 1.0
Newsgroups: comp.lang.java,aus.computers.java,borland.public.jbuilder.java,comp.lang.smalltalk