Hey,

On Mon, Jun 19, 2017 at 12:43 PM, <mhhc...@gmail.com> wrote:

> I don t feel like expanding code helps to better explain
> the how/what/why of a sudden 42 question ? (why this /whatever/ has
> failed, I believe it should not)
>

I may be biased in this regard by personal experience. I am running (as an
ops-person) several large web service written in Java and C++ (and some
written in go) and I am pretty consistently frustrated by the lack of good
comprehension tools for routing. I very often run into the situation of,
for example, a black-box monitoring system telling me that a request failed
and needing to understand how it traces from the main entry point of the
server to the failure site and how all the parameters used are chosen. Or
developing against a service and needing to understand what I am doing
wrong when one of my requests is failing. Or just getting paged because we
are serving errors and needing to grep through logs for patterns in the
failing requests and then figuring out why these specific requests are the
ones that are failing.

I talking about the concern of tracing routing through code not because
it's fun to me to make up problems, but because it's a frequent source of
frustration for me.


> I m pretty sure its a good way to multiply keystrokes, and harden
> maintenance and changes.
>

I don't think it is either more typing or making maintenance harder,
obviously :) For the latter, I already described my reasoning in the post
itself, so I'm not going into detail. For the latter, I gave an example here
<https://www.reddit.com/r/golang/comments/6i22tm/how_not_to_use_an_httprouter_in_go/dj3nc32/>,
of how you can reduce the number of keystrokes necessary, if that's your
primary concern while maintaining the same pattern and the advantages I'm
talking about.

I don't think you *should* do that, though; just as you shouldn't use test
frameworks with assert-functions. If what you are doing is comparing
values, you should write them as an if-clause, that's readable and what
they are designed for. But if you really want to, you can do it. It's an
orthogonal concern to what I'm talking about.


> The gorilla handler can handle the type checking and return a proper error
> code.
>

But that ignores the issue. The issue isn't, that the muxer (let's not talk
too specifically about gorilla, I only use it as an example) can't figure
out that there is a non-int given as a parameter. The issue is, that *by
design* (that is pretty much the point of a muxer), you can have
intersecting sets of routes that might or might not match; the muxer will
pick a strategy and try each route out in series, until it finds a match.

A request like "/foo/12a" would fail a pattern like "/foo/{id:[0-9]+}". But
should the muxer, when it tries this pattern for this path return a 400,
because the pattern is invalid, a 404, because there is no matching pattern
defined, a 405, because you used GET instead of POST or should it continue
trying? There might be another route to try, which defines a pattern for
/foo/12a. Or a route that defines "/foo/{id:0-9a-z]+". Or any other set of
routes.
Should it, when it exhausted all the configured routes, return the 400 of
the pattern "/foo/{id:[0-9]+}" it tried, the 405 of the route
Methods("GET").Path("/foo/12a") it tried or a 404?

I would boldy claim, that to solve this problem in general, a muxer API
would need to basically be Turing-complete (which is exactly why this
<https://godoc.org/github.com/gorilla/mux#Router.MatcherFunc> exists, by
the way). In my view, this negates the supposed advantages of a muxer.
Instead of calling the checks as Methods on the muxer, I can also just
write them in my handler, in the component, they belong to anyway.

It's not actually more verbose or complicated than calling methods on a
muxer-value, but it enables you to make an authoritative decision purely
based on local knowlege, so it becomes a *much* simpler problem to solve.
Plus, you actually *have* a Turing-complete language at your disposal.

The fact that it also makes the handler self-contained, so it can be
maintained by a separate team than the rest of the application or reused in
completely different applications is a then bonus.


>
> So, you can resolve the 42 question,
> not by diving in the code,
> but by reading the error messages,
> or *reading at the documentation.*
>
> (note: reading the error messages=> totally fail when you develop a
> website, not an api, as the error page is often generic and do not provide
> a deep explanation of the error, as the end user does not care about it
>

Totally disagree here. HTTP is primarily built for web pages and provides
well-defined status codes. A user might not need to care about the detailed
reasons for a 500, but they definitely want to know, that this is an
unforseen error condition in the server, as opposed to something they did
wrong. They want to know, if they entered an invalid phone number, that the
problem is the phone number they entered and not the database server not
responding, the form using the wrong method or that they need to log in
first. It's endlessly frustrating, as a user, to just get an "There was an
error" message. It's not actionable; should I call a support line? Change
the inputs I gave? Switch browsers?

It's just normal error-handling stuff; just like you want the message of
your error to be sufficiently descriptive to a user wanting to know what
changes they need to do to their usage to make your thing run, you want the
details delivered to a visitor of your website to be sufficiently
descriptive that *they* know what they could change to make it go (Do they
need to login? Do they need to change what they entered in a form? Is a
website not available in their language or does their browser not
understand the format the server is sending?).


> In both case its an additional job to be done, in one way or another.
>
> Somewhere you also talk about the idea that using a router would tightly
> link
> components by their types, adn that is bad in your opinion.
>

No, not by their types, just in general. The router needs to get a handle
to all transitive dependencies. The issue even is the opposite: The router
is generic, so it *doesn't* know anything about actual, concrete types,
making static analysis hard or impossible.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to