<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    As OP I take the liberty to do a top post and try to summarise a few
    things at this point.<br>
    <br>
    I am not alone when it comes to having an urge to remove some of the
    boilerplate code. I guess we all want value for our money and when
    we have to do something that does not provide that we want to
    improve. If we did not have that craving we might as well be coding
    enterprise Java applications using dozens of frameworks ;-)<br>
    <br>
    I had a look at the e2project and it actually does remove some of
    the boilerplate that I find the most iritating, namely the tagging
    of messages from the API function to the handle_* function. It is a
    lot clearer in e2project where you reference a function in the
    e2_service:call - I like that a lot.<br>
    <br>
    The approach with parse transforms has its merits, but I think that
    the e2project can do away with most of the pains I have been
    feeling, so I think I will leave out the semi-black magic of parse
    transforms for now... it is a tool that should be used with caution
    as other posters have mentioned.<br>
    <br>
    The IDL approach I had in mind was nothing about CORBA - I should
    never have mentioned CORBA in my original mail, there are too many
    negative feelings associated to CORBA. <br>
    What I like about IDLs is that it allows you to spec your API in a
    nice way and in many cases it will be possible to avoid writing
    boilerplate code (either through code generation or using a parse
    transform).<br>
    <br>
    Given the good point made about separating the client and the server
    side of things I think that what is needed is simply to spec up the
    API function (who doesn't do that already?!?!) and then try out
    e2project. The spec will give me a slap over my fingers if I do not
    provide the function (I like that) and e2project seems to minimise
    the tedious boilerplate stuff from standard gen_server without
    limiting my ability to express what I need.<br>
    <br>
    A big thanks to all posters - I am glad I asked the question!<br>
    <br>
    Cheers,<br>
    Torben<br>
    <br>
    On 21/3/12 21:10 , Tim Watson wrote:
    <blockquote
      cite="mid:6F99D60B-C45A-4E21-AAEC-FF5E1630298E@gmail.com"
      type="cite">
      <div>
        <div>On 21 Mar 2012, at 19:22, Garrett Smith wrote:</div>
        <blockquote type="cite">
          <div>
            <blockquote type="cite"><font class="Apple-style-span"
                color="#000000"><br>
              </font></blockquote>
            <br>
            This may come down to personal taste. I don't like having to
            dig<br>
            around in parse transform code to understand what my module
            looks<br>
            like.<br>
            <br>
          </div>
        </blockquote>
        <div><br>
        </div>
        <div>Neither do I - that's why I simply run 'escript `evm
          site`/parse_trans/ebin/parse_trans_pp.beam
          ebin/<target>.beam' over the generated beam to see what
          it looks like at source level. ;)  </div>
        <br>
        <blockquote type="cite">
          <div>eunit is a great example. If you really love eunit, then
            I'm not going<br>
            to convince you :)<br>
            <br>
          </div>
        </blockquote>
        <div><br>
        </div>
        <div>Common test and PropEr do exactly the same thing. I'm not
          sure what you're expected testing frameworks to do instead!?</div>
        <br>
        <blockquote type="cite">
          <div>
            <blockquote type="cite">
              <blockquote type="cite">- Hiding the client-server
                distinction in Erlang is a terrible disservice<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite"><br>
            </blockquote>
            <blockquote type="cite">I agree with this wholeheartedly,
              but don't see what it has to do with code generation.<br>
            </blockquote>
            <br>
            If you consolidate both the client and server functions into
            one<br>
            function, you've obfuscated an important distinction.<br>
            <br>
          </div>
        </blockquote>
        <div><br>
        </div>
        <div>I never suggested doing that at all. Not that I mean to be
          prickly, as we're all part of the same community and whatnot,
          but nobody suggested separating both functions. What the OP
          suggested was that you could define the interface
          declaratively - e.g., without writing the code directly - and
          that was what I was responding to. As I mentioned later on, in
          this particular gen_server case I actually think your approach
          is probably cleaner and more appropriate, but it's good to
          separate these points and refine the discussion I think.</div>
        <br>
        <blockquote type="cite">
          <div>
            <blockquote type="cite">
              <blockquote type="cite">IMO, e2 solves the problem of "too
                much boiler plate". It's really<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">easy and requires zero magic.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">Here's a "gen_server" equivalent
                in e2:<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><a moz-do-not-send="true"
href="https://github.com/gar1t/e2v2/blob/master/examples/ping/src/ping_server.erl">https://github.com/gar1t/e2v2/blob/master/examples/ping/src/ping_server.erl</a><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite"><br>
            </blockquote>
            <blockquote type="cite">This is pretty cool though. :)<br>
            </blockquote>
            <blockquote type="cite"><br>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">You might object to the separation
                of "ping" and "handle_msg" -- it<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">appears to be just one function,
                so why break it up into two pieces?<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">The problem is that it's not one
                function -- it's definitely *two*<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">very separate pieces of code.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite"><br>
            </blockquote>
            <blockquote type="cite">Absolutely and a good point!<br>
            </blockquote>
            <blockquote type="cite"><br>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">When you write a gen_server style
                module, you're writing code that<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">support client-server
                interactions. You have, in the same module, code<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">that is called by the "client" and
                code that is called by the<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">"server". If you don't grok this,
                you're missing the entire point of<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">this type of module.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">Code that hides this difference --
                e.g. a parse transform that gloms<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">the client and server functions
                into one -- is IMO a Really Bad Idea.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite"><br>
            </blockquote>
            <blockquote type="cite">I don't necessarily agree with this,
              as the parse transform can be applied to a -spec which is
              potentially as intention revealing as a hand written
              function. I do take your point about them being two
              separate functions and perhaps in this particular case
              (for gen_server) you are actually correct and having two
              hand coded parts is actually better. I don't buy 'code-gen
              is bad' as a general argument (which perhaps you weren't
              going so far as to make anyway), and I do see your point
              in this instance.<br>
            </blockquote>
            <br>
            I'm certainly not arguing against code generation. I think
            Erlang's<br>
            parse transform scheme is *very* good -- flexible enough to
            enable<br>
            elegant solutions but with enough complexity to scare off
            casual "meta<br>
            programmers".<br>
            <br>
            But -- I think there should be a very clear payoff for using
            a parse<br>
            transform. I don't think the discussion here, which is
            "boilerplate"<br>
            is a good application for that.<br>
            <br>
          </div>
        </blockquote>
        <div><br>
        </div>
        <div>I think it depends on how much boilerplate you're looking
          at. As an OCaml programmer I have seen a *lot* of work going
          into removing boilerplate code, and the same in Haskell
          (although there I am less experienced) and overall I think the
          payoff you're describing is a value judgement based on the
          negative impact of using code generation. Generated code is
          brittle - there's no two ways about it. But it doesn't prevent
          you from testing or documenting, nor does it have to make your
          code opaque and difficult to understand, so long as it is not
          overused - a sprinkle here and there rather than a bucket
          load.</div>
        <br>
        <blockquote type="cite">
          <div>A good example of a value-add parse transform IMO is
            modlib, which<br>
            lets you create mods for inets httpd withou causing your
            brain to<br>
            explode [1].<br>
            <br>
            <blockquote type="cite">
              <blockquote type="cite">As an example of how this
                client/server difference is important,<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">consider form validation in a web
                app. There are two places you can<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">run code to validate form input --
                you can validate it in the browser<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">using JavaScript, or you can send
                the form data to the server. Web<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">developers may opt for browser
                validation to avoid the expense of<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">sending data to the server -- or
                they might prefer it on the server.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">Either way, it's an important
                consideration.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">This same dynamic applies to
                gen_server style modules. If you stick<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">with it, I think you'll appreciate
                the separateness of client and<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">server facing code.<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">As for the boilerplate, I couldn't
                agree with you more!<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">Garrett<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite"><br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">P.S. I'm giving a talk on e2 at
                the SF Factory in a couple weeks,<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">where I'll get into this in more
                details. Also, the e2 docs and github<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">project are in slight disarray at
                the moment, but will be put in order<br>
              </blockquote>
            </blockquote>
            <blockquote type="cite">
              <blockquote type="cite">this weekend!<br>
              </blockquote>
            </blockquote>
            <br>
            [1] <a moz-do-not-send="true"
              href="https://github.com/gar1t/modlib">https://github.com/gar1t/modlib</a><br>
          </div>
        </blockquote>
      </div>
      <br>
    </blockquote>
    <br>
    <pre class="moz-signature" cols="72">-- 
<a class="moz-txt-link-freetext" href="http://www.linkedin.com/in/torbenhoffmann">http://www.linkedin.com/in/torbenhoffmann</a></pre>
  </body>
</html>