Beans question...

Visto 13 veces
Saltar al primer mensaje no leído

theinternot

no leída,
4 ene 2008, 19:21:264/1/08
a model-glue
Hi all,

I am wondering if someone would take the time and offer a concise
explanation on when to use beans in your model glue app. Most of the
examples I have seen have been for simple form fields, but none of my
apps seem to fit that mold exactly.

I am wondering if you can use beans with dynamic getters/setters if
you don't know what the beans properties will be from the very
start?... Also, when is it better to use some other method of moving
around information in model glue, like a struct or query object. This
has been an area that has be eluding me and clarification would be
very appreciated.

Also, if I don't use beans is it necessary to use a service layer?
It seems rather redundant to have to pass arguments from controller,
to the service layer and then to the DAO or GW.

Thanks in advance.

- John

theinternot

no leída,
4 ene 2008, 19:58:134/1/08
a model-glue
I will answer my own question on this in case anyone else is
interested.

Did some googling and found a couple of links that were what I was
looking for:

http://coldfusionweekly.libsyn.com/index.php?post_id=95383

http://www.firemoss.com/blog/index.cfm?mode=entry&entry=207096B8-E081-2BAC-697F878438AD8E6A

- John

Sean Corfield

no leída,
5 ene 2008, 13:13:595/1/08
a model...@googlegroups.com
One piece of advice I'll give is to try to keep your beans - your
business domain objects - as smart as possible so that you don't end
up with all your logic in the service layer and just data and get/set
methods in your beans. That is an anti-pattern known as anemic domain
model. It's easy to fall into because it's a comfortable procedural
way of writing code. Writing smart objects is harder :)


--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

Dinner

no leída,
6 ene 2008, 6:41:246/1/08
a model...@googlegroups.com
On Jan 5, 2008 11:13 AM, Sean Corfield <seanco...@gmail.com> wrote:
>
> One piece of advice I'll give is to try to keep your beans - your
> business domain objects - as smart as possible so that you don't end
> up with all your logic in the service layer and just data and get/set
> methods in your beans. That is an anti-pattern known as anemic domain
> model. It's easy to fall into because it's a comfortable procedural
> way of writing code. Writing smart objects is harder :)

You like that better than the "fat service" model?

I should read a bit more on the established patterns, but so far, my
service is like, a dumbed down version of my model-- sorta like the
controller-- many times the functions are like two or three lines, and
just passing stuff off to objects, or object factories. But that's
still a lot of functions, ya know? Is the "fat" in reference to the
logic in the service, or how much logic the service "calls"?

And while I'm wondering, should we have lots of UserObjects in memory,
or one UserObject that just works on data that's passed to it? -- if
that makes any type of sense (userobject is just an example).

I flip flop, instead of just running some freaking load tests, to see
which performs better (If I could even target just that "question").
Guess maintainability, clarity/form are important too-- heh. Maybe
moreso than the cycyles-- computers are always getting faster anyways.
=]

It's funny to think I know so little, and [don't laugh!] so much, at
the same time. Eh. Story of my life. :-)

Guess I should get back to reading that head first book... *blush*

--
There is nothing worse than aggressive stupidity.
Johann Wolfgang von Goethe

Jon Messer

no leída,
6 ene 2008, 12:33:046/1/08
a model...@googlegroups.com

I think Sean is saying that logic which belongs to a business object should be in that business object, not in the Service. I don't think he is talking about the number of functions, at least my services tend to have quite a few related functions, they act as an API to groups of lower level model operations.

As for the number of transient objects in memory, I let transfer eat as much as it wants, singletons stay in memory, and as for other transients (in session scope) if they will be re-used often they can stay otherwise drop em.

At least that's how I try to do things...



On Jan 6, 2008 3:41 AM, Dinner <vallia...@gmail.com> wrote:

On Jan 5, 2008 11:13 AM, Sean Corfield <seanco...@gmail.com> wrote,

Sean Corfield

no leída,
6 ene 2008, 18:43:156/1/08
a model...@googlegroups.com
Jon is correct. If your beans have no logic - it's all in your
services, then you are suffering from an Anemic Domain Model. In
particular, a singleton userobject operating on data passed to it is
very procedural and not at all OO :)

Mike Kear

no leída,
6 ene 2008, 19:11:446/1/08
a model...@googlegroups.com
This might be a dumb question, but for a relative newbie on this, can
you give us some examples of the kinds of logic you'd put in a bean?
The vast majority of my bean methods are getters and setters, plus a
validation() method and a dump() method.

What other sorts of things would you put in a bean to make it smart?

Cheers
Mike Kear
Windsor, NSW, Australia
Adobe Certified Advanced ColdFusion Developer
AFP Webworks
http://afpwebworks.com
ColdFusion, PHP, ASP, ASP.NET hosting from AUD$15/month

Dinner

no leída,
6 ene 2008, 19:50:516/1/08
a model...@googlegroups.com
On Jan 6, 2008 10:33 AM, Jon Messer <sylvan...@gmail.com> wrote:
>
> I think Sean is saying that logic which belongs to a business object should
> be in that business object, not in the Service. I don't think he is talking
> about the number of functions, at least my services tend to have quite a few
> related functions, they act as an API to groups of lower level model
> operations.

I'm just a bit brain-dead, as far as correctly applying these simple
patterns. I'm happy just to get pretty good modularity, and "places"
for stuff-- consistent organization, if you will. But I want to
really understand what the hell I'm doing-- I can stand on the
shoulders of giants (and do, constantly), but I, like Rick, enjoy
having at the least, rudimentary understandings of the underlying
processes, or principals, or whatever. "Why am I trying to do X?"
besides it being "what one does", ya know?

And the funny thing is, conceptually, I haven't had any problem
"getting it", but when I go to apply it... er-- maybe I /don't/ have
it conceptually! Obviously, not quite.

The design patterns book I have is pretty java-oriented, which is
dandy, since I work with pure java too, but for java, hardly any of
the stuff I'm working on is "mine" thus... most of these decisions are
made by someone else, and I just, um... tweak things.

For instance, what would the "proper" way (don't worry about
explaining the why for now) of doing what I want to with my
HttpSession project:

The premise, is that I use the cf server and cfhttp to create a kind
of "proxy", to make screen-scraping and, um, remote website
interfaces(?) easier. Do to incredibly un-imaginative "facts", I've
got to interface with some of our data stored in other websites,
without any kind of back-end access. Screen-scraping and cfhttp
posts.

Anyways, the idea is to capture every request, replace any links or
form actions with custom links or form actions that go throu the
"proxy" (and thus can be recorded). I've actually got it working ok
for what I currently need, but I'm thinking about sharing it (as bad
as it could be in the hands of the wrong person ("Mom! Dad built
something that would be dangerous in the wrong hands, /and he's
holding it/! Love that line)), and so I'd like to have it be, you
know, a good example of how to "do" coldfusion. And it's good
practice for my work projects, to help ensure they are maintainable by
the future generations of lone gunmen.

So, I've got a session "facade". Lifted it off of, I think, litepost.
Twisted it a bit, and created a "SessionStorageService" (without
really "getting" services-- I just sorta used what I saw in various
open source cf projects as basic ideas, but man, they are all over the
place). My SessionStorageService has getSession(), which returns
(basically) the SessionFacade object, which is pretty much just
session getters and setters.

So in my HttpSessionService (I called it HttpSessionService, but I
haven't even created a HttpSession bean, so it's not, I guess), I do a
getSessionStorageService() in my HttpSessionService, to get the
session.

While I'm "recording" through the "proxy", I need a real session, that
links the requests together. When I'm "replaying" them, I don't
really need the session, and in fact, I wouldn't want them all to use
the same session (since I might run several, non-related "replays" in
succession, or at the same time), right? Course not.

So I want a "session" object, for my httpsession objects, but not a
"global" session object. How should I approach this? What I have
"works", pretty much, but I want to try to follow an established
pattern. How should I add in saving the session to disk? Right now,
I have getSessionStorageService() and getFileStorageService() in my
HttpSessionService object. What would be the OO way of handling this?

We've actually got a little bit of money to burn at my work, and they
told me they'd pay (I told them it might be pricey to get someone
good) someone else to help me out-- My hands are full with work, new
work, and training -- all at the same time -- ... if someone wants to
get some cash-money reimbursement for a solid example of "how to do
it", preferably "Test Driven" (or at least with some tests, maybe an
ant buildfile... ;), there's a couple of little, modular type deals
(to be done in MG, of course!) to be created.

I'm of course eternally grateful ("I'll dance at your wedding", as my
gran says) for the free pointers, and "community" building, but I
figured, well, money is swell too, right? Eh. Said I'd throw it out
there, and see what I could find (so far, the people they've tried
have been real hit-and-miss, and only one had heard of frameworks) but
I didn't want to cf-job it...

Well, jobs aside, if anyone wants to take a stab at setting my
httpsession example straight, conceptually, that would be k-rad.

--
An opinion should be the result of thought, not a substitute for it.
Jef Mallett

Dinner

no leída,
6 ene 2008, 20:11:156/1/08
a model...@googlegroups.com
On Jan 6, 2008 4:43 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> Jon is correct. If your beans have no logic - it's all in your
> services, then you are suffering from an Anemic Domain Model. In
> particular, a singleton userobject operating on data passed to it is
> very procedural and not at all OO :)

The scarry thing is that I think I might actually understand what a
"domain model" is -- for me, the hard part is the OO.

What best represents the domain, I guess? Does the duck Quack, or use
an interface (overloaded term indeed!) to implement QuackBehavior?

Bah. I'll just have to keep on rolling these concepts around, I guess.

Thanks for the communication!

--
If one speaks or acts with a cruel mind, misery follows, as the cart
follows the horse... If one speaks or acts with a pure mind, happiness
follows, as a shadow follows its source.
the Dhammapada

Brian Kotek

no leída,
7 ene 2008, 9:53:447/1/08
a model...@googlegroups.com
Not a dumb question, but a common one. The bean you describe is exactly what Sean is saying to try to avoid where possible, because your bean has no behavior. It is just a data container and is basically nothing but a structure.

What other things belong in the bean? Any behavior specific to that domain entity. What that means exactly will, of course, depend on the application and what your domain entity is supposed to be doing. It also depends on how complex your business logic is. As has been noted, a common approach is to have these simple beans with all the logic in the service layer, which results in a very procedural system where the service layer is doing everything and the beans are nothing but dumb data containers. Basically, if there is logic in the service layer that isn't coordinating multiple domain objects, managing transactions across multiple objects, etc., it probably belongs in the bean instead.

Sean Corfield

no leída,
7 ene 2008, 11:43:317/1/08
a model...@googlegroups.com
What Brian said...

One thing I'll add:

If you see code like this:

<cfset var a = someObj.getA() />
... do something to a ...
<cfset someObj.setA(modifiedA) />

then the chances are that you have that "do something to a" logic in
the wrong place. The more OO approach would be:

<cfset someObj.doSomething() />

and the object would "do something to a" internally.

Does that help?

Dinner

no leída,
7 ene 2008, 13:37:427/1/08
a model...@googlegroups.com
On Jan 7, 2008 9:43 AM, Sean Corfield <seanco...@gmail.com> wrote:
...
> Does that help?

It helps me a little, thanks.

Sean, out of all the source code that's available to the general
public, which project(s) would you say are done "right"? I know
"right" is a relative term, and things aren't choiceless, but taking
that into consideration, what would you recommend as a good place to
look for "hard' examples of, well, OO at the least, but OOed MG apps
would be best.

I'd been using litepost as a "good example" of "how to do it"--
should I just pay a bit more attention to it, or are there others that
you'd recommend as excellent, code-wise?

I directed it at Sean, but this question is of course open to everyone.

Off-list responses are welcome as well.

--
Time is a cruel thief to rob us of our former selves. We lose as much
to life as we do to death.
Elizabeth Forsythe Hailey

Dan Wilson

no leída,
7 ene 2008, 13:43:587/1/08
a model...@googlegroups.com
The application I feel is done 'right' is whichever application I just completed.




Mike Kear

no leída,
7 ene 2008, 13:58:517/1/08
a model...@googlegroups.com
Such as ....??

It's a BAD thing to have a bean that's just a container of
information?? This is new to me!

I thought a bean was a container for the properties of a single
instance of a real life object. Lets use an example of a users table
A bean contains all the properties of user mKear. - name, date of
birth, userId, password, address, phone number, etc etc . whatever's
relevant, and with the fully populated bean, you know all the system
needs to know about user mkear.

What else might you have in a userbean than the getters and setters
and a dump method?

Cheers
Mike Kear
Windsor, NSW, Australia
Adobe Certified Advanced ColdFusion Developer
AFP Webworks
http://afpwebworks.com
ColdFusion, PHP, ASP, ASP.NET hosting from AUD$15/month


On 1/8/08, Brian Kotek <bria...@gmail.com> wrote:
> Not a dumb question, but a common one. The bean you describe is exactly what
> Sean is saying to try to avoid where possible, because your bean has no
> behavior. It is just a data container and is basically nothing but a
> structure.
>
>

[snip]

Brian Kotek

no leída,
7 ene 2008, 14:27:537/1/08
a model...@googlegroups.com
Any behavior related to a User that the application requires:

user.signupForNewsletter()
user.getRecentOrders()
user.addFriend()
user.getProductRecommendations()
user.setPreferences()

and so on.

If you have a bean that is nothing but a container of properties, you're getting very little benefit from taking an OO approach to development. In fact (and I'm afraid this is probably how most people are doing things nowadays), if the whole model looks like this, it's probably making things worse. Because at that point the service layer is doing everything. It might as well be a bunch of procedural code doing nothing but manipulating structures.

To be fair, I think the majority of Java or C# or (insert OO language here) are probably doing the same thing. They think they're doing OOP but all they've really done is stuff procedural code into an Object.

One method I've found that can help delineate what behavior belongs where is to try role playing with CRC cards, similar to what is described here: http://books.google.com/books?id=SGOyQai2TboC&pg=PA105&lpg=PA105&dq=crc+card+acting&source=web&ots=uV4mUKNunC&sig=zT6ObPRWiku0X4pDXO4LWg_Ub84 . The idea being that one should be able to accomplish all of the goals of the application by having the "objects" talk to each other and collaborate. As my friend Hal Helms likes to say, "a good object-oriented design resembles nothing so much as a conversation between objects".

Charlie Griefer

no leída,
7 ene 2008, 14:40:577/1/08
a model...@googlegroups.com
On Jan 7, 2008 11:27 AM, Brian Kotek <bria...@gmail.com> wrote:
> Any behavior related to a User that the application requires:
>
> user.signupForNewsletter()
> user.getRecentOrders()
> user.addFriend()
> user.getProductRecommendations()
> user.setPreferences()
>
> and so on.

so... and forgive me if this is overly simplistic (i'm still trying to
grasp a lot of this conceptually), essentially move the UserGateway
methods into the bean?

--
"Scientists tell us that the fastest animal on earth, with a top speed
of 120 feet per second, is a cow that has been dropped out of a
helicopter." - Dave Barry

Charlie Griefer

no leída,
7 ene 2008, 14:43:317/1/08
a model...@googlegroups.com
On Jan 7, 2008 11:40 AM, Charlie Griefer <charlie...@gmail.com> wrote:
> On Jan 7, 2008 11:27 AM, Brian Kotek <bria...@gmail.com> wrote:
> > Any behavior related to a User that the application requires:
> >
> > user.signupForNewsletter()
> > user.getRecentOrders()
> > user.addFriend()
> > user.getProductRecommendations()
> > user.setPreferences()
> >
> > and so on.
>
> so... and forgive me if this is overly simplistic (i'm still trying to
> grasp a lot of this conceptually), essentially move the UserGateway
> methods into the bean?

Actually, allow me to expand on that. My understanding is that the
DAO gets the CRUD methods (assuming you're not using an ORM), and any
database-related tasks that are *not* CRUD would go into the Gateway.

Since the methods you're using in your example above aren't CRUD
methods for a User object, I'm assuming they'd be in the Gateway (if
one is following the Bean/DAO/Gateway way of doing things)... altho
what I'm reading from your suggestion seems to imply moving them out
of the Gateway and into the Bean itself?

Jon Messer

no leída,
7 ene 2008, 14:47:317/1/08
a model...@googlegroups.com
It's not a bad thing, it's a choice. If you are using "beans" as data containers then you don't really even have a domain model.
Your "beans" are not real business objects, so all of your logic and processing will be in service layers.

Take your example of a User; If your application (for example) allowed users to subscribe to a forum, then they way you are doing it would be something like this

ForumService.SubscribeUserToForum(user,forum)

but if your UserObject were more robust you'd do

user.SubscribeToForum(forum)

A UserObject knows what it can do and knows how to do it, a service layer would then be for orchestrating multiple objects interactions and such.

This may seem trivial like a trivial design choice, but in large scale complex applications having real and robust objects pays off in terms of maintenance and handling complexity.

Jon Messer

no leída,
7 ene 2008, 14:54:597/1/08
a model...@googlegroups.com
Persistence is a bit different, since it's a separate concern which might be subject to change that the UserObject shouldn't care about. So having CRUD in a DAO is appropriate (I don't go in for the DAO/Gateway distinction).

But presumably you are doing more than just CRUD, it's that behavior that should (could) be in the object and not a service layer. So a user object should not know how to save itself to a database, or god forbid get a list of userObjects, but it should know how to do anything meaningful like Brian listed...

Sean Corfield

no leída,
7 ene 2008, 15:02:087/1/08
a model...@googlegroups.com
On Jan 7, 2008 10:37 AM, Dinner <vallia...@gmail.com> wrote:
> Sean, out of all the source code that's available to the general
> public, which project(s) would you say are done "right"?

Well, there's no "One True Way" but I would say none of the open
source projects out there are done "right". Partly because there's
very few open source projects of any size out there and partly because
best practices are constantly evolving so, as Dan says, only the most
recent project could be close to "right".

There's also the reality, especially with the open source projects,
that very few web applications are big enough and complex enough to
show how to follow these patterns and some of those that are big
enough are so complex that they can mask the best practices under a
ton of code.

It's also worth pointing out - as I do repeatedly in my design
patterns talk - that patterns are not code and so you need to be
extremely careful about following example code. Download my design
patterns preso from my blog and look at some of the quotes I give from
Shalloway and Fowler on this subject.

Sean Corfield

no leída,
7 ene 2008, 15:05:177/1/08
a model...@googlegroups.com
On Jan 7, 2008 11:43 AM, Charlie Griefer <charlie...@gmail.com> wrote:
> Actually, allow me to expand on that. My understanding is that the
> DAO gets the CRUD methods (assuming you're not using an ORM), and any
> database-related tasks that are *not* CRUD would go into the Gateway.

Well, I no longer advocate that separation. In Java terminology a DAO
does both CRUD and aggregate operations. And in other pattern
literature a Gateway (or specifically Table Data Gateway) does both
aggregate operations and CRUD.

> Since the methods you're using in your example above aren't CRUD
> methods for a User object, I'm assuming they'd be in the Gateway (if
> one is following the Bean/DAO/Gateway way of doing things)...

Right. Keep your data access layer separate from your business logic
layer in order to make your business logic easier to test and also
make it easier to optimize and refactor your database without
impacting your business logic.

> what I'm reading from your suggestion seems to imply moving them out
> of the Gateway and into the Bean itself?

No, we're talking about moving business logic out of services into beans.

Sean Corfield

no leída,
7 ene 2008, 15:12:257/1/08
a model...@googlegroups.com
On Jan 7, 2008 11:47 AM, Jon Messer <sylvan...@gmail.com> wrote:
> It's not a bad thing, it's a choice. If you are using "beans" as data
> containers then you don't really even have a domain model.

Right. And many web applications *don't* really have a domain model
because they are simply data management applications that have no real
business logic.

> Your "beans" are not real business objects, so all of your logic and
> processing will be in service layers.

And if you think about it, this is a procedural model: data in one
place (a simple bean is a glorified struct) and functionality in
another (your service layer is little more than a function library).
This habit is the hardest one to break when trying to learn OO because
it's so deeply ingrained in how we build software.

> but if your UserObject were more robust you'd do
>
> user.SubscribeToForum(forum)

Or:

forum.subscribe(user)

But Jon's point still stands. Smarter objects know how to do stuff themselves.

My preference would be forum.subscribe(user) by the way since the
subscription is more the responsibility of the forum and it allows the
user to be somewhat more generic. In Jon's model, the user has to know
about the forum.

> A UserObject knows what it can do and knows how to do it, a service layer
> would then be for orchestrating multiple objects interactions and such.

Right. This is an important distinction. The service layer should
contain logic that doesn't belong in a single object.

In real-world applications, we often need to add methods to the
service layer that provide access to the business objects, especially
when our service is acting as the broker between the controller and
the data access layer (which it should be if you're trying to
encapsulate your data layer).

> This may seem trivial like a trivial design choice, but in large scale
> complex applications having real and robust objects pays off in terms of
> maintenance and handling complexity.

Totally agree.

Jon Messer

no leída,
7 ene 2008, 15:24:547/1/08
a model...@googlegroups.com


forum.subscribe(user)

 
That's a good point, since the forum has to know about users but users don't have to know about forums. I was just kinda winging it.

Brian Kotek

no leída,
7 ene 2008, 15:26:487/1/08
a model...@googlegroups.com
On Jan 7, 2008 2:43 PM, Charlie Griefer <charlie...@gmail.com> wrote:

Actually, allow me to expand on that.  My understanding is that the
DAO gets the CRUD methods (assuming you're not using an ORM), and any
database-related tasks that are *not* CRUD would go into the Gateway.

I think the focus on "database-related tasks" is one reason for the current prevalence of "dumb" beans. Forget the database for now, it is nothing but a persistence mechanism. The focus needs to be on "What does this Object need to DO?". The question of whether or not part of it's behavior involves persisting information shouldn't enter the picture at this point. The focus should be on what services an object exposes to the rest of the application, and what messages it can respond to.
 

Since the methods you're using in your example above aren't CRUD
methods for a User object, I'm assuming they'd be in the Gateway (if
one is following the Bean/DAO/Gateway way of doing things)... altho
what I'm reading from your suggestion seems to imply moving them out
of the Gateway and into the Bean itself?

Definitely not...anything specific to the database belongs in data layer components, not the domain objects. Now if the question is, "should the User object have a reference to a UserGateway", the answer might well be yes. But that's not the point. The point is that anything that has a reference to a User object asks IT to do something. How it does it should be of no concern to the requesting object. Internally, a User might (and almost certainly will) be sending messages to other objects in the system to do what has been asked of it. user.getProductRecommendations() might internally call recommendationService.getRecommendations(), which might call amazonService.getRecommendations(), which executes a web service call to Amazon to leverage it's recommendation engine. However it is done, all the client code knows is that it asked the User for product recommendations, and it got back product recommendations for that User.

Now, whether it makes sense to actually ask the User about it's product recommendations is a design decision, but I think it's a valid choice. We're talking about something specific to one User of the system. We're also not trying to model a real-world User, who might not know (at least consciously) what products should be recommended to him/her. In OO land we're free to have an idealized system, and in an ideal world, it would be wonderful if you could ask a User what products they might like and get a useful answer. But this is veering into Ontology and off the point of the thread.

Of course, all of this is my opinion, based on experience and my ongoing understanding of OOP design principles. Still, I hope it makes sense and is of some use to others.
 

Mike Kear

no leída,
7 ene 2008, 22:41:227/1/08
a model...@googlegroups.com
This is very interesting to me. I thought i was the cat's whiskers
(sorry Sean) using beans and DAOs and Coldspring to manipulate my
site and my data, but I'm barely scratching the surface.

Actually i have started moving out from just having a bean being a
data container with a couple of recent beans having a setter method
instantiate another CFC and call a method to derive its value rather
than just accept a value passed in to it.

And I"m pretty sure if I had built a forum, I'd have a
forum.subscribe(user) method, so maybe I'm not as far from the pace as
all that.

Anyway, thanks for the discussion folks, it's encouraged me to move
ahead a little faster!

Cheers
Mike Kear
Windsor, NSW, Australia
Adobe Certified Advanced ColdFusion Developer
AFP Webworks
http://afpwebworks.com
ColdFusion, PHP, ASP, ASP.NET hosting from AUD$15/month

Sean Corfield

no leída,
8 ene 2008, 1:27:598/1/08
a model...@googlegroups.com
Getting good at OO can be a long journey. I started back in January
1992 - when there was really not much mainstream OO information out
there and not much of a community to ask for help!

I'm still learning, 16 years later.

Dinner

no leída,
8 ene 2008, 2:31:178/1/08
a model...@googlegroups.com
...

> > A UserObject knows what it can do and knows how to do it, a service layer
> > would then be for orchestrating multiple objects interactions and such.
>
> Right. This is an important distinction. The service layer should
> contain logic that doesn't belong in a single object.
>
> In real-world applications, we often need to add methods to the
> service layer that provide access to the business objects, especially
> when our service is acting as the broker between the controller and
> the data access layer (which it should be if you're trying to
> encapsulate your data layer).

So continuing the analogy, how would the user be saved? Sounds like
you're thinking UserService.saveUser(user)? Not user.save()?

And did I infer correctly that services shouldn't really be doing
stuff with other services?

I inject services into controllers, and services into objects, and
objects into objects, but not controllers into controllers or services
into services? Or are there no general rules of thumb like that for
services?

--
There is no law of progress. Our future is in our own hands, to make
or to mar. It will be an uphill fight to the end, and would we have it
otherwise? Let no one suppose that evolution will ever exempt us from
struggles. 'You forget,' said the Devil, with a chuckle, 'that I have
been evolving too.'
William Ralph Inge

Jon Messer

no leída,
8 ene 2008, 11:21:278/1/08
a model...@googlegroups.com
It's ok to have user.save() that would be active record style (hopefully user.save() just calls a UserDAO() that is injected), but I prefer UserService|DAO|Gateway.save(user), that way user doesn't have to change if your persistence tier does.

Service on Service action is fine, if you have an AuthenticationService it will likely need access to a UserService and a DirectoryService, but like everything else it depends.

If ForumService needs just a user it's better to give it just the user not the whole UserService (no unnecessary dependencies), but it might need the whole service too.

In general, I wouldn't think too many business object need a service to actually be part of the object, but there could be a situation that called for it.

If you are getting Controller on Controller action you might need to rethink things and use some kind of messaging or event system, but then again...

I don't think that there are any real rules, just different design decisions and trade offs.



On Jan 7, 2008 11:31 PM, Dinner < vallia...@gmail.com> wrote:

...
> > A UserObject knows what it can do and knows how to do it, a service layer
> > would then be for orchestrating multiple objects interactions and such.
>
> Right. This is an important distinction. The service layer should
> contain logic that doesn't belong in a single object.
>
> In real-world applications, we often need to add methods to the
> service layer that provide access to the business objects, especially
> when our service is acting as the broker between the controller and
> the data access layer (which it should be if you're trying to
> encapsulate your data layer).

So continuing the analogy, how would the user be saved?  Sounds like
you're thinking UserService.saveUser (user)?  Not user.save()?

Brian Kotek

no leída,
8 ene 2008, 12:11:478/1/08
a model...@googlegroups.com
It really comes down to reducing dependencies as much as possible. In general, you want to strive to keep the direct encumbrance, that is, the direct class reference set of an object, as low as possible.

If an object needs to call on some other part of the system to perform some work, I always try to have it talk to a service layer object to do it. So in my earlier example, if User has a getProductRecommendations() method, that method would probably in turn call a ProductService or RecommendationService to get that information.

Brian erific

no leída,
8 ene 2008, 12:32:228/1/08
a model...@googlegroups.com
> user.signupForNewsletter()
> user.getRecentOrders()
> user.addFriend()
> user.getProductRecommendations()
> user.setPreferences()

Since we try to keep database access separate from the bean, and essentially all of these methods would require database access, how do they work in your bean?

Would you use coldspring, for example, to inject your recommendation service into the user bean? 

And how about when using Transfer?  My UserService for example has createUser, saveUser, deleteUser, etc, which basically just calls transfer.new(), transfer.save(user), etc.  Would you rather inject transfer into the user bean and call user.save() as a proxy to the Transfer method (or your hand-written DAO/etc?)


Brian

Brian Kotek

no leída,
8 ene 2008, 12:43:088/1/08
a model...@googlegroups.com
On Jan 8, 2008 12:32 PM, Brian erific <fla...@gmail.com> wrote:
> user.signupForNewsletter()
> user.getRecentOrders()
> user.addFriend()
> user.getProductRecommendations()
> user.setPreferences()

Since we try to keep database access separate from the bean, and essentially all of these methods would require database access, how do they work in your bean?

Would you use coldspring, for example, to inject your recommendation service into the user bean? 

Yes, exactly (though I do it with Transfer and have an Observer that injects dependencies into my Decorator when it is created).
 

And how about when using Transfer?  My UserService for example has createUser, saveUser, deleteUser, etc, which basically just calls transfer.new(), transfer.save(user), etc.  Would you rather inject transfer into the user bean and call user.save() as a proxy to the Transfer method (or your hand-written DAO/etc?)

If your app does nothing but create and save user data, and the user has no behavior of its own, then having your service persist the user via Transfer is just fine. Whether or not to have the user save itself is open to debate (this is the ActiveRecord pattern). However, whether you call user.save() or you call transfer.save(user) is really not much different. The main issue I had with ActiveRecord was always that your object was basically nothing but a data container. If you write your own object that can save itself, or if you use Transfer and decorate your object so that it can act as a rich business object, this issue goes away. Personally, I still have my service layer object call transfer.save(user) so that my business object isn't concerned with anything related to persistence. But that's just my choice.

 

brian

no leída,
8 ene 2008, 12:55:128/1/08
a model-glue

On Jan 8, 9:43 am, "Brian Kotek" <brian...@gmail.com> wrote:
> Yes, exactly (though I do it with Transfer and have an Observer that injects
> dependencies into my Decorator when it is created).

I think where I struggle is the application of "rules of thumb" to
real-world decision making. I'd be interested to hear how you handle
scenarios like user authentication. For example, do you inject
AuthenticationService and AuthorizationService into the User object
and then ask the user: user.isAuthorized(object, roles), or
user.login(username, password)? What about user.getRoles() or things
like that? Or instead do you have an MG event like "needLoginStatus"
that asks a UserController that asks the
AuthenticationService.isAuthenticated(user)?

If the former, I think I've built my service layer like you would
build a bean.

Some opposite examples would help too - what would you put in a
service layer that you *wouldn't* put into a bean (besides persistence
layer stuff)?

I realize there is less right/wrong and more shades of gray or trade-
offs but as I'm converting an existing app right now, I'm trying not
to paint myself into a big corner in the process. This thread is
really timely for me.


Brian

Seth MacPherson

no leída,
8 ene 2008, 13:34:388/1/08
a model...@googlegroups.com
I'd like to chime in and say this is the most interesting thread I've read
on this list in months. Thank you Brian(s), Sean, Jon, et al., for the
great questions and even better responses - it's been illuminating.

- Seth
............................................................................
.......

SETH MacPHERSON / FREELANCE DEVELOPER
360.241.8329

seth.ma...@gmail.com
822 June Street
Hood River, Oregon 97031
............................................................................
.......

Brian Kotek

no leída,
8 ene 2008, 13:51:438/1/08
a model...@googlegroups.com
On Jan 8, 2008 12:55 PM, brian <fla...@gmail.com> wrote:


On Jan 8, 9:43 am, "Brian Kotek" <brian...@gmail.com> wrote:
> Yes, exactly (though I do it with Transfer and have an Observer that injects
> dependencies into my Decorator when it is created).

I think where I struggle is the application of "rules of thumb" to
real-world decision making.  I'd be interested to hear how you handle
scenarios like user authentication.  For example, do you inject
AuthenticationService and AuthorizationService into the User object
and then ask the user: user.isAuthorized(object, roles), or
user.login(username, password)?  What about user.getRoles() or things
like that?  Or instead do you have an MG event like "needLoginStatus"
that asks a UserController that asks the
AuthenticationService.isAuthenticated(user)?

It's where everyone struggles, because there are only a few general rules and not a recipe. I would probably not ask a user if they are authorized since security is an application-level concern, not a user-level concern. getRoles() is appropriate for a user though, and would probably be available via a session-scoped instance of the User.
 

If the former, I think I've built my service layer like you would
build a bean.

And this is probably an example of the "fat service layer/dumb beans" approach that should probably be reconsidered.
 


Some opposite examples would help too - what would you put in a
service layer that you *wouldn't* put into a bean (besides persistence
layer stuff)?

Transactions that need to apply across multiple different calls to other objects. Security (most likely applied via AOP with ColdSpring). Other coordination that applies across multiple objects.
 
I realize there is less right/wrong and more shades of gray or trade-
offs but as I'm converting an existing app right now, I'm trying not
to paint myself into a big corner in the process.  This thread is
really timely for me.


Yes, everything comes down to trade offs, since all decisions you make have consequences that must be understood and considered.

Peter Bell

no leída,
8 ene 2008, 14:57:118/1/08
a model...@googlegroups.com
On 1/8/08 1:51 PM, "Brian Kotek" <bria...@gmail.com> wrote:

> I would probably not ask a user if they are authorized since security is an application-level concern, not a user-level
> concern. getRoles() is appropriate for a user though, and would probably be available via a session-scoped instance of the User.

I was playing around with this as I also didn’t think a User should know about whether they were authenticated, but I liked the convenience of being able to ask them whether they were – it worked out really well in the views to have access to that kind of information in the same bean I could get FirstName and LastName from for displaying “Hello FirstName LastName” and the like. In the end, I decided to instantiate a “SiteUser” object for every request that can handle the concerns of a user of the site. It extends user but has code and concerns specific to things like passing messages across a cflocation redirect using session scope and providing authentication information(via a composed authenticationService). That actually seems to be working out fairly well for me . . .

Best Wishes,
Peter



Brian Kotek

no leída,
8 ene 2008, 15:16:008/1/08
a model...@googlegroups.com
I usually have a SecurityService that I pass into the view that I ask about things like permissions:

securityService.isUserInRoleList(roles)

The SecurityService knows how to get this information (usually by asking the session-scoped User for it's roles and then checking against the provided role list.

Normally my views don't do a cflocation. That happens in the controller, and I have a generic Result object that I can store in the session temporarily that can hold things like messages or other information.

Peter Bell

no leída,
8 ene 2008, 15:23:418/1/08
a model...@googlegroups.com
I should have clarified, while I user SiteUser in the views for things like isAuthenticated(), I use the same SiteUser within the controller for storing session scoped messages before calling a base controller location() method that handle the redirects. I do however access those messages in the view.

Controller code would be:
SiteUser.PersistMessage(“Article saved successfully”);
Location(new-url);

And view code would be:

#SiteUser.consumeMessage()# which will display any session persisted messages that exist and nothing if they don’t. I’m still not sure whether I like or dislike that as opposed to getting the controller to consume the message and put it in the event object, but it’s working for now and reduces the number of moving parts . . .

Best Wishes,
Peter

Brian Kotek

no leída,
8 ene 2008, 19:37:098/1/08
a model...@googlegroups.com
Gotcha, Peter. Sounds like a fine approach!

Brian G

no leída,
9 ene 2008, 12:38:039/1/08
a model-glue

On Jan 8, 10:51 am, "Brian Kotek" <brian...@gmail.com> wrote:
> It's where everyone struggles, because there are only a few general rules
> and not a recipe. I would probably not ask a user if they are authorized
> since security is an application-level concern, not a user-level concern.
> getRoles() is appropriate for a user though, and would probably be available
> via a session-scoped instance of the User.

Let me enumerate some options here. In your beans, do you have
references to:

* DAOs?
* Gateways?
* Service Layers?

So in my application I'm working on now, I have two ways of looking at
an event registration. As the attendee or as the organizer. As the
attendee, I want to know stuff like:

member.getRegistrations()
member.getRegistration(event)
member.getPayments()
member.getPaymentsByEvent(event)

etc. Now, I have gateways and service objects for each "chunk" of my
app; so I have an attendeeService that provides all of the
interactions for registrations (the date, items ordered, status), an
eventService which handles the events themselves (their name,
locations, etc) and of course my memberService which is for updating
the member and so forth.

In the model we're discussing, I would need to pass into the member
bean references at least to the attendeeGateway and paymentGateway and
then add methods like above. But now, isn't my member bean heavily
coupled to all of these other components?

In my existing procedural app, I have a member.cfc which basically
does everything related to the member - it's a singleton though and
doesn't carry state (I always passed in a member ID). If I renamed it
"bean", stored the state, made it one-per-user and gone on my merry
way, would I have been fine? Because that would have been a lot
easier than what I did. ;-)


Brian

Brian Kotek

no leída,
9 ene 2008, 13:18:499/1/08
a model...@googlegroups.com
On Jan 9, 2008 12:38 PM, Brian G <brian-...@vfive.com> wrote:

On Jan 8, 10:51 am, "Brian Kotek" <brian...@gmail.com> wrote:
> It's where everyone struggles, because there are only a few general rules
> and not a recipe. I would probably not ask a user if they are authorized
> since security is an application-level concern, not a user-level concern.
> getRoles() is appropriate for a user though, and would probably be available
> via a session-scoped instance of the User.

Let me enumerate some options here.  In your beans, do you have
references to:

* DAOs?
* Gateways?
* Service Layers?

I use Transfer so I don't have DAOs; my Transfer object does CRUD plus other queries specific to that object. If I have a Gateway, it would usually be referenced by the service layer since these would generally be aggregated queries, not specific to one entity (such as Member). Where necessary, my bean does have references to other service layer CFCs.
 
So in my application I'm working on now, I have two ways of looking at
an event registration.  As the attendee or as the organizer.  As the
attendee, I want to know stuff like:

member.getRegistrations()
member.getRegistration(event)
member.getPayments()
member.getPaymentsByEvent(event)

etc.  Now, I have gateways and service objects for each "chunk" of my
app; so I have an attendeeService that provides all of the
interactions for registrations (the date, items ordered, status), an
eventService which handles the events themselves (their name,
locations, etc) and of course my memberService which is for updating
the member and so forth.

In the model we're discussing, I would need to pass into the member
bean references at least to the attendeeGateway and paymentGateway and
then add methods like above.  But now, isn't my member bean heavily
coupled to all of these other components?

I would have the Member talk to the AttendeeService or the PaymentService if they need that information, not the gateways. This is for all the same reasons you use a service layer in the first place, primarily encapsulation. If you change how the attendeeGateway works, you should not have to change anything in the Member.

It's also a design decision whether you ask a Member about their Events, or whether you ask an EventService about what Members are registered. Again, for behavior specific to an individual Member, it can make sense to ask the Member about these things. For behavior that applies to many Members, it probably makes sense to ask the relevant service ( i.e. eventService.getRegisteredMembers()).

Member would be coupled to AttendeeService and PaymentService, but nothing else. So however AttendeeService does its work is hidden from Member. Any way you slice it there will be some coupling. Either User has to know about AttendeeService, or something else has to pass AttendeeService a User (or information about a User). It also may be worth considering whether there is really enough of a difference between a "user" and an "attendee" for them to have separate services. These are all things that have to be weighed when creating a good design, and as always, it depends on the application.
 

In my existing procedural app, I have a member.cfc which basically
does everything related to the member - it's a singleton though and
doesn't carry state (I always passed in a member ID).  If I renamed it
"bean", stored the state, made it one-per-user and gone on my merry
way, would I have been fine?  Because that would have been a lot
easier than what I did. ;-)

What you're describing is basically the UserService, which would be a Singleton. I'm assuming this singleton User that you describe also deals with behavior that applies to many users. If so, then you would want to refactor so that the User only handles things related to an individual user. Remember that a business object is meant to model one actual concrete entity ( i.e. 'Tom', 'Invoice 24', etc.) Behavior related to many users would be handled by the UserService (probably with calls to a UserGateway).
 
Hope this helps.

Brian

Brian G

no leída,
10 ene 2008, 13:37:1610/1/08
a model-glue

On Jan 9, 10:18 am, "Brian Kotek" <brian...@gmail.com> wrote:
> Member would be coupled to AttendeeService and PaymentService, but nothing
> else. So however AttendeeService does its work is hidden from Member. Any
> way you slice it there will be some coupling. Either User has to know about
> AttendeeService, or something else has to pass AttendeeService a User (or
> information about a User). It also may be worth considering whether there is

I think that's a great point - somewhere, things have to talk to each
other. Where do we want to have that conversation take place? It's
certainly _easier_ to happen in the bean, from an API perspective.
There's less passing around which means less code to write.

But... now that bean has a ton of power right? I put my member bean
in the event object on each request (for the currently signed in user,
so I can get their name, etc) which means I would have access to all
of this data at all times.

Is it a good or a bad thing that, in my views, I can now get all that
data without interacting with the controllers much? I think it's
easier. But I don't know if it's a good thing. Does it make it
easier at the expense of some of the benefits of the framework?

Do you access the service through a reference like
member.getAttendeeService().getRegistrations() or do you generally
create proxy methods that in turn call the service like
member.getRegistrations()?

Lastly, I see real value in passing other services into the member
bean. What about passing a reference to the memberService to the
member bean? Such that I could have member.save() which proxies to
the memberService (which, in my case, is using Transfer)? Pros/Cons?

This has been an awesome thread. While I don't think I can implement
all of the changes immediately, I'm starting with making my member
bean a little chubby and we'll see where it goes from there as time
permits. There's only so much you can do in 13 hours a day. :) Most
importantly, I feel like I'm getting a better grasp on not just how I
will do things but what the trade offs are in each approach.


Brian

Brian Kotek

no leída,
10 ene 2008, 14:09:1810/1/08
a model...@googlegroups.com
On Jan 10, 2008 1:37 PM, Brian G <brian-...@vfive.com> wrote:

But... now that bean has a ton of power right?  I put my member bean
in the event object on each request (for the currently signed in user,
so I can get their name, etc) which means I would have access to all
of this data at all times.

Not sure I follow, or see a problem with this. What do you mean by "power"? If you mean you can ask a User to do anything that a User needs to do...then yes. That's a lot of power. ;-)
 
Is it a good or a bad thing that, in my views, I can now get all that
data without interacting with the controllers much?  I think it's
easier.  But I don't know if it's a good thing.  Does it make it
easier at the expense of some of the benefits of the framework?

Also not sure I follow. What would be interacting with the Controller? What benefits of an MVC framework do you think are compromised by having a smart Bean? My Controllers are dumb. Really dumb. They do almost nothing, most of my Controller methods are only a couple of lines of code. They call one or more Services, and occasionally perform some kind of redirect (after form submission, for example). That's basically it. Everything interesting happens in the Model, at the Service layer or below. So even in the "fat Service layer" approach, the Controller isn't involved. The Services would be talking to each other, and probably doing things in a very procedural way, but they still don't really have any direct interaction with the Controller. The just do stuff and sometimes return stuff to whatever called it (a Controller, a Flex remoting call, or whatever). The Service layer should be totally agnostic about how it is being called.
 
Do you access the service through a reference like
member.getAttendeeService().getRegistrations() or do you generally
create proxy methods that in turn call the service like
member.getRegistrations()?

In general, method chaining like that should be avoided because it increases coupling. This is the Law of Demeter. In your example, now the client code (whatever is calling Member) is not only coupled to the Member, but it is coupled to the AttendeeService. It's relying on an internal implementation detail of Member (the fact that it contains a reference to AttendeeService). While sometimes method chaining like this is unavoidable (or at least acceptable), the rule of thumb should be that the client code should see Member as a black box. For all it knows or cares, Member might be a single, giant, 10,000 line CFC that does everything itself. The fact that, internally, Member is actually a whole set of objects that coordinate to get the work done should be completely hidden from the outside. The main reason for this is encapsulation: you can change how Member does things internally and nothing outside of it will care. As long as you can call member.getRegistrations() and get back a query (or whatever the method interface of getRegistrations specifies), how Member does that can be changed or refactored at will.
 
Lastly, I see real value in passing other services into the member
bean.  What about passing a reference to the memberService to the
member bean?  Such that I could have member.save() which proxies to
the memberService (which, in my case, is using Transfer)?   Pros/Cons?

Sure you could do this (but it would then become this.save() I think?), but I probably wouldn't do this. save() means persisting, which means something I think the object itself should not be aware of. I'm not sold at all on the ActiveRecord approach, where objects know how to load and save themselves. To me, an object should "think" that it exists forever. The fact that something outside of it can save it and load it over time should be hidden from it. It's like putting it in suspended animation. A member might log out and come back a month later, but from the Member object's point of view, it's like it was sitting in memory the whole time.
 
This has been an awesome thread.  While I don't think I can implement
all of the changes immediately, I'm starting with making my member
bean a little chubby and we'll see where it goes from there as time
permits.  There's only so much you can do in 13 hours a day. :)  Most
importantly, I feel like I'm getting a better grasp on not just how I
will do things but what the trade offs are in each approach.


Glad it's helping. As always, having to explain my thoughts in a coherent way (a tough exercise I assure you! lol) always benefits me as well. The old saying about "the best way to learn something is to explain it to someone else" is absolutely true!

Dinner

no leída,
10 ene 2008, 18:44:3510/1/08
a model...@googlegroups.com
On Jan 10, 2008 11:37 AM, Brian G <brian-...@vfive.com> wrote:
...

> This has been an awesome thread. While I don't think I can implement
> all of the changes immediately, I'm starting with making my member
> bean a little chubby and we'll see where it goes from there as time
> permits. There's only so much you can do in 13 hours a day. :) Most
> importantly, I feel like I'm getting a better grasp on not just how I
> will do things but what the trade offs are in each approach.

I felt the same way after the first couple of chapters in the Head
First - Design Patterns book. Truly an excellent read, fun, light
hearted -- like the Pragmatic Programmer, another excellent book.

One of the things in HFDP is "lingo"-- It was helpful to /really/ see
what is meant when people are tossing terms around. I will be a bit
more careful in how I talk, because to someone who knows the patterns,
I must sound bass ackwards. Stupid words like "interface" -- bah!

This is the second time I've started on the HFDP book, and it made
sense the first time, but it's making even more sense the second
go-around (not that I finished the first). I wish I was better about
making time for such things. It is probably *essential* (probably,
not even probably!).

At any rate, I too have been enjoying this thread a great deal. Just
wanted to share a bit that someone shared with me (that book ain't
bad), as it's helped, like this thread is helping.

"Program to an interface, not an implementation" is a good one,
speaking of... :-)

--
One of the indictments of civilizations is that happiness and
intelligence are so rarely found in the same person.
William Feather

Sean Corfield

no leída,
10 ene 2008, 20:07:1010/1/08
a model...@googlegroups.com
On Jan 10, 2008 10:37 AM, Brian G <brian-...@vfive.com> wrote:
> Such that I could have member.save() which proxies to
> the memberService (which, in my case, is using Transfer)? Pros/Cons?

If you are using Transfer and your Member is a decorator then Member
already has access to Transfer and doesn't need memberService to save
itself:

function save() {
getTransfer().save(this);
}

That's all you need.

Dinner

no leída,
10 ene 2008, 23:31:5310/1/08
a model...@googlegroups.com
On Jan 10, 2008 6:07 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 10, 2008 10:37 AM, Brian G <brian-...@vfive.com> wrote:
> > Such that I could have member.save() which proxies to
> > the memberService (which, in my case, is using Transfer)? Pros/Cons?
>
> If you are using Transfer and your Member is a decorator then Member
> already has access to Transfer and doesn't need memberService to save
> itself:

Ability aside, what about the argument for separation of persistence?

Does a "smart" object know how to save itself? I mean, is that
something the user object does?

That is really where my abstract "StorageService" came from -- I
figured that persistence should be "swappable", because implementation
can (and maybe probably will) change.

That *still* doesn't get us around the question of "saving oneself",
so to speak, but maybe so long as it's encapsulated (however it's
done) is what matters?

Should my library book object know how to persist itself?
(theoretically, as I'm using the StorageService, within my
TitleService, to save titles already ;])

I think I grasp ActiveRecord-- but is it "records" or "data" that
we're modeling, or more (or is that less? bah! :-) insubstantial
thingies?

Heh.

--
Things don't fall apart. Things hold. Lines connect in thin ways that
last and last and lives become generations made out of pictures and
words just kept.
Lucille Clifton

Brian Kotek

no leída,
11 ene 2008, 0:04:3111/1/08
a model...@googlegroups.com
On Jan 10, 2008 11:31 PM, Dinner <vallia...@gmail.com> wrote:

Ability aside, what about the argument for separation of persistence?

Does a "smart" object know how to save itself?  I mean, is that
something the user object does?

That is really where my abstract "StorageService" came from -- I
figured that persistence should be "swappable", because implementation
can (and maybe probably will) change.

This is why you'd use something like ColdSpring to manage the dependencies, and keep you data access layer encapsulated. So that if you ever need to change the implementation, that change is hidden from the rest of the system.
 
That *still* doesn't get us around the question of "saving oneself",
so to speak, but maybe so long as it's encapsulated (however it's
done) is what matters?

Should my library book object know how to persist itself?
(theoretically, as I'm using the StorageService, within my
TitleService, to save titles already ;])

I think I grasp ActiveRecord-- but is it "records" or "data" that
we're modeling, or more (or is that less? bah! :-) insubstantial
thingies?

My comments in an earlier post summed up my thoughts on this:

Dinner

no leída,
11 ene 2008, 1:09:4711/1/08
a model...@googlegroups.com
On Jan 10, 2008 10:04 PM, Brian Kotek <bria...@gmail.com> wrote:
>
> On Jan 10, 2008 11:31 PM, Dinner <vallia...@gmail.com> wrote:
> >
> > Ability aside, what about the argument for separation of persistence?
> >
> > Does a "smart" object know how to save itself? I mean, is that
> > something the user object does?
> >
> > That is really where my abstract "StorageService" came from -- I
> > figured that persistence should be "swappable", because implementation
> > can (and maybe probably will) change.
> >
>
> This is why you'd use something like ColdSpring to manage the dependencies,
> and keep you data access layer encapsulated. So that if you ever need to
> change the implementation, that change is hidden from the rest of the
> system.

From the little I know about ColdSpring, and injection, or
inverted-control whatsis-- you could do just about anything with it.

Aspect Oriented Programming? Seems like that was one of the patterns
in this Designs book, but it went by a different name.

Anyways, I see the sheer power of the approach, but it also seems to
have some limitations (due to it's power, probably). Very yin-yang,
very similar to everything else. :-)

Naming things has always intrigued me... somehow, this relates... eh.
I'll try to explain what I'm thinking:

Since we have to keep all this stuff in our heads, how we choose to
organize it is important.

When you start talking about "dependencies", is where the stuff like
"program to an interface" come in, right? Being able to switch the
dependency up, and indeed, "wrap it" (AOP) with whatever you wish, is
heady stuff, but we're just swapping problems. Or scenery for
problems. Or something like that.

I think you address this a bit below, meaning you'd addressed it earlier:

> I'm not sold at all on the ActiveRecord approach, where objects know how to
> load and save themselves. To me, an object should "think" that it exists
> forever. The fact that something outside of it can save it and load it over
> time should be hidden from it. It's like putting it in suspended animation.
> A member might log out and come back a month later, but from the Member
> object's point of view, it's like it was sitting in memory the whole time.

This is probably the debatable part, right? I mean, you can
encapsulate the implementation, so save() could be whatever, but
should it be user.save() or userservice.save(user)? How "smart"
should the object be? Obviously there wouldn't be a pattern for it if
it didn't make some kind of sense (I've yet to get to that pattern, if
it's in the book I'm reading).

Maybe the answer is "it depends"? If so, I'm wondering when it
depends, or whatever.

Eh.

So should objects save other objects, and not know about "outside the
box" (which saving themselves sorta seems to be)?

It *is* fun to think about. Damn. Coding is fun too. Ah, how to
balance these competing desires!?!?! =]

--
Every child is an artist. The problem is how to remain an artist once
he grows up.
Pablo Picasso

Sean Corfield

no leída,
11 ene 2008, 1:24:3011/1/08
a model...@googlegroups.com
On Jan 10, 2008 8:31 PM, Dinner <vallia...@gmail.com> wrote:
> Ability aside, what about the argument for separation of persistence?

The persistence is encapsulated in Transfer and if you have a
decorator, you're already extending transfer.com.TransferDecorator so
that's a fairly tight coupling. That's not to say that you can't
uncouple it but this is a pragmatic trade off you make: the
convenience of ORM in exchange for some coupling. You *could*
completely separate them but then the trade off is the increased
complexity of doing so. Remember that there are no black and white,
wrong and right rules here.

> Does a "smart" object know how to save itself? I mean, is that
> something the user object does?

That's a choice and a trade off. I find the convenience of adding just
this code:

function save() {
getTransfer().save(this);
}

so that other layers can say aUser.save() when they have updated aUser
far outweighs the downsides of the "coupling" since otherwise I'd have
to have a save() method on my service and inject my service everywhere
that needs to modify (and save) a user object.

This isn't a full-blown active record but it is a useful convenience,
a pragmatic trade off.

> That is really where my abstract "StorageService" came from -- I
> figured that persistence should be "swappable", because implementation
> can (and maybe probably will) change.

My pragmatic trade off is that my database might change and my
database schema might change but, realistically, my actual persistence
format won't. If it ever did, I'd need to change the base class for
any beans that needed a difference persistence format and I'd need to
update any code that created / loaded them. Doable. Again, a trade
off.

If you follow the purity of encapsulation that you seem to be striving
for, you paint yourself into exactly the abstract corner in which you
sit and ponder the "best" way to do things. If you follow the
principles of Agile Development (even to some degree), then KISS and
YAGNI mean not overdoing the abstraction. In fact, the refactoring
approach in general means not introducing unnecessary complexity or
abstraction until you actually need it.

Dinner

no leída,
11 ene 2008, 2:59:4811/1/08
a model...@googlegroups.com
On Jan 10, 2008 11:24 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 10, 2008 8:31 PM, Dinner <vallia...@gmail.com> wrote:
> > Ability aside, what about the argument for separation of persistence?
>
> The persistence is encapsulated in Transfer and if you have a
> decorator, you're already extending transfer.com.TransferDecorator so
> that's a fairly tight coupling. That's not to say that you can't
> uncouple it but this is a pragmatic trade off you make: the
> convenience of ORM in exchange for some coupling. You *could*
> completely separate them but then the trade off is the increased
> complexity of doing so. Remember that there are no black and white,
> wrong and right rules here.

Heh. You're talking to a king of Relativity. ;-)

Existence is heady stuff to contemplate. Can anything actually exist,
if nothing else exists? Does it matter if the tree falls, if none
hear?

Is the object aware of it's existence (or, maybe,
afterlife/re-incarnation), or is another object responsible for that?
Meh. Can't quite express it right, but I think that some of these
coding questions are more philosophical, open ended questions than...
well, enough with that. [=

> > Does a "smart" object know how to save itself? I mean, is that
> > something the user object does?
>
> That's a choice and a trade off. I find the convenience of adding just
> this code:
>
> function save() {
> getTransfer().save(this);
> }
>
> so that other layers can say aUser.save() when they have updated aUser
> far outweighs the downsides of the "coupling" since otherwise I'd have
> to have a save() method on my service and inject my service everywhere
> that needs to modify (and save) a user object.

By doing:

function save() {
getConcreteStorageService.save(this);
}

You get another level of abstraction tho, right? I know you can go
off the deep end with it, but with just one more "step away" from
transfer, you've got a way of persisting stuff besides the database.

> This isn't a full-blown active record but it is a useful convenience,
> a pragmatic trade off.
>
> > That is really where my abstract "StorageService" came from -- I
> > figured that persistence should be "swappable", because implementation
> > can (and maybe probably will) change.
>
> My pragmatic trade off is that my database might change and my
> database schema might change but, realistically, my actual persistence
> format won't. If it ever did, I'd need to change the base class for
> any beans that needed a difference persistence format and I'd need to
> update any code that created / loaded them. Doable. Again, a trade
> off.

"Most of the time" is a pragmatic factor. Hell, maybe the definition.

> If you follow the purity of encapsulation that you seem to be striving
> for, you paint yourself into exactly the abstract corner in which you
> sit and ponder the "best" way to do things. If you follow the
> principles of Agile Development (even to some degree), then KISS and
> YAGNI mean not overdoing the abstraction. In fact, the refactoring
> approach in general means not introducing unnecessary complexity or
> abstraction until you actually need it.

Well, I don't know if I'm striving for purity, per say. Hehe! Moreso
just better, faster, smarter ways of doing things.

The only thing that worries me about a "fat object", is that, the
fatter it is, the less flexible and fast.

Sure, you load up your user object with everything it needs to know
for it's job-- but what do you do when you need a user object for
another job?

If you've fattened it up "the wrong way", or, shall we say, a less
good, slower, dumber way-- you won't be able to re-use it as easy as
you'd like.

But perhaps a user is such a trivial thing, rolling a new one for each
job ain't that bad-- how many jobs does the average joe have, anyways?
LOL.

Yes, I can see that a well thought-out application of things like
inheritance, and interfaces could potentially save a lot of time and
effort.

Not too well thought out, of course. :-)

--
If you watch a game, it's fun. If you play at it, it's recreation. If
you work at it, it's golf.
Bob Hope

Sean Corfield

no leída,
11 ene 2008, 15:06:2311/1/08
a model...@googlegroups.com
On Jan 10, 2008 11:59 PM, Dinner <vallia...@gmail.com> wrote:
> function save() {
> getConcreteStorageService.save(this);
> }
>
> You get another level of abstraction tho, right?

Yes. And you can keep adding abstractions. Every abstraction adds a
(small) performance penalty and every abstraction adds more code you
have to write (the first time, at least). Hence my reference to KISS
and YAGNI.

> Well, I don't know if I'm striving for purity, per say. Hehe! Moreso
> just better, faster, smarter ways of doing things.

Well, I won't argue "better" but I will argue faster in this case :)

> The only thing that worries me about a "fat object", is that, the
> fatter it is, the less flexible and fast.

The extra abstractions will affect performance more than the extra
methods in a "fat" object. As for less flexible... well, these are
business domain objects so they are, by definition, going to
encapsulate business logic that is likely to be specific to your
application. The flexibility comes from Transfer in this case, being
able to auto-generate / manage your basic user beans so you can reuse
the same DB schema and Transfer does most of the rest.

If you need a reusable smart user object, split the decorator in two:
ReusableUser extends TransferDecorator, ApplicationUser extends
ReusableUser. Like I say, pragmatic refactoring based on KISS / YAGNI.

> But perhaps a user is such a trivial thing, rolling a new one for each
> job ain't that bad-- how many jobs does the average joe have, anyways?

I reuse at a design level more than at a code level but the tools and
frameworks I use mean that I can implement those reusable design very
quickly in each new project.

cfCharlie

no leída,
11 ene 2008, 15:20:2511/1/08
a model-glue
Does anyone feel that a "fat bean" may violate the closed for
modifications open for extension OOP rule? Just curious...

Brian Kotek

no leída,
11 ene 2008, 15:37:4311/1/08
a model...@googlegroups.com
I'm not sure what your "fat bean" looks like. Can you explain your concern?

Sean Corfield

no leída,
11 ene 2008, 17:12:3211/1/08
a model...@googlegroups.com
On 1/11/08, cfCharlie <spill...@yahoo.com> wrote:
> Does anyone feel that a "fat bean" may violate the closed for
> modifications open for extension OOP rule? Just curious...

No, because it's still easy to extend the bean to add functionality
or, in the dynamic world of ColdFusion, mixin different methods at
runtime. You actually can't close a CFC for extension because there's
no syntax to prevent inheritance.

Also bear in mind that you're really creating an application-specific
domain object that you wouldn't expect to be reused in the open/closed
context.

Besides, if you really feel the need to refactor the user bean later
on to create a more reusable base class, it's acceptable to do so (the
open/closed principle really ignores the sort of refactoring that has
become widely accepted since that principle was established nearly 20
years ago).

Dinner

no leída,
11 ene 2008, 20:00:4411/1/08
a model...@googlegroups.com
On Jan 11, 2008 1:06 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 10, 2008 11:59 PM, Dinner <vallia...@gmail.com> wrote:
> > function save() {
> > getConcreteStorageService.save(this);
> > }
> >
> > You get another level of abstraction tho, right?
>
> Yes. And you can keep adding abstractions. Every abstraction adds a
> (small) performance penalty and every abstraction adds more code you
> have to write (the first time, at least). Hence my reference to KISS
> and YAGNI.

It's that "the first time, at least" that I care about. Write
something good enough first, and you won't pay as much later.

Depends on where your... there's probably a word for it, but-- the
long in the beginning and short at the end, or short at the beginning
and long at the end.

People always want it "now" or "yesterday", but seldom do they take
into consideration the "long haul" or "big picture"-- it takes
training to even get them to accept "the right way" (unit tests,
etc..).

My bosses had to learn the hard way, which is sad, because I've been
touting some of this stuff for a long time.

> > Well, I don't know if I'm striving for purity, per say. Hehe! Moreso
> > just better, faster, smarter ways of doing things.
>
> Well, I won't argue "better" but I will argue faster in this case :)

Speed is relative, my friend!

I'd rather spend a bit more up front, and much less "later", than the
game I'm playing (or was playing, with a couple projects) right now...
I mean, I love flying helicopters as much as the next guy, but... :-)

> > The only thing that worries me about a "fat object", is that, the
> > fatter it is, the less flexible and fast.
>
> The extra abstractions will affect performance more than the extra
> methods in a "fat" object. As for less flexible... well, these are
> business domain objects so they are, by definition, going to
> encapsulate business logic that is likely to be specific to your
> application. The flexibility comes from Transfer in this case, being
> able to auto-generate / manage your basic user beans so you can reuse
> the same DB schema and Transfer does most of the rest.

I'm just wary of depending on something... strange, as I'm a really
trusting person, but hey.

I started out using the GenericORMController stuff, which I thought
was the bee's knees, thinking I might have to switch out Reactor at
some point.

But I needed stuff in my model, and didn't want to be tied to MG
either, so... the ORMStorageService was born! :-) Sorta trying a
generic idea like the one in MG (but not implemented nearly as cool,
obviously-- for lack of a real grasp of everything). Mostly it's a
placeholder... sorta :-/

> If you need a reusable smart user object, split the decorator in two:
> ReusableUser extends TransferDecorator, ApplicationUser extends
> ReusableUser. Like I say, pragmatic refactoring based on KISS / YAGNI.

I was thinking that persistence is such a fickle beast-- maybe I'll
have to save stuff to XML files, to use my nifty new SVN datasource
type deal (*giggles*) or whatnot.

I love the idea of inheritance for stuff (used right-- Eclipse has
shown me the folly of overdoing it), and I'm doing something similar,
but without the dependency on the ORM. Not that there's anything
wrong with depending on it, and just going whole hog-- "This App Will
Use X" is fine, and can let you worry about other stuff. Hell,
extending (inheritance) my AbstractStorageService means that I'm tied
to it, whereas maybe what I want is an interface. Hmm... it's working
well enough for now, and I run through enough projects to try
something different next time, if needed.

That is kind of a nice thing about having too much to do... you find
out how flexible your designs are /fast/! (And inversely, how
inflexible your "it's going to be /super/ flexible" methodology is.)

I wish I was a better programmer before I programmed, but that's the
age old "if I knew then, what I know now"... oh well. Part of the
wonderful life I live.

> > But perhaps a user is such a trivial thing, rolling a new one for each
> > job ain't that bad-- how many jobs does the average joe have, anyways?
>
> I reuse at a design level more than at a code level but the tools and
> frameworks I use mean that I can implement those reusable design very
> quickly in each new project.

Experience seems to be a key factor to this whole deal-- even with all
the books, and online resources, etc.. Really you just have to dive
in, try to make something flexible, and then flex 'em. After a while,
you get that "sixth sense" for when to apply X pattern, or whatnot.
And it's an ongoing process! I've constantly gotten better... but
it's all relative.

Plus, when you can *choose* what you're going to do, or how something
will behave, well... that's a factor too.

I think the best is to actually "mingle", as much as possible, with
excellent coders such as yourself. By "mingle" I mean conversations
such as this (although this isn't as cool as the spoken word), where
we're bouncing these concepts around, profiting from those with more
experience, and, oddly, those with less. What a trip life is, you
know? Totally counter-intuitive at times (well, depending on how you
intuit, I reckon ;]). How could a "mix" be better than a bunch of
experts? Yet, it is... at least in my experience.

Thanks for joining the fray, man, I value your, and everyone who's
contributed, input and thoughts on these matters.

Quite a fun thread, no doubt!

--
Travel is only glamorous in retrospect.
Paul Theroux

Sean Corfield

no leída,
11 ene 2008, 22:02:1711/1/08
a model...@googlegroups.com
On Jan 11, 2008 5:00 PM, Dinner <vallia...@gmail.com> wrote:
> It's that "the first time, at least" that I care about. Write
> something good enough first, and you won't pay as much later.

Right, and I'm all for that but you are going *beyond* that: you are
spending more time up front because you are imagining things that
"could" change even tho' they're very unlikely. In other words, I
think you're over-engineering and over-analyzing. But then it's hard
to make some of those judgment calls without lots of experience... :)

> Experience seems to be a key factor to this whole deal-- even with all
> the books, and online resources, etc.. Really you just have to dive
> in, try to make something flexible, and then flex 'em. After a while,
> you get that "sixth sense" for when to apply X pattern, or whatnot.

Yup, that's about the size of it.

> Quite a fun thread, no doubt!

Yup. I enjoy the threads that dig more deeply into architecture and design :)

Dinner

no leída,
12 ene 2008, 12:29:2312/1/08
a model...@googlegroups.com
On Jan 11, 2008 3:12 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On 1/11/08, cfCharlie <spill...@yahoo.com> wrote:
> > Does anyone feel that a "fat bean" may violate the closed for
> > modifications open for extension OOP rule? Just curious...
>
> No, because it's still easy to extend the bean to add functionality
> or, in the dynamic world of ColdFusion, mixin different methods at
> runtime. You actually can't close a CFC for extension because there's
> no syntax to prevent inheritance.

I'd say that maybe Sean is really saying yes. LOL. Bear with me here:

Extending the bean (as in, inheritance) isn't really having a fat
"base" bean. It's "extending" that base "bean" (also known as
"object") into a "business object", where the fatness comes in-- which
fits with inheritance, from what I gather (inheritance is probably the
most familiar pattern to me). InputStream was a good example-- look
how it gets "fat"-- /organized/!

I'd have a "base" (also called "abstract", I think) user object, that
did all the things a normal user object would do; set username, set
password, password strength, last login, failed login attempts...
maybe last IP and stuff, that you'd probably /mostly/ be having in the
majority of the projects you're planning to do. Maybe some of that
would be somewhere else, but you get the idea.

Then I'd use some inheritance and extend that object into my
UserBusinessObject (maybe a few sub-classes of AbstractUser, or
UserBusinessObjectValidator?).

But you have to be careful with inheritance, since you are locked into
that base class-- er, object. I mean bean. Hmm... guess object is
good. Anyways;

That's why it's recommended to do interfaces where appropriate, so
you're not bound to that base object at all. Take CFEclipse-- we've
got a buch of these editor actions (so many that it makes one think
that a pattern could be applied), some of which extend an object that
has an interface, and then in turn implement that same, already
extended interface.
But that's not all-- if we want to change something (like, for
instance, put the actions in an ActionSet so one can take advantage of
the built-in Eclipse code that does a lot of work for you), we've got
to change each one of those actions-- no big deal, that's what search
and replace and nifty refactoring tools are for, right? But things
like that can make or break a feature release, bug patch, or whatever,
you know? Time is money. If they all extended an abstract interface
(or even just an abstract class)-- bang, in one fell swoop, in one
place, they all change, but they don't know it. Eh...

And the thing is, even tho you can do all kinds of stuff with CF--
it's so flexible, almost as flexible as like, Javascript-- that
doesn't mean the patterns don't apply. It's not the Java "interface"
they're talking about, it's the /idea/ of an interface.

Thus, while CF, the language, doesn't prevent extension, I think the
idea is more design/maintenance related. There's not much you'd need
to change with that base user object, so, even tho it's easy to roll a
new one when needed, why not have one ready? If you made it lean
enough, you can fatten it up quite nice, wherever you need it, in
various ways.

Which, of course, is rather circular, since, what if your user object
/really/ changed? Guess that's a risk you have to take. "What if
your user turns into a car" is somewhat different than "what if I need
to store this in another manner".

As far as choosing to extend a concrete ORM object-- I'd rather try to
do an interface, since (and maybe this is different than "most
people") I know I'll be using objects that need to be stored in ways
other than a database. DAO doesn't mean "database access object", and
"data" is so loaded-- I went with storage, but maybe I should call it
persistence? Hmmm... LOL.

Hell, look at the situation with Reactor and Transfer-- why does MG
even have a generic ORM controller?

Why is there that level of abstraction?

I kind of like the idea-- so long as I'm within MG, I can code to more
of an interface, so why not bring that idea into my model, so I can
use my model with like, fusebox or mach or something?

Maybe I'm like "damn, I want to share this thing, but it uses an ORM--
Reactor, specifically. And I see a lot of people are using Transfer.
It would be a shame to force one or the other to change, just to use
my 'model'". This idea is of course /horribly biased/ towards using
an ORM of some sort. But that's why I called it ORMStorage. And why
it's a child of an abstract-- of course now I'm thinking, where should
I use interfaces? And I hear CF8 actually has things called
interfaces ... hmmmm... [= (I'd like to stay compatible with CF7
for a year or so at least tho, if possible-- another concern!!
Aaaaaa! How does one weight it all?!?! Heh. )

I think my take on the "open/closed" pattern is somewhat different from Seans.

And heck, just trying to wrap my head around AOP has shown me that
there are like a million ways to skin a cat. It's also shown me that
how your code is organized is important.

But I of course bow to his greater experience, I'm just a young(ish)
padawan... this OO stuff is still sorta new to me. I just thought
that maybe Sean was grouping some stuff into his "smart bean" that
implied it was more than just a single bean, if that makes sense.
Crap, probably mangled the expression of this idea, and maybe my logic
is silly, but I feel there's something... hmmm.

Rather stream of thought type post, neh? Bah. Just musing, really.
It's better to think about things before you do them, I figure. Maybe
prototype an idea or two, ya know. Hope I don't come off as uppish or
whatever. =]

--
Rudeness is the weak man's imitation of strength.
Eric Hoffer

Dinner

no leída,
12 ene 2008, 12:54:1412/1/08
a model...@googlegroups.com
On Jan 11, 2008 8:02 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 11, 2008 5:00 PM, Dinner <vallia...@gmail.com> wrote:
> > It's that "the first time, at least" that I care about. Write
> > something good enough first, and you won't pay as much later.
>
> Right, and I'm all for that but you are going *beyond* that: you are
> spending more time up front because you are imagining things that
> "could" change even tho' they're very unlikely. In other words, I
> think you're over-engineering and over-analyzing. But then it's hard
> to make some of those judgment calls without lots of experience... :)

With all due respect kind sir, aren't you assuming you know my project
objective, or requirements or whathaveyou? =]

For my scenario, the format in which things are persisted can and will change.

Would it still be over-engineering to abstract it a bit, if that is
the case? (Not that I don't love engineering things, so
over-engineering is something I have to watch)

I just really love a well engineered object. A pen that was designed
to have it's cap put right back on it after opening, vs. one that
expects you to hold it in your hand while writing.

> > Experience seems to be a key factor to this whole deal-- even with all
> > the books, and online resources, etc.. Really you just have to dive
> > in, try to make something flexible, and then flex 'em. After a while,
> > you get that "sixth sense" for when to apply X pattern, or whatnot.
>
> Yup, that's about the size of it.

And believe me, milking your brain has been wonderful. I really value
your experience, and your willingness to share it with me. You can
condense that 16 years into diamond like nuggets of sage advice.
"Apply that pattern... here!" Sweet, man.

I'm thinking hard about the basic point you're getting at, which I do
do-- think "too far" down the line-- maybe that first year is all I
should worry about. It will be somebody else's problem eventually,
and can they even manage to maintain it? Currently, it's going to be
a little like the Romans leaving the Barbarians to their own devices.
"There goes the aqueducts!" Heh. Actually I'm growing replacements,
but it's a valid concern. There really are so many factors that go
into software design.

I should note that, what I'm doing in my experimental "someday open
source" projects is different from what I've done at my Jay Oh Bee--
Sadly, I don't get enough time to do things the way I want too there.
It's their decision tho-- they'll pay the price later, as they've
done, time and again. I'm just a low head on the totem pole.
"Produce produce produce! That's what matters! Test Driven
Design?!?! You've got to be kidding me, this thing's due tomorrow!"
sadly, *I'm* the one that usually pays their price, later, and for
overtime (If I was a contractor, this would be way cooler, of course.
Also, I'm more interested in progress than making money, as it were).

> > Quite a fun thread, no doubt!
>
> Yup. I enjoy the threads that dig more deeply into architecture and design :)

Thanks again for sharing your knowledge. I don't agree about the
persistence debate, at least for my goals, but that's cool, right? I
don't want to appear unconvincable.

--
Quotation, n: The act of repeating erroneously the words of another.
Ambrose Bierce

Sean Corfield

no leída,
12 ene 2008, 13:31:0412/1/08
a model...@googlegroups.com
On Jan 12, 2008 9:29 AM, Dinner <vallia...@gmail.com> wrote:
> > On 1/11/08, cfCharlie <spill...@yahoo.com> wrote:
> > > Does anyone feel that a "fat bean" may violate the closed for
> > > modifications open for extension OOP rule? Just curious...
> > No, because it's still easy to extend the bean to add functionality
> > or, in the dynamic world of ColdFusion, mixin different methods at
> > runtime. You actually can't close a CFC for extension because there's
> > no syntax to prevent inheritance.
> I'd say that maybe Sean is really saying yes. LOL. Bear with me here:

No, I'm saying the fat bean in CF does not inherently violate the
open/closed principle. Java and some other languages have specific
constructs that prevent you extending them and therefore you can
easily write a class in Java that violates the open/closed principle.

> Extending the bean (as in, inheritance) isn't really having a fat
> "base" bean.

You can't tell that without seeing the base bean.

> It's "extending" that base "bean" (also known as
> "object") into a "business object"

That's not the scenario we're discussing.

> I'd have a "base" (also called "abstract", I think) user object, that
> did all the things a normal user object would do

As I said, that's a possibility for refactoring *if* you need to reuse
the user bean and you can't do it via simple extension. Bear in mind
however that using Transfer means that all the basic get/set
operations are determined by the underlying database schema and you
don't have to write any of that code. In other words, the "base" bean
you're referring to is more likely the bean generated by Transfer
(which is *not* a base class for the business object since Transfer
uses decorators instead).

> That's why it's recommended to do interfaces where appropriate, so
> you're not bound to that base object at all.

Make sure you use "interface" loosely here - Smalltalk and Ruby use
convention instead of actual interfaces (because they don't have
interfaces). The interface construct is a product of the Java
language. Don't get too hung up on it.

Your approach - going with abstraction from day one - is pretty much
completely opposed to what I'm suggesting :)

> Which, of course, is rather circular, since, what if your user object
> /really/ changed? Guess that's a risk you have to take. "What if
> your user turns into a car" is somewhat different than "what if I need
> to store this in another manner".

That's the entire point of KISS / YAGNI. Some change is obvious and
can be anticipated (and designed in) but most change is not obvious
and so you are wasting time trying to cater for all possibilities up
front. You are spending additional time getting the application
working by trying to anticipate changes that may not happen or may
happen in a direction that is at odds with your abstracted design.

Now, that's not to say that you shouldn't anticipate change. You still
need to design with potential change in mind but you only need to go
far enough to not paint yourself into a bad corner.

> Hell, look at the situation with Reactor and Transfer-- why does MG
> even have a generic ORM controller?

First off, the "GenericORMController" isn't really an abstraction per
se - there is no ReactorController or TransferController. It's generic
only insofar as it provides basic "generic" CRUD and list operations.

Second, behind the scenes, there is an AbstractORMAdapter - and that
is the "abstract base class" that has Reactor-specific and
Transfer-specific implementation. Even there, this is all about
creating adapters rather than separating functionality into common
logic and specific logic (i.e., it's closer to an interface than the
bean extension issue we are discussing).

And it needs that adapter because Reactor and Transfer provide different APIs.

> I kind of like the idea-- so long as I'm within MG, I can code to more
> of an interface, so why not bring that idea into my model, so I can
> use my model with like, fusebox or mach or something?

Well, that really has nothing to do with coding to an interface -
that's about layering your application and ensuring you have no
dependencies in your model on the presentation layer framework. You
should always be able to use your model with any presentation
framework - that's the idea behind the cat club frameworks sample code
I published as well as the LitePost sample blog application created
specifically to show how to write a framework-independent model.

> Aaaaaa! How does one weight it all?!?! Heh. )

You're slipping into "analysis paralysis" :)

> I think my take on the "open/closed" pattern is somewhat different from Seans.

I went and read the literature before I answered to make sure I was
basing my answer on the standard definitions :)

> that maybe Sean was grouping some stuff into his "smart bean" that
> implied it was more than just a single bean, if that makes sense.

I'm not sure what you mean. A "bean" is just a style of object - one
that encapsulates its data via get/set methods. Most domain objects
are beans (but not all beans are domain objects).

> It's better to think about things before you do them, I figure.

...but perhaps not *over*-think things ;)

Sean Corfield

no leída,
12 ene 2008, 13:43:1712/1/08
a model...@googlegroups.com
On Jan 12, 2008 9:54 AM, Dinner <vallia...@gmail.com> wrote:
> For my scenario, the format in which things are persisted can and will change.

Then you have a very unusual project and you should caveat your
discussions with that so that others don't think you are offering
blanket recommendations :)

> Would it still be over-engineering to abstract it a bit, if that is
> the case?

If you really know for a fact that you might need an ORM for a
non-database persistence mechanism, you would need to abstract further
than just Transfer (or Reactor). That level of abstraction is going to
have an extreme impact on your code in regards to how you deal with
the original discussion at hand. You essentially can't use Transfer or
Reactor in the standard way at all because both require your business
objects to extend something specific in those frameworks. You're
essentially going to have to build an entire framework around them in
order to isolate your code from them. That's a lot of work that goes
far beyond what we were discussing in this thread.

> I should note that, what I'm doing in my experimental "someday open
> source" projects is different from what I've done at my Jay Oh Bee--

I will offer some advice there: the best open source projects grow out
of real solutions to real business problems. Trying to create some
open source project in isolation with no real business drivers and no
real users is likely to create something that doesn't actually solve
anyone's problems. And, yes, the general work environment is often not
conducive to doing this which is unfortunate.

Dinner

no leída,
12 ene 2008, 17:16:3012/1/08
a model...@googlegroups.com
On Jan 12, 2008 11:31 AM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 12, 2008 9:29 AM, Dinner <vallia...@gmail.com> wrote:
> > > On 1/11/08, cfCharlie <spill...@yahoo.com> wrote:
> > > > Does anyone feel that a "fat bean" may violate the closed for
> > > > modifications open for extension OOP rule? Just curious...
> > > No, because it's still easy to extend the bean to add functionality
> > > or, in the dynamic world of ColdFusion, mixin different methods at
> > > runtime. You actually can't close a CFC for extension because there's
> > > no syntax to prevent inheritance.
> > I'd say that maybe Sean is really saying yes. LOL. Bear with me here:
>
> No, I'm saying the fat bean in CF does not inherently violate the
> open/closed principle. Java and some other languages have specific
> constructs that prevent you extending them and therefore you can
> easily write a class in Java that violates the open/closed principle.

Hmmm... doesn't it follow that languages that have specific
"anti-extension"constructs, would be *harder* to "open"?

But I'm not talking implementation, I'm talking the rule of thumb that
I got from this:

http://en.wikipedia.org/wiki/Open/closed_principle

Trying to get at the Zen-like "truth" (even tho it's an illusion ;) of
the principle. Being able to apply it to any language, if only by
convention.

> > Extending the bean (as in, inheritance) isn't really having a fat
> > "base" bean.
>
> You can't tell that without seeing the base bean.

I was commenting on your comment about using mixins or inheritance.
You do mean inheritance whey you say "extend", right? The actual cfc
attribute "extends="? Damn these non-specific terms! We need another
domain language, or whatever. :-)

I stand by my idea that a big ol' bean is inherently less flexible
than a little bean. But if you need a big ol' bean... it's the
classic "fighter-bomber" conundrum. I love how this stuff extends
to... er- :-)

> > It's "extending" that base "bean" (also known as
> > "object") into a "business object"
>
> That's not the scenario we're discussing.

Ah. I was aiming at finding out what you meant by "fat bean"-- "bean"
seems like one of those words... is the object fat because it has
mix-ins, and extends other, more localized objects, or are you
referring to a bean that's made up solely of it's own bulk?

Would the bean sorta become more of an interface, if it contains a
bunch of logic, but only exposes it as simple getters and setters?

Could a "bean" really be an object composed of other objects?

Or does that violate the "bean" principle? I'm thinking you're saying
something along these lines, and I'm trying to understand... don't
mean to be veering off...

> > I'd have a "base" (also called "abstract", I think) user object, that
> > did all the things a normal user object would do
>
> As I said, that's a possibility for refactoring *if* you need to reuse
> the user bean and you can't do it via simple extension. Bear in mind
> however that using Transfer means that all the basic get/set
> operations are determined by the underlying database schema and you
> don't have to write any of that code. In other words, the "base" bean
> you're referring to is more likely the bean generated by Transfer
> (which is *not* a base class for the business object since Transfer
> uses decorators instead).

Indeed! It seems like it would be tempting to make that Transfer
object your business object! Same with Reactor.

That's actually why I've been thinking about an ORM that doesn't
depend on a database for storing, or building, those relationships.
Maybe it would be an option, but I'm pretty interested in things like
Torque... maybe have a thing that can introspect a DB, or use an XML
file, or etc..

I'm not developing anything along these lines, just thinking about how
nice it might or might not be.

> > That's why it's recommended to do interfaces where appropriate, so
> > you're not bound to that base object at all.
>
> Make sure you use "interface" loosely here - Smalltalk and Ruby use
> convention instead of actual interfaces (because they don't have
> interfaces). The interface construct is a product of the Java
> language. Don't get too hung up on it.

Hehe! That's one of the points I'm trying to make regarding the
open/closed principle-- it doesn't rely on implementation, as much as,
well, thought-constructs.

> Your approach - going with abstraction from day one - is pretty much
> completely opposed to what I'm suggesting :)

Well, I'm not talking needless abstraction. Re: my comments on the
EditorActions and CFEclipse.

Abstract interfaces are interesting beasts...

abstraction is powerful, and I read you loud and clear on not getting,
um, too abstract? ;-)

> > Which, of course, is rather circular, since, what if your user object
> > /really/ changed? Guess that's a risk you have to take. "What if
> > your user turns into a car" is somewhat different than "what if I need
> > to store this in another manner".
>
> That's the entire point of KISS / YAGNI. Some change is obvious and
> can be anticipated (and designed in) but most change is not obvious
> and so you are wasting time trying to cater for all possibilities up
> front. You are spending additional time getting the application
> working by trying to anticipate changes that may not happen or may
> happen in a direction that is at odds with your abstracted design.

But you can use logical grouping to figure out where abstraction, and
sub-classes and such will, or might conceivably, come in handy.

And one of the hardest parts I got from the Pragmatic Programmer, as
far as implementing it in my own code, is the really, really flexible
approach to thinking that they promote. They're like, "just think
about 'what if'-- have you done your stuff in a way that is de-coupled
enough to be flexible?' -- persistence is one of the main ones that
is used as an example.

> Now, that's not to say that you shouldn't anticipate change. You still
> need to design with potential change in mind but you only need to go
> far enough to not paint yourself into a bad corner.

Ha! Take some, but not too much! Story of life. =]

I'm just working on the rules of thumb that let you do this stuff fast
(figuring out what should be sub-classed, what should be interfaced,
etc.), and then get into detail, but in a flexible, adaptable manner.

Experience, and maybe logic, if you don't have experience, is probably
the main ways of determining this stuff. ;-)

> > Hell, look at the situation with Reactor and Transfer-- why does MG
> > even have a generic ORM controller?
>
> First off, the "GenericORMController" isn't really an abstraction per
> se - there is no ReactorController or TransferController. It's generic
> only insofar as it provides basic "generic" CRUD and list operations.

Didn't mean to imply it was an concrete abstraction. Abstraction as
in interface, sorta? It doesn't have to be a "Database ORM" it's
controlling, right?

> Second, behind the scenes, there is an AbstractORMAdapter - and that
> is the "abstract base class" that has Reactor-specific and
> Transfer-specific implementation. Even there, this is all about
> creating adapters rather than separating functionality into common
> logic and specific logic (i.e., it's closer to an interface than the
> bean extension issue we are discussing).

Thank you for touching on this. Helps me "get" these patterns.

Why is an adapter not a separation of functionality into common logic
and specific logic?

An interface doesn't take the specific logic (implementation), and
hide it behind a sort of "common logic"? "So long as you speak the
common tongue, I'll take care of the details" type of deal?

> And it needs that adapter because Reactor and Transfer provide different APIs.

So it takes the specifics of the Reactor and Transfer APIs, and hides
them behind a common, um, really simple API (thinking of MG as the
application in this instance)?

Or am I just horribly mangling the concepts?

> > I kind of like the idea-- so long as I'm within MG, I can code to more
> > of an interface, so why not bring that idea into my model, so I can
> > use my model with like, fusebox or mach or something?
>
> Well, that really has nothing to do with coding to an interface -
> that's about layering your application and ensuring you have no
> dependencies in your model on the presentation layer framework. You
> should always be able to use your model with any presentation
> framework - that's the idea behind the cat club frameworks sample code
> I published as well as the LitePost sample blog application created
> specifically to show how to write a framework-independent model.

Yes, I'm trying to manage dependencies! Like, should I "depend" on
using a database to store my information? Or coldfusion's session
scope?

In the LitePost and I think the cat club examples, how hard would it
be to switch storage formats to, say, XML files instead of a database?

Wouldn't you have to work all those DAOs over by hand?

I love having that stuff generated for me, like off of XML or database
schema's or whatnot.

> > Aaaaaa! How does one weight it all?!?! Heh. )
>
> You're slipping into "analysis paralysis" :)

Hehe! I wasn't really lamenting any current situation, moreso the
amazing variability that comes with the territory. Release cycles,
development cycles, available resources, "future" resources, etc..

Then throw in like validation, and authentication, and using AOP
techniques... this is a heady brew, and it's probably why decent
programmers should be paid decent money. LOL.

Just defining people's business domain models should pay big, but I
see poor schmucks (like myself) suckered into doing it all the time.
"Here's an incredibly general spec, we don't know who will be
maintaining it, or what exactly we're "spec"ing, but I'd like to have
something on my desk by Tuesday". Course, there is freedom in that
approach. Heh. *sigh* Sometimes. =]

I commented about the quite clich[funky e] motto of "just do it"
earlier... and it sorta fits in with Agile development, as I
understand it. As you said, you can always refactor (and, the same
thing that helps people realize their domain model-- seeing it laid
down in axioms and whatnot-- is the same effect we get from seeing
things laid down in code. "Ah, you mind thinks", "this is less
ethereal".

> > I think my take on the "open/closed" pattern is somewhat different from Seans.
>
> I went and read the literature before I answered to make sure I was
> basing my answer on the standard definitions :)

Are you saying that it's implementation based? I was thinking it was
more Zen-like.

The lotus is open in the morning and closed at night type of deal.

> > that maybe Sean was grouping some stuff into his "smart bean" that
> > implied it was more than just a single bean, if that makes sense.
>
> I'm not sure what you mean. A "bean" is just a style of object - one
> that encapsulates its data via get/set methods. Most domain objects
> are beans (but not all beans are domain objects).

The fact that everything is "data" throws a semantic wrench into the
equation. And it seems like your definition of "bean" isn't the one I
read. Seems like beans are "skinny" by definition, depending on what
you define "data" as. At least, for some reason, I don't like the way
bean has been thrown around. Take this, off of some random web page:

Bean def:
1. Enterprise Java Beans. These are very seperated from the rest. EJBs
has very strict definition and rules to follow when creating such
classes. (session beans, entity beans etc...)

2. IDE Component Beans. The loose definition of this type of bean is
"any Java class that implements Serializable and exposes public
properties with get/set methods". So IDE can generate a nice GUI page
for the developer to change the properties of the class, and the IDE
can easily save the state of the class.

3. JSP Beans. These beans are less restricted and only need to exposes
get/set methods for special tag usage in JSPs.

4. Bean which people used it to means "small classes". Classes only
contains get/set methods and not much of other logics.

5. Or the last, no practicalar meaning at all, people just use Bean to
name their classes so they look cool.

I think you're talking about #4, but I don't see how they could then
be considered fat. Which is why I'm trying to move away from the
usage of the word "bean"...

> > It's better to think about things before you do them, I figure.
>
> ...but perhaps not *over*-think things ;)

Spoken as a true Engineer (which I'm not =]) : "Impossible!"
Heh. I *am* driving a choo-choo or two, tho, so, hmmm. :-)

--
The camera doesn't make a bit of difference. All of them can record
what you are seeing. But, you have to SEE.
Ernst Haas

Jon Messer

no leída,
12 ene 2008, 18:23:1712/1/08
a model...@googlegroups.com
Wow, this thread has gotten pretty abstract.   ;-)

I think one of the things that causes a LOT of confusion is the word "bean" (it's really starting to bug me a little because of the vague interpretations or implied meanings).

In the CF community it seems to be used most often to describe simple data containers with getX/setX methods (skinny glorified structs), but in the larger programming world I would say it just means a class the hides it's private instance data behind assessors and mutators. If that class is a simple data container or a rich business object that has an inheritance tree ten levels deep it could still be called a bean.

Also it's perfectly valid (and even desirable) to have a "bean" contain other "beans" not just simple data. If a person has an address and an address has a city,street,state have address be a separate class, then if later on you want to start collecting say AddressType you modify address not person, person doesn't care that address now has a type.

As to your concern about "depending" on the ORM, that could be valid. And it's easily worked around, define your business objects as stand alone classes not as transfer decorators or reactor records, write yourself a PersistanceService (not really ORMService because you suggest things other than (R)elational like file,session or xml) that exposes save,delete,create,list whatever. Then have that use TransferAdapter, XMLAdapter, PsychicAdapter or whatever to do the actual persistence.

As to the over-engineering I have to agree with Sean, you don't have to plan for EVERY possible change or use case down the road. If you just follow the KISS/YAGNI/DRY/JFDI  ;-)  path then any changes later shouldn't be that hard.

Hope I'm not adding any dissonance to this topic.


Peter Bell

no leída,
12 ene 2008, 18:20:4712/1/08
a model...@googlegroups.com
On 1/11/08 8:00 PM, "Dinner" <vallia...@gmail.com> wrote:
> It's that "the first time, at least" that I care about. Write
> something good enough first, and you won't pay as much later.
>
> I'd rather spend a bit more up front, and much less "later", than the
> game I'm playing (or was playing, with a couple projects) right now...
> I mean, I love flying helicopters as much as the next guy, but... :-)


I'd just like to +1 some of what Sean has been saying. I have spent a lot of
time on thinking about internal frameworks and approaches for my SPL. While
I learnt from all of it, what really works is coding something simple that
solves a real, immediate problem and then refactoring when you come across a
requirement that your initial approach doesn't support.

Don't write a generic library for validating forms. Hard code validation for
your first two forms and then see if maybe you could abstract some elements
of the code into a helper class that they could both use. Don't try to write
the ultimate templating language, just write a simple template that works
for your first screen and then extend it as you come across other screens
with additional requirements. Don't write a generalized approach to
persisting data. Just find some way of saving your first object, then your
second, then over time see if you can refactor to cut down on code. If
you're building a framework, stop - and start building a single project. By
the end of the third actual project you'll start to have the beginnings of a
framework and after 20 you'll have a kick ass framework for the collection
of use cases you have to solve.

I find all the time that my best learnings come from choosing a path - any
path, trying it out, and then refactoring if required. I've tried most of my
design decisions every which way. I have a pseudo-page controller in my
framework, but I'm now also adding an event controller and a remote
controller (to solve specific problems in projects I need to deliver this
month) so now I have three approaches for only a few extra lines of code. I
didn't ever anticipate needing an event controller model, but the
requirement came up so I just added another way to call my framework and it
works great. Initially my framework was for building entire apps, but I have
a project where I just need to add some features to a Savvy app, so I'm
refactoring so you can just drop it in. Initially my framework required
dedicated hosting as it assumed some files would be outside of the web root.
Refactoring to support either shared or dedicated hosting (because I have a
project I want to use my framework on which uses shared hosting) took a
morning.

I'd spend some time reading up on Agile and XP - really. I fully understand
where you are coming from, but in the general case, unless you're rebuilding
something you've done many times before and you KNOW of some things you'll
need to abstract out (in which case you won't be worrying about it - it'll
be an obvious design choice to you given your previous experiences), just
get a project working and allow the real use cases to drive the patterns and
areas of variability naturally. Its quicker, better and it ends up being a
lot more fun!

Best Wishes,
Peter



Sean Corfield

no leída,
13 ene 2008, 1:23:0613/1/08
a model...@googlegroups.com
Dinner, how do you ever get anything concrete done?

You are the hardest person to discuss design/architecture with because
you don't seem to be able to stay on topic - you expand every single
item to the size of the cosmos :)

OK, let's see where we get to on this round (and take note that both
Jon and Peter are urging you to scale back your abstractions).

On Jan 12, 2008 2:16 PM, Dinner <vallia...@gmail.com> wrote:
> Hmmm... doesn't it follow that languages that have specific
> "anti-extension"constructs, would be *harder* to "open"?

You're mixing several levels there. Open/closed doesn't apply to a
language, it applies to a class. So it can be easier to accidentally
write a closed class in a language that allows that, yes.

> But I'm not talking implementation, I'm talking the rule of thumb that
> I got from this:
>
> http://en.wikipedia.org/wiki/Open/closed_principle

...which talks about classes which are implementations pretty much by
definition. Strictly speaking it's referring to "software entities
(classes, modules, functions, etc.)" but it's specifically about
source code, therefore it is about implementation.

> Trying to get at the Zen-like "truth" (even tho it's an illusion ;) of
> the principle. Being able to apply it to any language, if only by
> convention.

Again, you're mixing levels. Open/closed applies to software entities,
i.e., code. It automatically applies to any structured language.

> You do mean inheritance whey you say "extend", right?

A child class inherits from a base class. A child class extends a base
class. A child class is a specialization of a base class.

> I stand by my idea that a big ol' bean is inherently less flexible
> than a little bean.

It depends on how you define "flexibility" but I understand your
point. Yes, for the most part, having lots of small classes is going
to be more flexible - but it's also going to be more complex to deal
with and potentially slower and those may not be acceptable trade
offs. You never seem to mention trade offs in any of your responses -
only abstract ideals - so I'm wondering whether you actually
understand that real world projects require trade offs? :) :)

> Ah. I was aiming at finding out what you meant by "fat bean"-- "bean"
> seems like one of those words... is the object fat because it has
> mix-ins, and extends other, more localized objects, or are you
> referring to a bean that's made up solely of it's own bulk?

It's why I prefer the term "richly functional business domain object"
or something similar. The "plumpness" is meant to indicate the
richness of business functionality in the bean. As opposed to "skinny"
- with just data and get/set methods.

> Would the bean sorta become more of an interface, if it contains a
> bunch of logic, but only exposes it as simple getters and setters?

A bean can contain "a bunch of logic". It is a bean by definition of
exposing its data only through getters and setters.

> Could a "bean" really be an object composed of other objects?

Yes, beans can be composed of other objects.

> Indeed! It seems like it would be tempting to make that Transfer
> object your business object! Same with Reactor.

Well, they can't really be "business objects" because they can't
contain any "business logic" but they could be (anemic) domain
objects.

> I'm not developing anything along these lines, just thinking about how
> nice it might or might not be.

I think a million dollars might be nice but that's not very relevant
to the discussion either ;)

> Hehe! That's one of the points I'm trying to make regarding the
> open/closed principle-- it doesn't rely on implementation, as much as,
> well, thought-constructs.

See above. Open/closed is really about code and implementation.

> Abstract interfaces are interesting beasts...

In most languages contexts an interface is abstract by definition.

> But you can use logical grouping to figure out where abstraction, and
> sub-classes and such will, or might conceivably, come in handy.

You can use all manner of rules of thumb and draw on your experience
etc. I prefer to consider where "abstraction, and sub-classes and such
will" come in handy rather than "might conceivably"...

> And one of the hardest parts I got from the Pragmatic Programmer, as
> far as implementing it in my own code, is the really, really flexible
> approach to thinking that they promote.

I think you're taking away just part of the message (at the expense of
the important part - pragmatism).

> Didn't mean to imply it was an concrete abstraction.

Now there's a tautology if ever I heard one! :)

> Abstraction as in interface, sorta? It doesn't have to be a "Database
> ORM" it's controlling, right?

In this case you're right - the GenericORMController relies on the ORM
adapter and ORM metadata to get its job done so it's *possible* that
you could write an XML persistence adapter for Model-Glue and still
use the GenericORMController on that. Being "generic" doesn't make
something an "abstraction" except in a very general sense. For
example, "generic programming" is a term used in the context of C++
(and, now, Java since they added syntax / semantics for it). Generic
programming involves creating code templates that usually don't
involve inheritance or polymorphism or abstraction. In many ways,
generic programming is the antithesis of abstract programming but they
can often be used to achieve similar goals.

> Why is an adapter not a separation of functionality into common logic
> and specific logic?

Because the functionality is all in the object it is adapting - the
adapter contains only enough code to translate the arguments / return
types and map the method calls. The adapter doesn't add functionality
- it just makes the existing functionality available to a new client.

> An interface doesn't take the specific logic (implementation), and
> hide it behind a sort of "common logic"?

No. An interface is bereft of logic. An interface is a specification
of the way you interact with the implementation but it says nothing
about what the implementation does. Interfaces are both very loose
contracts and at the same time very strict contracts. They are loose
in that any implementation is acceptable if it provides compatible
methods - that do absolutely anything. They are strict in that the
implementation must follow the interface exactly - it can only be a
pure superset, not a subset, nor a variant.

> So it takes the specifics of the Reactor and Transfer APIs, and hides
> them behind a common, um, really simple API (thinking of MG as the
> application in this instance)?

Yes.

> Or am I just horribly mangling the concepts?

Some of them, yes, but not that last point :)

> Yes, I'm trying to manage dependencies! Like, should I "depend" on
> using a database to store my information? Or coldfusion's session
> scope?

Not all dependencies are created equal tho'. Some dependencies are
fine. And in fact a class must either be dependent on something or
have something dependent on it - otherwise it isn't actually useful
(if nothing depends on you, you are pointless :)

> In the LitePost and I think the cat club examples, how hard would it
> be to switch storage formats to, say, XML files instead of a database?

They were designed to work with a database. Or at least the cat club
app was. I haven't looked at the LitePost example but I think it
assumes a database.

> Wouldn't you have to work all those DAOs over by hand?

If they were designed for a database, yes. Most people seem happy to
use a database with those applications tho'...

> I love having that stuff generated for me, like off of XML or database
> schema's or whatnot.

I don't mind Transfer's black box generation approach (and the same
goes for ColdSpring and, to some extent, Reactor) but I don't like
"generated code" per se. In other words, I won't use a generator to
write code that I then need to integrate / extend. Most code
generators simply aren't flexible enough for my taste (and if they
were, they'd be too complicated to use).

> I commented about the quite clich[funky e] motto of "just do it"
> earlier... and it sorta fits in with Agile development, as I
> understand it.

The "just do it" mentality you refer to is nothing like agile
development (at least, not like agile done right). A lot of people
mischaracterize agile as an excuse to just throw together the simplest
thing that works and you're done. Think of agile as "make it work and
then make it right" rather than just "make it work". That's why
refactoring is such a key element. It's the same with TDD: you make
the test pass and then you refactor to make the code "right" (without
breaking the test).

> > > I think my take on the "open/closed" pattern is somewhat different from Seans.

> Are you saying that it's implementation based? I was thinking it was
> more Zen-like.

See above. Your take was (is?) different.

> The fact that everything is "data" throws a semantic wrench into the
> equation.

I guess that depends on whether you think functions and logic are
"data" as well?

> 1. Enterprise Java Beans.

They're still beans at heart but definitely a complex beast.

> "any Java class that implements Serializable and exposes public
> properties with get/set methods".

That's the classic "JavaBean" definition.

> 3. JSP Beans. These beans are less restricted and only need to exposes
> get/set methods for special tag usage in JSPs.

A simpler variant (that doesn't need to be serializable) if I recall.

> 4. Bean which people used it to means "small classes".

I think you're projecting. Some people may incorrectly use it to mean that ;)

> 5. Or the last, no practicalar meaning at all, people just use Bean to
> name their classes so they look cool.

See my comment on 4.

> I think you're talking about #4

Nope. The key feature in definitions 1, 2 and 3 is data encapsulated
by set/get methods. Beans can be large or small.

> Which is why I'm trying to move away from the
> usage of the word "bean"...

And adopt what term in its place?

A bean is an object with a particular type of API. Lots of things can
be beans. Some (most) business domain objects are beans but the
reverse is not true (so you cannot use "business domain object"
instead of bean, for example).

I hope that helps?

Dinner

no leída,
13 ene 2008, 14:07:1213/1/08
a model...@googlegroups.com
On Jan 12, 2008 11:43 AM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 12, 2008 9:54 AM, Dinner <vallia...@gmail.com> wrote:
> > For my scenario, the format in which things are persisted can and will change.
>
> Then you have a very unusual project and you should caveat your
> discussions with that so that others don't think you are offering
> blanket recommendations :)

Heh. My bad! I have a habit of thinking others know what I'm
thinking, which isn't how communication works (Unless people are on
acid or other hallucinogens. heh).

And I'm not recommending anything! Ahhh! I'm thinking aloud, doing
my best to move from a procedural attack angle, to an object oriented
(or "loose collection of algorithms" ;) one.

Not just object, but aspect, as well (I think ColdSpring is
super-powerful "pattern").

I have my own reasons for the angles I'm taking, rest assured, I'm not
just idling...

> > I should note that, what I'm doing in my experimental "someday open
> > source" projects is different from what I've done at my Jay Oh Bee--
>
> I will offer some advice there: the best open source projects grow out
> of real solutions to real business problems. Trying to create some
> open source project in isolation with no real business drivers and no
> real users is likely to create something that doesn't actually solve
> anyone's problems. And, yes, the general work environment is often not
> conducive to doing this which is unfortunate.

Well, they're actually sorta models of how I'd like to do some of the
things that are rather hard to modify now, at "work", or CF interfaces
to things like the JasperServer webservice, or the jExcelAPI library,
SVNKit-- or strange ideas of using the Mylyn task tracking/wiki CF
interface I created, with an SVN based data-store, instead of just the
database I'm using now.
It may be dumb to use the little personal time I have for things
of this nature, but I have a dream of making stuff easier all around.
And giving back somehow, since it seems right to do so. Honorable,
perhaps.

But since I'm intending to share this stuff, instead of having a
closed implementation that's mostly convention (I don't have to do
anything at work but get it done, ASAP, so there's no documentation,
no unit tests-- training people to modify code I created 10 years ago
is insane, but it's what we've created by being stuck in a AAAAAA
loop[1] (action action action action)). I'm never given time to
refactor, etc.. I could bitch all day about it. (somedays I do bitch
quite a bit, which is why...)

Instead I'm trying to change it and then get the hell out. =]

I finally had to just demand we do things different. Start using
version control * Reactor was the cat's whiskers, it got all my messy,
sprinkled about SQL organized * MG has been pimp for moving everything
out of the webroot, and giving better organization. Something I
sorely needed * ColdSpring I've just barely started grasping the power
of...

The new project models at work are ugly and more procedural than not,
but they "work".

I want to have some elegant code to share, you know? Good examples of
how to do stuff, vs. just code scavenging material; "hey, he figured
out how to X... if only he'd made it easier to use". To be a good
example for those that take my place...
I've started pushing back on better specifications and whatnot,
but I really don't get paid enough to do everything, and being
disregarded has been frustrating. But I don't want the next person to
have to deal with it all, so I'm starting to work at taking off some
of my hats, one by one, and standardizing how things are done.

Not exactly germane to a beans thread, I know...

[1] http://www.stsc.hill.af.mil/CrossTalk/2007/04/0704Ullman.html

--
Do not throw the arrow which will return against you.
Kurdish Proverb

Dinner

no leída,
19 ene 2008, 14:44:1319/1/08
a model...@googlegroups.com
On 1/12/08, Jon Messer <sylvan...@gmail.com> wrote:
> Wow, this thread has gotten pretty abstract. ;-)

You are a bad, bad man. =]

[...good abstracted persistence implementation idea...]

> As to the over-engineering I have to agree with Sean, you don't have to plan
> for EVERY possible change or use case down the road. If you just follow the
> KISS/YAGNI/DRY/JFDI ;-) path then any changes later shouldn't be that
> hard.

I must have come across badly-- I'm not an advocate of over-engineering!
I was joking when I said it was impossible... :-)

The ORM/XML abstraction bit came from an idea to be able to use the
same project "tracker" with my custom datastore, or to let people use
reactor or transfer, since they probably already have their own
trackers, but maybe want the Mylyn integration. Guess I could just
copy MG's generic stuff... heh.

It seems to me that concepts like KISS/YAGNI/DRY/JFDI, and indeed,
abstraction, are relative to the size and scope of the project.

> Hope I'm not adding any dissonance to this topic.

The more the merrier! =]

--
That's the way things come clear. All of a sudden. And then you
realize how obvious they've been all along.
Madeleine L'Engle

Dinner

no leída,
19 ene 2008, 14:48:0519/1/08
a model...@googlegroups.com
On 1/12/08, Sean Corfield <seanco...@gmail.com> wrote:
>
> Dinner, how do you ever get anything concrete done?

By being plugged in way, way too much.

All I was doing was stirring concrete all freaking weak. I'd like to
pour it, and build with it, to analogize.

> You are the hardest person to discuss design/architecture with because
> you don't seem to be able to stay on topic - you expand every single
> item to the size of the cosmos :)

I also like to condense everything inversely. ;)

> OK, let's see where we get to on this round (and take note that both
> Jon and Peter are urging you to scale back your abstractions).

I am taking the recommendations to heart. And I value them taking the
time to contribute to our (and specifically my) education. I hope to
prove it's an investment. I mean a /smart/ investment. LOL.

Also of note is my context, which I think is different than most CF developers.

I'm working on fluid projects that will last years, and that are open
source, or will perhaps become open source...

My frame of reference is longer than most, and I worry about "the long
tail" (similar to the idea of "code for maintenance"), and "others"
working on, extending, etc., my creations.

And seeing as I get little time to refactor, I'd rather tell 'em (my
work) it'll take longer up front, and save myself from having to do
silly, disorganizing things later (due to a lack of time to refactor).

But I hear the "don't overdue it" comments-- Normalizing databases is
a similar typeodeal...
And I do err on the side of over-normalization, but due to the way I
work (or rather, the way I get my work orders), I sorta have to. On
day one "the specs" say a one-to-one will work, but by day 2 it's a
many-to-many, etc..
I pretty much have to learn the domain, and then explain to the people
who run the domain, what they're doing-- if that makes sense.
Each project is a discovery quest for everyone involved; "oh, /that's/
what we're doing? Then we need X Y and Z! Can't believe we didn't
realize that from the beginning!"

If you already have objects set up for a normalized database, you can
feel good about normalizing, too. "They may say they don't need it
now, but experience has shown..."

Bah. We're way away from beans and services now tho...

> On Jan 12, 2008 2:16 PM, Dinner <vallia...@gmail.com> wrote:

> > http://en.wikipedia.org/wiki/Open/closed_principle


> > Trying to get at the Zen-like "truth" (even tho it's an illusion ;) of
> > the principle. Being able to apply it to any language, if only by
> > convention.
>
> Again, you're mixing levels. Open/closed applies to software entities,
> i.e., code. It automatically applies to any structured language.

Yes, mixing levels is one of my problems. Not using the correct words
is a problem too, so it's nice to work on vocabulary building.

I thought you were saying that you could only apply open/closed to
specific languages, i.e. Java, but if it's for any language, we're on
the same page now.

> > You do mean inheritance whey you say "extend", right?
>
> A child class inherits from a base class. A child class extends a base
> class. A child class is a specialization of a base class.

Excellent. So then polymorphism is... just kidding. :-)

Inheritance seems to extend (punny, eh?) the open/closed principle. Right?

The base classes are closed like the lotus at night (as much as
possible, I'm not necisarily talking a java "Final" here), and yet
open to extension through, um, extension.

The SiteUser object extends the User object, because more will change
with SiteUser than with User. At least that's part of the idea,
correct?

> > I stand by my idea that a big ol' bean is inherently less flexible
> > than a little bean.
>
> It depends on how you define "flexibility" but I understand your
> point. Yes, for the most part, having lots of small classes is going
> to be more flexible - but it's also going to be more complex to deal
> with and potentially slower and those may not be acceptable trade
> offs. You never seem to mention trade offs in any of your responses -
> only abstract ideals - so I'm wondering whether you actually
> understand that real world projects require trade offs? :) :)

The "real world"? What's that? :] :]

A lot of my stuff (especially the old stuff) is at the opposite end of
"abstract".

I don't like the current trade-off-- my time-- working harder instead
of smarter.

What is the real world to you? How long do your average projects
last, what kind of hardware are you targeting, and does that affect
the abstractions?

> > Ah. I was aiming at finding out what you meant by "fat bean"-- "bean"
> > seems like one of those words... is the object fat because it has
> > mix-ins, and extends other, more localized objects, or are you
> > referring to a bean that's made up solely of it's own bulk?
>
> It's why I prefer the term "richly functional business domain object"
> or something similar. The "plumpness" is meant to indicate the
> richness of business functionality in the bean. As opposed to "skinny"
> - with just data and get/set methods.

Now we're headed for that death-star exhaust port...

> > Would the bean sorta become more of an interface, if it contains a
> > bunch of logic, but only exposes it as simple getters and setters?
>
> A bean can contain "a bunch of logic". It is a bean by definition of
> exposing its data only through getters and setters.

When you say "it's data", do you mean simple structs/variables
containing like, strings? Or are we also passing objects around, and
whatnot?

> > Indeed! It seems like it would be tempting to make that Transfer
> > object your business object! Same with Reactor.
>
> Well, they can't really be "business objects" because they can't
> contain any "business logic" but they could be (anemic) domain
> objects.

Alright.

(I think I need to look up business objects and business logic next.)

> You can use all manner of rules of thumb and draw on your experience
> etc. I prefer to consider where "abstraction, and sub-classes and such
> will" come in handy rather than "might conceivably"...

10-4 = Pragmatism!

I've got "real world" situations for these abstractions, too. Not just
academic (but mostly it is) :)

I really do want to abstract the database dependency for at least one
project. Jon's PersistenceService ideas sound pretty good. (Thanks
Jon!)

> > Didn't mean to imply it was an concrete abstraction.
>
> Now there's a tautology if ever I heard one! :)

Hey, they're real! Real unreal. Thanks for bearing with me. =]

[...nice clarification on vocabulary...]

> Not all dependencies are created equal tho'. Some dependencies are
> fine. And in fact a class must either be dependent on something or
> have something dependent on it - otherwise it isn't actually useful
> (if nothing depends on you, you are pointless :)

I was thinking something along these lines about existence the other day...
oh yeah, it was the original post!

Either the object knows about the service, and carries it with it
wherever it goes, or it doesn't, and the service takes care of knowing
about the objects existence. Something like that.

The chicken and the egg. -- I know you have to violate these design
principles to actually "make" stuff-- I want to know when, why, where,
and to limit the violations as much as possible tho. Or something
along those lines.
At least academically, and then I'll use context for the pragmatic bits. =]
...


> > I commented about the quite clich[funky e] motto of "just do it"
> > earlier... and it sorta fits in with Agile development, as I
> > understand it.
>
> The "just do it" mentality you refer to is nothing like agile
> development (at least, not like agile done right). A lot of people
> mischaracterize agile as an excuse to just throw together the simplest
> thing that works and you're done. Think of agile as "make it work and
> then make it right" rather than just "make it work". That's why
> refactoring is such a key element. It's the same with TDD: you make
> the test pass and then you refactor to make the code "right" (without
> breaking the test).

I wasn't referring to "just do it... and it's done"-- I was referring
to: you get the current specifications (as crappy as they are) bang
out what they think they want (sometimes, when you know the domain,
what they really need), have them give it a whirl, tell you either
they loved how you guessed they'd need X, or that they forgot to tell
you that they'd need X-- rinse, wash, repeat.

Maybe bust some alpha/beta/production type stuff, or follow another
cycle, but basically you're working it as you're working it.

At least, that's sorta more what I was thinking.

...


> > The fact that everything is "data" throws a semantic wrench into the
> > equation.
>
> I guess that depends on whether you think functions and logic are
> "data" as well?

Sorta, I do. Maybe a kind of meta-data? We probably don't want to
get into "meta" tho! =]

Lets say we're passing objects-- are they data? Depends on what your
perspective is as to what you consider data, perhaps? Maybe this is
part of the confusion with the term "bean"? Usually I see them as
like "getFirstName()" vs. "getUserObject()". That's probably part of
my problem with the use/understanding of the word in the CF world.

Ah ha! The CS "beans"! That was one of the first confusing bean bits for me.

> > Which is why I'm trying to move away from the
> > usage of the word "bean"...
>
> And adopt what term in its place?

Well, now that I know what your bean is, we could use it, but that's
after like, a lot of typing (thanks, everyone, 'specially Sean).
*LOL*

Considering the confusion with "beans","factories","facades" and
"services", maybe we should type a little more, so we're sure people
are on the same page?

( For instance, does this definition of a facade match the way most CF
folks use the term? :
http://en.wikipedia.org/wiki/Facade_pattern )

Bah! Who likes typing? Maybe we need to just make up a word, since
those definitions I posted (and you agreed with) seemed different
enough to cause confusion. I bet if you threw "factory" out there,
off the cuff, I'd be wondering about what that meant too (but not if
we are talking Java (unless it's the pattern vs. the object ;])).

> A bean is an object with a particular type of API. Lots of things can
> be beans. Some (most) business domain objects are beans but the
> reverse is not true (so you cannot use "business domain object"
> instead of bean, for example).

I think that when you said this: "One piece of advice I'll give is to
try to keep your beans - your business domain objects - as smart as
possible" it started me wondering.

> I hope that helps?

The bean talk has helped quite a bit. At first, it was like:

Beans? CF Beans? ColdSpring Beans? EJB(1/2/3)? -- Beans beans, the
magical fruit... and then I started wondering what you meant by, um,
"robust" business domain objects, and then, if that advice centered
around projects of a certain type, like the "you've got a month to do
X" vs. "I want everyone to be able to use this", or whatever.

This thread has been, well, just plain fun for me. I hope it hasn't
been trying for any of you, and please, feel free to write this thread
off at any time.
I just couldn't let it die, since I've been thinking about it all week. =]

--
When you want to believe in something, you also have to believe in
everything that's necessary for believing in it.
Ugo Betti,

Sean Corfield

no leída,
20 ene 2008, 16:30:4320/1/08
a model...@googlegroups.com
On Jan 19, 2008 11:48 AM, Dinner <vallia...@gmail.com> wrote:
> Also of note is my context, which I think is different than most CF developers.

I don't think it is. Most all of us work on fluid projects that will
last years and many of us work on OSS or potential future OSS. You
shouldn't think you're special (unless you mean in a "short bus" kinda
way... LOL!).

> My frame of reference is longer than most, and I worry about "the long
> tail" (similar to the idea of "code for maintenance"), and "others"
> working on, extending, etc., my creations.

We all do. Or we all should do. I certainly do.

> And seeing as I get little time to refactor, I'd rather tell 'em (my
> work) it'll take longer up front, and save myself from having to do
> silly, disorganizing things later (due to a lack of time to refactor).

Well, that's a problem with the way you estimate subsequent work
orders. You should factor in refactoring time :)

> I thought you were saying that you could only apply open/closed to
> specific languages, i.e. Java, but if it's for any language, we're on
> the same page now.

No, you're still misunderstanding I think. The concept applies to all
languages but the specifics are different for each language. Hence my
comment that it's harder to violate the principle in CF than in Java.

> The SiteUser object extends the User object, because more will change
> with SiteUser than with User. At least that's part of the idea,
> correct?

That doesn't make any sense to me - which is why I think you're still
misunderstanding.

Java easily lets you create a User class that you can't extend - hence
User would not be open (open and closed are not opposites in the
stated principle: open is about language-specific design, closed is
just a recommendation for developers).

> I don't like the current trade-off-- my time-- working harder instead
> of smarter.

Then change the process.

> What is the real world to you? How long do your average projects
> last, what kind of hardware are you targeting, and does that affect
> the abstractions?

Most projects I work on last years. Sometimes many, many years.
Hardware rarely affects the abstractions - almost never in fact. Not
sure what you're getting at there?

> When you say "it's data", do you mean simple structs/variables
> containing like, strings? Or are we also passing objects around, and
> whatnot?

I mean "data". You're on the wrong level (again).

> Lets say we're passing objects-- are they data? Depends on what your
> perspective is as to what you consider data, perhaps? Maybe this is
> part of the confusion with the term "bean"? Usually I see them as
> like "getFirstName()" vs. "getUserObject()". That's probably part of
> my problem with the use/understanding of the word in the CF world.

If the object on which you're calling these methods has-a user object
then that is part of its data (the user object itself also contains
its own behavior).

> Ah ha! The CS "beans"! That was one of the first confusing bean bits for me.

All objects are beans from ColdSpring's point of view because it
interacts with them only through constructors and set methods. And
factory methods of course (so it understands that some beans are
factories too).

> Considering the confusion with "beans","factories","facades" and
> "services", maybe we should type a little more, so we're sure people
> are on the same page?

These are not disjoint sets.

> ( For instance, does this definition of a facade match the way most CF
> folks use the term? :
> http://en.wikipedia.org/wiki/Facade_pattern )

It matches the way I use it :)

But just because something is a facade, doesn't mean it's not a
service or a bean as well. I think that might be part of your problem.

> This thread has been, well, just plain fun for me. I hope it hasn't
> been trying for any of you, and please, feel free to write this thread
> off at any time.

It's been extremely trying (hey, you wanted me to be honest, right?)
and I'm sure it will continue to be so :)

Dinner

no leída,
21 ene 2008, 2:17:4521/1/08
a model...@googlegroups.com
On Jan 20, 2008 2:30 PM, Sean Corfield <seanco...@gmail.com> wrote:
>
> On Jan 19, 2008 11:48 AM, Dinner <vallia...@gmail.com> wrote:
> > Also of note is my context, which I think is different than most CF developers.
>
> I don't think it is. Most all of us work on fluid projects that will
> last years and many of us work on OSS or potential future OSS. You
> shouldn't think you're special (unless you mean in a "short bus" kinda
> way... LOL!).

Ah la! Sean, you are sooooo un-PC!! :-) I'm happy to hear a
half-full opinion tho. =]

> > I thought you were saying that you could only apply open/closed to
> > specific languages, i.e. Java, but if it's for any language, we're on
> > the same page now.
>
> No, you're still misunderstanding I think. The concept applies to all
> languages but the specifics are different for each language. Hence my
> comment that it's harder to violate the principle in CF than in Java.

Yes, I'm surely misunderstanding then.

I thought this was a fundamental pattern, that the "specifics" are
more about choosing where and when to abstract.

Where and when to abstract seem to be problems with CF and Java, and indeed, C++

http://www.objectmentor.com/resources/articles/ocp.pdf

Pretty much a "programming philosophy" more than anything else-- seems
like it would be just as easy to violate with Java as with CF.

> > The SiteUser object extends the User object, because more will change
> > with SiteUser than with User. At least that's part of the idea,
> > correct?
>
> That doesn't make any sense to me - which is why I think you're still
> misunderstanding.
>
> Java easily lets you create a User class that you can't extend - hence
> User would not be open (open and closed are not opposites in the
> stated principle: open is about language-specific design, closed is
> just a recommendation for developers).

I was referring to the inheritance pattern, not Java, per say, for the
user object example.

Not to be cheeky, but are you sure you grok the open/closed principle?
;-))) LOL!

I'm talking about the classic "flying the helicopter" analogy here.
The idea is that we should encapsulate change, so we can, well,
change, without everything else changing as well.

Patently impossible, but you know, it's the ideal, right?

The emphasis you're putting on open being one thing and closed being
another, I'm not quite getting. I thought they were both just
recommendation for developers?

A type of logic pattern that prevents one from having to fly
helicopters so much (although they do rock! Guess I like complicated
stuff... :] maybe I'm making this principle too complicated?).

Open to extension, closed to modification? I'm looking at it as a
rule of thumb, but it seems like you're coming from a more formal,
Computer Science type vantage?

> > I don't like the current trade-off-- my time-- working harder instead
> > of smarter.
>
> Then change the process.

Keep digging, Holmes! ;-)

Change is happening, slowly (tho it would be a kind of fun, to just
shake it up for everyone... ).

Sorta like SLC Punk, but not as cool, and I may just say screw it.

Just some context for why I'm pushing the abstract the way I am (I
hear the "too much", I'll scale it back ;).

> > What is the real world to you? How long do your average projects
> > last, what kind of hardware are you targeting, and does that affect
> > the abstractions?
>
> Most projects I work on last years. Sometimes many, many years.
> Hardware rarely affects the abstractions - almost never in fact. Not
> sure what you're getting at there?

That time, money, scope, and other factors impact what is possible--
and even wanted (as cool as it may be!).

> > When you say "it's data", do you mean simple structs/variables
> > containing like, strings? Or are we also passing objects around, and
> > whatnot?
>
> I mean "data". You're on the wrong level (again).

Remember that part in the Matrix where everything becomes those green
characters? :-P

Heh. Sorry, we'll stick to the meaning in context. The next bit clarified:

> If the object on which you're calling these methods has-a user object
> then that is part of its data (the user object itself also contains
> its own behavior).

Right on. "Get it. Set it. Good." (to paraphrase an old movie).

> > Ah ha! The CS "beans"! That was one of the first confusing bean bits for me.
>
> All objects are beans from ColdSpring's point of view because it
> interacts with them only through constructors and set methods. And
> factory methods of course (so it understands that some beans are
> factories too).

Yes, I get this now, but it was pretty confusing at first. Seemed
almost like people were calling XML files beans and whatnot, for a
second.

Even though I was a sped, I'm not that slow (I swear!), and you gotta
see how using "beans" to mean so many things leads to a steeper curve
for those just getting on board.

I can be pretty thick at times, however.

Thanks for taking the time to try and explain so much. My brain is
about pickled with this stuff now. I'm full! :-)

> > Considering the confusion with "beans","factories","facades" and
> > "services", maybe we should type a little more, so we're sure people
> > are on the same page?
>
> These are not disjoint sets.

...


> But just because something is a facade, doesn't mean it's not a
> service or a bean as well. I think that might be part of your problem.

Totally!

A core OO tenant is to not have public properties... which equates to
using getters and setters, right? Bah- I think java is sorta of like
spanish for french. hehehe... seriously though, there's that sorta...
hmm... how to explain it?

I first learned about beans in the sole Java class I took (don't
laugh! It was an excellent class! :) several years ago; the new looser
definition was confusing at first. I think I'm better, now. :)

> > This thread has been, well, just plain fun for me. I hope it hasn't
> > been trying for any of you, and please, feel free to write this thread
> > off at any time.
>
> It's been extremely trying (hey, you wanted me to be honest, right?)
> and I'm sure it will continue to be so :)

Naw, we can let this one ride off into the sunset, as it were.

I don't want to scare you away-- your contributions are better than mine. :)

We should switch it up a little, talk about some implementation, so to
speak. =]]

--
Well-timed silence hath more eloquence than speech.
Martin Fraquhar Tupper

Sean Corfield

no leída,
21 ene 2008, 12:01:3521/1/08
a model...@googlegroups.com
On Jan 20, 2008 11:17 PM, Dinner <vallia...@gmail.com> wrote:
> Ah la! Sean, you are sooooo un-PC!! :-)

I'm British. PC didn't make it to Britain :)

Although, technically, I'm American now (passport-carrying, even).

> Pretty much a "programming philosophy" more than anything else-- seems
> like it would be just as easy to violate with Java as with CF.

Well, the principle is two-fold:
1. Open for extension. You can add behavior by extending the object
(without touching its source code).
2. Closed for modification. You never, ever touch the source code of
an existing "finished" module.

That's easy to violate in languages that can prevent extension or
overriding. It's much harder to violate in dynamic languages where you
can always extend and override - and you can even replace methods at
runtime (through mixins or injection).

So it is easier to violate in Java than in CF.

Does that clarify?

In CF, it's almost impossible to prevent something being open for extension.

Now, as a design principle, that means you need to isolate potentially
variable behavior into separate methods that can be overridden - or
parameterize into an external object (via the Strategy design pattern
for example).

> Not to be cheeky, but are you sure you grok the open/closed principle?

I grok it :)

> I'm talking about the classic "flying the helicopter" analogy here.

So classic, I've never heard of it and have no idea what you're on
about (again :)

> The emphasis you're putting on open being one thing and closed being
> another, I'm not quite getting. I thought they were both just
> recommendation for developers?

Closed for modification is a rule for developers (don't mess with the
source code) and it has nothing to do with design per se. Open for
extension is much more about design - but it's also
design-in-a-language-context since you have to consider how to keep a
class "open"...

> That time, money, scope, and other factors impact what is possible--
> and even wanted (as cool as it may be!).

Well, yes, to some extent. But if you're pragmatic about design
(remember: KISS, YAGNI, DRY) then you're less likely to be impacted by
those factors, IMO.

> Right on. "Get it. Set it. Good." (to paraphrase an old movie).

Yup.

> Yes, I get this now, but it was pretty confusing at first. Seemed
> almost like people were calling XML files beans and whatnot, for a
> second.

Yeah, "bean" is a broad term. Like "object" :)

Not all objects are beans but there sure are a lot of beans out there.

> Thanks for taking the time to try and explain so much. My brain is
> about pickled with this stuff now. I'm full! :-)

"Please sir... can I be excused? My brain is full!"

> A core OO tenant is to not have public properties... which equates to
> using getters and setters, right?

A core OO tenet is to think about objects in terms of behavior, not
data (which is where most people get hung up). Getters/setters is a
very data-centric approach - even tho' many (most?) objects end up
with (some) getters/setters because they have to have data to maintain
state, the key aspect of an object is its behavior or its
"responsibilities".

Dinner

no leída,
21 ene 2008, 15:53:1821/1/08
a model...@googlegroups.com
On Jan 21, 2008 10:01 AM, Sean Corfield <seanco...@gmail.com> wrote:

> In CF, it's almost impossible to prevent something being open for extension.

I was thinking more like, instead of hard-coding the kind of shape,
you make something that takes a shape and does stuff with it, so you
don't have to constantly go back and update your kinds of shapes
everywhere. (<-- lifted from the PDF I linked to).
You've "closed" the function that would have been changing all the
time otherwise ('cause it was open in the bad way, see ;).

Sure, in CF you can extend easily, but that doesn't mean you're
following the pattern, not even close.

It seems almost easier to build these large components, that extend
this or that such that, changing one of the components you extended
wreaks havoc on everything else down the line.

It seems like /not/ having some type of "Final" would lead to more
"hey, I'll just alter this base object instead, and...", but maybe
not... *shrug* =]

> > I'm talking about the classic "flying the helicopter" analogy here.
>
> So classic, I've never heard of it and have no idea what you're on
> about (again :)

Oh! I thought *everyone* flew helicopters (at least model ones! :).

The idea is that you can't increase altitude without increasing
tail-rotor speed.

The controls are not decoupled, so a change in one system is a change
in another system.

> Closed for modification is a rule for developers (don't mess with the
> source code) and it has nothing to do with design per se. Open for

Au contraire! Closed for modification means you've already abstracted
(not literally) the bits that change, so you don't have to go back and
modify later.
Total design, nothing to do with actually editing code. (IMHO).

You should write it "right" the first time, so you don't have to go
back and change it repeatedly.

> > That time, money, scope, and other factors impact what is possible--
> > and even wanted (as cool as it may be!).
>
> Well, yes, to some extent. But if you're pragmatic about design
> (remember: KISS, YAGNI, DRY) then you're less likely to be impacted by
> those factors, IMO.

Well, there's pragmatic, and there's practical.

I think it's a huge extent, personally. Pragmatic long-term, may not
be practical short-term. (If we're in a screwed up situation, which
can happen more than one would wish).

> A core OO tenet is to think about objects in terms of behavior, not
> data (which is where most people get hung up). Getters/setters is a

I'm digging on the "collections of algorithms" more than "collections
of behaviors" idea... blame that design patterns book. ;-)

PS- Heh. I /thought/ tenant looked funny. Thanks!

--
Change your thoughts and you change your world.
Norman Vincent Peale

Sean Corfield

no leída,
26 ene 2008, 2:18:2526/1/08
a model...@googlegroups.com
Closed means "don't touch the code" plain and simple. Open means can
be extended. Period.

Dinner

no leída,
26 ene 2008, 16:02:4226/1/08
a model...@googlegroups.com
On Jan 26, 2008 12:18 AM, Sean Corfield <seanco...@gmail.com> wrote:
>
> Closed means "don't touch the code" plain and simple. Open means can
> be extended. Period.

Hehe!

I like the idea of that, but here's a quote from that PDF I linked to earlier:

**
It should be clear that no significant program can be 100% closed. For
example, consider
what would happen to the DrawAllShapes function from Listing 2 if we
decided that
all Circles should be drawn before any Squares. The DrawAllShapes function is
not closed against a change like this. In general, no matter how
"closed" a module is, there
will always be some kind of change against which it is not closed.
Since closure cannot be complete, it must be strategic. That is,
the designer must
choose the kinds of changes against which to close his design. This
takes a certain amount
of prescience derived from experience. The experienced designer knows
the users and the
industry well enough to judge the probability of different kinds of
changes. He then makes
sure that the open-closed principle is invoked for the most probable changes.
**

Which is more what I was after, sorta, I think, vs. things like Java
"Final" methods and classes and whatnot.

But I totally get what you mean (I got to the "Template Pattern" the
other day-- factors in there pretty good!).

Thanks for taking the time to flesh out the concept for me, Sean! You
get a beer too, if ever we meat in RL. :-)
And assuming you drink. ( Tea and crumpets if not. :-)

--
I used to believe that marriage would diminish me, reduce my options.
That you had to be someone less to live with someone else when, of
course, you have to be someone more.
Candice Bergen

Sean Corfield

no leída,
26 ene 2008, 23:14:1026/1/08
a model...@googlegroups.com
After this discussion, I'll certainly accept a beer from you :)

Responder a todos
Responder al autor
Reenviar
0 mensajes nuevos