LiftRules

30 views
Skip to first unread message

Timothy Perrett

unread,
Oct 11, 2010, 4:57:03 AM10/11/10
to liftweb
Hey all,

So i've been sitting on this for a while, and wanted to bring it on list to discuss further. LiftRules has become a very large class in Lift, one of the biggest in fact. I feel that as time moves on, we could do with a more componentized approach to configuration so that code navigation is easier and use of the configuration object is more intuitive.

I would like to propose splitting out everything in LiftRules in the following manner:

1. create a namespace for rules: net.liftweb.rules
2. create composable but critically sealed traits that include inner objects for configuration. For example:

sealed trait AJAX {
object AJAX {
...
}
}

there would of course be several different configuration elements and parts relating to session, http, ajax, comet and so forth. I was originally concerned that as some of the functions span contexts, it might be an issue, but whilst refactoring I actually didn't find that to be too much of an issue as things could be logically ordered. From a client API perspective, they would then have a more normalized API:

AJAX.path

rather than

LiftRules.ajaxPath

That is of course one example, but hopefully it illustrates what I am proposing. Moreover, I think it would also be good to normalize the API to use FactoryMaker. Whilst in an of itself, this could be a breaking change, testing has shown me that it is indeed possible to make a 100% backward compatible LiftRules object using delegation, so a large refactor like this could be introduced without impacting on API usage in the near term, whilst allowing us room to grow and continue to make lift flexible and extensible. From a long-term POV, if there was a concern around keeping LiftRules, it could be factored out into lift-legacy project or something where it could delegate to the main configuration object so that people who are slow to migrate could have an easier time.

Hopefully this is enough information to start a helpful discussion :-)

Cheers, Tim

Christoph Henkelmann

unread,
Oct 11, 2010, 5:56:24 AM10/11/10
to lif...@googlegroups.com
+1

> discuss further. LiftRules has become a very large class in Lift, one of
> the biggest in fact. I feel that as time moves on, we could do with a more
> componentized approach to configuration so that code navigation is easier
> and use of the configuration object is more intuitive.

Speaking as a relatively new Lift User I must say that I found dealing with
the giant LiftRules a bit unwieldy. If you don't know exactly what you are
looking for it is hard to find your way around. Splitting up LiftRules the way
you suggested would make it much easier for newcomers to find the necessary
configuration. Also, the current naming is not always consistent, most ajax
configurations are named ajaxFooBar, like ajaxRetryCount but then some do not
follow that convention like autoIncludeAjax. Because of this one always has to
go through the whole javadoc of LiftRules.

Still loads better than struts xml, though ;)

Jeppe Nejsum Madsen

unread,
Oct 11, 2010, 6:33:43 AM10/11/10
to lif...@googlegroups.com
On Mon, Oct 11, 2010 at 10:57 AM, Timothy Perrett
<tim...@getintheloop.eu> wrote:
> Hey all,
>
> So i've been sitting on this for a while, and wanted to bring it on list to discuss further. LiftRules has become a very large class in Lift, one of the biggest in fact. I feel that as time moves on, we could do with a more componentized approach to configuration so that code navigation is easier and use of the configuration object is more intuitive.

Agreed 100%

> I would like to propose splitting out everything in LiftRules in the following manner:
>
> 1. create a namespace for rules: net.liftweb.rules
> 2. create composable but critically sealed traits that include inner objects for configuration. For example:
>
> sealed trait AJAX {
>  object AJAX {
>   ...
>  }
> }
>

I'm not sure I see clearly how this works/should be used.

I assume you have a trait so you mixin this trait where e.g. Ajax
rules are needed and thus don't rely on a global AJAX object?

Why should the trait be sealed?

/Jeppe

Timothy Perrett

unread,
Oct 11, 2010, 6:46:19 AM10/11/10
to lif...@googlegroups.com
I was thinking more something like:

sealed trait Environment {
object Environment {
...
}
}

sealed trait HTTP { _: => Environment
object HTTP {
...
}
}


sealed trait AJAX { _: => Environment with HTTP
object AJAX {
...
}
}

object Application
extends Environment
with HTTP
with AJAX

...something like that at least. The thinking being that then the configuration is name-spaced within Applicaiton, so you'd have a boot file like:

class Boot {
def boot {
import Application._
// config goes here
}
}

Does that help clarify?

Cheers, Tim

Timothy Perrett

unread,
Oct 11, 2010, 7:09:10 AM10/11/10
to lif...@googlegroups.com
Sorry I didnt answer this point before. The traits would need to be sealed so that people don't mix them into their own classes or anything silly like that. I'm not saying anyone would try, but better to have that enforced by the compiler, right?.

Cheers, Tim

On 11 Oct 2010, at 11:33, Jeppe Nejsum Madsen wrote:

Jeppe Nejsum Madsen

unread,
Oct 11, 2010, 7:32:05 AM10/11/10
to lif...@googlegroups.com
On Mon, Oct 11, 2010 at 12:46 PM, Timothy Perrett
<tim...@getintheloop.eu> wrote:
> I was thinking more something like:
>
> sealed trait Environment {
>  object Environment {
>  ...
>  }
> }
>
> sealed trait HTTP { _: => Environment
>  object HTTP {
>  ...
>  }
> }
>
>
> sealed trait AJAX { _: => Environment with HTTP
>  object AJAX {
>  ...
>  }
> }
>
> object Application
>  extends Environment
>  with HTTP
>  with AJAX
>
> ...something like that at least. The thinking being that then the configuration is name-spaced within Applicaiton, so you'd have a boot file like:
>
> class Boot {
>  def boot {
>    import Application._
>    // config goes here
>  }
> }
>
> Does that help clarify?


Somewhat, but how do you use the rules? Is Application Lift code or
User code? Something needs to be declared somewhere for the Lift code
to use :-)

/Jeppe

Timothy Perrett

unread,
Oct 11, 2010, 7:41:14 AM10/11/10
to lif...@googlegroups.com
Exactly right... Application is intended to be isomorphic to LiftRules, but with a new API. In this scenario, LiftRules would delegate to Application to provide the required deprecation cycle and mediate between LiftRules methods and Application factory makers.

Cheers, Tim

Ross Mellgren

unread,
Oct 11, 2010, 10:26:06 AM10/11/10
to lif...@googlegroups.com
So, to expand the example, if I took a basic kind of Boot and wrote it using the new idea, it'd be like:

class Boot {
def boot {
import net.liftweb.http.config.Application._

if (!DB.jndiJdbcConnAvailable_?) {
val vendor = new StandardDBVendor(...)
HTTP.unloadHooks.append(vendor.closeAllConnections_! _)
DB.defineConnectionManager(DefaultConnectionIdentifier, vendor)
}

HTTP.addToPackages("test")
Schemifier.schemify(true, Schemifier.infoF _, User)

def sitemap() = SiteMap(...)

Sitemap.setSiteMapFunc(sitemap)

// FIXME probably should be AJAX.start / AJAX.end
Comet.ajaxStart = Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
Comet.ajaxEnd = Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)

HTTP.early.append(_.setCharacterEncoding("UTF-8"))

loggedInTest = Full(() => User.loggedIn_?)

S.addAround(DB.buildLoanWrapper)
}
}

Yeah?

I'm for it, modulo the FIXME of course.

-Ross

> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
>

Timothy Perrett

unread,
Oct 11, 2010, 10:32:57 AM10/11/10
to lif...@googlegroups.com
Pretty much :-)

I mean, we are essentially doing this in some places of Lift anyways... consider ScreenRules, MapperRules and PaypalRules. In my mind at least, it seems to make sense to unify these under a single namespace and implementation idiom.

I only did a partial implementation whilst playing around with the idea to see if it would even work, so your FIXME is probably one of a bunch of things that should be cleaned up :-)

Cheers, Tim

Ross Mellgren

unread,
Oct 11, 2010, 10:57:29 AM10/11/10
to lif...@googlegroups.com
On Oct 11, 2010, at 10:32 AM, Timothy Perrett wrote:

> Pretty much :-)
>
> I mean, we are essentially doing this in some places of Lift anyways... consider ScreenRules, MapperRules and PaypalRules. In my mind at least, it seems to make sense to unify these under a single namespace and implementation idiom.

Well, you're actually breaking apart into namespaces, since you're not going to bring in Mapper or Paypal rules or the other rules objects for separate packages, yes?

-Ross

David Pollak

unread,
Oct 11, 2010, 11:08:55 AM10/11/10
to lif...@googlegroups.com
I completely oppose this.

While I agree that certain parts of the configuration rules should live in other places (e.g., some of the localization stuff that lives in LiftRules should live elsewhere), I think that having a unified place where all the global parameters (even if they can be overridden on a session, request, and stack basis as per the FactoryMaker and RulesSeq) live.

Yes, there is a documentation issue with LiftRules (and with Scala more broadly), but as per our conversation in London, having tags associated with different methods will allow for better organization of the methods (rules).

So, the idea of breaking up LiftRules, I oppose on its face.  There may be certain rules to move elsewhere, but I believe that having a unified place for a developer to look for the appropriate control over the Lift request/response behavior should be LiftRules.

Splitting LiftRules into a separate package will cause some problems as there are parts of LiftRules that access private[http] data (this is necessary).  Having the rules live in a different package increases the complexity of defining access control rules (this is not insurmountable, but may lead to a certain amount of extra work.)

Having traits/objects vs. a unified object (LiftRules) with a collection of properties makes it harder to find things... you wind up with a collection of objects in a package rather than a collection of properties on a single object.  It seems to me that this will make it harder, rather than easier, to find the appropriate rule.

In the prototypical Boot.scala code, we do not object-import LiftRules.  This is intentional.  It was my intent to let people know that they were accessing LiftRules rather than something else.  Yeah... it looks like a lot of repetition in Boot, but it serves the purpose of defining these rules and letting the developer know that it is a rule (with particular definition semantics... only during Boot time) is of a certain class.

There are many areas of improvement in Lift.  There are even improvements we can make to LiftRules (e.g., FactoryMaker vs. function vars).  But this suggestion does not address the core issue (navigation to find appropriate rules [or more specifically makes it harder to navigate]) as well as giving the developer less context about being a rule vs. being just something to set.  It will entail substantial work (hours that could be better spent on documentation and tests) and may lead to some breaking changes.

So... that's why I strongly oppose this proposal.

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.




--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Blog: http://goodstuff.im
Surf the harmonics

Timothy Perrett

unread,
Oct 11, 2010, 12:22:35 PM10/11/10
to lif...@googlegroups.com
David,

I hear what you are saying and did take on board what we had discussed at #scalalol. There is always going to be more than one view on something, of course, that is life.

I'm not married to the idea of a separate package, im just proposing something that seems (IMO) to be a positive improvement. I was aware of the private[http] stuff currently placed within LiftRules; and it does indeed add more complexity.

Let me redefine part of what has been discussed here; I was only thinking to import a composed "Application" object in boot, because those objects were nested within the composed object, so you don't wind up polluting the overall namespace of boot. I mean, if you didn't do the import, you'd just end up with: Application.AJAX.path or whatever; that however seems to be more of a stylistic thing in usage. Irrespective of the implementation (I propose one route here), I am ultimately proposing some way of "grouping" configuration aspects together. In my mind, if you are looking for an AJAX related property, it seems logical to find it in Application -> AJAX -> whateverYouWant as opposed to the current scenario where one has to load LiftRules and use "find" in the scaladoc (at least, that is what i do as the naming is not consistent)

Whilst I do believe this needs changing, I can fully appreciate that you do not feel this need. Looking at the other responses in this thread, I am not alone. We have traditionally been "by the people, for the people" in ethos, so can I propose that this topic stay open for a little while in order to collate more feedback and possibly find a mutually agreeable route forward. If that is for change, or no change, so be it. What are your thoughts?

Cheers, Tim

Derek Chen-Becker

unread,
Oct 11, 2010, 2:04:24 PM10/11/10
to lif...@googlegroups.com
I agree with Tim on this one. I wasn't privy to the conversation in London, so I'm not sure what you're referring to when you talk about "tags", but I feel like the current LiftRules implementation is just getting too big and unwieldy. I actually don't think that this needs to be broken into a separate namespace, so we avoid the access control issues, but I think that having a well organized taxonomy of rules/vars would make it easier for people to locate things and also make the code more maintainable. LiftRules.scala is second only to S.scala in LoC and although, as you suggest, we may be able to move some unrelated items into more appropriate places, it's still going to be a really big chunk of code and most likely will continue to get bigger in the future as we refine Lift's customization.

I do agree with you that more time needs to be spent on documentation, and that this would help ameliorate some of the issues, but I feel like past a certain point we're documenting to work around some of our design decisions.

Derek

Jon-Anders Teigen

unread,
Oct 11, 2010, 3:03:15 PM10/11/10
to lif...@googlegroups.com
+1

As another relatively new Lift User I very much have the same impression as Christoph.
Having first class namespaces/modules in LiftRules would make it much much easier to understand.

If I for example wants to find out what ajax options are available I now have to have to read through all 1414 lines of LiftRules
including comments to try and figure out what options are ajax related and whats not.
I would very much have preferred just looking in LiftRules.Ajax instead

Best Regards

Jon-Anders Teigen

Brian Smith

unread,
Oct 11, 2010, 3:51:44 PM10/11/10
to lif...@googlegroups.com
As a new user to Lift (and Scala) I'd like this change.

I find that having a single place to go to for everything does not make it easier for me personally.  At least, not when everything is so broad a remit - I know I should probably not think OO so much but does an object with such varied responsibilities make sense?

Whether rightly or wrongly, I feel like I can't safely ignore anything in LiftRules and I'm left with the uneasy feeling there's something else I should have set up.  However if LiftRules were split as Tim proposes my default assumption would be that I can safely ignore the Comet trait if I'm not using Comet for example.

I can still go to one place to find Rules, they're in one namespace and I can now drill down through them more easily since they're grouped more logically than the alphabetically sorted list in scaladoc.  Aside from the difficulty of implementing this without breaking existing code which I definitely can't have an opinion on I don't see a disadvantage.

Regards

Brian

sean8223

unread,
Oct 11, 2010, 9:19:43 PM10/11/10
to Lift

-1

I admit LiftRules is a large class, but it really works like a roadmap
to the rest of the framework. No problem with consolidating some of
its many options into more logical groupings via helper objects or
whatever, but don't discount the value of this class to the newcomer
(or otherwise) trying to figure out what is going on. The reality of
Lift is that while the documentation (wiki, etc.) is improving, the
source code is the often the last if not first resort to problem
solving. Pretty much every control flow in the framework can be
debugged at some point in this file or LiftSession.

On Oct 11, 3:51 pm, Brian Smith <bmjsm...@gmail.com> wrote:oI

Naftoli Gugenheim

unread,
Oct 11, 2010, 10:08:36 PM10/11/10
to liftweb
Why not take the approach of Helpers: Let one top level object inherit top level traits, end of story. To prevent them from being used elsewhere, make the traits private to the package; as opposed to sealed that won't require being in the same file. Code will stay exactly the same, but LiftRules' content will be organized into several files.




David Pollak

unread,
Oct 11, 2010, 10:15:09 PM10/11/10
to lif...@googlegroups.com
On Mon, Oct 11, 2010 at 7:08 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:
Why not take the approach of Helpers: Let one top level object inherit top level traits, end of story. To prevent them from being used elsewhere, make the traits private to the package; as opposed to sealed that won't require being in the same file. Code will stay exactly the same, but LiftRules' content will be organized into several files.

There is no material issue with the maintenance of LiftRules.  When was the last defect reported against it?

One of Lift's biggest mistakes was breaking Helpers into multiple files.  It makes finding things hard.  It means that people mix things in with nasty issues related to dependent types.

No matter what the outcome of this discussion, there will be no composition of big gnarley objects via traits... it's not a solution, it's a much bigger problem.
 

David Pollak

unread,
Oct 11, 2010, 11:14:59 PM10/11/10
to lif...@googlegroups.com
On Mon, Oct 11, 2010 at 11:04 AM, Derek Chen-Becker <dchen...@gmail.com> wrote:
I agree with Tim on this one. I wasn't privy to the conversation in London, so I'm not sure what you're referring to when you talk about "tags", but I feel like the current LiftRules implementation is just getting too big and unwieldy. I actually don't think that this needs to be broken into a separate namespace, so we avoid the access control issues, but I think that having a well organized taxonomy of rules/vars would make it easier for people to locate things and also make the code more maintainable. LiftRules.scala is second only to S.scala in LoC and although, as you suggest, we may be able to move some unrelated items into more appropriate places, it's still going to be a really big chunk of code and most likely will continue to get bigger in the future as we refine Lift's customization.

I do agree with you that more time needs to be spent on documentation, and that this would help ameliorate some of the issues, but I feel like past a certain point we're documenting to work around some of our design decisions.

There are a couple of issues... let me address them as I understand them:

  • LiftRules is a big file with lots of lines of code.  So what?  It's not an issue.  There are few defects (none that I can remember) reported against it.  It's a simple pattern repeated.
  • LiftRules has a combination of a lot of different types of definitions (function vars, factory makers, RulesSeq, etc.).  Yeah... this should be normalized into as few different types as possible (e.g., get rid of function vars).
  • LiftRules spans a lot of ground.  I'm all for a discussion about what not to put into LiftRules in the future and things that could potentially be moved from LiftRules to other places (the latter would require a lot of work.)
  • LiftRules is hard to consume because there's so much stuff there... it should be divided into a taxonomy.  This is a lot harder than it sounds.  Figuring out what part gets put into what taxonomy is hard.  Figuring out the taxonomies is hard.  Figuring out when we need a new taxonomy is harder.  And inevitably, someone will get grumpy because we put something in the Foo taxonomy rather than the Bar taxonomy and it'll lead to more pain.  But it's easier to document the code and help guide users to the key options in LiftRules.
  • LiftRules should be moved to a separate package and split into traits for no good reason... just because it sounds cool.  Nope... it's not going to happen.
 
So, I think we need some documentation around LiftRules.  Before the documentation, there's no discussion to be had and given that Tim's passionate about the issue, I nominate him to document LiftRules.  Specifically, he has the following assignment to be completed before Lift 2.2-M2:
  • Completely document every option in LiftRules
  • Add @tag attributed to each option in LiftRules... tags include comet, ajax, web services, important, etc. I'll work with DavidB to include tagged information in VScalaDoc so that people can navigate the tags.  That gives us taxonomy at the documentation level (that's the real issue for users), yet certain options may be tagged with multiple tags.
  • In the documentation at the top of LiftRules, identify the options that will most likely be used (the stuff in the standard boot files is a good start).  This should be about a dozen or so commonly used options listed in the head.  This will give most users what they need to get started.
  • A list of options that are in LiftRules and shouldn't be (e.g., stuff related to I18N of dates and times, currency, etc.)
Once we have the above complete and we've shipped 2.2, then we can ask the question of our user base... are you able to adequately navigate LiftRules and find what you need?  If the answer to the question is similar to the answers in this thread even with documentation and better ability to navigate, then I'll be open to discussing how we can further improve LiftRules.

But, I don't want to solve a documentation problem by working really hard on changes that are most likely to be breaking to solve a problem that results in far fewer discussions on this list than other facets of Lift.

And in terms of making design decisions based on "feelings"... I'm an INTJ http://typelogic.com/intj.html  The operative pieces there are TJ.  That's "Thinking" and "Judging".  I base my design decisions on looking at the goals and the facts and applying logic to them.  It's not about feelings.  Feelings are "I feel like a steak tonight" or "I feeling like going to see a comedy" not "I feeling like making a pile of breaking changes to code".  We can disagree with the best approach to achieve goals (or we can even disagree on goals), but trivializing the approach that I've taken to shepherding Lift's design down to feelings does not reflect the uniformity in the underlying design of Lift.

Thanks,

David

David Brooks

unread,
Oct 12, 2010, 6:17:09 AM10/12/10
to lif...@googlegroups.com
Hi all,

I'm relatively new to Lift. I agree with Tim that LiftRules is unwieldy due to naming conventions, but I'd also agree with David that the best solution to that may be tagging (overlapping taxonomies being a persuasive argument).

I also think singling out LiftRules for refactoring or documentation work is unfair - from my limited interaction with it, it's not /that/ complicated that it needs the extra work. A broader documentation effort would be a higher priority for me, and I'm happy to get involved.

Cheers,
D

Timothy Perrett

unread,
Oct 12, 2010, 7:19:42 AM10/12/10
to lif...@googlegroups.com
David,

I added some responses in-line.

Cheers, Tim


> There are a couple of issues... let me address them as I understand them:
>
> • LiftRules is a big file with lots of lines of code. So what? It's not an issue. There are few defects (none that I can remember) reported against it. It's a simple pattern repeated.

LiftRules is big. Yes. I know you do not find this to be an issue, but for mere mortals such as myself, I feel it is. Other responses in this thread concur with that. That is my opinon, and you have yours - its a subjective thing, not something that can be fact one way or the other. I never complained about any reported defects; I do not have an issue with the substance of LiftRules, just its organisation.

> • LiftRules has a combination of a lot of different types of definitions (function vars, factory makers, RulesSeq, etc.). Yeah... this should be normalized into as few different types as possible (e.g., get rid of function vars).

I agree, these should be normalised.

> • LiftRules spans a lot of ground. I'm all for a discussion about what not to put into LiftRules in the future and things that could potentially be moved from LiftRules to other places (the latter would require a lot of work.)

I am not trying to say that things shouldn't get added to LiftRules. Ironically, it provides a single point for configuration and gives a lot of flexibility within Lift... I am not trying to propose that changes. Its not about substance, its organisation.

> • LiftRules is hard to consume because there's so much stuff there... it should be divided into a taxonomy. This is a lot harder than it sounds. Figuring out what part gets put into what taxonomy is hard. Figuring out the taxonomies is hard. Figuring out when we need a new taxonomy is harder. And inevitably, someone will get grumpy because we put something in the Foo taxonomy rather than the Bar taxonomy and it'll lead to more pain. But it's easier to document the code and help guide users to the key options in LiftRules.

The point about taxonomy is true; it would be difficult. Not impossible though. People get grumpy from time to time about other choices in Lift, so I wouldn't see this as being wholly different.

> • LiftRules should be moved to a separate package and split into traits for no good reason... just because it sounds cool. Nope... it's not going to happen.

I actually rescinded this earlier in the thread and stated that I was not married to it... it was a pure suggestion.

> So, I think we need some documentation around LiftRules. Before the documentation, there's no discussion to be had and given that Tim's passionate about the issue, I nominate him to document LiftRules. Specifically, he has the following assignment to be completed before Lift 2.2-M2:
> • Completely document every option in LiftRules
> • Add @tag attributed to each option in LiftRules... tags include comet, ajax, web services, important, etc. I'll work with DavidB to include tagged information in VScalaDoc so that people can navigate the tags. That gives us taxonomy at the documentation level (that's the real issue for users), yet certain options may be tagged with multiple tags.
> • In the documentation at the top of LiftRules, identify the options that will most likely be used (the stuff in the standard boot files is a good start). This should be about a dozen or so commonly used options listed in the head. This will give most users what they need to get started.
> • A list of options that are in LiftRules and shouldn't be (e.g., stuff related to I18N of dates and times, currency, etc.)
> Once we have the above complete and we've shipped 2.2, then we can ask the question of our user base... are you able to adequately navigate LiftRules and find what you need? If the answer to the question is similar to the answers in this thread even with documentation and better ability to navigate, then I'll be open to discussing how we can further improve LiftRules.

Ok, so I understand why you "nominate" me. I am passionate about this; however, you are also fully aware of the burden of writing a book (having done it yourself) and thus also likely aware that nominating me pushes this topic into a situation where by I either stop working on the book to do this, or just drop this whole thing - again, as you are likely aware, I cannot stop working on the book. Documenting LiftRules in depth is a huge task and one that I cannot commit too because of the impact that would have on Lift in Action. I was hoping to stimulate discussion about what I felt to be positive and intuitive change, not create a documentation vs design debate.

> But, I don't want to solve a documentation problem by working really hard on changes that are most likely to be breaking to solve a problem that results in far fewer discussions on this list than other facets of Lift.

For what its worth, in my opinion documenting is far harder than coding. If it were easy and we all loved doing it, we would have done it by now.

Derek Chen-Becker

unread,
Oct 12, 2010, 8:55:05 AM10/12/10
to lif...@googlegroups.com
Well, I was going to write a response but it looks like Tim has already covered the salient points in much the way I envisioned. There are two things I'd like to emphasize, however:

  1. As Tim said, documentation is harder than coding. I just spent almost a week working on 13 pages in Exploring Lift covering REST in Lift, and only about 20% of that time was the actual work on the PocketChange codebase. I try to add or improve scaladoc on methods and classes whenever I work on defects in Lift, and for a while I was even doing pure documentation (see some of the methods on the S class, for example), but in my experience it's a lot more work to provide examples and in-depth discussion of a particular method than to write the method itself. Scala, particularly how we use it in Lift, has a pretty high information density, so a few lines of code can require quite a few lines of documentation.
  2. I think it's a bit disingenuous to imply that we're either not thinking or using judgment when we debate these issues. This isn't some whimsy. After years (OK, so I can only barely pluralize that) of working on Lift, I have an appreciation for the thought and effort that's gone into its design, but I also have an idea of where things are sub-optimal.
This debate is not about, as you say, "trivializing the approach that I've taken to shepherding Lift's design". It's about making Lift better, a goal I think we can all agree on whether we agree or disagree on particular issues.

Derek

David Pollak

unread,
Oct 12, 2010, 9:45:12 AM10/12/10
to lif...@googlegroups.com
On Tue, Oct 12, 2010 at 5:55 AM, Derek Chen-Becker <dchen...@gmail.com> wrote:
Well, I was going to write a response but it looks like Tim has already covered the salient points in much the way I envisioned. There are two things I'd like to emphasize, however:

  1. As Tim said, documentation is harder than coding. I just spent almost a week working on 13 pages in Exploring Lift covering REST in Lift, and only about 20% of that time was the actual work on the PocketChange codebase. I try to add or improve scaladoc on methods and classes whenever I work on defects in Lift, and for a while I was even doing pure documentation (see some of the methods on the S class, for example), but in my experience it's a lot more work to provide examples and in-depth discussion of a particular method than to write the method itself. Scala, particularly how we use it in Lift, has a pretty high information density, so a few lines of code can require quite a few lines of documentation.

I understand this.  Even if we were to adopt Tim's initial suggestion without modification, all of the documentation that I've asked for would have to be written anyway, so this is less work, not more.  It is also designed to let Tim learn about the class so that if in fact there are continuing issues with the maintenance or usability of LiftRules, he'd be in a much better place to make recommendations based on familiarity with the code.  I'm working on a post in response to his that should shed a little more light on my first ever assignment of a task to a committer based on code that they did not originally write.
 
  1. I think it's a bit disingenuous to imply that we're either not thinking or using judgment when we debate these issues. This isn't some whimsy. After years (OK, so I can only barely pluralize that) of working on Lift, I have an appreciation for the thought and effort that's gone into its design, but I also have an idea of where things are sub-optimal.
I totally agree that there are many things that are suboptimal in Lift and there are plenty of things that can be improved.  I also totally agree that our experiences writing apps with Lift, supporting people on this list and writing Lift itself form the perspective that we have about what can be improved.  And for the most part, those things can be articulated beyond "gee David, you feel one way and I feel another."  For the most part, arguments can be made about number of questions on the list, number of tickets opened, experience ourselves in coding against an API and the pitfalls that our teams encounter in these situations.  These are data points.  We may reach different conclusions as to where the data points lead us.  But the data points and logical reasoning can take us a whole lot further than what we feel.  If it's just a feelings contest, then how are we to understand how to reach a conclusion?
 
This debate is not about, as you say, "trivializing the approach that I've taken to shepherding Lift's design". It's about making Lift better, a goal I think we can all agree on whether we agree or disagree on particular issues.

I totally agree and I'm all for having an informed and rational discussion about the issues.  The word "feel" has very little place in such a discussion.

Thanks,

David
 

Timothy Perrett

unread,
Oct 12, 2010, 10:05:00 AM10/12/10
to lif...@googlegroups.com
David,

I shall wait for your other mail, but I thought I was fairly clear in my previous post that it is a simple case of logistics for me - I don't have time to write documentation for LiftRules... I am too busy with the book which is turning out to be a pretty good source of documentation for the whole framework based on reader feedback thus far. Moreover, you assume I don't know LiftRules at all; I know it very well, use it extensively most days and I trawled the entire class file before making this post in the first instance. Not to mention having studied it in detail for the book.

Tim

David Pollak

unread,
Oct 17, 2010, 10:03:13 AM10/17/10
to lif...@googlegroups.com
On Tue, Oct 12, 2010 at 7:05 AM, Timothy Perrett <tim...@getintheloop.eu> wrote:
David,

I shall wait for your other mail, but I thought I was fairly clear in my previous post that it is a simple case of logistics for me - I don't have time to write documentation for LiftRules... I am too busy with the book which is turning out to be a pretty good source of documentation for the whole framework based on reader feedback thus far. Moreover, you assume I don't know LiftRules at all; I know it very well, use it extensively most days and I trawled the entire class file before making this post in the first instance. Not to mention having studied it in detail for the book.

Tim,

Lift is an entirely voluntary project.  Very rarely do I assign anything to committers.  However, once a committer takes responsibility for a module, a section of code, a piece of Lift, they also take on the responsibility for supporting and maintaining that piece of code.  This is why Lift is both production stable and is well supported... the folks who created parts of Lift support it and those folks continue to support it and find others to help them... thus Marius can take a break because I'm willing to support his code... and those times that I've been less available, Marius and Derek support most of the code in WebKit that I'm primarily responsible for.  Joni supports the JSON code, but there is a network of folks who help out when Joni's on vacation.

But for each substantial part of Lift, there's a responsible party.  Marius and I share responsibility for LiftRules.

With authority comes responsibility.  You are asking for the authority to make wholesale changes to LiftRules, but you are not willing to take the responsibility to even maintain the documentation for LiftRules.  The changes you propose to LiftRules *require* documentation and analysis.  The documentation that I assigned to you is a perfect subset of the work required to change the structure of LiftRules and a test to see if you were willing to take responsibility... you failed the test.  If there are logistical problems with you simply writing the required documentation, then the same logistical problems are going to bar you from making the structural changes to LiftRules, insuring backward compatibility and writing the tests necessary to insure all of these things. If you have time commitment problems just writing the documentation, then there's no way that you can claim that you're going to have the time to be the primarily responsible party for LiftRules going forward.  So, at this point, there's no reason for you to make any further suggestions about wholesale changes to LiftRules.  If there are specific user-facing issues with LiftRules, I'm all for hearing about feedback for improving them.  I have no tolerance for you telling me about the maintainer-facing complexity of LiftRules because there have been few defects opened against LiftRules and I'm both the primary committer to LiftRules (more than 50% of the commits in the last year vs. 1 substantive commit from you) and I'm the person responsible for LiftRules.

More broadly:
  • When Derek, Tyler, and Marius wrote the Lift Book, they contributed substantially to the ScalaDocs in Lift.  That level of contributing back to Lift as a by-product of writing a book is not required, but does go a long way to getting me to spend extra time writing code samples and explaining things privately.
  • When I spend one on one time with you at an event (the post-party after the Lift Off London day 1) and explain that (1) breaking things into traits just to be rolled into a unified class is a bad design decision that I would be loath to repeat after the problems with Helpers and (2) that I viewed the LiftRules issue as a documentation issue and that was a good place to start in terms of seeing if better documentation addresses the issues, to see you totally ignore my feedback, raise the issue on the Lift mailing list and then make weak arguments about "feelings", it tells me I should be spending a whole lot less time discussing issues with you and helping you in private IMs and emails.
  • Any discussion that has the word "feelings" in it will not compel me to accept the proposition.  If we measure the relative value of "feelings" by experience, then very few people's feelings on this list count more than mine because I've had 30+ years of API design experience (including some APIs that are in their 18th year of active production and maintenance), and on and on.  But this is a terrifically terrible way to design APIs, engender discussion, or improve a product.  Having discussions based around rational arguments like comprehensibility, lines of code, number of defects, ability to locate appropriate documentation, etc. are much much better ways to have a discussion.  They allow everyone to participate.  Being able to separate the problem from the solution means that a single problem may have multiple solutions and many of those solutions can be explored before settling on one.  The problem that remains is making LiftRules more accessible to Lift coders... the newbies and the more experienced coders.  The "how to do this" is a challenging issue, but starting with better documentation and seeing if that measurably reduces the problem is a start that does not require nearly as much work as anything else.  A discussion about any of the issues will also take into account the various constituencies (in this case end coders and Lift committers are two separate constituencies and making arguments about complexity with respect to the Lift committers without understanding that the person you are arguing against is the one making most of the code changes and improvements hurts your argument a whole lot.)  A discussion of issues will at least highly the balance among different important factors.  For example, what's the balance between a breaking change and extra work on the part of the committers.  While we always want to improve Lift, what's the balance between legacy design decisions that may not be optimal in hindsight and changes that require a new mental model for existing developers.  There are plenty of ways to make logical arguments based on facts rather than making feelings-based arguments that wind up pitting your experience vs. my experience.
So, to conclude:
  • I'll write improved documentation for LiftRules.  If this does make LiftRules materially easier for coders to consume, then we'll explore other options post 2.2.
  • Tim -- next time you make a material proposal to change Lift, be prepared to have a rational discussion that does not use the word "feelings" and be prepared to do the work.  If you've got a feature request and want someone else to do the work, you're welcome to submit the feature request.
  • Community -- The Lift committers care about improving Lift and the best way to do that is to listen to the community.  There are good ways to present improvements to Lift and there are less good ways.  The approach that Tim has taken in this thread is an example of a less good way.
Thanks,

David
 

Tim

On 12 Oct 2010, at 14:45, David Pollak wrote:

> I understand this.  Even if we were to adopt Tim's initial suggestion without modification, all of the documentation that I've asked for would have to be written anyway, so this is less work, not more.  It is also designed to let Tim learn about the class so that if in fact there are continuing issues with the maintenance or usability of LiftRules, he'd be in a much better place to make recommendations based on familiarity with the code.  I'm working on a post in response to his that should shed a little more light on my first ever assignment of a task to a committer based on code that they did not originally write.

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.

Strom

unread,
Oct 17, 2010, 2:56:17 PM10/17/10
to Lift
Don't know if I'm at the right level to enter this conversation, but I
am -0 on the changes to LiftRules. I've only skimmed much of the above
as far as tags and splitting the LiftRules object. I can also say that
I personally get overwhelmed with the scaladoc api...here and in other
packages. Mainly it's because most methods have a one liner that can
be cryptic without example usage.

I believe that the fundamental issue is in depth documentation. I
wouldn't need much code navigation if I'm just using LiftRules and
know what and how to set. Not sure what this entails, but if scaladocs
and tags is not appropriate or mature enough, we can at least have a
wiki section devoted to LiftRules split into the various sections that
Tim suggested from the beginning (Ajax, Http, etc). Each method could
then have an explanation on what it does when set (on, off, by
default), and an example usage of how to set it. I'm sorry I don't
have a good example of any LiftRules method; to be honest, I only look
at it on a need to know basis, and that usually happens when something
undesirable is happening in my app ;)

I know this seems like a lot of work, but it's not anymore than it
would take to split LiftRules out into packages (testing, notifying
all lift users of a breaking change, etc). And this way, none of the
code changes, you have better documentation (which would help scan the
code in LiftRules for what you are looking for), and configuration can
be more intuitive.

Just my opinion.

Strom

On Oct 17, 7:03 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
>    - When Derek, Tyler, and Marius wrote the Lift Book, they contributed
>    substantially to the ScalaDocs in Lift.  That level of contributing back to
>    Lift as a by-product of writing a book is not required, but does go a long
>    way to getting me to spend extra time writing code samples and explaining
>    things privately.
>    - When I spend one on one time with you at an event (the post-party after
>    the Lift Off London day 1) and explain that (1) breaking things into traits
>    just to be rolled into a unified class is a bad design decision that I would
>    be loath to repeat after the problems with Helpers and (2) that I viewed the
>    LiftRules issue as a documentation issue and that was a good place to start
>    in terms of seeing if better documentation addresses the issues, to see you
>    totally ignore my feedback, raise the issue on the Lift mailing list and
>    then make weak arguments about "feelings", it tells me I should be spending
>    a whole lot less time discussing issues with you and helping you in private
>    IMs and emails.
>    - Any discussion that has the word "feelings" in it will not compel me to
>    - I'll write improved documentation for LiftRules.  If this does make
>    LiftRules materially easier for coders to consume, then we'll explore other
>    options post 2.2.
>    - Tim -- next time you make a material proposal to change Lift, be
>    prepared to have a rational discussion that does not use the word "feelings"
>    and be prepared to do the work.  If you've got a feature request and want
>    someone else to do the work, you're welcome to submit the feature request.
>    - Community -- The Lift committers care about improving Lift and the best
>    way to do that is to listen to the community.  There are good ways to
>    present improvements to Lift and there are less good ways.  The approach
>    that Tim has taken in this thread is an example of a less good way.
>
> Thanks,
>
> David
>
>
>
>
>
> > Tim
>
> > On 12 Oct 2010, at 14:45, David Pollak wrote:
>
> > > I understand this.  Even if we were to adopt Tim's initial suggestion
> > without modification, all of the documentation that I've asked for would
> > have to be written anyway, so this is less work, not more.  It is also
> > designed to let Tim learn about the class so that if in fact there are
> > continuing issues with the maintenance or usability of LiftRules, he'd be in
> > a much better place to make recommendations based on familiarity with the
> > code.  I'm working on a post in response to his that should shed a little
> > more light on my first ever assignment of a task to a committer based on
> > code that they did not originally write.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Lift" group.
> > To post to this group, send email to lif...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/liftweb?hl=en.
>
> --
> Lift, the simply functional web frameworkhttp://liftweb.net
> Beginning Scalahttp://www.apress.com/book/view/1430219890

Strom

unread,
Oct 17, 2010, 3:02:51 PM10/17/10
to Lift
Also, having a section open on the wiki would help Tim as far as
documentation because the community could help write it. He, as the
owner/maintainer of LiftRules, may then edit, add, or remove from the
existing community contributed work vs writing it all himself.

And in response to Derek, I know that documentation may seem harder
than coding itself, but think about how much time it saves from having
to answer another duplicate question on this group about
"MapperRules.createForeignKeys_? = c => true", for instance. All this
comes without pushing the headache to the end user who has already
built their app on the existing code.

Strom

David Pollak

unread,
Oct 17, 2010, 6:23:58 PM10/17/10
to lif...@googlegroups.com
Thanks for the suggestions.

I've created a LiftRules section on the Wiki: http://www.assembla.com/wiki/show/liftweb/LiftRules

As I document LiftRules, I'll organize subsections in LiftRules.  Community contribution is always appreciated.

To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.




--
Lift, the simply functional web framework http://liftweb.net

Derek Chen-Becker

unread,
Oct 18, 2010, 11:29:29 AM10/18/10
to lif...@googlegroups.com
I've been thinking about the required documentation and I think we may want to consider another aspect of this. I'm often looking at a method somewhere else in Lift (say, S), and I want to figure out how to customize its behavior. Having accurate documentation at both the configuration and use point is going to help make this more comprehensible, and make it easier to explore the API via ScalaDoc (something I do a lot in libraries). I've already done some work adding "@see" tags to cross-reference things (see S.addSessionRewriter for an example), but currently that doesn't appear to be supported in the same way that it is in JavaDoc. In other words, this is more than just documenting LiftRules itself, this is tying all of the various classes into a comprehensive whole.

Derek

David Pollak

unread,
Oct 18, 2010, 12:25:19 PM10/18/10
to lif...@googlegroups.com
On Mon, Oct 18, 2010 at 8:29 AM, Derek Chen-Becker <dchen...@gmail.com> wrote:
I've been thinking about the required documentation and I think we may want to consider another aspect of this. I'm often looking at a method somewhere else in Lift (say, S), and I want to figure out how to customize its behavior. Having accurate documentation at both the configuration and use point is going to help make this more comprehensible, and make it easier to explore the API via ScalaDoc (something I do a lot in libraries). I've already done some work adding "@see" tags to cross-reference things (see S.addSessionRewriter for an example), but currently that doesn't appear to be supported in the same way that it is in JavaDoc. In other words, this is more than just documenting LiftRules itself, this is tying all of the various classes into a comprehensive whole.

I've updated the Wiki page to include the documentation criteria.  Please update if I missed something: https://liftweb.assembla.com/wiki/show/a-L5GeVBGr3RE_eJe5aVNr/LiftRules
Reply all
Reply to author
Forward
0 new messages