May 15, 2011
Alexander wrote:
> page-a.html:
> <?d var = "value" ?>
> page-b.html:
> <?= var ?>
>
> And this I expect to work.

That doesn't work in PHP nor ASP. In them, you *must* have page-a include page-b, or a parent page include both, unless you are populating the var from the session (see below).

Try it. It's identical to dhp's preprocessor approach.

> *and* persistent.

That never works in PHP nor ASP, not even with php's register_globals. You have to use an explicit session to keep variables around between calls.

Note that PHP's register_globals, if you're actually using it, is a huge huge mistake that they've deprecated in new versions.
May 15, 2011
On 15.05.2011 17:36, Adam D. Ruppe wrote:

> But Wordpress' code *is* an xml template, just with other crap mixed in.

  Not really "XML template". XML template, in my view, is something that is pure XML, without any code in it. In WordPress, those are mix of HTML and code, nothing more.

> One of the downsides of me writing my document in notepad is adding code examples in a pain. I didn't want to manually write &lt;div&gt;
> over and over again, so I just sidestepped it.

  Well, normally, code examples are not something which is displayed on (say) internet shop pages ;)

  I couldn't even remember when I had to do this last time, to be honest - so quoting is not a concern for me.

  Perhaps, you don't need it, but I do want to have an option to modify application logic on the fly, in the template or any other dynamic page, that's why I like mix of code and data - especially when the code is insignificant fraction of data.

> The D side, btw, looks like so:
> 
> auto table = cast(Table) document.getElementById("our-data");
> foreach(row; data)
>    table.appendRow(row...);

> Much easier than the PHP equivalent too - it's all clear. And all properly closed and entity encoded with zero effort.

  "all clear" to you - who is the author :) To me, this all is not so clear - as I don't know (=see) where exactly in the document all this happens.

  The whole reason to mix code with templates is to see where specific values are written, that's why to me code like:

        <div id="page-content">
            <?php output_page_content(); ?>
        </div>

  is much more clear - whatever it is - PHP, ASP, D or something else.

  You may call it ugly, bad practice, incorrect, etc - that's, probably, is true for you - but not for everyone out there. People have different preferences :) Some even like to write HTTP servers in bash or postscript, and, though this is doable -
it is not really practical to anyone who is used to something different - that's what I want to say.

/Alexander
May 15, 2011
Jacob Carlborg wrote:
> But that way you would need to declare different types of Options structs all over the place?

Sometimes, but most functions are fine with regular argument lists, to me, using enums for options where appropriate.

> I think there are other languages available that is far better than PHP that you could compare with instead. Ruby on Rails:

Come to think to fit, PHP's $_REQUEST() would have worked here too
and shaved off a couple lines.


Anyway, I've used Ruby before, but never Rails. The to_i and to_s things are familiar.. me forgetting to write them caused many problems in that project. I hate dynamic languages so much. That Ruby project is what put the nail in the coffin.

I want to get an idea of how Rails works though, so see how well my approaches stack up. But, aside from discussions like this one, I haven't had a chance to get into it.

> This will try to find a Post with the given id and automatically converted the given value to an integer.

This is similar to how my database libs work. It actually lets the database do the conversion though.


> I've been thinking for a while to try and create something similar as Rails' ActiveRecrod for D but every time I tried to do it turns out to work quite badly with a static type system.

Have you seen Piotr Szturmaj's Postgres code?

http://www.digitalmars.com/d/archives/digitalmars/D/learn/D2_postgresql_interface_-_Phobos2_23693.html#N23695

(there's more posts than that on it too if you search)

It might give you some ideas.


I went the other way; I don't mind writing SQL. (I always find automatic mappings the other way to be inefficient and lacking anyway.)


> As I said above, I don't see the big advantage if I have to use Variants all over the place .

The thing is it's not *all* over the place. There's a small area where you use them, and you get the static type benefits everywhere else.

Even with the variant areas, the static type system helps a little bit. At least misspelled variable names are caught ahead of time by the compiler.

> HAML, generates HTML - http://haml-lang.com/

Syntax and indenting aside, concepturally, that's similar to how my DOM based code works.

auto profile = holder.addChild("div").className("profile");
auto left = profile.addChild("div").className("left column");

left.addChild("div", print_date).id("date");
left.addChild("div", current_user.address).id("address");


One big difference, semantically, is my code always escapes HTML
by default. Looks like haml uses &= for escaping, while = does
not.... so their homepage example is both incorrect and
open to XSS attacks!


(I offer two ways to write HTML: some functions take arguments of type Html, like Table.appendRow:

table.appendRow("&nbsp;", Html("&nbsp;"));

First column appears as literally &nbsp;. Second column shows up as a non breaking space.


But, mostly, if you want to mess with html, you use the innerHTML property. It's a pain to use because outputting HTML is, 9 times out of 10, wrong. Any template system that doesn't do this gets a big point against it in my book, similarly to any database library that makes mixing unescaped text in the easiest way...)



Anyway, their syntax is certainly brief. I can see the appeal in that.


Curious though, how does haml handle forms? Looking through the documentation, it doesn't seem to at all.

This is one of the nicest things about my DOM approach. You can write the form in standard HTML, with default values written there if you want, and the code will fill it in later.


> * SASS, generates CSS - http://sass-lang.com/ (I'm using the sass
> syntax and not the scss syntax)

Heh, I looked at that not long ago. I'm annoyed by CSS's lack of nesting.

Not annoyed enough to introduce Ruby to the project, although I rather like what they did here. I'll probably spin my own version eventually.


> * CoffeeScript, generates JavaScript -

Eh, I thought about something along these lines, write some of it, but I decided against going far with it.

There's two reasons:

a) If you're writing enough Javascript to make using a replacement worth it, you're writing too much Javascript.

b) Javascript's biggest problem is that it's loosely and dynamically typed, not that it's whitespace is ignored.


The auto-generated javascript to access my D code make using it almost easy anyway

http://arsdnet.net/cgi-bin/apidemo/javascript

<button onclick="
  CoolApi.getABox('green').appendTo('playground');
" type="button">Get a green box</button>


Those are all basic examples. The idea is the server does most the work, and Javascript simply plugs it in somewhere in the document - the same way the page is built on the server side. appendTo's argument can be a string for a trivial ID or an element as returned by any of the built in browser functions (such as querySelector - no need to load up a big piece of shit like jQuery to have that.)

The generic get() function does partial application so it's reusable
with other functions:

function fadeIn(parent, speed, html) { ... }

  CoolApi.getABox('green').get(fadeIn, this.parentNode, 10);


Since the server might return data, such might not always work. That's where the format modifier comes in:

  CoolApi.getPeople(0).format('table').get(fadeIn, this.parentNode, 10);



Thus, javascript functions become fairly trivial and/or reusable, so you don't have to deal with the language very much at all.



I also toyed with generating Javascript from D:

auto js = new ClientSideScript();

js.alert("Hello, world!");

js.var("wat") = 10;

js.alert(js.wat);


That kind of thing. Each method call to the js object builds a code string inside it. D variables passed as arguments are converted to Javascript literals and added to the code.

It actually kinda works, and I use it from time to time, but only for little things. For the big, I don't think it's worth it.
May 15, 2011
Alexander wrote:
>  Perhaps, you don't need it, but I do want to have an option to
>  modify application logic on the fly, in the template or any other
>  dynamic page, that's why I like mix of code and data - especially
>  when the code is insignificant fraction of data.

I think you'll feel differently once you see people abuse that
option. It becomes hard to follow what's going on. Then, when
the customer reports a bug or a change, you spend all night pounding
your head over it instead of 5 minutes doing it, then goofing off
arguing on newsgroups for the rest of the day :P


> all clear" to you - who is the author :) To me, this all is not
> so clear - as I don't know (=see) where exactly in the document
> all this happens.

You're also not used to it. (When I write this for newbies, I often put a comment in there: <!-- filled by program -->)

It's an easy pattern though: an empty element with an ID is
meant to be filled in, and the ID should be descriptive enough
to make a good guess at what it's doing. (at least no worse than
guessing a function's behavior based on it's name. Similarly,
knowing what ID to use is the same as knowing what function to use.)

I sometimes get concerned that the id's will get out of sync, or the new guy won't understand what's going on, but it hasn't been a problem in practice. After you see it used once, it's not a mystery anymore.
May 15, 2011
On 15.05.2011 18:17, Adam D. Ruppe wrote:

> That doesn't work in PHP nor ASP. In them, you *must* have page-a include page-b, or a parent page include both, unless you are populating the var from the session (see below).

  Don't take my example literally, please - I just wanted to point that there is some globally visible storage accessible to all pages, be it session or something else, but which exists while the server is running and is very fast (i.e. not in DB).

> That never works in PHP nor ASP, not even with php's register_globals. You have to use an explicit session to keep variables around between calls.

  Again - session data s something that is transparently (more or less) accessible to all pages. dhp doesn't do this, as far as I can see.

  If application is a set of pages, there should be a way to share data between pages without using complicated or expensive persistent storage.

/Alexander
May 15, 2011
On 15.05.2011 19:36, Adam D. Ruppe wrote:

> I think you'll feel differently once you see people abuse that option. It becomes hard to follow what's going on.

  Sure I will feel differently, that's why I've said "if used correctly" - and I do use it correctly :)

> You're also not used to it. (When I write this for newbies, I often put a comment in there: <!-- filled by program -->)

  That kind of a comment made me crazy many times - because then I had to dig inside the program to find the place where it was filled :)

> It's an easy pattern though: an empty element with an ID is meant to be filled in, and the ID should be descriptive enough
> to make a good guess at what it's doing.

  If at some point I want to change output from table view to something else - then I've to change the application as well, as it generates series of tr/td elements, which I don't need anymore. To me, it is much easier to change it in place - i.e.
where this is done actually. Bouncing from template to code is quite annoying, to be honest, especially when that code is not your own :)

> After you see it used once, it's not a mystery anymore.

  It is not a mystery, just something that is blocking my productivity :) I just don't like it - and because of this I am less productive.

  From my point of view, it makes no sense to say "that is wrong" or "that is bad" - unless there is *objective* (and only) way to do something *right* - which is not the case in web development (and any software development in general).

  So, to some people (including myself) unless and until D may be embedded like PHP/ASP, it will be a show stopper. For some others - it will not, that's all.

  For this reason, I prefer to use D as a backend only (=performance critical), and frontends will be in PHP or ASP (=UI only). Though, currently I evaluate option to use D to host a server (HTTP) with dmdscript as server-side scripting language.
What blocks me is the absence of good, robust and high-performance socket/file I/O framework for D2.

/Alexander
May 15, 2011
Alexander wrote:
> If application is a set of pages, there should be a way to share data between pages without using complicated or expensive persistent storage.

FYI, PHP uses files on the hard drive for sessions by default... optionally, it can use a database too. AFAIK, there is no in-memory option beyond the options the kernel or database provide for file/table caching.

> Again - session data s something that is transparently (more or less) accessible to all pages. dhp doesn't do this, as far as I can see.

Nope, it'd be provided by an external library.

Like I said in another sub-thread, I thought about cloning PHP's approach for a while. (There's a small amount of code to this end still commented out in my cgi.d and phphelpers.d modules)

But, I never finished it, because I use sessions so rarely. Most
usages of it don't match well with the web's stateless design -
if someone opens a link on your site in a new window, can be
browse both windows independently? Changing one *usually* shouldn't
change the other.

The two exceptions are logging in, which barely requires session data at all - matching session id and other identifiers to user id is all that's really necessary. Another big exception is something like a shopping cart. In cases like that, I prefer to use the database to store the cart anyway.

So I've had no need for a fancy session system, and thus, never finished mine. It provides some session ID functions, but lets you do whatever you want with it beyond that. I can use them to store temporary files, as keys into the database, whatever.

(BTW, PHP's automatic session handling *only* uses the session id.
This leaves it open to trivial session hijacking. In web.d, the
session functions automatically check IP address and user agent
as well as cookies. It can still be hijacked in some places, but
it's a little harder. To prevent hijacking in all situations,
https is a required part of the solution, and the cgi library can't
force that unilaterally. Well, maybe it could, but it'd suck.)


I have considered adding a library for some persistent stuff though. One example is a service that pushes updates to clients. (The client uses ajax long polling or something similar to work around the limitations of the web environment.)

I've written two programs in D that work like this - a real time web chat server and the more generic (and incomplete) D Windowing System's ajax bridge.

But neither one simply broadcasts messages to waiting http clients.

This would be useful for doing updates like Facebook. If someone posts a new wall post, it shows up on everyone's browser, pretty quickly.

The usage code would look like this:

broadcaster.push(channelId, message);


The waiting clients run javascript that looks like so:

var listener = new Listener("channelId");
listener.messageReceived = function(message) { ... };


Very simple. Maybe I'll write that today.



There's two other things a longer running process is good for:

1) Session storage (see, on topic!). You speak a protocol to it... it's basically a reinvention of a database engine using memory tables. Might as well just use a real database engine with in-memory tables, or temporary files, relying on the kernel to keep them in memory.

I'm in no rush to write this, since there's little need and existing stuff does it well when you do want it. If you have complex objects, you might want to keep them in memory.

In that case, you can just use an embedded http server instead of cgi. My cgi class lets you do this without changing the bulk of your client code, and I've written an embedded http server in D to go with it.


2) Doing work that takes a long time or needs to be scheduled. There's three approaches to this, all of which work today:

a) fork() your process, letting the child do the work while the
main cgi program finishes.

This is very convenient to program:

// prepare stuff

runInBackground( {
      // write code here to run, using variables prepared above
});

// terminate, not worrying about the background process. It will // live on without you.



The downside is I *believe* it doesn't scale to massiveness. Then again, most our sites aren't massive anyway, so does it matter?

Also, I'm not sure if it scales or not, since I haven't tried. The most I've actually done using it for real was about 20 concurrent users. It did fine there, but everything does fine for small n.

Another downside is communicating with it is hard. Could be solved by adding some message passing functions to the library, or combining it with the persistent notifier service described above. You would have to store it's process ID or the name of a pipe to talk to it though.

Also, remember if it is doing work, you don't want to talk to it again. A cross-process lock is probably desired. Such is not handled automatically either.

Finally, long running processes can't be updated. You have to kill them and restart, but if their state is only in memory, this means you lose data.

Still, it is quite convenient!


b) The way most PHP sites do things is to write out work to do later to the database, then depend on a cron job to check it and execute the stored commands.

While it still takes care to ensure things are locked, communication is a little easier - instead of talking to the process, you poll the work list in the database. It could also use the persistent notification service.

The cron job may be triggered by a lot of things. Page views (ugh),
including automatic refreshes (double ugh), a real cron daemon, or
user action, such as hitting ok on a schedule screen then doing
it in the foreground, or a desktop application.


One of my work projects went with the latter. The server cron app was moved to the user's desktops. Thanks to it all being written in a real programming language like D, reusing the code from the server app in a compiled GUI application was no trouble. I imported the same modules and compiled them for distribution. The users didn't have to install an interpreter or an httpd.

3) Use a persistent process in the first place, and run long work in a background thread, or even a foreground thread that isn't killed off by timeouts or disconnections.

An embedded http server and std.concurrency can help with this.




While all of these are possible, I usually stick with the traditional cron approach. It's simple enough, it's effective, and it's pretty resilient to things like the server going down. The worklist is still in the db so it can be restarted later.



wow, I went off at length again.
May 15, 2011
Alexander:
> That kind of a comment made me crazy many times - because then I had to dig inside the program to find the place where it was filled

Meh, is it any worse than digging into the program to figure out what a function referenced in the template does?

> If at some point I want to change output from table view to something else - then I've to change the application as well

Not necessarily - you could add format strings to the html, or have the output dependent on the tag name.

The Javascript access to my code I pointed to earlier includes this:

HTML, using a custom formatter provided by the Person object:

http://arsdnet.net/cgi-bin/apidemo/get-people?startingId=0&format=html

String, using a part custom, part automatic formatter:

http://arsdnet.net/cgi-bin/apidemo/get-people?startingId=0&format=string

Table, using an automatic formatter:

http://arsdnet.net/cgi-bin/apidemo/get-people?startingId=0&format=table

Json, using an automatic formatter:

http://arsdnet.net/cgi-bin/apidemo/get-people?startingId=0&format=json


The D function simply returned a Person[]. The formatting is flexible, automatic in a lot of cases, hookable by the object if needed.



But, in a lot of cases, you have to change the model to change
the data you're showing anyway... the view only has what's available
to it.

Even when mixed php code/data, you're going to either repeat yourself a lot, or be limited by what's available in existing functions or in the database.

The semantics of the data won't change without touching app code, so the tags at this low level probably won't either. Changing their appearance is done by CSS.


Take this table:

http://arsdnet.net/cgi-bin/apidemo/get-people?startingId=0&format=table

Want to show it as a list? Use CSS:

table { display: block; border: none; padding-left: 2em; }

thead { display: none; }

tr { display: list-item; }

th, td { display: inline; border: none; margin-left: 0.2em; }


Boom, the table now looks like an unordered list. Semantically though, it's still tabular data, and the markup reflects that.

See it live here:

http://arsdnet.net/get-people.htm



> What blocks me is the absence of good, robust and high-performance socket/file I/O framework for D2.

When I wrote my http code, one of which is a kind of proxy/webapp
build in one, so it does server and client work, I just used
the appropriate C functions. Everything accessible from C is
also accessible from D, so even if phobos isn't quite up to it,
you can always do without.

I agree it will be nice when phobos' offering improves though.
May 15, 2011
"Adam D. Ruppe" <destructionator@gmail.com> wrote in message news:iqp7gu$7l6$1@digitalmars.com...
>
> (BTW, PHP's automatic session handling *only* uses the session id.
> This leaves it open to trivial session hijacking. In web.d, the
> session functions automatically check IP address and user agent
> as well as cookies. It can still be hijacked in some places, but
> it's a little harder. To prevent hijacking in all situations,
> https is a required part of the solution, and the cgi library can't
> force that unilaterally. Well, maybe it could, but it'd suck.)
>

My understanding is that you CANNOT assume different requests in the same session from the same computer are coming from the same IP. Apperently there are a lot of networks, such as corporate networks and anonymizing networks, which will cause different requests from the same user to wind up coming from different IPs.

The *ONLY* reliable way to prevent session hijacking without breaking your site for many users is to force everything (and I mean EVERYTHING) through https from the time the session is created to the time the session is killed.

Yes, that does suck, but you'll certainly never see me claim that the web isn't the absolute worst, piece of shit excuse for an "applications platform" in history.

One of the reasons for this particular mess (besides the whole "shoving applications through a stateless protocol" bullshit) is idiotic limitations of cookies. More specifically, there isn't nearly enough you can do to restrict the URLs for which the browser will send a particular cookie.


May 15, 2011
"Alexander" <aldem+dmars@nk7.net> wrote in message news:iqp58d$3lh$1@digitalmars.com...
>
>  From my point of view, it makes no sense to say "that is wrong" or "that
> is bad" - unless there is *objective* (and only) way to do something
> *right* - which is not the case in web development (and any software
> development in general).
>

That's just plain rediculous. Software development isn't some damn hippie commune where "There are never any wrong answers, just different opinions! Tee hee hee :) :) :)". There *are* better ways and worse ways to do many things. Despite what everyone seems to have been brainwashed into believing these days, not everything is a matter of personal preference or opinion. Fuck, what's next? "Well, *for me* I like to have 2+2 equal 5, you can't say it's wrong, it's just my preference and my opinion." If some city architect decided to make the primary structural frame of a giant high-rise out of wood because "I like it, and it works well for me", that stupid screw-up would get fired on the spot, drummed out of the industry, and for good reason.