But that code snippet is horrible; you should never catch an exception
and 'just log it' - ONLY the very top level should ever do that.
Secondly, if you do log-and-swallow, then whatever the heck you do,
don't continue with your method!
On Aug 24, 1:21 am, Martin Wildam mwil...@gmail.com wrote:
Martin Wildam wrote:
[...]
Maybe we should look at error handling from different point of views.
First, there is the very normal dummy user who don't have a clue on
what is there running in the background. Second there is a system
administrator who - if something goes wrong - could see
What about the signal-to-noise aspect? I find that to be annoying with
logging and the only sane reason to use AOP. However since I have an
issue with complexity and library creep, I prefer to simply have a
NetBeans plugin suppress the font color of logging statements. In the
perfect world, the
It's not out of band, Peter - this stuff happens, in real life, even
if you never explicitly accepted the burden of responsibility by e.g.
using @SneakyThrows. Just mixing class files compiled against
different versions of the same code base is enough to get there. Thus,
you *CANNOT* just swallow
On Aug 23, 12:52 am, Martin Wildam mwil...@gmail.com wrote:
In reality programmers could live without exceptions for many, many
years. ;-)
We all coded assembly too. You're flipping the argument around now,
Martin: Just because something is old, it's true.
That's just as logically invalid as
On Aug 23, 11:39 am, Reinier Zwitserloot reini...@gmail.com wrote:
A full and exhaustive treatise doesn't exist, but there are a few
rules almost everyone can agree with, and yet these rules are not
followed by the JDK, probably because we didn't know any better back
then. i.e.:
[...]
I can't let this horse puckey about 'exceptions are less readable'
stand. It's hogwash.
Consider that any operation, anywhere in the entirety of your java
source base, can throw just about any exception. Not just
theoretically, but practically: You can get an OutOfMemoryError, or a
Peter, your code sample is very much broken - exceptions are just
silently swallowed in the safe version. Sure, you declared that the
exception can't happen, but as I've mentioned a few times already,
because checked exceptions aren't enforced on the JVM level, they can
occur at _any_ time.
I think I might have caused some confusion by being too lazy: Ex is
meant to be a particular checked exception, not a shorthand for Exception.
If you are referring to your sneaky throws: I consider them out of
scope. There are many ways to subvert Java code, particularly if
reflection is
After initially disagreeing completely I can see a point in that
exceptions break the normal control flow and can thus cause surprising
behavior. But I agree with you that the alternatives aren't necessarily
better.
Somehow error handling is never easy. Just take one of these nice
graphical
On Aug 21, 4:46 pm, B Smith-Mannschott bsmith.o...@gmail.com wrote:
Checked exceptions *are* a failed experiment.
My first experience and after reading Joel's post I was thinking that
but previous posters convinced me that this is not necessarily true -
but I think there lies some truth also in
Martin Wildam wrote:
On Aug 22, 7:23 am, Peter Becker peter.becker...@gmail.com wrote:
While I'm still arguing for checked exceptions, I'm not 100% convinced
their good yet either. But nearly every argument I see why they are bad
is about how they are used badly, with the conclusion of
On 23 Aug., 01:25, Peter Becker peter.becker...@gmail.com wrote:
Someone should probably write a nice book talking only about error
handling, the different ways to propagate errors (special return values,
checked exceptions, unchecked exceptions, union types) and the different
ways to deal
Casper Bang wrote:
On 23 Aug., 01:25, Peter Becker peter.becker...@gmail.com wrote:
Someone should probably write a nice book talking only about error
handling, the different ways to propagate errors (special return values,
checked exceptions, unchecked exceptions, union types) and the
Hello,
Let me to say what I think on that topic.
Guys If you don't know how to handle exception for a given method then
you are better off simply throwing it. Just add it to the method
declaration. That's all about that.
Handle only exceptions in case you are know for sure how to deal with
a
Yep. That's my approach.
Guys If you don't know how to handle exception for a given method then
you are better off simply throwing it.
This sentence may confuse some who will assume they have to catch it
in the first place. Maybe a better phrase is:
If you don't know how to handle exception
I still kind-of like listening to Joel and Jeff. Both make me cringe at
times, but I like their attitude towards product design and I think Joel
has quite some insight into the marketing/business side of software.
But I don't think I'd want either as the chief architect of some
enterprise
Number one clearly does not apply to checked exceptions, number two
applies to returning values, too. Of course you could assign a value and
follow the approach of having a single return statement at the end, but
I never understood why the resulting code should be any easier.
Peter
Martin
As I said: in cases where you want to have a version of your code where
the exception bubbles up and one where it doesn't you'll get the
duplication. I think that is usually a bad idea, although I must admit
the wrapper case you describe is an exception since the layer is the
same. I don't
On Aug 21, 11:33 am, Peter Becker peter.becker...@gmail.com wrote:
Number one clearly does not apply to checked exceptions, number two
applies to returning values, too. Of course you could assign a value and
follow the approach of having a single return statement at the end, but
I never
I can follow your argument to some extent, but wouldn't the equivalent,
exception-based code have a try/catch block per if(goAhead)? I agree
that this would create code that is more verbose, but otherwise it seems
equivalent.
I take the point that it is possible to make code harder to read
I take the point that it is possible to make code harder to read using
exceptions in a way that is not possible without. I must admit I didn't
really think it through when I read Joel's blog post.
Joel seems to think of exceptions as mere alternative return points
and in that goto light, he
On 21 Aug., 15:50, Martin Wildam mwil...@gmail.com wrote:
I think the problem of context you also have when dealing with an
exception on the low level. Context is known most likely only by some
parent caller but on the other hand the parent caller often does not
have any clue about how some
On Aug 21, 2:07 pm, Peter Becker peter.becker...@gmail.com wrote:
I take the point that it is possible to make code harder to read using
exceptions in a way that is not possible without. I must admit I didn't
really think it through when I read Joel's blog post.
I think the reduced
Hi Possefolks,
I've been following both of the Exception-handling mega-threads and
have some opinions too, though unlikely original given the length of
the thread.
Checked exceptions *are* a failed experiment.
I thought they were a good idea when I first ran into them, but the
reality is quite
Martin Wildam wrote:
On Aug 21, 2:07 pm, Peter Becker peter.becker...@gmail.com wrote:
I take the point that it is possible to make code harder to read using
exceptions in a way that is not possible without. I must admit I didn't
really think it through when I read Joel's blog post.
B Smith-Mannschott wrote:
[...]
Some have argued that there's nothing wrong with checked exceptions,
per se, it's just that people don't use them right. This is akin to
acknowledging that every attempt to practice communism on a national
level has lead to a repressive police state, and yet
The one trick is to realize that the safe version is actually the more
specific one. If you think of the exception in terms of the type union
(not accurate, but a decent analogy), then Unsafe.method() returns
void|IOException while Safe.method() returns void, which is a more
specific type,
On 19 Aug., 20:45, Reinier Zwitserloot reini...@gmail.com wrote:
disjoint types are structural in that you weaken the namespacing of
members.
Members are only namespaced by virtue of their container. So lets say
I do this (I apologize in advance for the cliché factor of this
example):
Ben Schulz wrote:
The one trick is to realize that the safe version is actually the more
specific one. If you think of the exception in terms of the type union
(not accurate, but a decent analogy), then Unsafe.method() returns
void|IOException while Safe.method() returns void, which is a more
Joel on Software's view that exceptions are bad and you should be
using archaic C style error codes is, in a word: Effing Retarded.
Follow his advice at your own peril.
On Aug 20, 4:03 pm, Martin Wildam mwil...@gmail.com wrote:
Anyone a fan of
Anyone a fan of this: http://www.joelonsoftware.com/items/2003/10/13.html
I am. :-)
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups The
Java Posse group.
To post to this group, send email to
I lost my respect for Joel a while ago - he comes at you in very
bold, definitive and authoritative fashion (especially on
StackOverflow where he's down right annoying). Exceptions cater well
to OO, you can centralize error handling and dispatching via
polymorphism as well as associate whatever
On Aug 20, 4:13 pm, Casper Bang casper.b...@gmail.com wrote:
Exceptions cater well to OO, you can centralize error handling and
dispatching via
polymorphism as well as associate whatever context that's needed. I
don't think (hope) many in here wants to go back to interpreting
return values.
Peter, I still don't see how that'll avoid code duplication.
Let's say, for argument's sake, that a FilterInputStream's read()
method contains 4 pages of complex code. This code calls back into the
filtered stream's read method loads of times. How would we avoid
duplicating these 4 pages if we
On Wed, Aug 19, 2009 at 11:45 AM, Reinier Zwitserloot reini...@gmail.comwrote:
disjoint types are structural in that you weaken the namespacing of
members.
Disjoint types aren't structural unless the language makes them so. Java
could be extended with disjoint types that compute a least
Exactly. The Camera/Gun argument against structural typing doesn't hold
water because the programmer's error is exactly the same semantic problem as
// my library
interface Camera {
void shoot();
}
// somebody else's code
class Bazooka extends Camera {...}
The only constraints that Java
well put :)
On Aug 20, 8:36 am, Reinier Zwitserloot reini...@gmail.com wrote:
Joel on Software's view that exceptions are bad and you should be
using archaic C style error codes is, in a word: Effing Retarded.
Follow his advice at your own peril.
On Aug 20, 4:03 pm, Martin Wildam
This thread inspired me. Thanks in particular to Casper. Here you go,
an annotation processor that removes the notion of checked exceptions
completely from your javac:
http://groups.google.com/group/javaposse/browse_thread/thread/26ec00e0601023d
On Aug 21, 12:00 am, phil swenson
I'd much rather have a closure proposal where a method that takes a
closure that has tennant's correspondence principle is strictly
enforced by the compiler to keep the closure stack-safe. In other
words, legal operations are:
1. Running the closure,
2. Grabbing info off of the closure
Interestingly Java's generics allow the dual construction on interfaces:
public T extends Interface1 Interface2 void someMethod(T param) {...}
I really like the idea of having the anonymous unions/joins and
considering that the resulting type system should be a complete lattice
they sound
So there IS a bug for that.
I've added a link to http://bugs.sun.com/view_bug.do?bug_id=6534270 to
the documentation for lombok's @SupressWarnings, which does the exact
same thing.
Christian: If you go in with a class file editor and remove the throws
clauses, the code will continue to run just
I really like the idea of having the anonymous unions/joins and
considering that the resulting type system should be a complete lattice
they sound manageable to me -- both for the compiler and the human
reader. Does anyone know reasons why no language seems to have this feature?
I'm not much
I can confirm this is practice, in fact, the modification to
Check.java I described a few posts ago would also allow compilation of
code with catch clauses of checked exceptions not really being thrown.
/Casper
On 19 Aug., 13:14, Reinier Zwitserloot reini...@gmail.com wrote:
So there IS a bug
Yes, it would lose you the ability to parallelize. There may be a way
out of this: Have the following system call:
public class System {
public static R R unsafe(do R closure) { return closure; }
}
The above code would not compile (you may not let a 'do' parameter
escape, but the method is
Replies inline. The problem is simply this: You think I was trying to
argue against checked exceptions in general. I wasn't. I was arguing
that the checked exception system isn't perfect, and therefore
programmers need to be given a tool to say to the compiler: I know
better than you. Stop
Jess, I think you misunderstand my closure proposal.
It *DOES* have exception transparency. That's in fact exactly what it
has.
You further claim that you can't add exception transparency to
Collections.sort() without making a change to the API. This isn't
true! Read my post again - in my
I see this as an important change quite apart from the current debate.
Catching an exception that cannot be thrown should be a *warning* not an
error.
I'm sick of having code stop compiling because someone stopped throwing
a checked exception! That should *not* be a breaking change. There is
Catching an exception that cannot be thrown should be a *warning* not an
error.
I totally agree, talk about idiosyncrasies getting in the way of the
job. Anyway, if someone wants to give it a try, grab this build of
javac:
http://82.103.135.236/javac.jar
And notice there's no problem
On Wed, Aug 19, 2009 at 1:03 AM, Peter Becker peter.becker...@gmail.comwrote:
Interestingly Java's generics allow the dual construction on interfaces:
public T extends Interface1 Interface2 void someMethod(T param) {...}
Yeah, you can do intersection types in generics. But you can't write
I may have mentioned it before, but due to very complex reasons I
won't go into here, catching a checked exception that cannot be
thrown will most likely become a warning and not an error in java 7.
So, Jess, your #1 gripe may be about to be resolved*.
*) As there isn't an umbrella JSR, let
I don't follow. Union types don't seem particularly structural to me.
They're the disjunction of other types, and if the other types are
nominative then so is the union of them. A type like String | Integer
contians all expressions that are Strings or Integers. The idea would be
that you can
That's what I was refering to as having to check the runtime type. I
don't feel like you gained much in your sample, you could just replace
String | Integer with Object and add a default: throw new
AssertionError();. Obviously you gained type safety, but it would be
much more useful if unions
On Wed, Aug 19, 2009 at 7:36 AM, Ben Schulz ya...@gmx.net wrote:
don't feel like you gained much in your sample, you could just replace
String | Integer with Object and add a default: throw new
AssertionError();. Obviously you gained type safety,
Isn't that kinda the point of a type
Thanks for the info.
That would be *great*.
Reinier Zwitserloot wrote:
I may have mentioned it before, but due to very complex reasons I
won't go into here, catching a checked exception that cannot be
thrown will most likely become a warning and not an error in java 7.
So, Jess, your #1
Obviously you gained type safety,
Isn't that kinda the point of a type system? :-)
I suppose, but for me it's more about why I should write down the
types. If we asked Gilad Bracha, he'd probably say it's a bad idea
because they restrain your thinking. Me, I say it's good because the
On Aug 18, 4:48 pm, Peter Becker peter.becker...@gmail.com wrote:
phil swenson wrote:
So you are saying it is better to quietly change behaviour than to make
a change to an API that breaks source compatibility? I certainly would
not agree to that.
So every API written in every other
Hi all,
A few days ago I ran into an interesting article about Java Exceptions
Handling on the Oracle technology website:
http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html
It covers checked/unchecked exceptions and multi-tier hints.
Lorenzo
Reinier Zwitserloot wrote:
Replies inline. The problem is simply this: You think I was trying to
argue against checked exceptions in general. I wasn't. I was arguing
that the checked exception system isn't perfect, and therefore
programmers need to be given a tool to say to the compiler: I
Ben Schulz wrote:
Obviously you gained type safety,
Isn't that kinda the point of a type system? :-)
I suppose, but for me it's more about why I should write down the
types. If we asked Gilad Bracha, he'd probably say it's a bad idea
because they restrain your thinking. Me, I say
Why don't we just change checked exception from being an error to
being a warning? It would not break any kind of compatibility. And as
a library author, you still get the power to tell your clients that
here's something to pay special attention to, but without getting in
the way of people doing
On Aug 20, 12:21 am, Peter Becker peter.becker...@gmail.com wrote:
No implementation would be duplicated, the safe version could be a
subtype of the unsafe one. Not too many interfaces will face that
problem. To me it seems much better than not distinguishing.
Can you show me how this would
public void handleWebRequest(String target, Request req, Response res)
throws Exception {
@Cleanup(release) Db db = worker.getDb();
db.doWhatever();
}
couldn't be simpler, really. @Cleanup is from project lombok, and it
ensures the db is released even if this method errors out. Note
On Aug 18, 5:27 am, phil swenson phil.swen...@gmail.com wrote:
Someone should short-circuit javac, since
checked exceptions really is just a figment of its imagination.
Done, sort of, if you use eclipse, at any rate. Install project lombok
and stick:
@SneakyThrows
on every method that you
In Scala you get the Either type. That is superior for most cases where
one might use checked exceptions in Java.
I have used that style in Java, but you usually don't make friends with it.
Peter
Michael Neale wrote:
What do people think of the scala approach of no checked exceptions -
I still believe that the main reason people hate checked exceptions is
that they have been used badly.
But I don't really like them either, I just dislike runtime exceptions
more ;-) The reason for that is that they hide things I might want to
know about when using an API. No one reads
The problem I feel is that an Exception should denote an EXCEPTIONAL
occurrence, and be able to list all things that can happen is just plain
impossible.
So switching to a fully checked exceptions would mean that every method
signature should mandatory include stuff like:
public void foo(Bar bar)
Regarding closing JDBC resources when exceptions happen...
I like to have one close in the 'finally' block, but execute only when
the reference isn't null. (Yes, that's evil -- but JDBC's
SQLException is evil.)
What I'd like to do is to add any 'close()' SQLException to the
exception that may
Reinier Zwitserloot wrote:
Yes, an utopia with checked exceptions is probably pretty decent, but
as a practical matter they've been horribly abused. Not just by third
party libraries; the java core library is inconsistent in places and
has a lot of missing throws clauses in interfaces that
Lombok - is that named after Lombok in bali - near the island of
Java?
On Aug 18, 5:00 pm, Reinier Zwitserloot reini...@gmail.com wrote:
public void handleWebRequest(String target, Request req, Response res)
throws Exception {
@Cleanup(release) Db db = worker.getDb();
Is it really that bad? Most of the common exceptions shouldn't be there
at all, for example NullPointerException, ClassCastException and
ArrayStoreException are all just signs of a broken type system. Some of
the Errors seem unavoidable, but with the Exceptions I still prefer the
idea of
Proably would use a set of case classes I guess, but would end up
looking like a pretty version of that (someone like Viktor will
probably show us !).
On Aug 18, 9:11 pm, Peter Becker peter.becker...@gmail.com wrote:
Reinier Zwitserloot wrote:
Yes, an utopia with checked exceptions is
Lombok looks interesting. Groovy makes this sort of code very
palatable too, instead of:
@Cleanup PreparedStatement ps = connection.prepareStatement
(sql);
@Cleanup ResultSet resultSet = ps.executeQuery();
while (resultSet.next()) {
// stuff
}
You
I guess should have used a different variable name in the last example:
db.eachRow(sql) { /* stuff */ }
Cheers, Paul.
On Tue, Aug 18, 2009 at 11:37 PM, Paul Kingpaul.king.as...@gmail.com wrote:
Lombok looks interesting. Groovy makes this sort of code very
palatable too, instead of:
://wcollage.sourceforge.net
From: Peter Becker peter.becker...@gmail.com
To: javaposse@googlegroups.com
Sent: Tuesday, August 18, 2009 6:13:54 AM
Subject: [The Java Posse] Re: How do YOU handle Exceptions?
I still believe that the main reason people hate checked
On 18 Aug., 16:51, Alexey Zinger inline_f...@yahoo.com wrote:
Maybe what this discussion needs is some real-world anecdotes of checked vs
unchecked exceptions in production environments and how they helped or not to
save the day.
I would think it's a fairly real-world anecdote how no other
On Aug 18, 11:03 am, Casper Bang casper.b...@gmail.com wrote:
On 18 Aug., 16:51, Alexey Zinger inline_f...@yahoo.com wrote:
Maybe what this discussion needs is some real-world anecdotes of checked vs
unchecked exceptions in production environments and how they helped or not
to save the
I understand the theoretical benefit of checked exceptions, but
reality trumps theory. They simply don't scale and lead to swallowed/
hidden exceptions.
I've seen quite a few open source APIs that have throws Exception in
them. And generally the open source APIs are done by some of the best
Yes. And the indonesian word for chili paste, which is also lombok.
(Spice up your java is the tag line, after all.)
On Aug 18, 1:22 pm, Michael Neale michael.ne...@gmail.com wrote:
Lombok - is that named after Lombok in bali - near the island of
Java?
On Aug 18, 5:00 pm, Reinier Zwitserloot
Exceptions aren't just for exceptional situations. This seems
perfectly legit to me:
public class BankAccount {
public void transferFundsTo(BankAccount other, int amount) throws
InsufficientBalanceException {}
}
The InsufficientBalanceException is not an exceptional situation. It
happens
Reinier Zwitserloot wrote:
Concrete examples:
Runnable does not let you throw Exceptions. Anyone up for defending
this grievous API design? The amount of annoyance that this is caused
me is almost limitless.
Well Runnable is really for cases where run() should eat any exceptions
other
The way I normally think about it is, business exceptions are (usually)
checked exceptions. Error conditions are RuntimeExceptions.
-Mario.
--
I want to change the world but they won't give me the source code.
On Tue, Aug 18, 2009 at 19:56, Reinier Zwitserloot reini...@gmail.comwrote:
BGGA's checked exception handling is extremely complex. I don't like
it at all.
I'd much rather have a closure proposal where a method that takes a
closure that has tennant's correspondence principle is strictly
enforced by the compiler to keep the closure stack-safe. In other
words, legal
On Tue, Aug 18, 2009 at 3:13 AM, Peter Becker peter.becker...@gmail.comwrote:
What I would really like to see is a meet/or/disjunction/union operator
in the type system, with a case-like construct to resolve the resulting
types. Scala has two things that are halfway there (Either, case
I'm slightly embarrassed to admit I'm a fan of
http://bugs.sun.com/view_bug.do?bug_id=6534270
On Aug 15, 5:56 am, Jeff Grigg jeffgr...@charter.net wrote:
I like the beauty and simplicity of completely empty catch blocks. ;- OK,
some developers, to comply with corporate documentation
BGGA's exception transparency hinges on disjunctive types, of course...
James Iry wrote:
On Tue, Aug 18, 2009 at 3:13 AM, Peter Becker peter.becker.de
http://peter.becker.de@gmail.com http://gmail.com wrote:
What I would really like to see is a meet/or/disjunction/union
operator
Reinier Zwitserloot wrote:
BGGA's checked exception handling is extremely complex. I don't like
it at all.
You can gripe about that, but it is the only thing that really makes a
code block work normally.
If you have something like:
for ( ... )
{
// some code that throw
According to Joshua Engel's Programming for the Java VM, that is not
part of the verification algorithm. I had planned to do something
similar in Kijaro, and instead have NetBeans issue warnings when
neglecting to catch a checked exception - but I never really found out
how to override NetBeans
I really hate phrasing something like this as being a figment. That's
like saying that short and char are figments of the JVM's imagination
because it's all just bits.
None-the-less, the answer is that checked exceptions are enforced by Java's
static system and not by the JVM at all. So Scala,
On 19 Aug., 04:06, James Iry james...@gmail.com wrote:
I really hate phrasing something like this as being a figment. That's
like saying that short and char are figments of the JVM's imagination
because it's all just bits.
Yeah well, it depends how you look at it I suppose. I would also
I can think of a hack. But it's not a very nice one and probably has
limited use. You compile with throws Exception on the method and
then edit the method signature in the resulting byte code. Perhaps
easier than hacking javac.
--~--~-~--~~~---~--~~
You
On 19 Aug., 04:24, Christian Catchpole christ...@catchpole.net
wrote:
I can think of a hack. But it's not a very nice one and probably has
limited use. You compile with throws Exception on the method and
then edit the method signature in the resulting byte code. Perhaps
easier than
Maybe is good if something may or may not be there such in a dictionary
lookup. The element not being available is a normal occurrence in that case.
In the case of errors it would hide what the actual error was.
Peter
Michael Neale wrote:
Or Maybe - (in which case you don't care about the
Reinier Zwitserloot wrote:
Concrete examples:
Runnable does not let you throw Exceptions. Anyone up for defending
this grievous API design? The amount of annoyance that this is caused
me is almost limitless.
Where would that exception go?
Servlets require you to wrap checked exceptions
Let me just say that I fully agree with this post. I believe most people
look at the way checked exceptions are used and since that is mostly bad
they assume the whole idea is bad. Since I can think of nicer solutions
with checked exceptions for pretty much everything people complain about
I
phil swenson wrote:
[...]
Another issue I didn't mention is checked exceptions pollute the
interface. Lets say you have a public API (interface) and add a new
exception type. This makes every consumer of your API's code break.
This violates the concept of having an API contract. So with
I agree that there is a blurry line between exception and alternate
return value and as stated elsewhere I would prefer a union type in most
cases.
In your example the exception should be reasonable exceptional, though
-- after all people should not try a transfer unless they checked the
On Tue, Aug 18, 2009 at 7:11 PM, Casper Bang casper.b...@gmail.com wrote:
Yeah well, it depends how you look at it I suppose. I would also claim
generics to be a figment of the JVM's imagination, since you can not
implement ComparableInteger and ComparableBigInteger due to it
being an
Well actually, Stephen Colebourne has made is real easy to hack on the
Java compiler - especially small hacks strictly at the parser level,
which we're talking about here. If you want to try it check out a
branch of Kijaro, locate the Check.java class and the methods matching
the signatures:
especially small hacks strictly at the parser level
Ok yeah, I know technically it's at the semantic analysis level, but I
always think of the entire front-end (lexer, parser, semantic
analysis) as just the parser. Somewhat simpler than optimizer and
emitter.
/Casper
1 - 100 of 130 matches
Mail list logo